<?php /** * MrssFormat - RSS 2.0 + Media RSS * http://www.rssboard.org/rss-specification * http://www.rssboard.org/media-rss * * Validators: * https://validator.w3.org/feed/ * http://www.rssboard.org/rss-validator/ * * Notes about the implementation: * * - The item author is not supported as it needs to be an e-mail address to be * valid. * - The RSS specification does not explicitly allow to have more than one * enclosure as every item is meant to provide one "story", thus having * multiple enclosures per item may lead to unexpected behavior. * On top of that, it requires to have a length specified, which RSS-Bridge * can't provide. * - The Media RSS extension comes in handy, since it allows to have multiple * enclosures, even though they recommend to have only one enclosure because * of the one-story-per-item reason. It only requires to specify the URL, * everything else is optional. * - Since the Media RSS extension has its own namespace, the output is a valid * RSS 2.0 feed that works with feed readers that don't support the extension. */ class MrssFormat extends FormatAbstract { const MIME_TYPE = 'application/rss+xml'; const ALLOWED_IMAGE_EXT = array( '.gif', '.jpg', '.png' ); public function stringify(){ $urlPrefix = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') ? 'https://' : 'http://'; $urlHost = (isset($_SERVER['HTTP_HOST'])) ? $_SERVER['HTTP_HOST'] : ''; $urlPath = (isset($_SERVER['PATH_INFO'])) ? $_SERVER['PATH_INFO'] : ''; $urlRequest = (isset($_SERVER['REQUEST_URI'])) ? $_SERVER['REQUEST_URI'] : ''; $feedUrl = $this->xml_encode($urlPrefix . $urlHost . $urlRequest); $extraInfos = $this->getExtraInfos(); $title = $this->xml_encode($extraInfos['name']); $icon = $extraInfos['icon']; if(!empty($extraInfos['uri'])) { $uri = $this->xml_encode($extraInfos['uri']); } else { $uri = REPOSITORY; } $items = ''; foreach($this->getItems() as $item) { $itemTimestamp = $item->getTimestamp(); $itemTitle = $this->xml_encode($item->getTitle()); $itemUri = $this->xml_encode($item->getURI()); $itemContent = $this->xml_encode($this->sanitizeHtml($item->getContent())); $entryID = $item->getUid(); $isPermaLink = 'false'; if (empty($entryID) && !empty($itemUri)) { // Fallback to provided URI $entryID = $itemUri; $isPermaLink = 'true'; } if (empty($entryID)) // Fallback to title and content $entryID = hash('sha1', $itemTitle . $itemContent); $entryTitle = ''; if (!empty($itemTitle)) $entryTitle = '<title>' . $itemTitle . '</title>'; $entryLink = ''; if (!empty($itemUri)) $entryLink = '<link>' . $itemUri . '</link>'; $entryPublished = ''; if (!empty($itemTimestamp)) { $entryPublished = '<pubDate>' . $this->xml_encode(gmdate(DATE_RFC2822, $itemTimestamp)) . '</pubDate>'; } $entryDescription = ''; if (!empty($itemContent)) $entryDescription = '<description>' . $itemContent . '</description>'; $entryEnclosures = ''; foreach($item->getEnclosures() as $enclosure) { $entryEnclosures .= '<media:content url="' . $this->xml_encode($enclosure) . '" type="' . getMimeType($enclosure) . '"/>' . PHP_EOL; } $entryCategories = ''; foreach($item->getCategories() as $category) { $entryCategories .= '<category>' . $category . '</category>' . PHP_EOL; } $items .= <<<EOD <item> {$entryTitle} {$entryLink} <guid isPermaLink="{$isPermaLink}">{$entryID}</guid> {$entryPublished} {$entryDescription} {$entryEnclosures} {$entryCategories} </item> EOD; } $charset = $this->getCharset(); $feedImage = ''; if (!empty($icon) && in_array(substr($icon, -4), self::ALLOWED_IMAGE_EXT)) { $feedImage .= <<<EOD <image> <url>{$icon}</url> <title>{$title}</title> <link>{$uri}</link> </image> EOD; } /* Data are prepared, now let's begin the "MAGIE !!!" */ $toReturn = <<<EOD <?xml version="1.0" encoding="{$charset}"?> <rss version="2.0" xmlns:media="http://search.yahoo.com/mrss/" xmlns:atom="http://www.w3.org/2005/Atom"> <channel> <title>{$title}</title> <link>{$uri}</link> <description>{$title}</description> {$feedImage} <atom:link rel="alternate" type="text/html" href="{$uri}"/> <atom:link rel="self" href="{$feedUrl}" type="application/atom+xml"/> {$items} </channel> </rss> EOD; // Remove invalid non-UTF8 characters ini_set('mbstring.substitute_character', 'none'); $toReturn = mb_convert_encoding($toReturn, $this->getCharset(), 'UTF-8'); return $toReturn; } public function display(){ $this ->setContentType(self::MIME_TYPE . '; charset=' . $this->getCharset()) ->callContentType(); return parent::display(); } private function xml_encode($text){ return htmlspecialchars($text, ENT_XML1); } }