]> git.immae.eu Git - github/shaarli/Shaarli.git/commitdiff
Empty tag search will look for not tagged links 841/head
authorArthurHoaro <arthur@hoa.ro>
Sat, 1 Apr 2017 10:17:37 +0000 (12:17 +0200)
committerArthurHoaro <arthur@hoa.ro>
Thu, 25 May 2017 13:51:12 +0000 (15:51 +0200)
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

12 files changed:
application/FeedBuilder.php
application/LinkDB.php
application/LinkFilter.php
application/Utils.php
index.php
tests/LinkDBTest.php
tests/LinkFilterTest.php
tests/api/controllers/GetLinksTest.php
tests/api/controllers/InfoTest.php
tests/utils/ReferenceLinkDB.php
tpl/default/linklist.html
tpl/vintage/linklist.html

index a1f4da4810c0b25dceebb8d6698de93cf4eb81e9..7377bcec09c3fa21b92434953661133b386e0829 100644 (file)
@@ -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);
 
index 4cee2af9942559fd122189687058ddddc1fc4ebf..a03c2c0633e1648c12d977b713d722aef6566e06 100644 (file)
@@ -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);
index 81832a4b428f4bc650d3049b8e0ced2a850c1cdc..0e887d3805a2fa7ef2024f5da2d6b155dc4a870e 100644 (file)
@@ -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
      *
index 5c077450e3a65016f55b0ede559dad4552b47e2b..87e5cc8fff3de21b4c27890cfdd4ee53eac8475c 100644 (file)
@@ -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) {
index 5c21c2f6a7f967c2f2f54e43225b22ec926248b5..c96d01367ab1aee7b2cf4c62a1029fd6b451d078 100644 (file)
--- 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)) {
index 1f62a34a160ea5e17c31bbaa0117ef7785ff4202..6fbf597ae175d1e07f22c33f41a964639a63436e 100644 (file)
@@ -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);
index 37d5ca306e4f128edd350e1f88542fab7880ea84..741623580ce30e0980638675db8f17b9e02d2e70 100644 (file)
@@ -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(
index 10330cd9a8d845a77f7d623ad92bd6be4f911949..f1b262bc16faa2d8193cc0dc8f7eb68910ee2ad1 100644 (file)
@@ -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));
index 4beef3f7f7120a11173b81df275d8583959d4430..5d6a23298670fe694f75bb4dd51a78a3b66ecb8e 100644 (file)
@@ -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']);
index 36d58c683e449eb11ac2388c3c4fe43bda2bd1b6..29d63facf7a92adeec871ee0f4844dc40ecd7cbf 100644 (file)
@@ -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;
index 57ef4567a8ee754c1f308c3b153e6d0188223b86..3d6be52993f292ee19513d696f75e7b74f4ca52c 100644 (file)
@@ -89,7 +89,7 @@
         <div id="searchcriteria">{'Nothing found.'|t}</div>
       </div>
     </div>
-  {elseif="!empty($search_term) or !empty($search_tags) or !empty($visibility)"}
+  {elseif="!empty($search_term) or $search_tags !== '' or !empty($visibility)"}
     <div class="pure-g pure-alert pure-alert-success search-result">
       <div class="pure-u-2-24"></div>
       <div class="pure-u-20-24">
                 <a href="?removetag={function="urlencode($value)"}">{$value}<span class="remove"><i class="fa fa-times"></i></span></a>
               </span>
           {/loop}
+        {elseif="$search_tags === false"}
+          <span class="label label-tag" title="{'Remove tag'|t}">
+            <a href="?">{'untagged'|t}<span class="remove"><i class="fa fa-times"></i></span></a>
+          </span>
         {/if}
         {if="!empty($visibility)"}
           {'with status'|t}
index fc116667aac83dd12bb4d45bbfad8d5744cbb560..8458caa1c89224f377370b34ecfaedeb2ae8b395 100644 (file)
@@ -55,7 +55,7 @@
 
     {if="count($links)==0"}
         <div id="searchcriteria">Nothing found.</div>
-    {elseif="!empty($search_term) or !empty($search_tags)"}
+    {elseif="!empty($search_term) or $search_tags !== ''"}
         <div id="searchcriteria">
             {$result_count} results
             {if="!empty($search_term)"}
                         <a href="?removetag={function="urlencode($value)"}">{$value} <span class="remove">x</span></a>
                     </span>
                 {/loop}
+            {elseif="$search_tags === false"}
+                <span class="linktag" title="Remove tag">
+                    <a href="?">untagged <span class="remove">x</span></a>
+                </span>
             {/if}
         </div>
     {/if}