From 938b067ba0f3a4d494edbdb1241d054e7d15b633 Mon Sep 17 00:00:00 2001 From: Hidehito Nozawa Date: Thu, 21 Jul 2016 23:05:32 +0900 Subject: [PATCH] Support PubSubHubbub Signed-off-by: Hidehito Nozawa --- README.md | 9 +++++--- examples/simple-feed.php | 1 + src/Suin/RSSWriter/Channel.php | 29 +++++++++++++++++++++++++ src/Suin/RSSWriter/Feed.php | 2 +- src/Suin/RSSWriter/Item.php | 2 +- src/Suin/RSSWriter/SimpleXMLElement.php | 19 +++++++++++++--- tests/Suin/RSSWriter/ChannelTest.php | 9 ++++++++ tests/Suin/RSSWriter/FeedTest.php | 6 ++--- tests/Suin/RSSWriter/ItemTest.php | 6 ++--- 9 files changed, 69 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 0e07d1c..3a55db0 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,7 @@ $channel ->pubDate(strtotime('Tue, 21 Aug 2012 19:50:37 +0900')) ->lastBuildDate(strtotime('Tue, 21 Aug 2012 19:50:37 +0900')) ->ttl(60) + ->pubsubhubbub('http://example.com/feed.xml', 'http://pubsubhubbub.appspot.com') // This is optional. Specify PubSubHubbub discovery if you want. ->appendTo($feed); // Blog item @@ -58,7 +59,7 @@ Output: ```xml - + Channel Title http://blog.example.com @@ -68,11 +69,13 @@ Output: Tue, 21 Aug 2012 10:50:37 +0000 Tue, 21 Aug 2012 10:50:37 +0000 60 - + + + <![CDATA[Blog Entry Title]]> http://blog.example.com/2012/08/21/blog-entry/ Blog body]]> - Blog body]]> + Blog body]]> http://blog.example.com/2012/08/21/blog-entry/ Tue, 21 Aug 2012 10:50:37 +0000 Hidehito Nozawa diff --git a/examples/simple-feed.php b/examples/simple-feed.php index 58927d3..99eea87 100644 --- a/examples/simple-feed.php +++ b/examples/simple-feed.php @@ -22,6 +22,7 @@ ->pubDate(strtotime('Tue, 21 Aug 2012 19:50:37 +0900')) ->lastBuildDate(strtotime('Tue, 21 Aug 2012 19:50:37 +0900')) ->ttl(60) + ->pubsubhubbub('http://example.com/feed.xml', 'http://pubsubhubbub.appspot.com') // This is optional. Specify PubSubHubbub discovery if you want. ->appendTo($feed); // Blog item diff --git a/src/Suin/RSSWriter/Channel.php b/src/Suin/RSSWriter/Channel.php index ebfe185..66b2b7d 100644 --- a/src/Suin/RSSWriter/Channel.php +++ b/src/Suin/RSSWriter/Channel.php @@ -32,6 +32,9 @@ class Channel implements ChannelInterface /** @var int */ protected $ttl; + /** @var string[] */ + protected $pubsubhubbub; + /** @var ItemInterface[] */ protected $items = []; @@ -129,6 +132,21 @@ public function ttl($ttl) return $this; } + /** + * Enable PubSubHubbub discovery + * @param string $feedUrl + * @param string $hubUrl + * @return $this + */ + public function pubsubhubbub($feedUrl, $hubUrl) + { + $this->pubsubhubbub = [ + 'feedUrl' => $feedUrl, + 'hubUrl' => $hubUrl, + ]; + return $this; + } + /** * Add item object * @param ItemInterface $item @@ -182,6 +200,17 @@ public function asXML() $xml->addChild('ttl', $this->ttl); } + if ($this->pubsubhubbub !== null) { + $feedUrl = $xml->addChild('xmlns:atom:link'); + $feedUrl->addAttribute('rel', 'self'); + $feedUrl->addAttribute('href', $this->pubsubhubbub['feedUrl']); + $feedUrl->addAttribute('type', 'application/rss+xml'); + + $hubUrl = $xml->addChild('xmlns:atom:link'); + $hubUrl->addAttribute('rel', 'hub'); + $hubUrl->addAttribute('href', $this->pubsubhubbub['hubUrl']); + } + foreach ($this->items as $item) { $toDom = dom_import_simplexml($xml); $fromDom = dom_import_simplexml($item->asXML()); diff --git a/src/Suin/RSSWriter/Feed.php b/src/Suin/RSSWriter/Feed.php index eac9e14..e805049 100644 --- a/src/Suin/RSSWriter/Feed.php +++ b/src/Suin/RSSWriter/Feed.php @@ -30,7 +30,7 @@ public function addChannel(ChannelInterface $channel) */ public function render() { - $xml = new SimpleXMLElement('', LIBXML_NOERROR | LIBXML_ERR_NONE | LIBXML_ERR_FATAL); + $xml = new SimpleXMLElement('', LIBXML_NOERROR | LIBXML_ERR_NONE | LIBXML_ERR_FATAL); foreach ($this->channels as $channel) { $toDom = dom_import_simplexml($xml); diff --git a/src/Suin/RSSWriter/Item.php b/src/Suin/RSSWriter/Item.php index 85c48e7..1000a6f 100644 --- a/src/Suin/RSSWriter/Item.php +++ b/src/Suin/RSSWriter/Item.php @@ -126,7 +126,7 @@ public function asXML() } if ($this->contentEncoded) { - $xml->addCdataChild('encoded', $this->contentEncoded, 'http://purl.org/rss/1.0/modules/content/'); + $xml->addCdataChild('xmlns:content:encoded', $this->contentEncoded); } foreach ($this->categories as $category) { diff --git a/src/Suin/RSSWriter/SimpleXMLElement.php b/src/Suin/RSSWriter/SimpleXMLElement.php index 70309d5..e731f94 100644 --- a/src/Suin/RSSWriter/SimpleXMLElement.php +++ b/src/Suin/RSSWriter/SimpleXMLElement.php @@ -8,6 +8,12 @@ */ class SimpleXMLElement extends \SimpleXMLElement { + /** + * @param string $name + * @param string $value + * @param string $namespace + * @return \SimpleXMLElement + */ public function addChild($name, $value = null, $namespace = null) { if ($value !== null and is_string($value) === true) { @@ -17,11 +23,18 @@ public function addChild($name, $value = null, $namespace = null) return parent::addChild($name, $value, $namespace); } + /** + * @param string $name + * @param string $value + * @param string $namespace + * @return \SimpleXMLElement + */ public function addCdataChild($name, $value = null, $namespace = null) { $element = $this->addChild($name, null, $namespace); - $element = dom_import_simplexml($element); - $elementOwner = $element->ownerDocument; - $element->appendChild($elementOwner->createCDATASection($value)); + $dom = dom_import_simplexml($element); + $elementOwner = $dom->ownerDocument; + $dom->appendChild($elementOwner->createCDATASection($value)); + return $element; } } diff --git a/tests/Suin/RSSWriter/ChannelTest.php b/tests/Suin/RSSWriter/ChannelTest.php index 911b9f2..a7a94c3 100644 --- a/tests/Suin/RSSWriter/ChannelTest.php +++ b/tests/Suin/RSSWriter/ChannelTest.php @@ -71,6 +71,15 @@ public function testTtl() $this->assertAttributeSame($ttl, 'ttl', $channel); } + public function testPubsubhubbub() + { + $channel = new Channel(); + $channel->pubsubhubbub('http://example.com/feed.xml', 'http://pubsubhubbub.appspot.com'); + $xml = $channel->asXML()->asXML(); + $this->assertContains('', $xml); + $this->assertContains('', $xml); + } + public function testAddItem() { $item = $this->getMock($this->itemInterface); diff --git a/tests/Suin/RSSWriter/FeedTest.php b/tests/Suin/RSSWriter/FeedTest.php index 10bd405..97203f1 100644 --- a/tests/Suin/RSSWriter/FeedTest.php +++ b/tests/Suin/RSSWriter/FeedTest.php @@ -30,7 +30,7 @@ public function testRender() $channel3->expects($this->once())->method('asXML')->will($this->returnValue($xml3)); $this->reveal($feed)->attr('channels', [$channel1, $channel2, $channel3]); $expect = ' - + channel1 channel2 channel3 @@ -54,7 +54,7 @@ public function testRender_with_japanese() $this->reveal($feed)->attr('channels', [$channel1, $channel2, $channel3]); $expect = <<< 'XML' - + 日本語1 @@ -85,7 +85,7 @@ public function test__toString() $channel3->expects($this->once())->method('asXML')->will($this->returnValue($xml3)); $this->reveal($feed)->attr('channels', [$channel1, $channel2, $channel3]); $expect = ' - + channel1 channel2 channel3 diff --git a/tests/Suin/RSSWriter/ItemTest.php b/tests/Suin/RSSWriter/ItemTest.php index a19b5df..9d9658e 100644 --- a/tests/Suin/RSSWriter/ItemTest.php +++ b/tests/Suin/RSSWriter/ItemTest.php @@ -44,16 +44,16 @@ public function testContentEncoded() $channel->appendTo($feed); $expected = ' - + <link/> <description/> - <item xmlns:default="http://purl.org/rss/1.0/modules/content/"> + <item> <title/> <link/> <description/> - <content:encoded xmlns="http://purl.org/rss/1.0/modules/content/"><![CDATA[<div>contents</div>]]></content:encoded> + <content:encoded><![CDATA[<div>contents</div>]]></content:encoded> </item> </channel> </rss>';