From 9ccca40189652e529732683abcdf54fcf775c9ec Mon Sep 17 00:00:00 2001
From: ArthurHoaro <arthur@hoa.ro>
Date: Tue, 10 May 2016 23:18:04 +0200
Subject: Hashtag system

  * Hashtag are auto-linked with a filter search
  * Supports unicode
  * Compatible with markdown (excluded in code blocks)
---
 tests/LinkDBTest.php            |  4 +-
 tests/LinkFilterTest.php        | 26 ++++++++++++
 tests/LinkUtilsTest.php         | 88 +++++++++++++++++++++++++++++++++++++++++
 tests/UtilsTest.php             | 37 -----------------
 tests/utils/ReferenceLinkDB.php | 14 +++----
 5 files changed, 124 insertions(+), 45 deletions(-)

(limited to 'tests')

diff --git a/tests/LinkDBTest.php b/tests/LinkDBTest.php
index 30ea4e01..0db81fd6 100644
--- a/tests/LinkDBTest.php
+++ b/tests/LinkDBTest.php
@@ -256,7 +256,7 @@ class LinkDBTest extends PHPUnit_Framework_TestCase
         $link = self::$publicLinkDB->getLinkFromUrl('http://mediagoblin.org/');
 
         $this->assertNotEquals(false, $link);
-        $this->assertEquals(
+        $this->assertContains(
             'A free software media publishing platform',
             $link['description']
         );
@@ -293,6 +293,7 @@ class LinkDBTest extends PHPUnit_Framework_TestCase
                 // The DB contains a link with `sTuff` and another one with `stuff` tag.
                 // They need to be grouped with the first case found (`sTuff`).
                 'sTuff' => 2,
+                'hashtag' => 2,
             ),
             self::$publicLinkDB->allTags()
         );
@@ -315,6 +316,7 @@ class LinkDBTest extends PHPUnit_Framework_TestCase
                 'sTuff' => 2,
                 '-exclude' => 1,
                 '.hidden' => 1,
+                'hashtag' => 2,
             ),
             self::$privateLinkDB->allTags()
         );
diff --git a/tests/LinkFilterTest.php b/tests/LinkFilterTest.php
index 1620bb78..7d45fc59 100644
--- a/tests/LinkFilterTest.php
+++ b/tests/LinkFilterTest.php
@@ -387,4 +387,30 @@ class LinkFilterTest extends PHPUnit_Framework_TestCase
             ))
         );
     }
+
+    /**
+     * Filter links by #hashtag.
+     */
+    public function testFilterByHashtag()
+    {
+        $hashtag = 'hashtag';
+        $this->assertEquals(
+            3,
+            count(self::$linkFilter->filter(
+                LinkFilter::$FILTER_TAG,
+                $hashtag
+            ))
+        );
+
+        $hashtag = 'private';
+        $this->assertEquals(
+            1,
+            count(self::$linkFilter->filter(
+                LinkFilter::$FILTER_TAG,
+                $hashtag,
+                false,
+                true
+            ))
+        );
+    }
 }
diff --git a/tests/LinkUtilsTest.php b/tests/LinkUtilsTest.php
index d1b022fd..7c0d4b0b 100644
--- a/tests/LinkUtilsTest.php
+++ b/tests/LinkUtilsTest.php
@@ -93,4 +93,92 @@ class LinkUtilsTest extends PHPUnit_Framework_TestCase
         $refDB = new ReferenceLinkDB();
         $this->assertEquals($refDB->countPrivateLinks(), count_private($refDB->getLinks()));
     }
+
+    /**
+     * Test text2clickable without a redirector being set.
+     */
+    public function testText2clickableWithoutRedirector()
+    {
+        $text = 'stuff http://hello.there/is=someone#here otherstuff';
+        $expectedText = 'stuff <a href="http://hello.there/is=someone#here">http://hello.there/is=someone#here</a> otherstuff';
+        $processedText = text2clickable($text, '');
+        $this->assertEquals($expectedText, $processedText);
+    }
+
+    /**
+     * Test text2clickable a redirector set.
+     */
+    public function testText2clickableWithRedirector()
+    {
+        $text = 'stuff http://hello.there/is=someone#here otherstuff';
+        $redirector = 'http://redirector.to';
+        $expectedText = 'stuff <a href="'.
+            $redirector .
+            urlencode('http://hello.there/is=someone#here') .
+            '">http://hello.there/is=someone#here</a> otherstuff';
+        $processedText = text2clickable($text, $redirector);
+        $this->assertEquals($expectedText, $processedText);
+    }
+
+    /**
+     * Test testSpace2nbsp.
+     */
+    public function testSpace2nbsp()
+    {
+        $text = '  Are you   thrilled  by flags   ?'. PHP_EOL .' Really?';
+        $expectedText = '&nbsp; Are you &nbsp; thrilled &nbsp;by flags &nbsp; ?'. PHP_EOL .'&nbsp;Really?';
+        $processedText = space2nbsp($text);
+        $this->assertEquals($expectedText, $processedText);
+    }
+
+    /**
+     * Test hashtags auto-link.
+     */
+    public function testHashtagAutolink()
+    {
+        $index = 'http://domain.tld/';
+        $rawDescription = '#hashtag\n
+            # nothashtag\n
+            test#nothashtag #hashtag \#nothashtag\n
+            test #hashtag #hashtag test #hashtag.test\n
+            #hashtag #hashtag-nothashtag #hashtag_hashtag\n
+            What is #ашок anyway?\n
+            カタカナ #カタカナ」カタカナ\n';
+        $autolinkedDescription = hashtag_autolink($rawDescription, $index);
+
+        $this->assertContains($this->getHashtagLink('hashtag', $index), $autolinkedDescription);
+        $this->assertNotContains(' #hashtag', $autolinkedDescription);
+        $this->assertNotContains('>#nothashtag', $autolinkedDescription);
+        $this->assertContains($this->getHashtagLink('ашок', $index), $autolinkedDescription);
+        $this->assertContains($this->getHashtagLink('カタカナ', $index), $autolinkedDescription);
+        $this->assertContains($this->getHashtagLink('hashtag_hashtag', $index), $autolinkedDescription);
+        $this->assertNotContains($this->getHashtagLink('hashtag-nothashtag', $index), $autolinkedDescription);
+    }
+
+    /**
+     * Test hashtags auto-link without index URL.
+     */
+    public function testHashtagAutolinkNoIndex()
+    {
+        $rawDescription = 'blabla #hashtag x#nothashtag';
+        $autolinkedDescription = hashtag_autolink($rawDescription);
+
+        $this->assertContains($this->getHashtagLink('hashtag'), $autolinkedDescription);
+        $this->assertNotContains(' #hashtag', $autolinkedDescription);
+        $this->assertNotContains('>#nothashtag', $autolinkedDescription);
+    }
+
+    /**
+     * Util function to build an hashtag link.
+     *
+     * @param string $hashtag Hashtag name.
+     * @param string $index   Index URL.
+     *
+     * @return string HTML hashtag link.
+     */
+    private function getHashtagLink($hashtag, $index = '')
+    {
+        $hashtagLink = '<a href="'. $index .'?addtag=$1" title="Hashtag $1">#$1</a>';
+        return str_replace('$1', $hashtag, $hashtagLink);
+    }
 }
