From 7d86f40bdb2135655b5b4fe8cbcc1ac102114f86 Mon Sep 17 00:00:00 2001 From: ArthurHoaro Date: Sat, 1 Apr 2017 12:17:37 +0200 Subject: [PATCH] Empty tag search will look for not tagged links Fixes #784 From now, searching for tags with an empty value will return only not tagged links, with the search bar showing `x results [not tagged]`. Note that using the api, the searchtags request parameter must be set to `false` to get the same result. - [ ] Update API doc --- application/FeedBuilder.php | 5 +++++ application/LinkDB.php | 27 +++++------------------ application/LinkFilter.php | 30 ++++++++++++++++++++++++++ application/Utils.php | 4 ++++ index.php | 18 +++++++++++++--- tests/LinkDBTest.php | 2 +- tests/LinkFilterTest.php | 19 +++++++++++++--- tests/api/controllers/GetLinksTest.php | 4 ++-- tests/api/controllers/InfoTest.php | 4 ++-- tests/utils/ReferenceLinkDB.php | 26 +++++++++++++++++++++- tpl/default/linklist.html | 6 +++++- tpl/vintage/linklist.html | 6 +++++- 12 files changed, 115 insertions(+), 36 deletions(-) diff --git a/application/FeedBuilder.php b/application/FeedBuilder.php index a1f4da48..7377bcec 100644 --- a/application/FeedBuilder.php +++ b/application/FeedBuilder.php @@ -97,6 +97,11 @@ class FeedBuilder */ public function buildData() { + // Search for untagged links + if (isset($this->userInput['searchtags']) && empty($this->userInput['searchtags'])) { + $this->userInput['searchtags'] = false; + } + // Optionally filter the results: $linksToDisplay = $this->linkDB->filterSearch($this->userInput); diff --git a/application/LinkDB.php b/application/LinkDB.php index 4cee2af9..a03c2c06 100644 --- a/application/LinkDB.php +++ b/application/LinkDB.php @@ -450,29 +450,12 @@ You use the community supported version of the original Shaarli project, by Seba public function filterSearch($filterRequest = array(), $casesensitive = false, $visibility = 'all') { // Filter link database according to parameters. - $searchtags = !empty($filterRequest['searchtags']) ? escape($filterRequest['searchtags']) : ''; - $searchterm = !empty($filterRequest['searchterm']) ? escape($filterRequest['searchterm']) : ''; + $searchtags = isset($filterRequest['searchtags']) ? escape($filterRequest['searchtags']) : ''; + $searchterm = isset($filterRequest['searchterm']) ? escape($filterRequest['searchterm']) : ''; - // Search tags + fullsearch. - if (! empty($searchtags) && ! empty($searchterm)) { - $type = LinkFilter::$FILTER_TAG | LinkFilter::$FILTER_TEXT; - $request = array($searchtags, $searchterm); - } - // Search by tags. - elseif (! empty($searchtags)) { - $type = LinkFilter::$FILTER_TAG; - $request = $searchtags; - } - // Fulltext search. - elseif (! empty($searchterm)) { - $type = LinkFilter::$FILTER_TEXT; - $request = $searchterm; - } - // Otherwise, display without filtering. - else { - $type = ''; - $request = ''; - } + // Search tags + fullsearch - blank string parameter will return all links. + $type = LinkFilter::$FILTER_TAG | LinkFilter::$FILTER_TEXT; + $request = [$searchtags, $searchterm]; $linkFilter = new LinkFilter($this); return $linkFilter->filter($type, $request, $casesensitive, $visibility); diff --git a/application/LinkFilter.php b/application/LinkFilter.php index 81832a4b..0e887d38 100644 --- a/application/LinkFilter.php +++ b/application/LinkFilter.php @@ -253,6 +253,9 @@ class LinkFilter { // Implode if array for clean up. $tags = is_array($tags) ? trim(implode(' ', $tags)) : $tags; + if ($tags === false) { + return $this->filterUntagged($visibility); + } if (empty($tags)) { return $this->noFilter($visibility); } @@ -295,6 +298,33 @@ class LinkFilter return $filtered; } + /** + * Return only links without any tag. + * + * @param string $visibility return only all/private/public links. + * + * @return array filtered links. + */ + public function filterUntagged($visibility) + { + $filtered = []; + foreach ($this->links as $key => $link) { + if ($visibility !== 'all') { + if (! $link['private'] && $visibility === 'private') { + continue; + } else if ($link['private'] && $visibility === 'public') { + continue; + } + } + + if (empty(trim($link['tags']))) { + $filtered[$key] = $link; + } + } + + return $filtered; + } + /** * Returns the list of articles for a given day, chronologically sorted * diff --git a/application/Utils.php b/application/Utils.php index 5c077450..87e5cc8f 100644 --- a/application/Utils.php +++ b/application/Utils.php @@ -91,6 +91,10 @@ function endsWith($haystack, $needle, $case = true) */ function escape($input) { + if (is_bool($input)) { + return $input; + } + if (is_array($input)) { $out = array(); foreach($input as $key => $value) { diff --git a/index.php b/index.php index 5c21c2f6..c96d0136 100644 --- a/index.php +++ b/index.php @@ -1609,7 +1609,15 @@ function renderPage($conf, $pluginManager, $LINKSDB) function buildLinkList($PAGE,$LINKSDB, $conf, $pluginManager) { // Used in templates - $searchtags = !empty($_GET['searchtags']) ? escape(normalize_spaces($_GET['searchtags'])) : ''; + if (isset($_GET['searchtags'])) { + if (! empty($_GET['searchtags'])) { + $searchtags = escape(normalize_spaces($_GET['searchtags'])); + } else { + $searchtags = false; + } + } else { + $searchtags = ''; + } $searchterm = !empty($_GET['searchterm']) ? escape(normalize_spaces($_GET['searchterm'])) : ''; // Smallhash filter @@ -1624,7 +1632,11 @@ function buildLinkList($PAGE,$LINKSDB, $conf, $pluginManager) } else { // Filter links according search parameters. $visibility = ! empty($_SESSION['privateonly']) ? 'private' : 'all'; - $linksToDisplay = $LINKSDB->filterSearch($_GET, false, $visibility); + $request = [ + 'searchtags' => $searchtags, + 'searchterm' => $searchterm, + ]; + $linksToDisplay = $LINKSDB->filterSearch($request, false, $visibility); } // ---- Handle paging. @@ -1671,7 +1683,7 @@ function buildLinkList($PAGE,$LINKSDB, $conf, $pluginManager) } // Compute paging navigation - $searchtagsUrl = empty($searchtags) ? '' : '&searchtags=' . urlencode($searchtags); + $searchtagsUrl = $searchtags === '' ? '' : '&searchtags=' . urlencode($searchtags); $searchtermUrl = empty($searchterm) ? '' : '&searchterm=' . urlencode($searchterm); $previous_page_url = ''; if ($i != count($keys)) { diff --git a/tests/LinkDBTest.php b/tests/LinkDBTest.php index 1f62a34a..6fbf597a 100644 --- a/tests/LinkDBTest.php +++ b/tests/LinkDBTest.php @@ -448,7 +448,7 @@ class LinkDBTest extends PHPUnit_Framework_TestCase public function testReorderLinksDesc() { self::$privateLinkDB->reorder('ASC'); - $linkIds = array(42, 4, 1, 0, 7, 6, 8, 41); + $linkIds = array(42, 4, 9, 1, 0, 7, 6, 8, 41); $cpt = 0; foreach (self::$privateLinkDB as $key => $value) { $this->assertEquals($linkIds[$cpt++], $key); diff --git a/tests/LinkFilterTest.php b/tests/LinkFilterTest.php index 37d5ca30..74162358 100644 --- a/tests/LinkFilterTest.php +++ b/tests/LinkFilterTest.php @@ -63,6 +63,12 @@ class LinkFilterTest extends PHPUnit_Framework_TestCase count(self::$linkFilter->filter(LinkFilter::$FILTER_TAG, '')) ); + // Untagged only + $this->assertEquals( + self::$refDB->countUntaggedLinks(), + count(self::$linkFilter->filter(LinkFilter::$FILTER_TAG, false)) + ); + $this->assertEquals( ReferenceLinkDB::$NB_LINKS_TOTAL, count(self::$linkFilter->filter(LinkFilter::$FILTER_TEXT, '')) @@ -146,7 +152,7 @@ class LinkFilterTest extends PHPUnit_Framework_TestCase public function testFilterDay() { $this->assertEquals( - 3, + 4, count(self::$linkFilter->filter(LinkFilter::$FILTER_DAY, '20121206')) ); } @@ -339,7 +345,7 @@ class LinkFilterTest extends PHPUnit_Framework_TestCase ); $this->assertEquals( - 7, + ReferenceLinkDB::$NB_LINKS_TOTAL - 1, count(self::$linkFilter->filter(LinkFilter::$FILTER_TEXT, '-revolution')) ); } @@ -399,7 +405,7 @@ class LinkFilterTest extends PHPUnit_Framework_TestCase ); $this->assertEquals( - 7, + ReferenceLinkDB::$NB_LINKS_TOTAL - 1, count(self::$linkFilter->filter(LinkFilter::$FILTER_TAG, '-free')) ); } @@ -425,6 +431,13 @@ class LinkFilterTest extends PHPUnit_Framework_TestCase array('', $terms) )) ); + $this->assertEquals( + 1, + count(self::$linkFilter->filter( + LinkFilter::$FILTER_TAG | LinkFilter::$FILTER_TEXT, + array(false, 'PSR-2') + )) + ); $this->assertEquals( 1, count(self::$linkFilter->filter( diff --git a/tests/api/controllers/GetLinksTest.php b/tests/api/controllers/GetLinksTest.php index 10330cd9..f1b262bc 100644 --- a/tests/api/controllers/GetLinksTest.php +++ b/tests/api/controllers/GetLinksTest.php @@ -94,7 +94,7 @@ class GetLinksTest extends \PHPUnit_Framework_TestCase $this->assertEquals($this->refDB->countLinks(), count($data)); // Check order - $order = [41, 8, 6, 7, 0, 1, 4, 42]; + $order = [41, 8, 6, 7, 0, 1, 9, 4, 42]; $cpt = 0; foreach ($data as $link) { $this->assertEquals(self::NB_FIELDS_LINK, count($link)); @@ -163,7 +163,7 @@ class GetLinksTest extends \PHPUnit_Framework_TestCase $data = json_decode((string) $response->getBody(), true); $this->assertEquals($this->refDB->countLinks(), count($data)); // Check order - $order = [41, 8, 6, 7, 0, 1, 4, 42]; + $order = [41, 8, 6, 7, 0, 1, 9, 4, 42]; $cpt = 0; foreach ($data as $link) { $this->assertEquals(self::NB_FIELDS_LINK, count($link)); diff --git a/tests/api/controllers/InfoTest.php b/tests/api/controllers/InfoTest.php index 4beef3f7..5d6a2329 100644 --- a/tests/api/controllers/InfoTest.php +++ b/tests/api/controllers/InfoTest.php @@ -80,7 +80,7 @@ class InfoTest extends \PHPUnit_Framework_TestCase $this->assertEquals(200, $response->getStatusCode()); $data = json_decode((string) $response->getBody(), true); - $this->assertEquals(8, $data['global_counter']); + $this->assertEquals(\ReferenceLinkDB::$NB_LINKS_TOTAL, $data['global_counter']); $this->assertEquals(2, $data['private_counter']); $this->assertEquals('Shaarli', $data['settings']['title']); $this->assertEquals('?', $data['settings']['header_link']); @@ -103,7 +103,7 @@ class InfoTest extends \PHPUnit_Framework_TestCase $this->assertEquals(200, $response->getStatusCode()); $data = json_decode((string) $response->getBody(), true); - $this->assertEquals(8, $data['global_counter']); + $this->assertEquals(\ReferenceLinkDB::$NB_LINKS_TOTAL, $data['global_counter']); $this->assertEquals(2, $data['private_counter']); $this->assertEquals($title, $data['settings']['title']); $this->assertEquals($headerLink, $data['settings']['header_link']); diff --git a/tests/utils/ReferenceLinkDB.php b/tests/utils/ReferenceLinkDB.php index 36d58c68..29d63fac 100644 --- a/tests/utils/ReferenceLinkDB.php +++ b/tests/utils/ReferenceLinkDB.php @@ -4,7 +4,7 @@ */ class ReferenceLinkDB { - public static $NB_LINKS_TOTAL = 8; + public static $NB_LINKS_TOTAL = 9; private $_links = array(); private $_publicCount = 0; @@ -37,6 +37,16 @@ class ReferenceLinkDB 'ut' ); + $this->addLink( + 9, + 'PSR-2: Coding Style Guide', + 'http://www.php-fig.org/psr/psr-2/', + 'This guide extends and expands on PSR-1, the basic coding standard.', + 0, + DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20121206_152312'), + '' + ); + $this->addLink( 8, 'Free as in Freedom 2.0 @website', @@ -161,6 +171,20 @@ class ReferenceLinkDB return $this->_privateCount; } + /** + * Returns the number of links without tag + */ + public function countUntaggedLinks() + { + $cpt = 0; + foreach ($this->_links as $link) { + if (empty($link['tags'])) { + ++$cpt; + } + } + return $cpt; + } + public function getLinks() { return $this->_links; diff --git a/tpl/default/linklist.html b/tpl/default/linklist.html index 57ef4567..3d6be529 100644 --- a/tpl/default/linklist.html +++ b/tpl/default/linklist.html @@ -89,7 +89,7 @@
{'Nothing found.'|t}
- {elseif="!empty($search_term) or !empty($search_tags) or !empty($visibility)"} + {elseif="!empty($search_term) or $search_tags !== '' or !empty($visibility)"}
@@ -105,6 +105,10 @@ {$value} {/loop} + {elseif="$search_tags === false"} + + {'untagged'|t} + {/if} {if="!empty($visibility)"} {'with status'|t} diff --git a/tpl/vintage/linklist.html b/tpl/vintage/linklist.html index fc116667..8458caa1 100644 --- a/tpl/vintage/linklist.html +++ b/tpl/vintage/linklist.html @@ -55,7 +55,7 @@ {if="count($links)==0"}
Nothing found.
- {elseif="!empty($search_term) or !empty($search_tags)"} + {elseif="!empty($search_term) or $search_tags !== ''"}
{$result_count} results {if="!empty($search_term)"} @@ -69,6 +69,10 @@ {$value} x {/loop} + {elseif="$search_tags === false"} + + untagged x + {/if}
{/if} -- 2.41.0