mirror of
https://github.com/RSS-Bridge/rss-bridge.git
synced 2024-11-25 19:06:23 +03:00
213 lines
8.7 KiB
PHP
213 lines
8.7 KiB
PHP
<?php
|
|
|
|
/**
|
|
* AtomFormat - RFC 4287: The Atom Syndication Format
|
|
* https://tools.ietf.org/html/rfc4287
|
|
*
|
|
* Validator:
|
|
* https://validator.w3.org/feed/
|
|
*/
|
|
class AtomFormat extends FormatAbstract
|
|
{
|
|
const MIME_TYPE = 'application/atom+xml';
|
|
|
|
protected const ATOM_NS = 'http://www.w3.org/2005/Atom';
|
|
protected const MRSS_NS = 'http://search.yahoo.com/mrss/';
|
|
|
|
public function stringify()
|
|
{
|
|
$document = new \DomDocument('1.0', $this->getCharset());
|
|
$document->formatOutput = true;
|
|
|
|
$feedUrl = get_current_url();
|
|
|
|
$feed = $document->createElementNS(self::ATOM_NS, 'feed');
|
|
$document->appendChild($feed);
|
|
$feed->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:media', self::MRSS_NS);
|
|
|
|
$feedArray = $this->getFeed();
|
|
foreach ($feedArray as $feedKey => $feedValue) {
|
|
if (in_array($feedKey, ['donationUri'])) {
|
|
continue;
|
|
}
|
|
if ($feedKey === 'name') {
|
|
$title = $document->createElement('title');
|
|
$feed->appendChild($title);
|
|
$title->setAttribute('type', 'text');
|
|
$title->appendChild($document->createTextNode($feedValue));
|
|
} elseif ($feedKey === 'icon') {
|
|
if ($feedValue) {
|
|
$icon = $document->createElement('icon');
|
|
$feed->appendChild($icon);
|
|
$icon->appendChild($document->createTextNode($feedValue));
|
|
|
|
$logo = $document->createElement('logo');
|
|
$feed->appendChild($logo);
|
|
$logo->appendChild($document->createTextNode($feedValue));
|
|
}
|
|
} elseif ($feedKey === 'uri') {
|
|
if ($feedValue) {
|
|
$linkAlternate = $document->createElement('link');
|
|
$feed->appendChild($linkAlternate);
|
|
$linkAlternate->setAttribute('rel', 'alternate');
|
|
$linkAlternate->setAttribute('type', 'text/html');
|
|
$linkAlternate->setAttribute('href', $feedValue);
|
|
|
|
$linkSelf = $document->createElement('link');
|
|
$feed->appendChild($linkSelf);
|
|
$linkSelf->setAttribute('rel', 'self');
|
|
$linkSelf->setAttribute('type', 'application/atom+xml');
|
|
$linkSelf->setAttribute('href', $feedUrl);
|
|
}
|
|
} elseif ($feedKey === 'itunes') {
|
|
// todo: skip?
|
|
} else {
|
|
$element = $document->createElement($feedKey);
|
|
$feed->appendChild($element);
|
|
$element->appendChild($document->createTextNode($feedValue));
|
|
}
|
|
}
|
|
|
|
$id = $document->createElement('id');
|
|
$feed->appendChild($id);
|
|
$id->appendChild($document->createTextNode($feedUrl));
|
|
|
|
$feedTimestamp = gmdate(DATE_ATOM, $this->lastModified);
|
|
$updated = $document->createElement('updated');
|
|
$feed->appendChild($updated);
|
|
$updated->appendChild($document->createTextNode($feedTimestamp));
|
|
|
|
// since we can't guarantee that all items have an author,
|
|
// a global feed author is mandatory
|
|
$feedAuthor = 'RSS-Bridge';
|
|
$author = $document->createElement('author');
|
|
$feed->appendChild($author);
|
|
$authorName = $document->createElement('name');
|
|
$author->appendChild($authorName);
|
|
$authorName->appendChild($document->createTextNode($feedAuthor));
|
|
|
|
|
|
|
|
foreach ($this->getItems() as $item) {
|
|
$itemArray = $item->toArray();
|
|
$entryTimestamp = $item->getTimestamp();
|
|
$entryTitle = $item->getTitle();
|
|
$entryContent = $item->getContent();
|
|
$entryUri = $item->getURI();
|
|
$entryID = '';
|
|
|
|
if (!empty($item->getUid())) {
|
|
$entryID = 'urn:sha1:' . $item->getUid();
|
|
}
|
|
|
|
if (empty($entryID)) {
|
|
// Fallback to provided URI
|
|
$entryID = $entryUri;
|
|
}
|
|
|
|
if (empty($entryID)) {
|
|
// Fallback to title and content
|
|
$entryID = 'urn:sha1:' . hash('sha1', $entryTitle . $entryContent);
|
|
}
|
|
|
|
if (empty($entryTimestamp)) {
|
|
$entryTimestamp = $this->lastModified;
|
|
}
|
|
|
|
if (empty($entryTitle)) {
|
|
$entryTitle = str_replace("\n", ' ', strip_tags($entryContent));
|
|
if (strlen($entryTitle) > 140) {
|
|
$wrapPos = strpos(wordwrap($entryTitle, 140), "\n");
|
|
$entryTitle = substr($entryTitle, 0, $wrapPos) . '...';
|
|
}
|
|
}
|
|
|
|
if (empty($entryContent)) {
|
|
$entryContent = ' ';
|
|
}
|
|
|
|
$entry = $document->createElement('entry');
|
|
$feed->appendChild($entry);
|
|
|
|
$title = $document->createElement('title');
|
|
$entry->appendChild($title);
|
|
$title->setAttribute('type', 'html');
|
|
$title->appendChild($document->createTextNode($entryTitle));
|
|
|
|
$entryTimestamp = gmdate(\DATE_ATOM, $entryTimestamp);
|
|
$published = $document->createElement('published');
|
|
$entry->appendChild($published);
|
|
$published->appendChild($document->createTextNode($entryTimestamp));
|
|
|
|
$updated = $document->createElement('updated');
|
|
$entry->appendChild($updated);
|
|
$updated->appendChild($document->createTextNode($entryTimestamp));
|
|
|
|
$id = $document->createElement('id');
|
|
$entry->appendChild($id);
|
|
$id->appendChild($document->createTextNode($entryID));
|
|
|
|
if (isset($itemArray['itunes'])) {
|
|
$feed->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:itunes', self::ITUNES_NS);
|
|
foreach ($itemArray['itunes'] as $itunesKey => $itunesValue) {
|
|
$itunesProperty = $document->createElementNS(self::ITUNES_NS, $itunesKey);
|
|
$entry->appendChild($itunesProperty);
|
|
$itunesProperty->appendChild($document->createTextNode($itunesValue));
|
|
}
|
|
if (isset($itemArray['enclosure'])) {
|
|
$itunesEnclosure = $document->createElement('enclosure');
|
|
$entry->appendChild($itunesEnclosure);
|
|
$itunesEnclosure->setAttribute('url', $itemArray['enclosure']['url']);
|
|
$itunesEnclosure->setAttribute('length', $itemArray['enclosure']['length']);
|
|
$itunesEnclosure->setAttribute('type', $itemArray['enclosure']['type']);
|
|
}
|
|
} elseif (!empty($entryUri)) {
|
|
$entryLinkAlternate = $document->createElement('link');
|
|
$entry->appendChild($entryLinkAlternate);
|
|
$entryLinkAlternate->setAttribute('rel', 'alternate');
|
|
$entryLinkAlternate->setAttribute('type', 'text/html');
|
|
$entryLinkAlternate->setAttribute('href', $entryUri);
|
|
}
|
|
|
|
if (!empty($item->getAuthor())) {
|
|
$author = $document->createElement('author');
|
|
$entry->appendChild($author);
|
|
$authorName = $document->createElement('name');
|
|
$author->appendChild($authorName);
|
|
$authorName->appendChild($document->createTextNode($item->getAuthor()));
|
|
}
|
|
|
|
$content = $document->createElement('content');
|
|
$content->setAttribute('type', 'html');
|
|
$content->appendChild($document->createTextNode($entryContent));
|
|
$entry->appendChild($content);
|
|
|
|
foreach ($item->getEnclosures() as $enclosure) {
|
|
$entryEnclosure = $document->createElement('link');
|
|
$entry->appendChild($entryEnclosure);
|
|
$entryEnclosure->setAttribute('rel', 'enclosure');
|
|
$entryEnclosure->setAttribute('type', parse_mime_type($enclosure));
|
|
$entryEnclosure->setAttribute('href', $enclosure);
|
|
}
|
|
|
|
foreach ($item->getCategories() as $category) {
|
|
$entryCategory = $document->createElement('category');
|
|
$entry->appendChild($entryCategory);
|
|
$entryCategory->setAttribute('term', $category);
|
|
}
|
|
|
|
if (!empty($item->thumbnail)) {
|
|
$thumbnail = $document->createElementNS(self::MRSS_NS, 'thumbnail');
|
|
$entry->appendChild($thumbnail);
|
|
$thumbnail->setAttribute('url', $item->thumbnail);
|
|
}
|
|
}
|
|
|
|
$xml = $document->saveXML();
|
|
|
|
// Remove invalid characters
|
|
ini_set('mbstring.substitute_character', 'none');
|
|
$xml = mb_convert_encoding($xml, $this->getCharset(), 'UTF-8');
|
|
return $xml;
|
|
}
|
|
}
|