diff --git a/tests/UtilsTest.php b/tests/UtilsTest.php
index 3073b5eb..6a7870c4 100644
--- a/tests/UtilsTest.php
+++ b/tests/UtilsTest.php
@@ -253,41 +253,4 @@ class UtilsTest extends PHPUnit_Framework_TestCase
             is_session_id_valid('c0ZqcWF3VFE2NmJBdm1HMVQ0ZHJ3UmZPbTFsNGhkNHI=')
         );
     }
-
-    /**
-     * Test text2clickable without a redirector being set.
-     */
-    public function testText2clickableWithoutRedirector()
-    {
-        $text = 'stuff http://hello.there/is=someone#here otherstuff';
-        $expectedText = 'stuff <a href="http://hello.there/is=someone#here">http://hello.there/is=someone#here</a> otherstuff';
-        $processedText = text2clickable($text, '');
-        $this->assertEquals($expectedText, $processedText);
-    }
-
-    /**
-     * Test text2clickable a redirector set.
-     */
-    public function testText2clickableWithRedirector()
-    {
-        $text = 'stuff http://hello.there/is=someone#here otherstuff';
-        $redirector = 'http://redirector.to';
-        $expectedText = 'stuff <a href="'.
-            $redirector .
-            urlencode('http://hello.there/is=someone#here') .
-            '">http://hello.there/is=someone#here</a> otherstuff';
-        $processedText = text2clickable($text, $redirector);
-        $this->assertEquals($expectedText, $processedText);
-    }
-
-    /**
-     * Test testSpace2nbsp.
-     */
-    public function testSpace2nbsp()
-    {
-        $text = '  Are you   thrilled  by flags   ?'. PHP_EOL .' Really?';
-        $expectedText = '&nbsp; Are you &nbsp; thrilled &nbsp;by flags &nbsp; ?'. PHP_EOL .'&nbsp;Really?';
-        $processedText = space2nbsp($text);
-        $this->assertEquals($expectedText, $processedText);
-    }
 }
diff --git a/tests/utils/ReferenceLinkDB.php b/tests/utils/ReferenceLinkDB.php
index 46165b4d..fe16baac 100644
--- a/tests/utils/ReferenceLinkDB.php
+++ b/tests/utils/ReferenceLinkDB.php
@@ -18,7 +18,7 @@ class ReferenceLinkDB
         $this->addLink(
             'Link title: @website',
             '?WDWyig',
-            'Stallman has a beard and is part of the Free Software Foundation (or not). Seriously, read this.',
+            'Stallman has a beard and is part of the Free Software Foundation (or not). Seriously, read this. #hashtag',
             0,
             '20150310_114651',
             'sTuff'
@@ -27,25 +27,25 @@ class ReferenceLinkDB
         $this->addLink(
             'Free as in Freedom 2.0 @website',
             'https://static.fsf.org/nosvn/faif-2.0.pdf',
-            'Richard Stallman and the Free Software Revolution. Read this.',
+            'Richard Stallman and the Free Software Revolution. Read this. #hashtag',
             0,
             '20150310_114633',
-            'free gnu software stallman -exclude stuff'
+            'free gnu software stallman -exclude stuff hashtag'
         );
 
         $this->addLink(
             'MediaGoblin',
             'http://mediagoblin.org/',
-            'A free software media publishing platform',
+            'A free software media publishing platform #hashtagOther',
             0,
             '20130614_184135',
-            'gnu media web .hidden'
+            'gnu media web .hidden hashtag'
         );
 
         $this->addLink(
             'w3c-markup-validator',
             'https://dvcs.w3.org/hg/markup-validator/summary',
-            'Mercurial repository for the W3C Validator',
+            'Mercurial repository for the W3C Validator #private',
             1,
             '20141125_084734',
             'css html w3c web Mercurial'
@@ -54,7 +54,7 @@ class ReferenceLinkDB
         $this->addLink(
             'UserFriendly - Web Designer',
             'http://ars.userfriendly.org/cartoons/?id=20121206',
-            'Naming conventions...',
+            'Naming conventions... #private',
             0,
             '20121206_142300',
             'dev cartoon web'
-- 
cgit v1.2.3