]> git.immae.eu Git - github/shaarli/Shaarli.git/commitdiff
Refactor filter in LinkDB 515/head
authorArthurHoaro <arthur@hoa.ro>
Mon, 21 Mar 2016 20:40:49 +0000 (21:40 +0100)
committerArthurHoaro <arthur@hoa.ro>
Fri, 25 Mar 2016 18:17:59 +0000 (19:17 +0100)
  * search type now carried by LinkDB in order to factorize code between different search sources.
  * LinkDB->filter split in 3 method: filterSearch, filterHash, filterDay (we know what type of filter is needed).
  * filterHash now throw a LinkNotFoundException if it doesn't exist: internal implementation choice, still displays a 404.
  * Smallhash regex has been rewritten.
  * Unit tests update

application/FeedBuilder.php
application/LinkDB.php
application/LinkFilter.php
application/Updater.php
index.php
tests/LinkDBTest.php
tests/LinkFilterTest.php
tests/Updater/UpdaterTest.php

index 50e0983152484a3e9fc53d06dd15f62debe60b7e..ddefe6ce93a83ed8f6869d1eee57941264731e72 100644 (file)
@@ -103,23 +103,7 @@ class FeedBuilder
     public function buildData()
     {
         // Optionally filter the results:
-        $searchtags = !empty($this->userInput['searchtags']) ? escape($this->userInput['searchtags']) : '';
-        $searchterm = !empty($this->userInput['searchterm']) ? escape($this->userInput['searchterm']) : '';
-        if (! empty($searchtags) && ! empty($searchterm)) {
-            $linksToDisplay = $this->linkDB->filter(
-                LinkFilter::$FILTER_TAG | LinkFilter::$FILTER_TEXT,
-                array($searchtags, $searchterm)
-            );
-        }
-        elseif ($searchtags) {
-            $linksToDisplay = $this->linkDB->filter(LinkFilter::$FILTER_TAG, $searchtags);
-        }
-        elseif ($searchterm) {
-            $linksToDisplay = $this->linkDB->filter(LinkFilter::$FILTER_TEXT, $searchterm);
-        }
-        else {
-            $linksToDisplay = $this->linkDB;
-        }
+        $linksToDisplay = $this->linkDB->filterSearch($this->userInput);
 
         $nblinksToDisplay = $this->getNbLinks(count($linksToDisplay));
 
index 1b505620959c3a6a06061dabd4ea6f982b39f3fd..a62341fc638e2c078e401bdedb58e6aa635e990c 100644 (file)
@@ -341,17 +341,71 @@ You use the community supported version of the original Shaarli project, by Seba
     }
 
     /**
-     * Filter links.
+     * Returns the shaare corresponding to a smallHash.
      *
-     * @param string $type          Type of filter.
-     * @param mixed  $request       Search request, string or array.
+     * @param string $request QUERY_STRING server parameter.
+     *
+     * @return array $filtered array containing permalink data.
+     *
+     * @throws LinkNotFoundException if the smallhash is malformed or doesn't match any link.
+     */
+    public function filterHash($request)
+    {
+        $request = substr($request, 0, 6);
+        $linkFilter = new LinkFilter($this->_links);
+        return $linkFilter->filter(LinkFilter::$FILTER_HASH, $request);
+    }
+
+    /**
+     * Returns the list of articles for a given day.
+     *
+     * @param string $request day to filter. Format: YYYYMMDD.
+     *
+     * @return array list of shaare found.
+     */
+    public function filterDay($request) {
+        $linkFilter = new LinkFilter($this->_links);
+        return $linkFilter->filter(LinkFilter::$FILTER_DAY, $request);
+    }
+
+    /**
+     * Filter links according to search parameters.
+     *
+     * @param array  $filterRequest Search request content. Supported keys:
+     *                                - searchtags: list of tags
+     *                                - searchterm: term search
      * @param bool   $casesensitive Optional: Perform case sensitive filter
      * @param bool   $privateonly   Optional: Returns private links only if true.
      *
-     * @return array filtered links
+     * @return array filtered links, all links if no suitable filter was provided.
      */
-    public function filter($type = '', $request = '', $casesensitive = false, $privateonly = false)
+    public function filterSearch($filterRequest = array(), $casesensitive = false, $privateonly = false)
     {
+        // Filter link database according to parameters.
+        $searchtags = !empty($filterRequest['searchtags']) ? escape($filterRequest['searchtags']) : '';
+        $searchterm = !empty($filterRequest['searchterm']) ? escape($filterRequest['searchterm']) : '';
+
+        // Search tags + fullsearch.
+        if (empty($type) && ! 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 = '';
+        }
+
         $linkFilter = new LinkFilter($this->_links);
         return $linkFilter->filter($type, $request, $casesensitive, $privateonly);
     }
index 3fd803cb81f4d79c08538a8fc3a7079d8f0b9644..5e0d801594533174e7bd5aaef188d3eda81dfc4a 100644 (file)
@@ -44,7 +44,7 @@ class LinkFilter
      * Filter links according to parameters.
      *
      * @param string $type          Type of filter (eg. tags, permalink, etc.).
-     * @param string $request       Filter content.
+     * @param mixed  $request       Filter content.
      * @param bool   $casesensitive Optional: Perform case sensitive filter if true.
      * @param bool   $privateonly   Optional: Only returns private links if true.
      *
@@ -110,6 +110,8 @@ class LinkFilter
      * @param string $smallHash permalink hash.
      *
      * @return array $filtered array containing permalink data.
