Move PubSubHubbub code as a default plugin
This commit is contained in:
parent
085efc33cc
commit
db90dfcbbc
12 changed files with 183 additions and 38 deletions
|
@ -62,11 +62,6 @@ class FeedBuilder
|
||||||
*/
|
*/
|
||||||
protected $hideDates;
|
protected $hideDates;
|
||||||
|
|
||||||
/**
|
|
||||||
* @var string PubSub hub URL.
|
|
||||||
*/
|
|
||||||
protected $pubsubhubUrl;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var string server locale.
|
* @var string server locale.
|
||||||
*/
|
*/
|
||||||
|
@ -120,7 +115,6 @@ public function buildData()
|
||||||
}
|
}
|
||||||
|
|
||||||
$data['language'] = $this->getTypeLanguage();
|
$data['language'] = $this->getTypeLanguage();
|
||||||
$data['pubsubhub_url'] = $this->pubsubhubUrl;
|
|
||||||
$data['last_update'] = $this->getLatestDateFormatted();
|
$data['last_update'] = $this->getLatestDateFormatted();
|
||||||
$data['show_dates'] = !$this->hideDates || $this->isLoggedIn;
|
$data['show_dates'] = !$this->hideDates || $this->isLoggedIn;
|
||||||
// Remove leading slash from REQUEST_URI.
|
// Remove leading slash from REQUEST_URI.
|
||||||
|
@ -182,16 +176,6 @@ protected function buildItem($link, $pageaddr)
|
||||||
return $link;
|
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.
|
* Set this to true to use permalinks instead of direct links.
|
||||||
*
|
*
|
||||||
|
|
|
@ -13,7 +13,8 @@
|
||||||
"php": ">=5.5",
|
"php": ">=5.5",
|
||||||
"shaarli/netscape-bookmark-parser": "1.*",
|
"shaarli/netscape-bookmark-parser": "1.*",
|
||||||
"erusev/parsedown": "1.6",
|
"erusev/parsedown": "1.6",
|
||||||
"slim/slim": "^3.0"
|
"slim/slim": "^3.0",
|
||||||
|
"pubsubhubbub/publisher": "dev-master"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"phpmd/phpmd" : "@stable",
|
"phpmd/phpmd" : "@stable",
|
||||||
|
|
|
@ -910,10 +910,6 @@ function renderPage($conf, $pluginManager, $LINKSDB)
|
||||||
$feedGenerator->setLocale(strtolower(setlocale(LC_COLLATE, 0)));
|
$feedGenerator->setLocale(strtolower(setlocale(LC_COLLATE, 0)));
|
||||||
$feedGenerator->setHideDates($conf->get('privacy.hide_timestamps') && !isLoggedIn());
|
$feedGenerator->setHideDates($conf->get('privacy.hide_timestamps') && !isLoggedIn());
|
||||||
$feedGenerator->setUsePermalinks(isset($_GET['permalinks']) || !$conf->get('feed.rss_permalinks'));
|
$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();
|
$data = $feedGenerator->buildData();
|
||||||
|
|
||||||
// Process plugin hook.
|
// Process plugin hook.
|
||||||
|
@ -1289,7 +1285,6 @@ function renderPage($conf, $pluginManager, $LINKSDB)
|
||||||
|
|
||||||
$LINKSDB[$id] = $link;
|
$LINKSDB[$id] = $link;
|
||||||
$LINKSDB->save($conf->get('resource.page_cache'));
|
$LINKSDB->save($conf->get('resource.page_cache'));
|
||||||
pubsubhub($conf);
|
|
||||||
|
|
||||||
// If we are called from the bookmarklet, we must close the popup:
|
// If we are called from the bookmarklet, we must close the popup:
|
||||||
if (isset($_GET['source']) && ($_GET['source']=='bookmarklet' || $_GET['source']=='firefoxsocialapi')) {
|
if (isset($_GET['source']) && ($_GET['source']=='bookmarklet' || $_GET['source']=='firefoxsocialapi')) {
|
||||||
|
|
20
plugins/pubsubhubbub/README.md
Normal file
20
plugins/pubsubhubbub/README.md
Normal file
|
@ -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.
|
||||||
|
|
1
plugins/pubsubhubbub/hub.atom.xml
Normal file
1
plugins/pubsubhubbub/hub.atom.xml
Normal file
|
@ -0,0 +1 @@
|
||||||
|
<link rel="hub" href="%s" />
|
1
plugins/pubsubhubbub/hub.rss.xml
Normal file
1
plugins/pubsubhubbub/hub.rss.xml
Normal file
|
@ -0,0 +1 @@
|
||||||
|
<atom:link rel="hub" href="%s" />
|
2
plugins/pubsubhubbub/pubsubhubbub.meta
Normal file
2
plugins/pubsubhubbub/pubsubhubbub.meta
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
description="Enable PubSubHubbub feed publishing."
|
||||||
|
parameters="PUBSUBHUB_URL"
|
101
plugins/pubsubhubbub/pubsubhubbub.php
Normal file
101
plugins/pubsubhubbub/pubsubhubbub.php
Normal file
|
@ -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;
|
||||||
|
}
|
|
@ -75,7 +75,6 @@ public function testRSSBuildData()
|
||||||
$data = $feedBuilder->buildData();
|
$data = $feedBuilder->buildData();
|
||||||
// Test headers (RSS)
|
// Test headers (RSS)
|
||||||
$this->assertEquals(self::$RSS_LANGUAGE, $data['language']);
|
$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->assertRegExp('/Wed, 03 Aug 2016 09:30:33 \+\d{4}/', $data['last_update']);
|
||||||
$this->assertEquals(true, $data['show_dates']);
|
$this->assertEquals(true, $data['show_dates']);
|
||||||
$this->assertEquals('http://host.tld/index.php?do=feed', $data['self_link']);
|
$this->assertEquals('http://host.tld/index.php?do=feed', $data['self_link']);
|
||||||
|
@ -210,19 +209,6 @@ public function testBuildDataHideDates()
|
||||||
$this->assertTrue($data['show_dates']);
|
$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
|
* Test buildData when Shaarli is served from a subdirectory
|
||||||
*/
|
*/
|
||||||
|
|
54
tests/plugins/PluginPubsubhubbubTest.php
Normal file
54
tests/plugins/PluginPubsubhubbubTest.php
Normal file
|
@ -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]);
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,7 +6,7 @@
|
||||||
<updated>{$last_update}</updated>
|
<updated>{$last_update}</updated>
|
||||||
{/if}
|
{/if}
|
||||||
<link rel="self" href="{$self_link}#" />
|
<link rel="self" href="{$self_link}#" />
|
||||||
{loop="$plugins_feed_header"}
|
{loop="$feed_plugins_header"}
|
||||||
{$value}
|
{$value}
|
||||||
{/loop}
|
{/loop}
|
||||||
<author>
|
<author>
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
<copyright>{$index_url}</copyright>
|
<copyright>{$index_url}</copyright>
|
||||||
<generator>Shaarli</generator>
|
<generator>Shaarli</generator>
|
||||||
<atom:link rel="self" href="{$self_link}" />
|
<atom:link rel="self" href="{$self_link}" />
|
||||||
{loop="$plugins_feed_header"}
|
{loop="$feed_plugins_header"}
|
||||||
{$value}
|
{$value}
|
||||||
{/loop}
|
{/loop}
|
||||||
{loop="$links"}
|
{loop="$links"}
|
||||||
|
|
Loading…
Reference in a new issue