)
-// This function fills all the necessary fields in the $PAGE for the template 'linklist.html'
+/**
+ * Template for the list of links (
)
+ * This function fills all the necessary fields in the $PAGE for the template 'linklist.html'
+ *
+ * @param pageBuilder $PAGE pageBuilder instance.
+ * @param LinkDB $LINKSDB LinkDB instance.
+ */
function buildLinkList($PAGE,$LINKSDB)
{
- // Filter link database according to parameters.
+ // Used in templates
$searchtags = !empty($_GET['searchtags']) ? escape($_GET['searchtags']) : '';
- $searchterm = !empty($_GET['searchterm']) ? escape(trim($_GET['searchterm'])) : '';
- $privateonly = !empty($_SESSION['privateonly']) ? true : false;
+ $searchterm = !empty($_GET['searchterm']) ? escape($_GET['searchterm']) : '';
- // Search tags + fullsearch.
- if (! empty($searchtags) && ! empty($searchterm)) {
- $linksToDisplay = $LINKSDB->filter(
- LinkFilter::$FILTER_TAG | LinkFilter::$FILTER_TEXT,
- array($searchtags, $searchterm),
- false,
- $privateonly
- );
- }
- // Search by tags.
- elseif (! empty($searchtags)) {
- $linksToDisplay = $LINKSDB->filter(
- LinkFilter::$FILTER_TAG,
- $searchtags,
- false,
- $privateonly
- );
- }
- // Fulltext search.
- elseif (! empty($searchterm)) {
- $linksToDisplay = $LINKSDB->filter(
- LinkFilter::$FILTER_TEXT,
- $searchterm,
- false,
- $privateonly
- );
- }
- // Detect smallHashes in URL.
- elseif (! empty($_SERVER['QUERY_STRING'])
- && preg_match('/[a-zA-Z0-9-_@]{6}(&.+?)?/', $_SERVER['QUERY_STRING'])
- ) {
- $linksToDisplay = $LINKSDB->filter(
- LinkFilter::$FILTER_HASH,
- substr(trim($_SERVER["QUERY_STRING"], '/'), 0, 6)
- );
-
- if (count($linksToDisplay) == 0) {
- $PAGE->render404('The link you are trying to reach does not exist or has been deleted.');
+ // Smallhash filter
+ if (! empty($_SERVER['QUERY_STRING'])
+ && preg_match('/^[a-zA-Z0-9-_@]{6}($|&|#)/', $_SERVER['QUERY_STRING'])) {
+ try {
+ $linksToDisplay = $LINKSDB->filterHash($_SERVER['QUERY_STRING']);
+ } catch (LinkNotFoundException $e) {
+ $PAGE->render404($e->getMessage());
exit;
}
- }
- // Otherwise, display without filtering.
- else {
- $linksToDisplay = $LINKSDB->filter('', '', false, $privateonly);
+ } else {
+ // Filter links according search parameters.
+ $privateonly = !empty($_SESSION['privateonly']);
+ $linksToDisplay = $LINKSDB->filterSearch($_GET, false, $privateonly);
}
// ---- Handle paging.
@@ -2584,8 +2380,6 @@ function resizeImage($filepath)
}
if (isset($_SERVER["QUERY_STRING"]) && startswith($_SERVER["QUERY_STRING"],'do=genthumbnail')) { genThumbnail(); exit; } // Thumbnail generation/cache does not need the link database.
-if (isset($_SERVER["QUERY_STRING"]) && startswith($_SERVER["QUERY_STRING"],'do=rss')) { showRSS(); exit; }
-if (isset($_SERVER["QUERY_STRING"]) && startswith($_SERVER["QUERY_STRING"],'do=atom')) { showATOM(); exit; }
if (isset($_SERVER["QUERY_STRING"]) && startswith($_SERVER["QUERY_STRING"],'do=dailyrss')) { showDailyRSS(); exit; }
if (!isset($_SESSION['LINKS_PER_PAGE'])) $_SESSION['LINKS_PER_PAGE']=$GLOBALS['config']['LINKS_PER_PAGE'];
renderPage();
diff --git a/plugins/demo_plugin/demo_plugin.php b/plugins/demo_plugin/demo_plugin.php
index f5f028e0..18834e53 100644
--- a/plugins/demo_plugin/demo_plugin.php
+++ b/plugins/demo_plugin/demo_plugin.php
@@ -322,4 +322,29 @@ function hook_demo_plugin_delete_link($data)
if (strpos($data['url'], 'youtube.com') !== false) {
exit('You can not delete a YouTube link. Don\'t ask.');
}
-}
\ No newline at end of file
+}
+
+/**
+ * Execute render_feed hook.
+ * Called with ATOM and RSS feed.
+ *
+ * Special data keys:
+ * - _PAGE_: current page
+ * - _LOGGEDIN_: true/false
+ *
+ * @param array $data data passed to plugin
+ *
+ * @return array altered $data.
+ */
+function hook_demo_plugin_render_feed($data)
+{
+ foreach ($data['links'] as &$link) {
+ if ($data['_PAGE_'] == Router::$PAGE_FEED_ATOM) {
+ $link['description'] .= ' - ATOM Feed' ;
+ }
+ elseif ($data['_PAGE_'] == Router::$PAGE_FEED_RSS) {
+ $link['description'] .= ' - RSS Feed';
+ }
+ }
+ return $data;
+}
diff --git a/tests/FeedBuilderTest.php b/tests/FeedBuilderTest.php
new file mode 100644
index 00000000..069b1581
--- /dev/null
+++ b/tests/FeedBuilderTest.php
@@ -0,0 +1,212 @@
+write(self::$testDatastore);
+ self::$linkDB = new LinkDB(self::$testDatastore, true, false);
+ self::$serverInfo = array(
+ 'HTTPS' => 'Off',
+ 'SERVER_NAME' => 'host.tld',
+ 'SERVER_PORT' => '80',
+ 'SCRIPT_NAME' => '/index.php',
+ 'REQUEST_URI' => '/index.php?do=feed',
+ );
+ }
+
+ /**
+ * Test GetTypeLanguage().
+ */
+ public function testGetTypeLanguage()
+ {
+ $feedBuilder = new FeedBuilder(null, FeedBuilder::$FEED_ATOM, null, null, false);
+ $feedBuilder->setLocale(self::$LOCALE);
+ $this->assertEquals(self::$ATOM_LANGUAGUE, $feedBuilder->getTypeLanguage());
+ $feedBuilder = new FeedBuilder(null, FeedBuilder::$FEED_RSS, null, null, false);
+ $feedBuilder->setLocale(self::$LOCALE);
+ $this->assertEquals(self::$RSS_LANGUAGE, $feedBuilder->getTypeLanguage());
+ $feedBuilder = new FeedBuilder(null, FeedBuilder::$FEED_ATOM, null, null, false);
+ $this->assertEquals('en', $feedBuilder->getTypeLanguage());
+ $feedBuilder = new FeedBuilder(null, FeedBuilder::$FEED_RSS, null, null, false);
+ $this->assertEquals('en-en', $feedBuilder->getTypeLanguage());
+ }
+
+ /**
+ * Test buildData with RSS feed.
+ */
+ public function testRSSBuildData()
+ {
+ $feedBuilder = new FeedBuilder(self::$linkDB, FeedBuilder::$FEED_RSS, self::$serverInfo, null, false);
+ $feedBuilder->setLocale(self::$LOCALE);
+ $data = $feedBuilder->buildData();
+ // Test headers (RSS)
+ $this->assertEquals(self::$RSS_LANGUAGE, $data['language']);
+ $this->assertEmpty($data['pubsubhub_url']);
+ $this->assertEquals('Tue, 10 Mar 2015 11:46:51 +0100', $data['last_update']);
+ $this->assertEquals(true, $data['show_dates']);
+ $this->assertEquals('http://host.tld/index.php?do=feed', $data['self_link']);
+ $this->assertEquals('http://host.tld/', $data['index_url']);
+ $this->assertFalse($data['usepermalinks']);
+ $this->assertEquals(ReferenceLinkDB::$NB_LINKS_TOTAL, count($data['links']));
+
+ // Test first link (note link)
+ $link = array_shift($data['links']);
+ $this->assertEquals('20150310_114651', $link['linkdate']);
+ $this->assertEquals('http://host.tld/?WDWyig', $link['guid']);
+ $this->assertEquals('http://host.tld/?WDWyig', $link['url']);
+ $this->assertEquals('Tue, 10 Mar 2015 11:46:51 +0100', $link['iso_date']);
+ $this->assertContains('Stallman has a beard', $link['description']);
+ $this->assertContains('Permalink', $link['description']);
+ $this->assertContains('http://host.tld/?WDWyig', $link['description']);
+ $this->assertEquals(1, count($link['taglist']));
+ $this->assertEquals('stuff', $link['taglist'][0]);
+
+ // Test URL with external link.
+ $this->assertEquals('https://static.fsf.org/nosvn/faif-2.0.pdf', $data['links']['20150310_114633']['url']);
+
+ // Test multitags.
+ $this->assertEquals(5, count($data['links']['20141125_084734']['taglist']));
+ $this->assertEquals('css', $data['links']['20141125_084734']['taglist'][0]);
+ }
+
+ /**
+ * Test buildData with ATOM feed (test only specific to ATOM).
+ */
+ public function testAtomBuildData()
+ {
+ $feedBuilder = new FeedBuilder(self::$linkDB, FeedBuilder::$FEED_ATOM, self::$serverInfo, null, false);
+ $feedBuilder->setLocale(self::$LOCALE);
+ $data = $feedBuilder->buildData();
+ $this->assertEquals(ReferenceLinkDB::$NB_LINKS_TOTAL, count($data['links']));
+ $link = array_shift($data['links']);
+ $this->assertEquals('2015-03-10T11:46:51+01:00', $link['iso_date']);
+ }
+
+ /**
+ * Test buildData with search criteria.
+ */
+ public function testBuildDataFiltered()
+ {
+ $criteria = array(
+ 'searchtags' => 'stuff',
+ 'searchterm' => 'beard',
+ );
+ $feedBuilder = new FeedBuilder(self::$linkDB, FeedBuilder::$FEED_ATOM, self::$serverInfo, $criteria, false);
+ $feedBuilder->setLocale(self::$LOCALE);
+ $data = $feedBuilder->buildData();
+ $this->assertEquals(1, count($data['links']));
+ $link = array_shift($data['links']);
+ $this->assertEquals('20150310_114651', $link['linkdate']);
+ }
+
+ /**
+ * Test buildData with nb limit.
+ */
+ public function testBuildDataCount()
+ {
+ $criteria = array(
+ 'nb' => '1',
+ );
+ $feedBuilder = new FeedBuilder(self::$linkDB, FeedBuilder::$FEED_ATOM, self::$serverInfo, $criteria, false);
+ $feedBuilder->setLocale(self::$LOCALE);
+ $data = $feedBuilder->buildData();
+ $this->assertEquals(1, count($data['links']));
+ $link = array_shift($data['links']);
+ $this->assertEquals('20150310_114651', $link['linkdate']);
+ }
+
+ /**
+ * Test buildData with permalinks on.
+ */
+ public function testBuildDataPermalinks()
+ {
+ $feedBuilder = new FeedBuilder(self::$linkDB, FeedBuilder::$FEED_ATOM, self::$serverInfo, null, false);
+ $feedBuilder->setLocale(self::$LOCALE);
+ $feedBuilder->setUsePermalinks(true);
+ $data = $feedBuilder->buildData();
+ $this->assertEquals(ReferenceLinkDB::$NB_LINKS_TOTAL, count($data['links']));
+ $this->assertTrue($data['usepermalinks']);
+ // First link is a permalink
+ $link = array_shift($data['links']);
+ $this->assertEquals('20150310_114651', $link['linkdate']);
+ $this->assertEquals('http://host.tld/?WDWyig', $link['guid']);
+ $this->assertEquals('http://host.tld/?WDWyig', $link['url']);
+ $this->assertContains('Direct link', $link['description']);
+ $this->assertContains('http://host.tld/?WDWyig', $link['description']);
+ // Second link is a direct link
+ $link = array_shift($data['links']);
+ $this->assertEquals('20150310_114633', $link['linkdate']);
+ $this->assertEquals('http://host.tld/?kLHmZg', $link['guid']);
+ $this->assertEquals('https://static.fsf.org/nosvn/faif-2.0.pdf', $link['url']);
+ $this->assertContains('Direct link', $link['description']);
+ $this->assertContains('https://static.fsf.org/nosvn/faif-2.0.pdf', $link['description']);
+ }
+
+ /**
+ * Test buildData with hide dates settings.
+ */
+ public function testBuildDataHideDates()
+ {
+ $feedBuilder = new FeedBuilder(self::$linkDB, FeedBuilder::$FEED_ATOM, self::$serverInfo, null, false);
+ $feedBuilder->setLocale(self::$LOCALE);
+ $feedBuilder->setHideDates(true);
+ $data = $feedBuilder->buildData();
+ $this->assertEquals(ReferenceLinkDB::$NB_LINKS_TOTAL, count($data['links']));
+ $this->assertFalse($data['show_dates']);
+
+ // Show dates while logged in
+ $feedBuilder = new FeedBuilder(self::$linkDB, FeedBuilder::$FEED_ATOM, self::$serverInfo, null, true);
+ $feedBuilder->setLocale(self::$LOCALE);
+ $feedBuilder->setHideDates(true);
+ $data = $feedBuilder->buildData();
+ $this->assertEquals(ReferenceLinkDB::$NB_LINKS_TOTAL, count($data['links']));
+ $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']);
+ }
+}
diff --git a/tests/LinkDBTest.php b/tests/LinkDBTest.php
index b6a273b3..52d31400 100644
--- a/tests/LinkDBTest.php
+++ b/tests/LinkDBTest.php
@@ -17,8 +17,20 @@ class LinkDBTest extends PHPUnit_Framework_TestCase
{
// datastore to test write operations
protected static $testDatastore = 'sandbox/datastore.php';
+
+ /**
+ * @var ReferenceLinkDB instance.
+ */
protected static $refDB = null;
+
+ /**
+ * @var LinkDB public LinkDB instance.
+ */
protected static $publicLinkDB = null;
+
+ /**
+ * @var LinkDB private LinkDB instance.
+ */
protected static $privateLinkDB = null;
/**
@@ -335,9 +347,10 @@ class LinkDBTest extends PHPUnit_Framework_TestCase
public function testFilterString()
{
$tags = 'dev cartoon';
+ $request = array('searchtags' => $tags);
$this->assertEquals(
2,
- count(self::$privateLinkDB->filter(LinkFilter::$FILTER_TAG, $tags, true, false))
+ count(self::$privateLinkDB->filterSearch($request, true, false))
);
}
@@ -347,9 +360,10 @@ class LinkDBTest extends PHPUnit_Framework_TestCase
public function testFilterArray()
{
$tags = array('dev', 'cartoon');
+ $request = array('searchtags' => $tags);
$this->assertEquals(
2,
- count(self::$privateLinkDB->filter(LinkFilter::$FILTER_TAG, $tags, true, false))
+ count(self::$privateLinkDB->filterSearch($request, true, false))
);
}
@@ -360,14 +374,48 @@ class LinkDBTest extends PHPUnit_Framework_TestCase
public function testHiddenTags()
{
$tags = '.hidden';
+ $request = array('searchtags' => $tags);
$this->assertEquals(
1,
- count(self::$privateLinkDB->filter(LinkFilter::$FILTER_TAG, $tags, true, false))
+ count(self::$privateLinkDB->filterSearch($request, true, false))
);
$this->assertEquals(
0,
- count(self::$publicLinkDB->filter(LinkFilter::$FILTER_TAG, $tags, true, false))
+ count(self::$publicLinkDB->filterSearch($request, true, false))
);
}
+
+ /**
+ * Test filterHash() with a valid smallhash.
+ */
+ public function testFilterHashValid()
+ {
+ $request = smallHash('20150310_114651');
+ $this->assertEquals(
+ 1,
+ count(self::$publicLinkDB->filterHash($request))
+ );
+ }
+
+ /**
+ * Test filterHash() with an invalid smallhash.
+ *
+ * @expectedException LinkNotFoundException
+ */
+ public function testFilterHashInValid1()
+ {
+ $request = 'blabla';
+ self::$publicLinkDB->filterHash($request);
+ }
+
+ /**
+ * Test filterHash() with an empty smallhash.
+ *
+ * @expectedException LinkNotFoundException
+ */
+ public function testFilterHashInValid()
+ {
+ self::$publicLinkDB->filterHash('');
+ }
}
diff --git a/tests/LinkFilterTest.php b/tests/LinkFilterTest.php
index ef1cc10a..1620bb78 100644
--- a/tests/LinkFilterTest.php
+++ b/tests/LinkFilterTest.php
@@ -12,8 +12,6 @@ class LinkFilterTest extends PHPUnit_Framework_TestCase
*/
protected static $linkFilter;
- protected static $NB_LINKS_REFDB = 7;
-
/**
* Instanciate linkFilter with ReferenceLinkDB data.
*/
@@ -29,7 +27,7 @@ class LinkFilterTest extends PHPUnit_Framework_TestCase
public function testFilter()
{
$this->assertEquals(
- self::$NB_LINKS_REFDB,
+ ReferenceLinkDB::$NB_LINKS_TOTAL,
count(self::$linkFilter->filter('', ''))
);
@@ -40,12 +38,12 @@ class LinkFilterTest extends PHPUnit_Framework_TestCase
);
$this->assertEquals(
- self::$NB_LINKS_REFDB,
+ ReferenceLinkDB::$NB_LINKS_TOTAL,
count(self::$linkFilter->filter(LinkFilter::$FILTER_TAG, ''))
);
$this->assertEquals(
- self::$NB_LINKS_REFDB,
+ ReferenceLinkDB::$NB_LINKS_TOTAL,
count(self::$linkFilter->filter(LinkFilter::$FILTER_TEXT, ''))
);
}
@@ -167,13 +165,12 @@ class LinkFilterTest extends PHPUnit_Framework_TestCase
/**
* No link for this hash
+ *
+ * @expectedException LinkNotFoundException
*/
public function testFilterUnknownSmallHash()
{
- $this->assertEquals(
- 0,
- count(self::$linkFilter->filter(LinkFilter::$FILTER_HASH, 'Iblaah'))
- );
+ self::$linkFilter->filter(LinkFilter::$FILTER_HASH, 'Iblaah');
}
/**
@@ -383,7 +380,7 @@ class LinkFilterTest extends PHPUnit_Framework_TestCase
))
);
$this->assertEquals(
- self::$NB_LINKS_REFDB,
+ ReferenceLinkDB::$NB_LINKS_TOTAL,
count(self::$linkFilter->filter(
LinkFilter::$FILTER_TAG | LinkFilter::$FILTER_TEXT,
''
diff --git a/tests/Updater/UpdaterTest.php b/tests/Updater/UpdaterTest.php
index d865066b..a29d9067 100644
--- a/tests/Updater/UpdaterTest.php
+++ b/tests/Updater/UpdaterTest.php
@@ -236,9 +236,9 @@ class UpdaterTest extends PHPUnit_Framework_TestCase
$refDB = new ReferenceLinkDB();
$refDB->write(self::$testDatastore);
$linkDB = new LinkDB(self::$testDatastore, true, false);
- $this->assertEmpty($linkDB->filter(LinkFilter::$FILTER_TAG, 'exclude'));
+ $this->assertEmpty($linkDB->filterSearch(array('searchtags' => 'exclude')));
$updater = new Updater(array(), self::$configFields, $linkDB, true);
$updater->updateMethodRenameDashTags();
- $this->assertNotEmpty($linkDB->filter(LinkFilter::$FILTER_TAG, 'exclude'));
+ $this->assertNotEmpty($linkDB->filterSearch(array('searchtags' => 'exclude')));
}
}
diff --git a/tests/utils/ReferenceLinkDB.php b/tests/utils/ReferenceLinkDB.php
index 61faef05..dc4f5dfa 100644
--- a/tests/utils/ReferenceLinkDB.php
+++ b/tests/utils/ReferenceLinkDB.php
@@ -4,6 +4,8 @@
*/
class ReferenceLinkDB
{
+ public static $NB_LINKS_TOTAL = 7;
+
private $_links = array();
private $_publicCount = 0;
private $_privateCount = 0;
@@ -13,6 +15,15 @@ class ReferenceLinkDB
*/
function __construct()
{
+ $this->addLink(
+ 'Link title: @website',
+ '?WDWyig',
+ 'Stallman has a beard and is part of the Free Software Foundation (or not). Seriously, read this.',
+ 0,
+ '20150310_114651',
+ 'stuff'
+ );
+
$this->addLink(
'Free as in Freedom 2.0 @website',
'https://static.fsf.org/nosvn/faif-2.0.pdf',
@@ -22,15 +33,6 @@ class ReferenceLinkDB
'free gnu software stallman -exclude stuff'
);
- $this->addLink(
- 'Link title: @website',
- 'local',
- 'Stallman has a beard and is part of the Free Software Foundation (or not). Seriously, read this.',
- 0,
- '20150310_114651',
- 'stuff'
- );
-
$this->addLink(
'MediaGoblin',
'http://mediagoblin.org/',
diff --git a/tpl/configure.html b/tpl/configure.html
index 9c725a51..77c8b7d9 100644
--- a/tpl/configure.html
+++ b/tpl/configure.html
@@ -22,9 +22,12 @@
- Enable RSS Permalinks |
+ RSS direct links |
-
+
+
|
diff --git a/tpl/feed.atom.html b/tpl/feed.atom.html
new file mode 100644
index 00000000..2ebb162a
--- /dev/null
+++ b/tpl/feed.atom.html
@@ -0,0 +1,40 @@
+
+
+ {$pagetitle}
+ Shaared links
+ {if="$show_dates"}
+ {$last_update}
+ {/if}
+
+ {if="!empty($pubsubhub_url)"}
+
+
+
+ {/if}
+
+ {$index_url}
+ {$index_url}
+
+ {$index_url}
+ Shaarli
+ {loop="links"}
+
+ {$value.title}
+ {if="$usepermalinks"}
+
+ {else}
+
+ {/if}
+ {$value.guid}
+ {if="$show_dates"}
+ {$value.iso_date}
+ {/if}
+
+
+
+ {loop="$value.taglist"}
+
+ {/loop}
+
+ {/loop}
+
diff --git a/tpl/feed.rss.html b/tpl/feed.rss.html
new file mode 100644
index 00000000..26de7f19
--- /dev/null
+++ b/tpl/feed.rss.html
@@ -0,0 +1,34 @@
+
+
+
+ {$pagetitle}
+ {$index_url}
+ Shaared links
+ {$language}
+ {$index_url}
+ Shaarli
+
+ {if="!empty($pubsubhub_url)"}
+
+
+ {/if}
+ {loop="links"}
+ -
+ {$value.title}
+ {$value.guid}
+ {if="$usepermalinks"}
+ {$value.guid}
+ {else}
+ {$value.url}
+ {/if}
+ {if="$show_dates"}
+ {$value.iso_date}
+ {/if}
+
+ {loop="$value.taglist"}
+ {$value}
+ {/loop}
+
+ {/loop}
+
+