]> git.immae.eu Git - github/shaarli/Shaarli.git/commitdiff
Move PubSubHubbub code as a default plugin 620/head
authorArthurHoaro <arthur@hoa.ro>
Tue, 2 Aug 2016 09:55:49 +0000 (11:55 +0200)
committerArthurHoaro <arthur@hoa.ro>
Tue, 20 Dec 2016 10:41:24 +0000 (11:41 +0100)
12 files changed:
application/FeedBuilder.php
composer.json
index.php
plugins/pubsubhubbub/README.md [new file with mode: 0644]
plugins/pubsubhubbub/hub.atom.xml [new file with mode: 0644]
plugins/pubsubhubbub/hub.rss.xml [new file with mode: 0644]
plugins/pubsubhubbub/pubsubhubbub.meta [new file with mode: 0644]
plugins/pubsubhubbub/pubsubhubbub.php [new file with mode: 0644]
tests/FeedBuilderTest.php
tests/plugins/PluginPubsubhubbubTest.php [new file with mode: 0644]
tpl/feed.atom.html
tpl/feed.rss.html

index fedd90e661faefc4d6cec4a3152eaae2996bcbf9..a1f4da4810c0b25dceebb8d6698de93cf4eb81e9 100644 (file)
@@ -62,11 +62,6 @@ class FeedBuilder
      */
     protected $hideDates;
 
-    /**
-     * @var string PubSub hub URL.
-     */
-    protected $pubsubhubUrl;
-
     /**
      * @var string server locale.
      */
@@ -120,7 +115,6 @@ class FeedBuilder
         }
 
         $data['language'] = $this->getTypeLanguage();
-        $data['pubsubhub_url'] = $this->pubsubhubUrl;
         $data['last_update'] = $this->getLatestDateFormatted();
         $data['show_dates'] = !$this->hideDates || $this->isLoggedIn;
         // Remove leading slash from REQUEST_URI.
@@ -182,16 +176,6 @@ class FeedBuilder
         return $link;
     }
 
