mirror of
https://github.com/RSS-Bridge/rss-bridge.git
synced 2025-08-03 01:25:21 +02:00
[{Atom,Mrss}Format]: Generate using DomDocument (#2771)
* [AtomFormat]: Generate using DomDocument This will escape the HTML content for us as needed. * [MrssFormat]: Generate using DomDocument This will escape the HTML content for us as needed.
This commit is contained in:
parent
fb501652d5
commit
90d22f0d80
2 changed files with 198 additions and 162 deletions
|
@ -9,6 +9,9 @@
|
|||
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/';
|
||||
|
||||
const LIMIT_TITLE = 140;
|
||||
|
||||
public function stringify(){
|
||||
|
@ -17,26 +20,66 @@ class AtomFormat extends FormatAbstract{
|
|||
$urlPath = (isset($_SERVER['PATH_INFO'])) ? $_SERVER['PATH_INFO'] : '';
|
||||
$urlRequest = (isset($_SERVER['REQUEST_URI'])) ? $_SERVER['REQUEST_URI'] : '';
|
||||
|
||||
$feedUrl = $this->xml_encode($urlPrefix . $urlHost . $urlRequest);
|
||||
$feedUrl = $urlPrefix . $urlHost . $urlRequest;
|
||||
|
||||
$extraInfos = $this->getExtraInfos();
|
||||
$title = $this->xml_encode($extraInfos['name']);
|
||||
$uri = !empty($extraInfos['uri']) ? $extraInfos['uri'] : REPOSITORY;
|
||||
|
||||
$document = new DomDocument('1.0', $this->getCharset());
|
||||
$document->formatOutput = true;
|
||||
$feed = $document->createElementNS(self::ATOM_NS, 'feed');
|
||||
$feed->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:media', self::MRSS_NS);
|
||||
$document->appendChild($feed);
|
||||
|
||||
$title = $document->createElement('title');
|
||||
$title->setAttribute('type', 'text');
|
||||
$title->appendChild($document->createTextNode($extraInfos['name']));
|
||||
$feed->appendChild($title);
|
||||
|
||||
$id = $document->createElement('id');
|
||||
$id->appendChild($document->createTextNode($feedUrl));
|
||||
$feed->appendChild($id);
|
||||
|
||||
$uriparts = parse_url($uri);
|
||||
if(!empty($extraInfos['icon'])) {
|
||||
$iconUrl = $extraInfos['icon'];
|
||||
} else {
|
||||
$iconUrl = $uriparts['scheme'] . '://' . $uriparts['host'] . '/favicon.ico';
|
||||
}
|
||||
$icon = $document->createElement('icon');
|
||||
$icon->appendChild($document->createTextNode($iconUrl));
|
||||
$feed->appendChild($icon);
|
||||
|
||||
$logo = $document->createElement('logo');
|
||||
$logo->appendChild($document->createTextNode($iconUrl));
|
||||
$feed->appendChild($logo);
|
||||
|
||||
$feedTimestamp = gmdate(DATE_ATOM, $this->lastModified);
|
||||
$updated = $document->createElement('updated');
|
||||
$updated->appendChild($document->createTextNode($feedTimestamp));
|
||||
$feed->appendChild($updated);
|
||||
|
||||
// since we can't guarantee that all items have an author,
|
||||
// a global feed author is mandatory
|
||||
$feedAuthor = 'RSS-Bridge';
|
||||
$author = $document->createElement('author');
|
||||
$authorName = $document->createElement('name');
|
||||
$authorName->appendChild($document->createTextNode($feedAuthor));
|
||||
$author->appendChild($authorName);
|
||||
$feed->appendChild($author);
|
||||
|
||||
$uriparts = parse_url($uri);
|
||||
if(!empty($extraInfos['icon'])) {
|
||||
$icon = $extraInfos['icon'];
|
||||
} else {
|
||||
$icon = $this->xml_encode($uriparts['scheme'] . '://' . $uriparts['host'] . '/favicon.ico');
|
||||
}
|
||||
$linkAlternate = $document->createElement('link');
|
||||
$linkAlternate->setAttribute('rel', 'alternate');
|
||||
$linkAlternate->setAttribute('type', 'text/html');
|
||||
$linkAlternate->setAttribute('href', $uri);
|
||||
$feed->appendChild($linkAlternate);
|
||||
|
||||
$uri = $this->xml_encode($uri);
|
||||
$linkSelf = $document->createElement('link');
|
||||
$linkSelf->setAttribute('rel', 'self');
|
||||
$linkSelf->setAttribute('type', 'application/atom+xml');
|
||||
$linkSelf->setAttribute('href', $feedUrl);
|
||||
$feed->appendChild($linkSelf);
|
||||
|
||||
$entries = '';
|
||||
foreach($this->getItems() as $item) {
|
||||
$entryTimestamp = $item->getTimestamp();
|
||||
$entryTitle = $item->getTitle();
|
||||
|
@ -48,7 +91,7 @@ class AtomFormat extends FormatAbstract{
|
|||
$entryID = 'urn:sha1:' . $item->getUid();
|
||||
|
||||
if (empty($entryID)) // Fallback to provided URI
|
||||
$entryID = $this->xml_encode($entryUri);
|
||||
$entryID = $entryUri;
|
||||
|
||||
if (empty($entryID)) // Fallback to title and content
|
||||
$entryID = 'urn:sha1:' . hash('sha1', $entryTitle . $entryContent);
|
||||
|
@ -67,96 +110,75 @@ class AtomFormat extends FormatAbstract{
|
|||
if (empty($entryContent))
|
||||
$entryContent = ' ';
|
||||
|
||||
$entryAuthor = '';
|
||||
if ($item->getAuthor()) {
|
||||
$entryAuthor = $this->xml_encode($item->getAuthor());
|
||||
}
|
||||
$entry = $document->createElement('entry');
|
||||
|
||||
$entryTitle = $this->xml_encode($entryTitle);
|
||||
$entryUri = $this->xml_encode($entryUri);
|
||||
$entryTimestamp = $this->xml_encode(gmdate(DATE_ATOM, $entryTimestamp));
|
||||
$entryContent = $this->xml_encode($this->sanitizeHtml($entryContent));
|
||||
$title = $document->createElement('title');
|
||||
$title->setAttribute('type', 'html');
|
||||
$title->appendChild($document->createTextNode($entryTitle));
|
||||
$entry->appendChild($title);
|
||||
|
||||
$entryEnclosures = '';
|
||||
foreach($item->getEnclosures() as $enclosure) {
|
||||
$entryEnclosures .= '<link rel="enclosure" href="'
|
||||
. $this->xml_encode($enclosure)
|
||||
. '" type="' . getMimeType($enclosure) . '" />'
|
||||
. PHP_EOL;
|
||||
}
|
||||
$entryTimestamp = gmdate(DATE_ATOM, $entryTimestamp);
|
||||
$published = $document->createElement('published');
|
||||
$published->appendChild($document->createTextNode($entryTimestamp));
|
||||
$entry->appendChild($published);
|
||||
|
||||
$entryCategories = '';
|
||||
foreach($item->getCategories() as $category) {
|
||||
$entryCategories .= '<category term="'
|
||||
. $this->xml_encode($category)
|
||||
. '"/>'
|
||||
. PHP_EOL;
|
||||
}
|
||||
$updated = $document->createElement('updated');
|
||||
$updated->appendChild($document->createTextNode($entryTimestamp));
|
||||
$entry->appendChild($updated);
|
||||
|
||||
$entryThumbnail = $item->thumbnail;
|
||||
if (!empty($entryThumbnail))
|
||||
$entryThumbnail = '<media:thumbnail url="' . $this->xml_encode($entryThumbnail) . '"/>';
|
||||
$id = $document->createElement('id');
|
||||
$id->appendChild($document->createTextNode($entryID));
|
||||
$entry->appendChild($id);
|
||||
|
||||
$entryLinkAlternate = '';
|
||||
if (!empty($entryUri)) {
|
||||
$entryLinkAlternate = '<link rel="alternate" type="text/html" href="'
|
||||
. $entryUri
|
||||
. '"/>';
|
||||
$entryLinkAlternate = $document->createElement('link');
|
||||
$entryLinkAlternate->setAttribute('rel', 'alternate');
|
||||
$entryLinkAlternate->setAttribute('type', 'text/html');
|
||||
$entryLinkAlternate->setAttribute('href', $entryUri);
|
||||
$entry->appendChild($entryLinkAlternate);
|
||||
}
|
||||
|
||||
if (!empty($entryAuthor)) {
|
||||
$entryAuthor = '<author><name>'
|
||||
. $entryAuthor
|
||||
. '</name></author>';
|
||||
if (!empty($item->getAuthor())) {
|
||||
$author = $document->createElement('author');
|
||||
$authorName = $document->createElement('name');
|
||||
$authorName->appendChild($document->createTextNode($item->getAuthor()));
|
||||
$author->appendChild($authorName);
|
||||
$entry->appendChild($author);
|
||||
}
|
||||
|
||||
$entries .= <<<EOD
|
||||
$content = $document->createElement('content');
|
||||
$content->setAttribute('type', 'html');
|
||||
$content->appendChild($document->createTextNode($this->sanitizeHtml($entryContent)));
|
||||
$entry->appendChild($content);
|
||||
|
||||
<entry>
|
||||
<title type="html">{$entryTitle}</title>
|
||||
<published>{$entryTimestamp}</published>
|
||||
<updated>{$entryTimestamp}</updated>
|
||||
<id>{$entryID}</id>
|
||||
{$entryLinkAlternate}
|
||||
{$entryAuthor}
|
||||
<content type="html">{$entryContent}</content>
|
||||
{$entryEnclosures}
|
||||
{$entryCategories}
|
||||
{$entryThumbnail}
|
||||
</entry>
|
||||
foreach($item->getEnclosures() as $enclosure) {
|
||||
$entryEnclosure = $document->createElement('link');
|
||||
$entryEnclosure->setAttribute('rel', 'enclosure');
|
||||
$entryEnclosure->setAttribute('type', getMimeType($enclosure));
|
||||
$entryEnclosure->setAttribute('href', $enclosure);
|
||||
$entry->appendChild($entryEnclosure);
|
||||
}
|
||||
|
||||
EOD;
|
||||
foreach($item->getCategories() as $category) {
|
||||
$entryCategory = $document->createElement('category');
|
||||
$entryCategory->setAttribute('term', $category);
|
||||
$entry->appendChild($entryCategory);
|
||||
}
|
||||
|
||||
if (!empty($item->thumbnail)) {
|
||||
$thumbnail = $document->createElementNS(self::MRSS_NS, 'media:thumbnail');
|
||||
$thumbnail->setAttribute('url', $item->thumbnail);
|
||||
$entry->appendChild($thumbnail);
|
||||
}
|
||||
|
||||
$feed->appendChild($entry);
|
||||
}
|
||||
|
||||
$feedTimestamp = gmdate(DATE_ATOM, $this->lastModified);
|
||||
$charset = $this->getCharset();
|
||||
|
||||
/* Data are prepared, now let's begin the "MAGIE !!!" */
|
||||
$toReturn = <<<EOD
|
||||
<?xml version="1.0" encoding="{$charset}"?>
|
||||
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/">
|
||||
|
||||
<title type="text">{$title}</title>
|
||||
<id>{$feedUrl}</id>
|
||||
<icon>{$icon}</icon>
|
||||
<logo>{$icon}</logo>
|
||||
<updated>{$feedTimestamp}</updated>
|
||||
<author>
|
||||
<name>{$feedAuthor}</name>
|
||||
</author>
|
||||
<link rel="alternate" type="text/html" href="{$uri}" />
|
||||
<link rel="self" type="application/atom+xml" href="{$feedUrl}" />
|
||||
{$entries}
|
||||
</feed>
|
||||
EOD;
|
||||
$toReturn = $document->saveXML();
|
||||
|
||||
// Remove invalid characters
|
||||
ini_set('mbstring.substitute_character', 'none');
|
||||
$toReturn = mb_convert_encoding($toReturn, $this->getCharset(), 'UTF-8');
|
||||
return $toReturn;
|
||||
}
|
||||
|
||||
private function xml_encode($text){
|
||||
return htmlspecialchars($text, ENT_XML1);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue