Merge pull request #1143 from ArthurHoaro/sort-equal-tags

Fix order of tags with the same number of occurrences
This commit is contained in:
ArthurHoaro 2018-06-04 18:34:50 +02:00 committed by GitHub
commit 17e45b2e9c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 121 additions and 8 deletions

View file

@ -436,15 +436,17 @@ public function filterSearch($filterRequest = array(), $casesensitive = false, $
/** /**
* Returns the list tags appearing in the links with the given tags * Returns the list tags appearing in the links with the given tags
* @param $filteringTags: tags selecting the links to consider *
* @param $visibility: process only all/private/public links * @param array $filteringTags tags selecting the links to consider
* @return: a tag=>linksCount array * @param string $visibility process only all/private/public links
*
* @return array tag => linksCount
*/ */
public function linksCountPerTag($filteringTags = [], $visibility = 'all') public function linksCountPerTag($filteringTags = [], $visibility = 'all')
{ {
$links = empty($filteringTags) ? $this->links : $this->filterSearch(['searchtags' => $filteringTags], false, $visibility); $links = $this->filterSearch(['searchtags' => $filteringTags], false, $visibility);
$tags = array(); $tags = [];
$caseMapping = array(); $caseMapping = [];
foreach ($links as $link) { foreach ($links as $link) {
foreach (preg_split('/\s+/', $link['tags'], 0, PREG_SPLIT_NO_EMPTY) as $tag) { foreach (preg_split('/\s+/', $link['tags'], 0, PREG_SPLIT_NO_EMPTY) as $tag) {
if (empty($tag)) { if (empty($tag)) {
@ -458,8 +460,19 @@ public function linksCountPerTag($filteringTags = [], $visibility = 'all')
$tags[$caseMapping[strtolower($tag)]]++; $tags[$caseMapping[strtolower($tag)]]++;
} }
} }
// Sort tags by usage (most used tag first)
arsort($tags); /*
* Formerly used arsort(), which doesn't define the sort behaviour for equal values.
* Also, this function doesn't produce the same result between PHP 5.6 and 7.
*
* So we now use array_multisort() to sort tags by DESC occurrences,
* then ASC alphabetically for equal values.
*
* @see https://github.com/shaarli/Shaarli/issues/1142
*/
$keys = array_keys($tags);
$tmpTags = array_combine($keys, $keys);
array_multisort($tags, SORT_DESC, $tmpTags, SORT_ASC, $tags);
return $tags; return $tags;
} }

View file

@ -542,4 +542,104 @@ public function testDeleteTag()
$this->assertEquals(3, count($res)); $this->assertEquals(3, count($res));
$this->assertNotContains('cartoon', $linkDB[4]['tags']); $this->assertNotContains('cartoon', $linkDB[4]['tags']);
} }
/**
* Test linksCountPerTag all tags without filter.
* Equal occurrences should be sorted alphabetically.
*/
public function testCountLinkPerTagAllNoFilter()
{
$expected = [
'web' => 4,
'cartoon' => 3,
'dev' => 2,
'gnu' => 2,
'hashtag' => 2,
'sTuff' => 2,
'-exclude' => 1,
'.hidden' => 1,
'Mercurial' => 1,
'css' => 1,
'free' => 1,
'html' => 1,
'media' => 1,
'samba' => 1,
'software' => 1,
'stallman' => 1,
'tag1' => 1,
'tag2' => 1,
'tag3' => 1,
'tag4' => 1,
'ut' => 1,
'w3c' => 1,
];
$tags = self::$privateLinkDB->linksCountPerTag();
$this->assertEquals($expected, $tags, var_export($tags, true));
}
/**
* Test linksCountPerTag all tags with filter.
* Equal occurrences should be sorted alphabetically.
*/
public function testCountLinkPerTagAllWithFilter()
{
$expected = [
'gnu' => 2,
'hashtag' => 2,
'-exclude' => 1,
'.hidden' => 1,
'free' => 1,
'media' => 1,
'software' => 1,
'stallman' => 1,
'stuff' => 1,
'web' => 1,
];
$tags = self::$privateLinkDB->linksCountPerTag(['gnu']);
$this->assertEquals($expected, $tags, var_export($tags, true));
}
/**
* Test linksCountPerTag public tags with filter.
* Equal occurrences should be sorted alphabetically.
*/
public function testCountLinkPerTagPublicWithFilter()
{
$expected = [
'gnu' => 2,
'hashtag' => 2,
'-exclude' => 1,
'.hidden' => 1,
'free' => 1,
'media' => 1,
'software' => 1,
'stallman' => 1,
'stuff' => 1,
'web' => 1,
];
$tags = self::$privateLinkDB->linksCountPerTag(['gnu'], 'public');
$this->assertEquals($expected, $tags, var_export($tags, true));
}
/**
* Test linksCountPerTag public tags with filter.
* Equal occurrences should be sorted alphabetically.
*/
public function testCountLinkPerTagPrivateWithFilter()
{
$expected = [
'cartoon' => 1,
'dev' => 1,
'tag1' => 1,
'tag2' => 1,
'tag3' => 1,
'tag4' => 1,
];
$tags = self::$privateLinkDB->linksCountPerTag(['dev'], 'private');
$this->assertEquals($expected, $tags, var_export($tags, true));
}
} }