-    /**
-     * Assign PubSub hub URL.
-     *
-     * @param string $pubsubhubUrl PubSub hub url.
-     */
-    public function setPubsubhubUrl($pubsubhubUrl)
-    {
-        $this->pubsubhubUrl = $pubsubhubUrl;
-    }
-
     /**
      * Set this to true to use permalinks instead of direct links.
      *
index 4786fe94a9d622a03c783fb1cf127ea8701871d4..cfbde1a0695ee7a58eb86ee93e340e36baa6e9d4 100644 (file)
@@ -13,7 +13,8 @@
         "php": ">=5.5",
         "shaarli/netscape-bookmark-parser": "1.*",
         "erusev/parsedown": "1.6",
-        "slim/slim": "^3.0"
+        "slim/slim": "^3.0",
+        "pubsubhubbub/publisher": "dev-master"
     },
     "require-dev": {
         "phpmd/phpmd" : "@stable",
index eb73941deded389a6521264cf9112358e71543fb..dd9b48bd2f84ed3cedea29ce0f8b7552a3b52cdf 100644 (file)
--- a/index.php
+++ b/index.php
@@ -910,10 +910,6 @@ function renderPage($conf, $pluginManager, $LINKSDB)
         $feedGenerator->setLocale(strtolower(setlocale(LC_COLLATE, 0)));
         $feedGenerator->setHideDates($conf->get('privacy.hide_timestamps') && !isLoggedIn());
         $feedGenerator->setUsePermalinks(isset($_GET['permalinks']) || !$conf->get('feed.rss_permalinks'));
-        $pshUrl = $conf->get('config.PUBSUBHUB_URL');
-        if (!empty($pshUrl)) {
-            $feedGenerator->setPubsubhubUrl($pshUrl);
-        }
         $data = $feedGenerator->buildData();
 
         // Process plugin hook.
@@ -1289,7 +1285,6 @@ function renderPage($conf, $pluginManager, $LINKSDB)
 
         $LINKSDB[$id] = $link;
         $LINKSDB->save($conf->get('resource.page_cache'));
-        pubsubhub($conf);
 
         // If we are called from the bookmarklet, we must close the popup:
         if (isset($_GET['source']) && ($_GET['source']=='bookmarklet' || $_GET['source']=='firefoxsocialapi')) {
diff --git a/plugins/pubsubhubbub/README.md b/plugins/pubsubhubbub/README.md
new file mode 100644 (file)
index 0000000..3a65492
--- /dev/null
@@ -0,0 +1,20 @@
+# PubSubHubbub plugin
+
+Enable this plugin to notify a Hub everytime you add or edit a link.
+This allow hub subcribers to receive update notifications in real time,
+which is useful for feed syndication service which supports PubSubHubbub.
+
+## Public Hub
+
+By default, Shaarli will use [Google's public hub](http://pubsubhubbub.appspot.com/).
+
+[Here](https://github.com/pubsubhubbub/PubSubHubbub/wiki/Hubs) is a list of public hubs.
+
+You can also host your own PubSubHubbub server implementation, such as [phubb](https://github.com/cweiske/phubb).
+
+## cURL
+
+While there is a fallback function to notify the hub, it's recommended that
+you have PHP cURL extension enabled to use this plugin.
+
diff --git a/plugins/pubsubhubbub/hub.atom.xml b/plugins/pubsubhubbub/hub.atom.xml
new file mode 100644 (file)
index 0000000..24d93d3
--- /dev/null
@@ -0,0 +1 @@
+<link rel="hub" href="%s" />
\ No newline at end of file
diff --git a/plugins/pubsubhubbub/hub.rss.xml b/plugins/pubsubhubbub/hub.rss.xml
new file mode 100644 (file)
index 0000000..27bf67a
--- /dev/null
@@ -0,0 +1 @@
+<atom:link rel="hub" href="%s" />
\ No newline at end of file
diff --git a/plugins/pubsubhubbub/pubsubhubbub.meta b/plugins/pubsubhubbub/pubsubhubbub.meta
new file mode 100644 (file)
index 0000000..289f5cd
--- /dev/null
@@ -0,0 +1,2 @@
+description="Enable PubSubHubbub feed publishing."
+parameters="PUBSUBHUB_URL"
diff --git a/plugins/pubsubhubbub/pubsubhubbub.php b/plugins/pubsubhubbub/pubsubhubbub.php
new file mode 100644 (file)
index 0000000..03b6757
--- /dev/null
@@ -0,0 +1,101 @@
+<?php
+
+/**
+ * PubSubHubbub plugin.
+ *
+ * PubSub is a protocol which fasten up RSS fetching:
+ *   - Every time a new link is posted, Shaarli notify the hub.
+ *   - The hub notify all feed subscribers that a new link has been posted.
+ *   - Subscribers retrieve the new link. 
+ */
+
+use pubsubhubbub\publisher\Publisher;
+
+/**
+ * Plugin init function - set the hub to the default appspot one.
+ *
+ * @param ConfigManager $conf instance.
+ */
+function pubsubhubbub_init($conf)
+{
+    $hub = $conf->get('plugins.PUBSUBHUB_URL');
+    if (empty($hub)) {
+        // Default hub.
+        $conf->set('plugins.PUBSUBHUB_URL', 'https://pubsubhubbub.appspot.com/');
+    }
+}
+
+
+/**
+ * Render feed hook.
+ * Adds the hub URL in ATOM and RSS feed.
+ *
+ * @param array         $data Template data.
+ * @param ConfigManager $conf instance.
+ *
+ * @return array updated template data.
+ */
+function hook_pubsubhubbub_render_feed($data, $conf)
+{
+    $feedType = $data['_PAGE_'] == Router::$PAGE_FEED_RSS ? FeedBuilder::$FEED_RSS : FeedBuilder::$FEED_ATOM;
+    $template = file_get_contents(PluginManager::$PLUGINS_PATH . '/pubsubhubbub/hub.'. $feedType .'.xml');
+    $data['feed_plugins_header'][] = sprintf($template, $conf->get('plugins.PUBSUBHUB_URL'));
+
+    return $data;
+}
+
+/**
+ * Save link hook.
+ * Publish to the hub when a link is saved.
+ *
+ * @param array         $data Template data.
+ * @param ConfigManager $conf instance.
+ *
+ * @return array unaltered data.
+ */
+function hook_pubsubhubbub_save_link($data, $conf)
+{
+    $feeds = array(
+        index_url($_SERVER) .'?do=atom',
+        index_url($_SERVER) .'?do=rss',
+    );
+
+    $httpPost = function_exists('curl_version') ? false : 'nocurl_http_post';
+    try {
+        $p = new Publisher($conf->get('plugins.PUBSUBHUB_URL'));
+        $p->publish_update($feeds, $httpPost);
+    } catch (Exception $e) {
+        error_log('Could not publish to PubSubHubbub: ' . $e->getMessage());
+    }
+
+    return $data;
+}
+
+/**
+ * Http function used to post to the hub endpoint without cURL extension.
+ *
+ * @param  string $url        Hub endpoint.
+ * @param  string $postString String to POST.
+ *
+ * @return bool
+ *
+ * @throws Exception An error occurred.
+ */
+function nocurl_http_post($url, $postString) {
+    $params = array('http' => array(
+        'method' => 'POST',
+        'content' => $postString,
+        'user_agent' => 'PubSubHubbub-Publisher-PHP/1.0',
+    ));
+
+    $context = stream_context_create($params);
+    $fp = @fopen($url, 'rb', false, $context);
+    if (!$fp) {
+        throw new Exception('Could not post to '. $url);
+    }
+    $response = @stream_get_contents($fp);
+    if ($response === false) {
+        throw new Exception('Bad response from the hub '. $url);
+    }
+    return $response;
+}
index 06a445064db3aab7c46fceda27ba08b205d1a143..a590306db54524e8fc4a98a6d5a2d8e023c3d4ee 100644 (file)
@@ -75,7 +75,6 @@ class FeedBuilderTest extends PHPUnit_Framework_TestCase
         $data = $feedBuilder->buildData();
         // Test headers (RSS)
         $this->assertEquals(self::$RSS_LANGUAGE, $data['language']);
