diff options
-rw-r--r-- | application/LinkDB.php | 6 | ||||
-rw-r--r-- | application/LinkFilter.php | 60 | ||||
-rw-r--r-- | application/api/controllers/Links.php | 3 | ||||
-rw-r--r-- | index.php | 4 | ||||
-rw-r--r-- | tests/LinkFilterTest.php | 73 |
5 files changed, 107 insertions, 39 deletions
diff --git a/application/LinkDB.php b/application/LinkDB.php index 1e13286a..4cee2af9 100644 --- a/application/LinkDB.php +++ b/application/LinkDB.php | |||
@@ -443,11 +443,11 @@ You use the community supported version of the original Shaarli project, by Seba | |||
443 | * - searchtags: list of tags | 443 | * - searchtags: list of tags |
444 | * - searchterm: term search | 444 | * - searchterm: term search |
445 | * @param bool $casesensitive Optional: Perform case sensitive filter | 445 | * @param bool $casesensitive Optional: Perform case sensitive filter |
446 | * @param bool $privateonly Optional: Returns private links only if true. | 446 | * @param string $visibility return only all/private/public links |
447 | * | 447 | * |
448 | * @return array filtered links, all links if no suitable filter was provided. | 448 | * @return array filtered links, all links if no suitable filter was provided. |
449 | */ | 449 | */ |
450 | public function filterSearch($filterRequest = array(), $casesensitive = false, $privateonly = false) | 450 | public function filterSearch($filterRequest = array(), $casesensitive = false, $visibility = 'all') |
451 | { | 451 | { |
452 | // Filter link database according to parameters. | 452 | // Filter link database according to parameters. |
453 | $searchtags = !empty($filterRequest['searchtags']) ? escape($filterRequest['searchtags']) : ''; | 453 | $searchtags = !empty($filterRequest['searchtags']) ? escape($filterRequest['searchtags']) : ''; |
@@ -475,7 +475,7 @@ You use the community supported version of the original Shaarli project, by Seba | |||
475 | } | 475 | } |
476 | 476 | ||
477 | $linkFilter = new LinkFilter($this); | 477 | $linkFilter = new LinkFilter($this); |
478 | return $linkFilter->filter($type, $request, $casesensitive, $privateonly); | 478 | return $linkFilter->filter($type, $request, $casesensitive, $visibility); |
479 | } | 479 | } |
480 | 480 | ||
481 | /** | 481 | /** |
diff --git a/application/LinkFilter.php b/application/LinkFilter.php index 57ebfd5c..81832a4b 100644 --- a/application/LinkFilter.php +++ b/application/LinkFilter.php | |||
@@ -51,12 +51,16 @@ class LinkFilter | |||
51 | * @param string $type Type of filter (eg. tags, permalink, etc.). | 51 | * @param string $type Type of filter (eg. tags, permalink, etc.). |
52 | * @param mixed $request Filter content. | 52 | * @param mixed $request Filter content. |
53 | * @param bool $casesensitive Optional: Perform case sensitive filter if true. | 53 | * @param bool $casesensitive Optional: Perform case sensitive filter if true. |
54 | * @param bool $privateonly Optional: Only returns private links if true. | 54 | * @param string $visibility Optional: return only all/private/public links |
55 | * | 55 | * |
56 | * @return array filtered link list. | 56 | * @return array filtered link list. |
57 | */ | 57 | */ |
58 | public function filter($type, $request, $casesensitive = false, $privateonly = false) | 58 | public function filter($type, $request, $casesensitive = false, $visibility = 'all') |
59 | { | 59 | { |
60 | if (! in_array($visibility, ['all', 'public', 'private'])) { | ||
61 | $visibility = 'all'; | ||
62 | } | ||
63 | |||
60 | switch($type) { | 64 | switch($type) { |
61 | case self::$FILTER_HASH: | 65 | case self::$FILTER_HASH: |
62 | return $this->filterSmallHash($request); | 66 | return $this->filterSmallHash($request); |
@@ -64,42 +68,44 @@ class LinkFilter | |||
64 | if (!empty($request)) { | 68 | if (!empty($request)) { |
65 | $filtered = $this->links; | 69 | $filtered = $this->links; |
66 | if (isset($request[0])) { | 70 | if (isset($request[0])) { |
67 | $filtered = $this->filterTags($request[0], $casesensitive, $privateonly); | 71 | $filtered = $this->filterTags($request[0], $casesensitive, $visibility); |
68 | } | 72 | } |
69 | if (isset($request[1])) { | 73 | if (isset($request[1])) { |
70 | $lf = new LinkFilter($filtered); | 74 | $lf = new LinkFilter($filtered); |
71 | $filtered = $lf->filterFulltext($request[1], $privateonly); | 75 | $filtered = $lf->filterFulltext($request[1], $visibility); |
72 | } | 76 | } |
73 | return $filtered; | 77 | return $filtered; |
74 | } | 78 | } |
75 | return $this->noFilter($privateonly); | 79 | return $this->noFilter($visibility); |
76 | case self::$FILTER_TEXT: | 80 | case self::$FILTER_TEXT: |
77 | return $this->filterFulltext($request, $privateonly); | 81 | return $this->filterFulltext($request, $visibility); |
78 | case self::$FILTER_TAG: | 82 | case self::$FILTER_TAG: |
79 | return $this->filterTags($request, $casesensitive, $privateonly); | 83 | return $this->filterTags($request, $casesensitive, $visibility); |
80 | case self::$FILTER_DAY: | 84 | case self::$FILTER_DAY: |
81 | return $this->filterDay($request); | 85 | return $this->filterDay($request); |
82 | default: | 86 | default: |
83 | return $this->noFilter($privateonly); | 87 | return $this->noFilter($visibility); |
84 | } | 88 | } |
85 | } | 89 | } |
86 | 90 | ||
87 | /** | 91 | /** |
88 | * Unknown filter, but handle private only. | 92 | * Unknown filter, but handle private only. |
89 | * | 93 | * |
90 | * @param bool $privateonly returns private link only if true. | 94 | * @param string $visibility Optional: return only all/private/public links |
91 | * | 95 | * |
92 | * @return array filtered links. | 96 | * @return array filtered links. |
93 | */ | 97 | */ |
94 | private function noFilter($privateonly = false) | 98 | private function noFilter($visibility = 'all') |
95 | { | 99 | { |
96 | if (! $privateonly) { | 100 | if ($visibility === 'all') { |
97 | return $this->links; | 101 | return $this->links; |
98 | } | 102 | } |
99 | 103 | ||
100 | $out = array(); | 104 | $out = array(); |
101 | foreach ($this->links as $key => $value) { | 105 | foreach ($this->links as $key => $value) { |
102 | if ($value['private']) { | 106 | if ($value['private'] && $visibility === 'private') { |
107 | $out[$key] = $value; | ||
108 | } else if (! $value['private'] && $visibility === 'public') { | ||
103 | $out[$key] = $value; | 109 | $out[$key] = $value; |
104 | } | 110 | } |
105 | } | 111 | } |
@@ -151,14 +157,14 @@ class LinkFilter | |||
151 | * - see https://github.com/shaarli/Shaarli/issues/75 for examples | 157 | * - see https://github.com/shaarli/Shaarli/issues/75 for examples |
152 | * | 158 | * |
153 | * @param string $searchterms search query. | 159 | * @param string $searchterms search query. |
154 | * @param bool $privateonly return only private links if true. | 160 | * @param string $visibility Optional: return only all/private/public links. |
155 | * | 161 | * |
156 | * @return array search results. | 162 | * @return array search results. |
157 | */ | 163 | */ |
158 | private function filterFulltext($searchterms, $privateonly = false) | 164 | private function filterFulltext($searchterms, $visibility = 'all') |
159 | { | 165 | { |
160 | if (empty($searchterms)) { | 166 | if (empty($searchterms)) { |
161 | return $this->links; | 167 | return $this->noFilter($visibility); |
162 | } | 168 | } |
163 | 169 | ||
164 | $filtered = array(); | 170 | $filtered = array(); |
@@ -189,8 +195,12 @@ class LinkFilter | |||
189 | foreach ($this->links as $id => $link) { | 195 | foreach ($this->links as $id => $link) { |
190 | 196 | ||
191 | // ignore non private links when 'privatonly' is on. | 197 | // ignore non private links when 'privatonly' is on. |
192 | if (! $link['private'] && $privateonly === true) { | 198 | if ($visibility !== 'all') { |
193 | continue; | 199 | if (! $link['private'] && $visibility === 'private') { |
200 | continue; | ||
201 | } else if ($link['private'] && $visibility === 'public') { | ||
202 | continue; | ||
203 | } | ||
194 | } | 204 | } |
195 | 205 | ||
196 | // Concatenate link fields to search across fields. | 206 | // Concatenate link fields to search across fields. |
@@ -235,16 +245,16 @@ class LinkFilter | |||
235 | * | 245 | * |
236 | * @param string $tags list of tags separated by commas or blank spaces. | 246 | * @param string $tags list of tags separated by commas or blank spaces. |
237 | * @param bool $casesensitive ignore case if false. | 247 | * @param bool $casesensitive ignore case if false. |
238 | * @param bool $privateonly returns private links only. | 248 | * @param string $visibility Optional: return only all/private/public links. |
239 | * | 249 | * |
240 | * @return array filtered links. | 250 | * @return array filtered links. |
241 | */ | 251 | */ |
242 | public function filterTags($tags, $casesensitive = false, $privateonly = false) | 252 | public function filterTags($tags, $casesensitive = false, $visibility = 'all') |
243 | { | 253 | { |
244 | // Implode if array for clean up. | 254 | // Implode if array for clean up. |
245 | $tags = is_array($tags) ? trim(implode(' ', $tags)) : $tags; | 255 | $tags = is_array($tags) ? trim(implode(' ', $tags)) : $tags; |
246 | if (empty($tags)) { | 256 | if (empty($tags)) { |
247 | return $this->links; | 257 | return $this->noFilter($visibility); |
248 | } | 258 | } |
249 | 259 | ||
250 | $searchtags = self::tagsStrToArray($tags, $casesensitive); | 260 | $searchtags = self::tagsStrToArray($tags, $casesensitive); |
@@ -255,8 +265,12 @@ class LinkFilter | |||
255 | 265 | ||
256 | foreach ($this->links as $key => $link) { | 266 | foreach ($this->links as $key => $link) { |
257 | // ignore non private links when 'privatonly' is on. | 267 | // ignore non private links when 'privatonly' is on. |
258 | if (! $link['private'] && $privateonly === true) { | 268 | if ($visibility !== 'all') { |
259 | continue; | 269 | if (! $link['private'] && $visibility === 'private') { |
270 | continue; | ||
271 | } else if ($link['private'] && $visibility === 'public') { | ||
272 | continue; | ||
273 | } | ||
260 | } | 274 | } |
261 | 275 | ||
262 | $linktags = self::tagsStrToArray($link['tags'], $casesensitive); | 276 | $linktags = self::tagsStrToArray($link['tags'], $casesensitive); |
@@ -341,7 +355,7 @@ class LinkFilter | |||
341 | * @param bool $casesensitive will convert everything to lowercase if false. | 355 | * @param bool $casesensitive will convert everything to lowercase if false. |
342 | * | 356 | * |
343 | * @return array filtered tags string. | 357 | * @return array filtered tags string. |
344 | */ | 358 | */ |
345 | public static function tagsStrToArray($tags, $casesensitive) | 359 | public static function tagsStrToArray($tags, $casesensitive) |
346 | { | 360 | { |
347 | // We use UTF-8 conversion to handle various graphemes (i.e. cyrillic, or greek) | 361 | // We use UTF-8 conversion to handle various graphemes (i.e. cyrillic, or greek) |
diff --git a/application/api/controllers/Links.php b/application/api/controllers/Links.php index 1c7b41cd..01b7e783 100644 --- a/application/api/controllers/Links.php +++ b/application/api/controllers/Links.php | |||
@@ -41,7 +41,8 @@ class Links extends ApiController | |||
41 | 'searchterm' => $request->getParam('searchterm', ''), | 41 | 'searchterm' => $request->getParam('searchterm', ''), |
42 | ], | 42 | ], |
43 | false, | 43 | false, |
44 | $private === 'true' || $private === '1' | 44 | // to updated in another PR depending on the API doc |
45 | ($private === 'true' || $private === '1') ? 'private' : 'all' | ||
45 | ); | 46 | ); |
46 | 47 | ||
47 | // Return links from the {offset}th link, starting from 0. | 48 | // Return links from the {offset}th link, starting from 0. |
@@ -1630,8 +1630,8 @@ function buildLinkList($PAGE,$LINKSDB, $conf, $pluginManager) | |||
1630 | } | 1630 | } |
1631 | } else { | 1631 | } else { |
1632 | // Filter links according search parameters. | 1632 | // Filter links according search parameters. |
1633 | $privateonly = !empty($_SESSION['privateonly']); | 1633 | $visibility = ! empty($_SESSION['privateonly']) ? 'private' : 'all'; |
1634 | $linksToDisplay = $LINKSDB->filterSearch($_GET, false, $privateonly); | 1634 | $linksToDisplay = $LINKSDB->filterSearch($_GET, false, $visibility); |
1635 | } | 1635 | } |
1636 | 1636 | ||
1637 | // ---- Handle paging. | 1637 | // ---- Handle paging. |
diff --git a/tests/LinkFilterTest.php b/tests/LinkFilterTest.php index 21d680a5..37d5ca30 100644 --- a/tests/LinkFilterTest.php +++ b/tests/LinkFilterTest.php | |||
@@ -13,12 +13,17 @@ class LinkFilterTest extends PHPUnit_Framework_TestCase | |||
13 | protected static $linkFilter; | 13 | protected static $linkFilter; |
14 | 14 | ||
15 | /** | 15 | /** |
16 | * @var ReferenceLinkDB instance | ||
17 | */ | ||
18 | protected static $refDB; | ||
19 | |||
20 | /** | ||
16 | * Instanciate linkFilter with ReferenceLinkDB data. | 21 | * Instanciate linkFilter with ReferenceLinkDB data. |
17 | */ | 22 | */ |
18 | public static function setUpBeforeClass() | 23 | public static function setUpBeforeClass() |
19 | { | 24 | { |
20 | $refDB = new ReferenceLinkDB(); | 25 | self::$refDB = new ReferenceLinkDB(); |
21 | self::$linkFilter = new LinkFilter($refDB->getLinks()); | 26 | self::$linkFilter = new LinkFilter(self::$refDB->getLinks()); |
22 | } | 27 | } |
23 | 28 | ||
24 | /** | 29 | /** |
@@ -27,14 +32,30 @@ class LinkFilterTest extends PHPUnit_Framework_TestCase | |||
27 | public function testFilter() | 32 | public function testFilter() |
28 | { | 33 | { |
29 | $this->assertEquals( | 34 | $this->assertEquals( |
30 | ReferenceLinkDB::$NB_LINKS_TOTAL, | 35 | self::$refDB->countLinks(), |
31 | count(self::$linkFilter->filter('', '')) | 36 | count(self::$linkFilter->filter('', '')) |
32 | ); | 37 | ); |
33 | 38 | ||
39 | $this->assertEquals( | ||
40 | self::$refDB->countLinks(), | ||
41 | count(self::$linkFilter->filter('', '', 'all')) | ||
42 | ); | ||
43 | |||
44 | $this->assertEquals( | ||
45 | self::$refDB->countLinks(), | ||
46 | count(self::$linkFilter->filter('', '', 'randomstr')) | ||
47 | ); | ||
48 | |||
34 | // Private only. | 49 | // Private only. |
35 | $this->assertEquals( | 50 | $this->assertEquals( |
36 | 2, | 51 | self::$refDB->countPrivateLinks(), |
37 | count(self::$linkFilter->filter('', '', false, true)) | 52 | count(self::$linkFilter->filter('', '', false, 'private')) |
53 | ); | ||
54 | |||
55 | // Public only. | ||
56 | $this->assertEquals( | ||
57 | self::$refDB->countPublicLinks(), | ||
58 | count(self::$linkFilter->filter('', '', false, 'public')) | ||
38 | ); | 59 | ); |
39 | 60 | ||
40 | $this->assertEquals( | 61 | $this->assertEquals( |
@@ -58,10 +79,26 @@ class LinkFilterTest extends PHPUnit_Framework_TestCase | |||
58 | count(self::$linkFilter->filter(LinkFilter::$FILTER_TAG, 'web', false)) | 79 | count(self::$linkFilter->filter(LinkFilter::$FILTER_TAG, 'web', false)) |
59 | ); | 80 | ); |
60 | 81 | ||
82 | $this->assertEquals( | ||
83 | 4, | ||
84 | count(self::$linkFilter->filter(LinkFilter::$FILTER_TAG, 'web', false, 'all')) | ||
85 | ); | ||
86 | |||
87 | $this->assertEquals( | ||
88 | 4, | ||
89 | count(self::$linkFilter->filter(LinkFilter::$FILTER_TAG, 'web', false, 'default-blabla')) | ||
90 | ); | ||
91 | |||
61 | // Private only. | 92 | // Private only. |
62 | $this->assertEquals( | 93 | $this->assertEquals( |
63 | 1, | 94 | 1, |
64 | count(self::$linkFilter->filter(LinkFilter::$FILTER_TAG, 'web', false, true)) | 95 | count(self::$linkFilter->filter(LinkFilter::$FILTER_TAG, 'web', false, 'private')) |
96 | ); | ||
97 | |||
98 | // Public only. | ||
99 | $this->assertEquals( | ||
100 | 3, | ||
101 | count(self::$linkFilter->filter(LinkFilter::$FILTER_TAG, 'web', false, 'public')) | ||
65 | ); | 102 | ); |
66 | } | 103 | } |
67 | 104 | ||
@@ -253,14 +290,30 @@ class LinkFilterTest extends PHPUnit_Framework_TestCase | |||
253 | public function testFilterFullTextTags() | 290 | public function testFilterFullTextTags() |
254 | { | 291 | { |
255 | $this->assertEquals( | 292 | $this->assertEquals( |
256 | 2, | 293 | 6, |
257 | count(self::$linkFilter->filter(LinkFilter::$FILTER_TEXT, 'gnu')) | 294 | count(self::$linkFilter->filter(LinkFilter::$FILTER_TEXT, 'web')) |
295 | ); | ||
296 | |||
297 | $this->assertEquals( | ||
298 | 6, | ||
299 | count(self::$linkFilter->filter(LinkFilter::$FILTER_TEXT, 'web', 'all')) | ||
300 | ); | ||
301 | |||
302 | $this->assertEquals( | ||
303 | 6, | ||
304 | count(self::$linkFilter->filter(LinkFilter::$FILTER_TEXT, 'web', 'bla')) | ||
258 | ); | 305 | ); |
259 | 306 | ||
260 | // Private only. | 307 | // Private only. |
261 | $this->assertEquals( | 308 | $this->assertEquals( |
262 | 1, | 309 | 1, |
263 | count(self::$linkFilter->filter(LinkFilter::$FILTER_TEXT, 'web', false, true)) | 310 | count(self::$linkFilter->filter(LinkFilter::$FILTER_TEXT, 'web', false, 'private')) |
311 | ); | ||
312 | |||
313 | // Public only. | ||
314 | $this->assertEquals( | ||
315 | 5, | ||
316 | count(self::$linkFilter->filter(LinkFilter::$FILTER_TEXT, 'web', false, 'public')) | ||
264 | ); | 317 | ); |
265 | } | 318 | } |
266 | 319 | ||
@@ -409,7 +462,7 @@ class LinkFilterTest extends PHPUnit_Framework_TestCase | |||
409 | LinkFilter::$FILTER_TAG, | 462 | LinkFilter::$FILTER_TAG, |
410 | $hashtag, | 463 | $hashtag, |
411 | false, | 464 | false, |
412 | true | 465 | 'private' |
413 | )) | 466 | )) |
414 | ); | 467 | ); |
415 | } | 468 | } |