diff options
-rw-r--r-- | application/LinkDB.php | 29 | ||||
-rw-r--r-- | tests/LinkDBTest.php | 100 |
2 files changed, 121 insertions, 8 deletions
diff --git a/application/LinkDB.php b/application/LinkDB.php index c1661d52..cd0f2967 100644 --- a/application/LinkDB.php +++ b/application/LinkDB.php | |||
@@ -436,15 +436,17 @@ You use the community supported version of the original Shaarli project, by Seba | |||
436 | 436 | ||
437 | /** | 437 | /** |
438 | * Returns the list tags appearing in the links with the given tags | 438 | * Returns the list tags appearing in the links with the given tags |
439 | * @param $filteringTags: tags selecting the links to consider | 439 | * |
440 | * @param $visibility: process only all/private/public links | 440 | * @param array $filteringTags tags selecting the links to consider |
441 | * @return: a tag=>linksCount array | 441 | * @param string $visibility process only all/private/public links |
442 | * | ||
443 | * @return array tag => linksCount | ||
442 | */ | 444 | */ |
443 | public function linksCountPerTag($filteringTags = [], $visibility = 'all') | 445 | public function linksCountPerTag($filteringTags = [], $visibility = 'all') |
444 | { | 446 | { |
445 | $links = empty($filteringTags) ? $this->links : $this->filterSearch(['searchtags' => $filteringTags], false, $visibility); | 447 | $links = $this->filterSearch(['searchtags' => $filteringTags], false, $visibility); |
446 | $tags = array(); | 448 | $tags = []; |
447 | $caseMapping = array(); | 449 | $caseMapping = []; |
448 | foreach ($links as $link) { | 450 | foreach ($links as $link) { |
449 | foreach (preg_split('/\s+/', $link['tags'], 0, PREG_SPLIT_NO_EMPTY) as $tag) { | 451 | foreach (preg_split('/\s+/', $link['tags'], 0, PREG_SPLIT_NO_EMPTY) as $tag) { |
450 | if (empty($tag)) { | 452 | if (empty($tag)) { |
@@ -458,8 +460,19 @@ You use the community supported version of the original Shaarli project, by Seba | |||
458 | $tags[$caseMapping[strtolower($tag)]]++; | 460 | $tags[$caseMapping[strtolower($tag)]]++; |
459 | } | 461 | } |
460 | } | 462 | } |
461 | // Sort tags by usage (most used tag first) | 463 | |
462 | arsort($tags); | 464 | /* |
465 | * Formerly used arsort(), which doesn't define the sort behaviour for equal values. | ||
466 | * Also, this function doesn't produce the same result between PHP 5.6 and 7. | ||
467 | * | ||
468 | * So we now use array_multisort() to sort tags by DESC occurrences, | ||
469 | * then ASC alphabetically for equal values. | ||
470 | * | ||
471 | * @see https://github.com/shaarli/Shaarli/issues/1142 | ||
472 | */ | ||
473 | $keys = array_keys($tags); | ||
474 | $tmpTags = array_combine($keys, $keys); | ||
475 | array_multisort($tags, SORT_DESC, $tmpTags, SORT_ASC, $tags); | ||
463 | return $tags; | 476 | return $tags; |
464 | } | 477 | } |
465 | 478 | ||
diff --git a/tests/LinkDBTest.php b/tests/LinkDBTest.php index 5b2f3667..3b980878 100644 --- a/tests/LinkDBTest.php +++ b/tests/LinkDBTest.php | |||
@@ -542,4 +542,104 @@ class LinkDBTest extends PHPUnit_Framework_TestCase | |||
542 | $this->assertEquals(3, count($res)); | 542 | $this->assertEquals(3, count($res)); |
543 | $this->assertNotContains('cartoon', $linkDB[4]['tags']); | 543 | $this->assertNotContains('cartoon', $linkDB[4]['tags']); |
544 | } | 544 | } |
545 | |||
546 | /** | ||
547 | * Test linksCountPerTag all tags without filter. | ||
548 | * Equal occurrences should be sorted alphabetically. | ||
549 | */ | ||
550 | public function testCountLinkPerTagAllNoFilter() | ||
551 | { | ||
552 | $expected = [ | ||
553 | 'web' => 4, | ||
554 | 'cartoon' => 3, | ||
555 | 'dev' => 2, | ||
556 | 'gnu' => 2, | ||
557 | 'hashtag' => 2, | ||
558 | 'sTuff' => 2, | ||
559 | '-exclude' => 1, | ||
560 | '.hidden' => 1, | ||
561 | 'Mercurial' => 1, | ||
562 | 'css' => 1, | ||
563 | 'free' => 1, | ||
564 | 'html' => 1, | ||
565 | 'media' => 1, | ||
566 | 'samba' => 1, | ||
567 | 'software' => 1, | ||
568 | 'stallman' => 1, | ||
569 | 'tag1' => 1, | ||
570 | 'tag2' => 1, | ||
571 | 'tag3' => 1, | ||
572 | 'tag4' => 1, | ||
573 | 'ut' => 1, | ||
574 | 'w3c' => 1, | ||
575 | ]; | ||
576 | $tags = self::$privateLinkDB->linksCountPerTag(); | ||
577 | |||
578 | $this->assertEquals($expected, $tags, var_export($tags, true)); | ||
579 | } | ||
580 | |||
581 | /** | ||
582 | * Test linksCountPerTag all tags with filter. | ||
583 | * Equal occurrences should be sorted alphabetically. | ||
584 | */ | ||
585 | public function testCountLinkPerTagAllWithFilter() | ||
586 | { | ||
587 | $expected = [ | ||
588 | 'gnu' => 2, | ||
589 | 'hashtag' => 2, | ||
590 | '-exclude' => 1, | ||
591 | '.hidden' => 1, | ||
592 | 'free' => 1, | ||
593 | 'media' => 1, | ||
594 | 'software' => 1, | ||
595 | 'stallman' => 1, | ||
596 | 'stuff' => 1, | ||
597 | 'web' => 1, | ||
598 | ]; | ||
599 | $tags = self::$privateLinkDB->linksCountPerTag(['gnu']); | ||
600 | |||
601 | $this->assertEquals($expected, $tags, var_export($tags, true)); | ||
602 | } | ||
603 | |||
604 | /** | ||
605 | * Test linksCountPerTag public tags with filter. | ||
606 | * Equal occurrences should be sorted alphabetically. | ||
607 | */ | ||
608 | public function testCountLinkPerTagPublicWithFilter() | ||
609 | { | ||
610 | $expected = [ | ||
611 | 'gnu' => 2, | ||
612 | 'hashtag' => 2, | ||
613 | '-exclude' => 1, | ||
614 | '.hidden' => 1, | ||
615 | 'free' => 1, | ||
616 | 'media' => 1, | ||
617 | 'software' => 1, | ||
618 | 'stallman' => 1, | ||
619 | 'stuff' => 1, | ||
620 | 'web' => 1, | ||
621 | ]; | ||
622 | $tags = self::$privateLinkDB->linksCountPerTag(['gnu'], 'public'); | ||
623 | |||
624 | $this->assertEquals($expected, $tags, var_export($tags, true)); | ||
625 | } | ||
626 | |||
627 | /** | ||
628 | * Test linksCountPerTag public tags with filter. | ||
629 | * Equal occurrences should be sorted alphabetically. | ||
630 | */ | ||
631 | public function testCountLinkPerTagPrivateWithFilter() | ||
632 | { | ||
633 | $expected = [ | ||
634 | 'cartoon' => 1, | ||
635 | 'dev' => 1, | ||
636 | 'tag1' => 1, | ||
637 | 'tag2' => 1, | ||
638 | 'tag3' => 1, | ||
639 | 'tag4' => 1, | ||
640 | ]; | ||
641 | $tags = self::$privateLinkDB->linksCountPerTag(['dev'], 'private'); | ||
642 | |||
643 | $this->assertEquals($expected, $tags, var_export($tags, true)); | ||
644 | } | ||
545 | } | 645 | } |