-        $this->assertEmpty($data['pubsubhub_url']);
         $this->assertRegExp('/Wed, 03 Aug 2016 09:30:33 \+\d{4}/', $data['last_update']);
         $this->assertEquals(true, $data['show_dates']);
         $this->assertEquals('http://host.tld/index.php?do=feed', $data['self_link']);
@@ -210,19 +209,6 @@ class FeedBuilderTest extends PHPUnit_Framework_TestCase
         $this->assertTrue($data['show_dates']);
     }
 
-    /**
-     * Test buildData with hide dates settings.
-     */
-    public function testBuildDataPubsubhub()
-    {
-        $feedBuilder = new FeedBuilder(self::$linkDB, FeedBuilder::$FEED_ATOM, self::$serverInfo, null, false);
-        $feedBuilder->setLocale(self::$LOCALE);
-        $feedBuilder->setPubsubhubUrl('http://pubsubhub.io');
-        $data = $feedBuilder->buildData();
-        $this->assertEquals(ReferenceLinkDB::$NB_LINKS_TOTAL, count($data['links']));
-        $this->assertEquals('http://pubsubhub.io', $data['pubsubhub_url']);
-    }
-
     /**
      * Test buildData when Shaarli is served from a subdirectory
      */
diff --git a/tests/plugins/PluginPubsubhubbubTest.php b/tests/plugins/PluginPubsubhubbubTest.php
new file mode 100644 (file)
index 0000000..24dd7a1
--- /dev/null
@@ -0,0 +1,54 @@
+<?php
+
+require_once 'plugins/pubsubhubbub/pubsubhubbub.php';
+require_once 'application/Router.php';
+
+/**
+ * Class PluginPubsubhubbubTest
+ * Unit test for the pubsubhubbub plugin
+ */
+class PluginPubsubhubbubTest extends PHPUnit_Framework_TestCase
+{
+    /**
+     * @var string Config file path (without extension).
+     */
+    protected static $configFile = 'tests/utils/config/configJson';
+
+    /**
+     * Reset plugin path
+     */
+    function setUp()
+    {
+        PluginManager::$PLUGINS_PATH = 'plugins';
+    }
+
+    /**
+     * Test render_feed hook with an RSS feed.
+     */
+    function testPubSubRssRenderFeed()
+    {
+        $hub = 'http://domain.hub';
+        $conf = new ConfigManager(self::$configFile);
+        $conf->set('plugins.PUBSUBHUB_URL', $hub);
+        $data['_PAGE_'] = Router::$PAGE_FEED_RSS;
+
+        $data = hook_pubsubhubbub_render_feed($data, $conf);
+        $expected = '<atom:link rel="hub" href="'. $hub .'" />';
+        $this->assertEquals($expected, $data['feed_plugins_header'][0]);
+    }
+
+    /**
+     * Test render_feed hook with an ATOM feed.
+     */
+    function testPubSubAtomRenderFeed()
+    {
+        $hub = 'http://domain.hub';
+        $conf = new ConfigManager(self::$configFile);
+        $conf->set('plugins.PUBSUBHUB_URL', $hub);
+        $data['_PAGE_'] = Router::$PAGE_FEED_ATOM;
+
+        $data = hook_pubsubhubbub_render_feed($data, $conf);
+        $expected = '<link rel="hub" href="'. $hub .'" />';
+        $this->assertEquals($expected, $data['feed_plugins_header'][0]);
+    }
+}
index 29187505deb8e0ea470d4f8eddf217ae2b2a18ff..ad7dd9357db2714d27014873711f68e814761b25 100644 (file)
@@ -6,7 +6,7 @@
     <updated>{$last_update}</updated>
   {/if}
   <link rel="self" href="{$self_link}#" />
-  {loop="$plugins_feed_header"}
+  {loop="$feed_plugins_header"}
     {$value}
   {/loop}
   <author>
index 66d9a8697b1ca9647305559c2da34f4a64d5ca14..73791f639ffc1a6a92bbf6e145f5efed74e4cae1 100644 (file)
@@ -8,7 +8,7 @@
     <copyright>{$index_url}</copyright>
     <generator>Shaarli</generator>
     <atom:link rel="self" href="{$self_link}"  />
-    {loop="$plugins_feed_header"}
+    {loop="$feed_plugins_header"}
       {$value}
     {/loop}
     {loop="$links"}