diff --git a/formats/MrssFormat.php b/formats/MrssFormat.php index 34b9a92a..836a361a 100644 --- a/formats/MrssFormat.php +++ b/formats/MrssFormat.php @@ -1,18 +1,45 @@ xml_encode($_SERVER['REQUEST_URI']) : ''; + 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']); @@ -20,34 +47,48 @@ class MrssFormat extends FormatAbstract { $uri = REPOSITORY; } - $uriparts = parse_url($uri); - $icon = $this->xml_encode($uriparts['scheme'] . '://' . $uriparts['host'] . '/favicon.ico'); - $items = ''; foreach($this->getItems() as $item) { - $itemAuthor = $this->xml_encode($item->getAuthor()); + $itemTimestamp = $item->getTimestamp(); $itemTitle = $this->xml_encode($item->getTitle()); $itemUri = $this->xml_encode($item->getURI()); - $itemTimestamp = $this->xml_encode(date(DATE_RFC2822, $item->getTimestamp())); $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 = '' . $itemTitle . ''; + + $entryLink = ''; + if (!empty($itemUri)) + $entryLink = '' . $itemUri . ''; + + $entryPublished = ''; + if (!empty($itemTimestamp)) { + $entryPublished = '' + . $this->xml_encode(gmdate(DATE_RFC2822, $itemTimestamp)) + . ''; + } + + $entryDescription = ''; + if (!empty($itemContent)) + $entryDescription = '' . $itemContent . ''; - $entryEnclosuresWarning = ''; $entryEnclosures = ''; - if(!empty($item->getEnclosures())) { - $entryEnclosures .= ''; - - if(count($item->getEnclosures()) > 1) { - $entryEnclosures .= PHP_EOL; - $entryEnclosuresWarning = '<br>Warning: -Some media files might not be shown to you. Consider using the ATOM format instead!'; - foreach($item->getEnclosures() as $enclosure) { - $entryEnclosures .= '' - . PHP_EOL; - } - } + foreach($item->getEnclosures() as $enclosure) { + $entryEnclosures .= '' + . PHP_EOL; } $entryCategories = ''; @@ -60,12 +101,11 @@ Some media files might not be shown to you. Consider using the ATOM format inste $items .= << - {$itemTitle} - {$itemUri} - {$itemUri} - {$itemTimestamp} - {$itemContent}{$entryEnclosuresWarning} - {$itemAuthor} + {$entryTitle} + {$entryLink} + {$entryID} + {$entryPublished} + {$entryDescription} {$entryEnclosures} {$entryCategories} @@ -75,22 +115,28 @@ EOD; $charset = $this->getCharset(); - /* xml attributes need to have certain characters escaped to be w3c compliant */ - $imageTitle = htmlspecialchars($title, ENT_COMPAT); + $feedImage = ''; + if (!empty($icon) && in_array(substr($icon, -4), self::ALLOWED_IMAGE_EXT)) { + $feedImage .= << + {$icon} + {$title} + {$uri} + +EOD; + } + /* Data are prepared, now let's begin the "MAGIE !!!" */ $toReturn = << - + {$title} - http{$https}://{$httpHost}{$httpInfo}/ + {$uri} {$title} - - - + {$feedImage} + + {$items} diff --git a/tests/MrssFormatTest.php b/tests/MrssFormatTest.php new file mode 100644 index 00000000..b4dd32a9 --- /dev/null +++ b/tests/MrssFormatTest.php @@ -0,0 +1,90 @@ +setSample($path); + $this->initFormat(); + + $this->assertContains( + 'Content-Type: application/rss+xml; charset=' . $this->format->getCharset(), + xdebug_get_headers() + ); + } + + /** + * @dataProvider sampleProvider + * @runInSeparateProcess + */ + public function testOutput($path) { + $this->setSample($path); + $this->initFormat(); + + $this->assertXmlStringEqualsXmlFile($this->sample->expected, $this->data); + } + + //////////////////////////////////////////////////////////////////////////// + + public function sampleProvider() { + $samples = array(); + foreach (glob(self::PATH_SAMPLES . '*.json') as $path) { + $samples[basename($path, '.json')] = array($path); + } + return $samples; + } + + private function setSample($path) { + $data = json_decode(file_get_contents($path), true); + if (isset($data['meta']) && isset($data['items'])) { + if (!empty($data['server'])) + $this->setServerVars($data['server']); + + $items = array(); + foreach($data['items'] as $item) { + $items[] = new \FeedItem($item); + } + + $this->sample = (object)array( + 'meta' => $data['meta'], + 'items' => $items, + 'expected' => self::PATH_EXPECTED . basename($path, '.json') . '.xml' + ); + } else { + $this->fail('invalid test sample: ' . basename($path, '.json')); + } + } + + private function setServerVars($list) { + $_SERVER = array_merge($_SERVER, $list); + } + + private function initFormat() { + $this->format = \Format::create('Mrss'); + $this->format->setItems($this->sample->items); + $this->format->setExtraInfos($this->sample->meta); + $this->format->setLastModified(strtotime('2000-01-01 12:00:00 UTC')); + + $this->data = $this->getActualOutput($this->format->display()); + $this->assertNotFalse(simplexml_load_string($this->data)); + ob_clean(); + } +} diff --git a/tests/samples/expectedMrssFormat/feed.common.xml b/tests/samples/expectedMrssFormat/feed.common.xml new file mode 100644 index 00000000..38a16f88 --- /dev/null +++ b/tests/samples/expectedMrssFormat/feed.common.xml @@ -0,0 +1,64 @@ + + + + Sample feed with common data + https://example.com/blog/ + Sample feed with common data + + https://example.com/logo.png + Sample feed with common data + https://example.com/blog/ + + + + + + Test Entry + http://example.com/blog/test-entry + http://example.com/blog/test-entry + Sat, 01 Dec 2018 12:00:00 +0000 + Hello world, this is a test entry. + test + Hello World + example + + + Announcing JSON Feed + https://jsonfeed.org/2017/05/17/announcing_json_feed + https://jsonfeed.org/2017/05/17/announcing_json_feed + Wed, 17 May 2017 13:02:12 +0000 + <p>We — Manton Reece and Brent Simmons — have noticed that JSON has become the developers’ choice for APIs, and that developers will often go out of their way to avoid XML. JSON is simpler to read and write, and it’s less prone to bugs.</p> + +<p>So we developed JSON Feed, a format similar to <a href="http://cyber.harvard.edu/rss/rss.html">RSS</a> and <a href="https://tools.ietf.org/html/rfc4287">Atom</a> but in JSON. It reflects the lessons learned from our years of work reading and publishing feeds.</p> + +<p><a href="https://jsonfeed.org/version/1">See the spec</a>. It’s at version 1, which may be the only version ever needed. If future versions are needed, version 1 feeds will still be valid feeds.</p> + +<h4>Notes</h4> + +<p>We have a <a href="https://github.com/manton/jsonfeed-wp">WordPress plugin</a> and, coming soon, a JSON Feed Parser for Swift. As more code is written, by us and others, we’ll update the <a href="https://jsonfeed.org/code">code</a> page.</p> + +<p>See <a href="https://jsonfeed.org/mappingrssandatom">Mapping RSS and Atom to JSON Feed</a> for more on the similarities between the formats.</p> + +<p>This website — the Markdown files and supporting resources — <a href="https://github.com/brentsimmons/JSONFeed">is up on GitHub</a>, and you’re welcome to comment there.</p> + +<p>This website is also a blog, and you can subscribe to the <a href="https://jsonfeed.org/xml/rss.xml">RSS feed</a> or the <a href="https://jsonfeed.org/feed.json">JSON feed</a> (if your reader supports it).</p> + +<p>We worked with a number of people on this over the course of several months. We list them, and thank them, at the bottom of the <a href="https://jsonfeed.org/version/1">spec</a>. But — most importantly — <a href="http://furbo.org/">Craig Hockenberry</a> spent a little time making it look pretty. :)</p> + + + Atom draft-07 snapshot + http://example.org/2005/04/02/atom + dd6b6c920d3b340ab9e07faf6682f2a7c4f70134 + Sun, 31 Jul 2005 12:29:29 +0000 + <p><i>[Update: The Atom draft is finished.]</i></p> + + + + Star City + http://liftoff.msfc.nasa.gov/news/2003/news-starcity.asp + http://liftoff.msfc.nasa.gov/news/2003/news-starcity.asp + Tue, 03 Jun 2003 09:39:21 +0000 + How do Americans get ready to work with Russians aboard the International Space Station? They take a crash course in culture, language and protocol at Russia's <a href="http://howe.iki.rssi.ru/GCTC/gctc_e.htm">Star City</a>. + + + diff --git a/tests/samples/expectedMrssFormat/feed.empty.xml b/tests/samples/expectedMrssFormat/feed.empty.xml new file mode 100644 index 00000000..888c42b6 --- /dev/null +++ b/tests/samples/expectedMrssFormat/feed.empty.xml @@ -0,0 +1,10 @@ + + + + Sample feed with minimum data + https://github.com/RSS-Bridge/rss-bridge/ + Sample feed with minimum data + + + + diff --git a/tests/samples/expectedMrssFormat/feed.emptyItems.xml b/tests/samples/expectedMrssFormat/feed.emptyItems.xml new file mode 100644 index 00000000..9e712ddd --- /dev/null +++ b/tests/samples/expectedMrssFormat/feed.emptyItems.xml @@ -0,0 +1,19 @@ + + + + Sample feed with minimum data + https://github.com/RSS-Bridge/rss-bridge/ + Sample feed with minimum data + + + + + Sample Item #1 + 29f59918d266c56a935da13e4122b524298e5a39 + + + Sample Item #2 + edf358cad1a7ae255d6bc97640dd9d27738f1b7b + + + diff --git a/tests/samples/expectedMrssFormat/feed.microblog.xml b/tests/samples/expectedMrssFormat/feed.microblog.xml new file mode 100644 index 00000000..81dac87a --- /dev/null +++ b/tests/samples/expectedMrssFormat/feed.microblog.xml @@ -0,0 +1,26 @@ + + + + Sample microblog feed + https://example.com/blog/ + Sample microblog feed + + https://example.com/logo.png + Sample microblog feed + https://example.com/blog/ + + + + + + 1918f084648b82057c1dd3faa3d091da82a6fac2 + Sun, 07 Oct 2018 16:53:03 +0000 + Oh 😲 I found three monkeys 🙈🙉🙊 + + + e62189168a06dfa74f61c621c79c33c4c8517e1f + Sun, 07 Oct 2018 16:38:17 +0000 + Something happened + + +