Empty tag search will look for not tagged links
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
This commit is contained in:
parent
b64d83cd2b
commit
7d86f40bdb
12 changed files with 115 additions and 36 deletions
|
@ -97,6 +97,11 @@ public function __construct($linkDB, $feedType, $serverInfo, $userInput, $isLogg
|
|||
*/
|
||||
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);
|
||||
|
||||
|
|
|
@ -450,29 +450,12 @@ public function filterDay($request) {
|
|||
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);
|
||||
|
|
|
@ -253,6 +253,9 @@ public function filterTags($tags, $casesensitive = false, $visibility = 'all')
|
|||
{
|
||||
// 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 @@ public function filterTags($tags, $casesensitive = false, $visibility = 'all')
|
|||
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
|
||||
*
|
||||
|
|
|
@ -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) {
|
||||
|
|
18
index.php
18
index.php
|
@ -1609,7 +1609,15 @@ function($a, $b) { return $a['order'] - $b['order']; }
|
|||
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)) {
|
||||
|
|
|
@ -448,7 +448,7 @@ public function testFilterHashInValid()
|
|||
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);
|
||||
|
|
|
@ -63,6 +63,12 @@ public function testFilter()
|
|||
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 @@ public function testFilterUnknownTag()
|
|||
public function testFilterDay()
|
||||
{
|
||||
$this->assertEquals(
|
||||
3,
|
||||
4,
|
||||
count(self::$linkFilter->filter(LinkFilter::$FILTER_DAY, '20121206'))
|
||||
);
|
||||
}
|
||||
|
@ -339,7 +345,7 @@ public function testExcludeSearch()
|
|||
);
|
||||
|
||||
$this->assertEquals(
|
||||
7,
|
||||
ReferenceLinkDB::$NB_LINKS_TOTAL - 1,
|
||||
count(self::$linkFilter->filter(LinkFilter::$FILTER_TEXT, '-revolution'))
|
||||
);
|
||||
}
|
||||
|
@ -399,7 +405,7 @@ public function testTagFilterWithExclusion()
|
|||
);
|
||||
|
||||
$this->assertEquals(
|
||||
7,
|
||||
ReferenceLinkDB::$NB_LINKS_TOTAL - 1,
|
||||
count(self::$linkFilter->filter(LinkFilter::$FILTER_TAG, '-free'))
|
||||
);
|
||||
}
|
||||
|
@ -425,6 +431,13 @@ public function testFilterCrossedSearch()
|
|||
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(
|
||||
|
|
|
@ -94,7 +94,7 @@ public function testGetLinks()
|
|||
$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 @@ public function testGetLinksLimitAll()
|
|||
$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));
|
||||
|
|
|
@ -80,7 +80,7 @@ public function testGetInfo()
|
|||
$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 @@ public function testGetInfo()
|
|||
$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']);
|
||||
|
|
|
@ -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 @@ public function __construct()
|
|||
'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 @@ public function countPrivateLinks()
|
|||
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;
|
||||
|
|
|
@ -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">
|
||||
|
@ -105,6 +105,10 @@
|
|||
<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}
|
||||
|
|
|
@ -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)"}
|
||||
|
@ -69,6 +69,10 @@
|
|||
<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}
|
||||
|
|
Loading…
Reference in a new issue