+     *
+     * @throws LinkNotFoundException if the smallhash doesn't match any link.
      */
     private function filterSmallHash($smallHash)
     {
@@ -121,6 +123,11 @@ class LinkFilter
                 return $filtered;
             }
         }
+
+        if (empty($filtered)) {
+            throw new LinkNotFoundException();
+        }
+
         return $filtered;
     }
 
@@ -318,3 +325,8 @@ class LinkFilter
         return array_filter(explode(' ', trim($tagsOut)), 'strlen');
     }
 }
+
+class LinkNotFoundException extends Exception
+{
+    protected $message = 'The link you are trying to reach does not exist or has been deleted.';
+}
index 773a1ffa1d8187e016e8ccbfb9200a1c5824bc01..58c13c07796ca44ada886b061b0b163e2321e302 100644 (file)
@@ -137,7 +137,7 @@ class Updater
      */
     public function updateMethodRenameDashTags()
     {
-        $linklist = $this->linkDB->filter();
+        $linklist = $this->linkDB->filterSearch();
         foreach ($linklist as $link) {
             $link['tags'] = preg_replace('/(^| )\-/', '$1', $link['tags']);
             $link['tags'] = implode(' ', array_unique(LinkFilter::tagsStrToArray($link['tags'], true)));
index 6e14ff3f65d30f1ee75c7afec96b4e5dd9d9bdf9..79c66648fdb882944060dbdf1ac624f48095b3f8 100644 (file)
--- a/index.php
+++ b/index.php
@@ -816,7 +816,7 @@ function showDaily($pageBuilder)
     }
 
     try {
-        $linksToDisplay = $LINKSDB->filter(LinkFilter::$FILTER_DAY, $day);
+        $linksToDisplay = $LINKSDB->filterDay($day);
     } catch (Exception $exc) {
         error_log($exc);
         $linksToDisplay = array();
@@ -962,24 +962,7 @@ function renderPage()
     if ($targetPage == Router::$PAGE_PICWALL)
     {
         // Optionally filter the results:
-        $searchtags = !empty($_GET['searchtags']) ? escape($_GET['searchtags']) : '';
-        $searchterm = !empty($_GET['searchterm']) ? escape($_GET['searchterm']) : '';
-        if (! empty($searchtags) && ! empty($searchterm)) {
-            $links = $LINKSDB->filter(
-                LinkFilter::$FILTER_TAG | LinkFilter::$FILTER_TEXT,
-                array($searchtags, $searchterm)
-            );
-        }
-        elseif ($searchtags) {
-            $links = $LINKSDB->filter(LinkFilter::$FILTER_TAG, $searchtags);
-        }
-        elseif ($searchterm) {
-            $links = $LINKSDB->filter(LinkFilter::$FILTER_TEXT, $searchterm);
-        }
-        else {
-            $links = $LINKSDB;
-        }
-
+        $links = $LINKSDB->filterSearch($_GET);
         $linksToDisplay = array();
 
         // Get only links which have a thumbnail.
@@ -1071,7 +1054,7 @@ function renderPage()
             startsWith($query,'do='. $targetPage) && !isLoggedIn()
         );
         $cached = $cache->cachedVersion();
-        if (!empty($cached)) {
+        if (false && !empty($cached)) {
             echo $cached;
             exit;
         }
@@ -1352,9 +1335,9 @@ function renderPage()
 
         // Delete a tag:
         if (isset($_POST['deletetag']) && !empty($_POST['fromtag'])) {
-            $needle=trim($_POST['fromtag']);
+            $needle = trim($_POST['fromtag']);
             // True for case-sensitive tag search.
-            $linksToAlter = $LINKSDB->filter(LinkFilter::$FILTER_TAG, $needle, true);
+            $linksToAlter = $LINKSDB->filterSearch(array('searchtags' => $needle), true);
             foreach($linksToAlter as $key=>$value)
             {
                 $tags = explode(' ',trim($value['tags']));
@@ -1369,9 +1352,9 @@ function renderPage()
 
         // Rename a tag:
         if (isset($_POST['renametag']) && !empty($_POST['fromtag']) && !empty($_POST['totag'])) {
-            $needle=trim($_POST['fromtag']);
+            $needle = trim($_POST['fromtag']);
             // True for case-sensitive tag search.
-            $linksToAlter = $LINKSDB->filter(LinkFilter::$FILTER_TAG, $needle, true);
+            $linksToAlter = $LINKSDB->filterSearch(array('searchtags' => $needle), true);
             foreach($linksToAlter as $key=>$value)
             {
                 $tags = explode(' ',trim($value['tags']));
@@ -1807,60 +1790,32 @@ function importFile()
     }
 }
 
-// -----------------------------------------------------------------------------------------------
-// Template for the list of links (<div id="linklist">)
-// This function fills all the necessary fields in the $PAGE for the template 'linklist.html'
+/**
+ * Template for the list of links (<div id="linklist">)
+ * 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;
-
-    // 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)
-        );
+    $searchterm = !empty($_GET['searchterm']) ? escape($_GET['searchterm']) : '';
 
-        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.
index b6a273b3338ed30477664f6ea0b5880e782c618a..52d31400b5a0716ebce5c2ab51ec3ab008af4c38 100644 (file)
@@ -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('');
+    }
 }
index f991a9c9a26dc1caf382d4cd2c1922b6f8a18e0b..1620bb78e91ee945b31deffb3fde1dd32bb5b033 100644 (file)
@@ -165,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');
     }
 
     /**
index d865066b99f9aa923bafbee30f9ce90b264de9d8..a29d90677dc0d7b611fd078b43e03e841f41bed2 100644 (file)
@@ -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')));
     }
 }