Add exclusion in tag search
* Searching '-mytag' will now exlude all shaares with 'mytag' tag. * All tags starting with a '-' are renamed without it (through the Updater). * Unit tests. Minor code changes: * LinkDB->filter() can now take no parameters (get all link depending on logged status). * tagsStrToArray() is now static and filters blank tags.
This commit is contained in:
parent
6e607ca613
commit
21979ff11c
7 changed files with 77 additions and 12 deletions
|
@ -340,7 +340,7 @@ public function getLinkFromUrl($url)
|
||||||
*
|
*
|
||||||
* @return array filtered links
|
* @return array filtered links
|
||||||
*/
|
*/
|
||||||
public function filter($type, $request, $casesensitive = false, $privateonly = false)
|
public function filter($type = '', $request = '', $casesensitive = false, $privateonly = false)
|
||||||
{
|
{
|
||||||
$linkFilter = new LinkFilter($this->_links);
|
$linkFilter = new LinkFilter($this->_links);
|
||||||
$requestFilter = is_array($request) ? implode(' ', $request) : $request;
|
$requestFilter = is_array($request) ? implode(' ', $request) : $request;
|
||||||
|
|
|
@ -209,19 +209,33 @@ private function filterFulltext($searchterms, $privateonly = false)
|
||||||
*/
|
*/
|
||||||
public function filterTags($tags, $casesensitive = false, $privateonly = false)
|
public function filterTags($tags, $casesensitive = false, $privateonly = false)
|
||||||
{
|
{
|
||||||
$searchtags = $this->tagsStrToArray($tags, $casesensitive);
|
$searchtags = self::tagsStrToArray($tags, $casesensitive);
|
||||||
$filtered = array();
|
$filtered = array();
|
||||||
|
if (empty($searchtags)) {
|
||||||
|
return $filtered;
|
||||||
|
}
|
||||||
|
|
||||||
foreach ($this->links as $l) {
|
foreach ($this->links as $link) {
|
||||||
// ignore non private links when 'privatonly' is on.
|
// ignore non private links when 'privatonly' is on.
|
||||||
if (! $l['private'] && $privateonly === true) {
|
if (! $link['private'] && $privateonly === true) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
$linktags = $this->tagsStrToArray($l['tags'], $casesensitive);
|
$linktags = self::tagsStrToArray($link['tags'], $casesensitive);
|
||||||
|
|
||||||
if (count(array_intersect($linktags, $searchtags)) == count($searchtags)) {
|
$found = true;
|
||||||
$filtered[$l['linkdate']] = $l;
|
for ($i = 0 ; $i < count($searchtags) && $found; $i++) {
|
||||||
|
// Exclusive search, quit if tag found.
|
||||||
|
// Or, tag not found in the link, quit.
|
||||||
|
if (($searchtags[$i][0] == '-' && in_array(substr($searchtags[$i], 1), $linktags))
|
||||||
|
|| ($searchtags[$i][0] != '-') && ! in_array($searchtags[$i], $linktags)
|
||||||
|
) {
|
||||||
|
$found = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($found) {
|
||||||
|
$filtered[$link['linkdate']] = $link;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
krsort($filtered);
|
krsort($filtered);
|
||||||
|
@ -266,12 +280,12 @@ public function filterDay($day)
|
||||||
*
|
*
|
||||||
* @return array filtered tags string.
|
* @return array filtered tags string.
|
||||||
*/
|
*/
|
||||||
public 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)
|
||||||
$tagsOut = $casesensitive ? $tags : mb_convert_case($tags, MB_CASE_LOWER, 'UTF-8');
|
$tagsOut = $casesensitive ? $tags : mb_convert_case($tags, MB_CASE_LOWER, 'UTF-8');
|
||||||
$tagsOut = str_replace(',', ' ', $tagsOut);
|
$tagsOut = str_replace(',', ' ', $tagsOut);
|
||||||
|
|
||||||
return explode(' ', trim($tagsOut));
|
return array_filter(explode(' ', trim($tagsOut)), 'strlen');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -131,6 +131,21 @@ public function updateMethodMergeDeprecatedConfigFile()
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rename tags starting with a '-' to work with tag exclusion search.
|
||||||
|
*/
|
||||||
|
public function updateMethodRenameDashTags()
|
||||||
|
{
|
||||||
|
$linklist = $this->linkDB->filter();
|
||||||
|
foreach ($linklist as $link) {
|
||||||
|
$link['tags'] = preg_replace('/(^| )\-/', '$1', $link['tags']);
|
||||||
|
$link['tags'] = implode(' ', array_unique(LinkFilter::tagsStrToArray($link['tags'], true)));
|
||||||
|
$this->linkDB[$link['linkdate']] = $link;
|
||||||
|
}
|
||||||
|
$this->linkDB->savedb($this->config['config']['PAGECACHE']);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -276,7 +276,8 @@ public function testAllTags()
|
||||||
'media' => 1,
|
'media' => 1,
|
||||||
'software' => 1,
|
'software' => 1,
|
||||||
'stallman' => 1,
|
'stallman' => 1,
|
||||||
'free' => 1
|
'free' => 1,
|
||||||
|
'-exclude' => 1,
|
||||||
),
|
),
|
||||||
self::$publicLinkDB->allTags()
|
self::$publicLinkDB->allTags()
|
||||||
);
|
);
|
||||||
|
@ -295,7 +296,8 @@ public function testAllTags()
|
||||||
'html' => 1,
|
'html' => 1,
|
||||||
'w3c' => 1,
|
'w3c' => 1,
|
||||||
'css' => 1,
|
'css' => 1,
|
||||||
'Mercurial' => 1
|
'Mercurial' => 1,
|
||||||
|
'-exclude' => 1,
|
||||||
),
|
),
|
||||||
self::$privateLinkDB->allTags()
|
self::$privateLinkDB->allTags()
|
||||||
);
|
);
|
||||||
|
|
|
@ -254,4 +254,20 @@ public function testFilterFullTextMixed()
|
||||||
count(self::$linkFilter->filter(LinkFilter::$FILTER_TEXT, 'free software'))
|
count(self::$linkFilter->filter(LinkFilter::$FILTER_TEXT, 'free software'))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tag search with exclusion.
|
||||||
|
*/
|
||||||
|
public function testTagFilterWithExclusion()
|
||||||
|
{
|
||||||
|
$this->assertEquals(
|
||||||
|
1,
|
||||||
|
count(self::$linkFilter->filter(LinkFilter::$FILTER_TAG, 'gnu -free'))
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertEquals(
|
||||||
|
5,
|
||||||
|
count(self::$linkFilter->filter(LinkFilter::$FILTER_TAG, '-free'))
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,11 @@ class UpdaterTest extends PHPUnit_Framework_TestCase
|
||||||
*/
|
*/
|
||||||
private static $configFields;
|
private static $configFields;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string Path to test datastore.
|
||||||
|
*/
|
||||||
|
protected static $testDatastore = 'sandbox/datastore.php';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Executed before each test.
|
* Executed before each test.
|
||||||
*/
|
*/
|
||||||
|
@ -31,6 +36,7 @@ public function setUp()
|
||||||
'config' => array(
|
'config' => array(
|
||||||
'CONFIG_FILE' => 'tests/Updater/config.php',
|
'CONFIG_FILE' => 'tests/Updater/config.php',
|
||||||
'DATADIR' => 'tests/Updater',
|
'DATADIR' => 'tests/Updater',
|
||||||
|
'PAGECACHE' => 'sandbox/pagecache',
|
||||||
'config1' => 'config1data',
|
'config1' => 'config1data',
|
||||||
'config2' => 'config2data',
|
'config2' => 'config2data',
|
||||||
)
|
)
|
||||||
|
@ -224,4 +230,16 @@ public function testMergeDeprecatedConfigNoFile()
|
||||||
include self::$configFields['config']['CONFIG_FILE'];
|
include self::$configFields['config']['CONFIG_FILE'];
|
||||||
$this->assertEquals(self::$configFields['login'], $GLOBALS['login']);
|
$this->assertEquals(self::$configFields['login'], $GLOBALS['login']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testRenameDashTags()
|
||||||
|
{
|
||||||
|
$refDB = new ReferenceLinkDB();
|
||||||
|
$refDB->write(self::$testDatastore);
|
||||||
|
$linkDB = new LinkDB(self::$testDatastore, true, false);
|
||||||
|
$this->assertEmpty($linkDB->filter(LinkFilter::$FILTER_TAG, 'exclude'));
|
||||||
|
$updater = new Updater(array(), self::$configFields, $linkDB, true);
|
||||||
|
$updater->updateMethodRenameDashTags();
|
||||||
|
var_dump($linkDB->filter(LinkFilter::$FILTER_TAG, 'exclude'));
|
||||||
|
$this->assertNotEmpty($linkDB->filter(LinkFilter::$FILTER_TAG, 'exclude'));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@ function __construct()
|
||||||
'Richard Stallman and the Free Software Revolution',
|
'Richard Stallman and the Free Software Revolution',
|
||||||
0,
|
0,
|
||||||
'20150310_114633',
|
'20150310_114633',
|
||||||
'free gnu software stallman'
|
'free gnu software stallman -exclude'
|
||||||
);
|
);
|
||||||
|
|
||||||
$this->addLink(
|
$this->addLink(
|
||||||
|
|
Loading…
Reference in a new issue