Update LinkFilter to be able to filter only public links

No update regarding the UI or the API for now

Fixes #758
This commit is contained in:
ArthurHoaro 2017-01-16 13:57:11 +01:00
parent ae7f6b9d09
commit 7f96d9ec21
5 changed files with 107 additions and 39 deletions

View file

@ -443,11 +443,11 @@ public function filterDay($request) {
* - searchtags: list of tags * - searchtags: list of tags
* - searchterm: term search * - searchterm: term search
* @param bool $casesensitive Optional: Perform case sensitive filter * @param bool $casesensitive Optional: Perform case sensitive filter
* @param bool $privateonly Optional: Returns private links only if true. * @param string $visibility return only all/private/public links
* *
* @return array filtered links, all links if no suitable filter was provided. * @return array filtered links, all links if no suitable filter was provided.
*/ */
public function filterSearch($filterRequest = array(), $casesensitive = false, $privateonly = false) public function filterSearch($filterRequest = array(), $casesensitive = false, $visibility = 'all')
{ {
// Filter link database according to parameters. // Filter link database according to parameters.
$searchtags = !empty($filterRequest['searchtags']) ? escape($filterRequest['searchtags']) : ''; $searchtags = !empty($filterRequest['searchtags']) ? escape($filterRequest['searchtags']) : '';
@ -475,7 +475,7 @@ public function filterSearch($filterRequest = array(), $casesensitive = false, $
} }
$linkFilter = new LinkFilter($this); $linkFilter = new LinkFilter($this);
return $linkFilter->filter($type, $request, $casesensitive, $privateonly); return $linkFilter->filter($type, $request, $casesensitive, $visibility);
} }
/** /**

View file

@ -51,12 +51,16 @@ public function __construct($links)
* @param string $type Type of filter (eg. tags, permalink, etc.). * @param string $type Type of filter (eg. tags, permalink, etc.).
* @param mixed $request Filter content. * @param mixed $request Filter content.
* @param bool $casesensitive Optional: Perform case sensitive filter if true. * @param bool $casesensitive Optional: Perform case sensitive filter if true.
* @param bool $privateonly Optional: Only returns private links if true. * @param string $visibility Optional: return only all/private/public links
* *
* @return array filtered link list. * @return array filtered link list.
*/ */
public function filter($type, $request, $casesensitive = false, $privateonly = false) public function filter($type, $request, $casesensitive = false, $visibility = 'all')
{ {
if (! in_array($visibility, ['all', 'public', 'private'])) {
$visibility = 'all';
}
switch($type) { switch($type) {
case self::$FILTER_HASH: case self::$FILTER_HASH:
return $this->filterSmallHash($request); return $this->filterSmallHash($request);
@ -64,42 +68,44 @@ public function filter($type, $request, $casesensitive = false, $privateonly = f
if (!empty($request)) { if (!empty($request)) {
$filtered = $this->links; $filtered = $this->links;
if (isset($request[0])) { if (isset($request[0])) {
$filtered = $this->filterTags($request[0], $casesensitive, $privateonly); $filtered = $this->filterTags($request[0], $casesensitive, $visibility);
} }
if (isset($request[1])) { if (isset($request[1])) {
$lf = new LinkFilter($filtered); $lf = new LinkFilter($filtered);
$filtered = $lf->filterFulltext($request[1], $privateonly); $filtered = $lf->filterFulltext($request[1], $visibility);
} }
return $filtered; return $filtered;
} }
return $this->noFilter($privateonly); return $this->noFilter($visibility);
case self::$FILTER_TEXT: case self::$FILTER_TEXT:
return $this->filterFulltext($request, $privateonly); return $this->filterFulltext($request, $visibility);
case self::$FILTER_TAG: case self::$FILTER_TAG:
return $this->filterTags($request, $casesensitive, $privateonly); return $this->filterTags($request, $casesensitive, $visibility);
case self::$FILTER_DAY: case self::$FILTER_DAY:
return $this->filterDay($request); return $this->filterDay($request);
default: default:
return $this->noFilter($privateonly); return $this->noFilter($visibility);
} }
} }
/** /**
* Unknown filter, but handle private only. * Unknown filter, but handle private only.
* *
* @param bool $privateonly returns private link only if true. * @param string $visibility Optional: return only all/private/public links
* *
* @return array filtered links. * @return array filtered links.
*/ */
private function noFilter($privateonly = false) private function noFilter($visibility = 'all')
{ {
if (! $privateonly) { if ($visibility === 'all') {
return $this->links; return $this->links;
} }
$out = array(); $out = array();
foreach ($this->links as $key => $value) { foreach ($this->links as $key => $value) {
if ($value['private']) { if ($value['private'] && $visibility === 'private') {
$out[$key] = $value;
} else if (! $value['private'] && $visibility === 'public') {
$out[$key] = $value; $out[$key] = $value;
} }
} }
@ -151,14 +157,14 @@ private function filterSmallHash($smallHash)
* - see https://github.com/shaarli/Shaarli/issues/75 for examples * - see https://github.com/shaarli/Shaarli/issues/75 for examples
* *
* @param string $searchterms search query. * @param string $searchterms search query.
* @param bool $privateonly return only private links if true. * @param string $visibility Optional: return only all/private/public links.
* *
* @return array search results. * @return array search results.
*/ */
private function filterFulltext($searchterms, $privateonly = false) private function filterFulltext($searchterms, $visibility = 'all')
{ {
if (empty($searchterms)) { if (empty($searchterms)) {
return $this->links; return $this->noFilter($visibility);
} }
$filtered = array(); $filtered = array();
@ -189,8 +195,12 @@ private function filterFulltext($searchterms, $privateonly = false)
foreach ($this->links as $id => $link) { foreach ($this->links as $id => $link) {
// ignore non private links when 'privatonly' is on. // ignore non private links when 'privatonly' is on.
if (! $link['private'] && $privateonly === true) { if ($visibility !== 'all') {
continue; if (! $link['private'] && $visibility === 'private') {
continue;
} else if ($link['private'] && $visibility === 'public') {
continue;
}
} }
// Concatenate link fields to search across fields. // Concatenate link fields to search across fields.
@ -235,16 +245,16 @@ private function filterFulltext($searchterms, $privateonly = false)
* *
* @param string $tags list of tags separated by commas or blank spaces. * @param string $tags list of tags separated by commas or blank spaces.
* @param bool $casesensitive ignore case if false. * @param bool $casesensitive ignore case if false.
* @param bool $privateonly returns private links only. * @param string $visibility Optional: return only all/private/public links.
* *
* @return array filtered links. * @return array filtered links.
*/ */
public function filterTags($tags, $casesensitive = false, $privateonly = false) public function filterTags($tags, $casesensitive = false, $visibility = 'all')
{ {
// Implode if array for clean up. // Implode if array for clean up.
$tags = is_array($tags) ? trim(implode(' ', $tags)) : $tags; $tags = is_array($tags) ? trim(implode(' ', $tags)) : $tags;
if (empty($tags)) { if (empty($tags)) {
return $this->links; return $this->noFilter($visibility);
} }
$searchtags = self::tagsStrToArray($tags, $casesensitive); $searchtags = self::tagsStrToArray($tags, $casesensitive);
@ -255,8 +265,12 @@ public function filterTags($tags, $casesensitive = false, $privateonly = false)
foreach ($this->links as $key => $link) { foreach ($this->links as $key => $link) {
// ignore non private links when 'privatonly' is on. // ignore non private links when 'privatonly' is on.
if (! $link['private'] && $privateonly === true) { if ($visibility !== 'all') {
continue; if (! $link['private'] && $visibility === 'private') {
continue;
} else if ($link['private'] && $visibility === 'public') {
continue;
}
} }
$linktags = self::tagsStrToArray($link['tags'], $casesensitive); $linktags = self::tagsStrToArray($link['tags'], $casesensitive);
@ -341,7 +355,7 @@ protected function searchTagAndHashTag($tag, $taglist, $description)
* @param bool $casesensitive will convert everything to lowercase if false. * @param bool $casesensitive will convert everything to lowercase if false.
* *
* @return array filtered tags string. * @return array filtered tags string.
*/ */
public static function tagsStrToArray($tags, $casesensitive) public static function tagsStrToArray($tags, $casesensitive)
{ {
// We use UTF-8 conversion to handle various graphemes (i.e. cyrillic, or greek) // We use UTF-8 conversion to handle various graphemes (i.e. cyrillic, or greek)

View file

@ -41,7 +41,8 @@ public function getLinks($request, $response)
'searchterm' => $request->getParam('searchterm', ''), 'searchterm' => $request->getParam('searchterm', ''),
], ],
false, false,
$private === 'true' || $private === '1' // to updated in another PR depending on the API doc
($private === 'true' || $private === '1') ? 'private' : 'all'
); );
// Return links from the {offset}th link, starting from 0. // Return links from the {offset}th link, starting from 0.

View file

@ -1630,8 +1630,8 @@ function buildLinkList($PAGE,$LINKSDB, $conf, $pluginManager)
} }
} else { } else {
// Filter links according search parameters. // Filter links according search parameters.
$privateonly = !empty($_SESSION['privateonly']); $visibility = ! empty($_SESSION['privateonly']) ? 'private' : 'all';
$linksToDisplay = $LINKSDB->filterSearch($_GET, false, $privateonly); $linksToDisplay = $LINKSDB->filterSearch($_GET, false, $visibility);
} }
// ---- Handle paging. // ---- Handle paging.

View file

@ -12,13 +12,18 @@ class LinkFilterTest extends PHPUnit_Framework_TestCase
*/ */
protected static $linkFilter; protected static $linkFilter;
/**
* @var ReferenceLinkDB instance
*/
protected static $refDB;
/** /**
* Instanciate linkFilter with ReferenceLinkDB data. * Instanciate linkFilter with ReferenceLinkDB data.
*/ */
public static function setUpBeforeClass() public static function setUpBeforeClass()
{ {
$refDB = new ReferenceLinkDB(); self::$refDB = new ReferenceLinkDB();
self::$linkFilter = new LinkFilter($refDB->getLinks()); self::$linkFilter = new LinkFilter(self::$refDB->getLinks());
} }
/** /**
@ -27,14 +32,30 @@ public static function setUpBeforeClass()
public function testFilter() public function testFilter()
{ {
$this->assertEquals( $this->assertEquals(
ReferenceLinkDB::$NB_LINKS_TOTAL, self::$refDB->countLinks(),
count(self::$linkFilter->filter('', '')) count(self::$linkFilter->filter('', ''))
); );
$this->assertEquals(
self::$refDB->countLinks(),
count(self::$linkFilter->filter('', '', 'all'))
);
$this->assertEquals(
self::$refDB->countLinks(),
count(self::$linkFilter->filter('', '', 'randomstr'))
);
// Private only. // Private only.
$this->assertEquals( $this->assertEquals(
2, self::$refDB->countPrivateLinks(),
count(self::$linkFilter->filter('', '', false, true)) count(self::$linkFilter->filter('', '', false, 'private'))
);
// Public only.
$this->assertEquals(
self::$refDB->countPublicLinks(),
count(self::$linkFilter->filter('', '', false, 'public'))
); );
$this->assertEquals( $this->assertEquals(
@ -58,10 +79,26 @@ public function testFilterOneTag()
count(self::$linkFilter->filter(LinkFilter::$FILTER_TAG, 'web', false)) count(self::$linkFilter->filter(LinkFilter::$FILTER_TAG, 'web', false))
); );
$this->assertEquals(
4,
count(self::$linkFilter->filter(LinkFilter::$FILTER_TAG, 'web', false, 'all'))
);
$this->assertEquals(
4,
count(self::$linkFilter->filter(LinkFilter::$FILTER_TAG, 'web', false, 'default-blabla'))
);
// Private only. // Private only.
$this->assertEquals( $this->assertEquals(
1, 1,
count(self::$linkFilter->filter(LinkFilter::$FILTER_TAG, 'web', false, true)) count(self::$linkFilter->filter(LinkFilter::$FILTER_TAG, 'web', false, 'private'))
);
// Public only.
$this->assertEquals(
3,
count(self::$linkFilter->filter(LinkFilter::$FILTER_TAG, 'web', false, 'public'))
); );
} }
@ -253,14 +290,30 @@ public function testFilterFullTextDescription()
public function testFilterFullTextTags() public function testFilterFullTextTags()
{ {
$this->assertEquals( $this->assertEquals(
2, 6,
count(self::$linkFilter->filter(LinkFilter::$FILTER_TEXT, 'gnu')) count(self::$linkFilter->filter(LinkFilter::$FILTER_TEXT, 'web'))
);
$this->assertEquals(
6,
count(self::$linkFilter->filter(LinkFilter::$FILTER_TEXT, 'web', 'all'))
);
$this->assertEquals(
6,
count(self::$linkFilter->filter(LinkFilter::$FILTER_TEXT, 'web', 'bla'))
); );
// Private only. // Private only.
$this->assertEquals( $this->assertEquals(
1, 1,
count(self::$linkFilter->filter(LinkFilter::$FILTER_TEXT, 'web', false, true)) count(self::$linkFilter->filter(LinkFilter::$FILTER_TEXT, 'web', false, 'private'))
);
// Public only.
$this->assertEquals(
5,
count(self::$linkFilter->filter(LinkFilter::$FILTER_TEXT, 'web', false, 'public'))
); );
} }
@ -409,7 +462,7 @@ public function testFilterByHashtag()
LinkFilter::$FILTER_TAG, LinkFilter::$FILTER_TAG,
$hashtag, $hashtag,
false, false,
true 'private'
)) ))
); );
} }