From ebd8075a896484e43c7c938bbc606b67df102013 Mon Sep 17 00:00:00 2001 From: Florian Voigt Date: Sun, 24 Jan 2016 06:13:11 +0000 Subject: [PATCH] Implemented searching for a phrase in double-quotes or all words in no particular order. + unit tests --- application/LinkFilter.php | 45 +++++++++++++++++++++++++++----------- tests/LinkFilterTest.php | 17 +++++++++++++- 2 files changed, 48 insertions(+), 14 deletions(-) diff --git a/application/LinkFilter.php b/application/LinkFilter.php index cf64737..b2e6530 100644 --- a/application/LinkFilter.php +++ b/application/LinkFilter.php @@ -136,16 +136,21 @@ class LinkFilter */ private function filterFulltext($searchterms, $privateonly = false) { - // FIXME: explode(' ',$searchterms) and perform a AND search. - // FIXME: accept double-quotes to search for a string "as is"? - $filtered = array(); - $search = mb_convert_case($searchterms, MB_CASE_LOWER, 'UTF-8'); + $search = mb_convert_case(html_entity_decode($searchterms), MB_CASE_LOWER, 'UTF-8'); $explodedSearch = explode(' ', trim($search)); $keys = array('title', 'description', 'url', 'tags'); + $found = true; + $searchExactPhrase = false; + // Check if we're using double-quotes to search for the exact string + if ($search[0] == '"' && $search[strlen($search) - 1] == '"') { + $searchExactPhrase = true; + + // Remove the double-quotes as they are not what we search for + $search = substr($search, 1, -1); + } // Iterate over every stored link. foreach ($this->links as $link) { - $found = false; // ignore non private links when 'privatonly' is on. if (! $link['private'] && $privateonly === true) { @@ -154,19 +159,33 @@ class LinkFilter // Iterate over searchable link fields. foreach ($keys as $key) { - // Search full expression. - if (strpos( - mb_convert_case($link[$key], MB_CASE_LOWER, 'UTF-8'), - $search - ) !== false) { - $found = true; - } + // Be optimistic + $found = true; + + // FIXME: Find a better word for where you're searching in + $haystack = mb_convert_case($link[$key], MB_CASE_LOWER, 'UTF-8'); + // When searching for the phrase, check if it's in the haystack... + if ( $searchExactPhrase && strpos($haystack, $search) !== false) { + break; + } + else { + // Iterate over keywords, if keyword is not found, + // no need to check for the others. We want all or nothing. + foreach($explodedSearch as $keyword) { + if(strpos($haystack, $keyword) === false) { + $found = false; + break; + } + } + } + + // One of the fields of the link matches, no need to check the other. if ($found) { break; } } - + if ($found) { $filtered[$link['linkdate']] = $link; } diff --git a/tests/LinkFilterTest.php b/tests/LinkFilterTest.php index 5107ab7..5fb2423 100644 --- a/tests/LinkFilterTest.php +++ b/tests/LinkFilterTest.php @@ -173,6 +173,11 @@ class LinkFilterTest extends PHPUnit_Framework_TestCase 2, count(self::$linkFilter->filter(LinkFilter::$FILTER_TEXT, 'ars.userfriendly.org')) ); + + $this->assertEquals( + 2, + count(self::$linkFilter->filter(LinkFilter::$FILTER_TEXT, 'ars org')) + ); } /** @@ -208,8 +213,18 @@ class LinkFilterTest extends PHPUnit_Framework_TestCase { $this->assertEquals( 1, - count(self::$linkFilter->filter(LinkFilter::$FILTER_TEXT, 'media publishing')) + count(self::$linkFilter->filter(LinkFilter::$FILTER_TEXT, 'publishing media')) ); + + $this->assertEquals( + 1, + count(self::$linkFilter->filter(LinkFilter::$FILTER_TEXT, 'mercurial w3c')) + ); + + $this->assertEquals( + 2, + count(self::$linkFilter->filter(LinkFilter::$FILTER_TEXT, '"free software"')) + ); } /**