<?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'; const LIMIT_TITLE = 140; 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']); $uri = !empty($extraInfos['uri']) ? $extraInfos['uri'] : REPOSITORY; // since we can't guarantee that all items have an author, // a global feed author is mandatory $feedAuthor = 'RSS-Bridge'; $uriparts = parse_url($uri); if(!empty($extraInfos['icon'])) { $icon = $extraInfos['icon']; } else { $icon = $this->xml_encode($uriparts['scheme'] . '://' . $uriparts['host'] . '/favicon.ico'); } $uri = $this->xml_encode($uri); $entries = ''; foreach($this->getItems() as $item) { $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 = $this->xml_encode($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) > self::LIMIT_TITLE) { $wrapPos = strpos(wordwrap($entryTitle, self::LIMIT_TITLE), "\n"); $entryTitle = substr($entryTitle, 0, $wrapPos) . '...'; } } if (empty($entryContent)) $entryContent = $entryTitle; $entryAuthor = $this->xml_encode($item->getAuthor()); $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)); $entryEnclosures = ''; foreach($item->getEnclosures() as $enclosure) { $entryEnclosures .= '<link rel="enclosure" href="' . $this->xml_encode($enclosure) . '" type="' . getMimeType($enclosure) . '" />' . PHP_EOL; } $entryCategories = ''; foreach($item->getCategories() as $category) { $entryCategories .= '<category term="' . $this->xml_encode($category) . '"/>' . PHP_EOL; } $entryThumbnail = $item->thumbnail; if (!empty($entryThumbnail)) $entryThumbnail = '<media:thumbnail url="' . $this->xml_encode($entryThumbnail) . '"/>'; $entryLinkAlternate = ''; if (!empty($entryUri)) { $entryLinkAlternate = '<link rel="alternate" type="text/html" href="' . $entryUri . '"/>'; } if (!empty($entryAuthor)) { $entryAuthor = '<author><name>' . $entryAuthor . '</name></author>'; } $entries .= <<<EOD <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> EOD; } $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; // Remove invalid 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); } }