diff options
-rw-r--r-- | application/LinkDB.php | 2 | ||||
-rw-r--r-- | application/LinkFilter.php | 33 | ||||
-rw-r--r-- | application/LinkUtils.php | 75 | ||||
-rw-r--r-- | application/Utils.php | 53 | ||||
-rw-r--r-- | plugins/markdown/markdown.php | 41 | ||||
-rw-r--r-- | tests/LinkDBTest.php | 4 | ||||
-rw-r--r-- | tests/LinkFilterTest.php | 26 | ||||
-rw-r--r-- | tests/LinkUtilsTest.php | 88 | ||||
-rw-r--r-- | tests/UtilsTest.php | 37 | ||||
-rw-r--r-- | tests/utils/ReferenceLinkDB.php | 14 |
10 files changed, 270 insertions, 103 deletions
diff --git a/application/LinkDB.php b/application/LinkDB.php index b1072e07..929a6b0f 100644 --- a/application/LinkDB.php +++ b/application/LinkDB.php | |||
@@ -409,7 +409,7 @@ You use the community supported version of the original Shaarli project, by Seba | |||
409 | $searchterm = !empty($filterRequest['searchterm']) ? escape($filterRequest['searchterm']) : ''; | 409 | $searchterm = !empty($filterRequest['searchterm']) ? escape($filterRequest['searchterm']) : ''; |
410 | 410 | ||
411 | // Search tags + fullsearch. | 411 | // Search tags + fullsearch. |
412 | if (empty($type) && ! empty($searchtags) && ! empty($searchterm)) { | 412 | if (! empty($searchtags) && ! empty($searchterm)) { |
413 | $type = LinkFilter::$FILTER_TAG | LinkFilter::$FILTER_TEXT; | 413 | $type = LinkFilter::$FILTER_TAG | LinkFilter::$FILTER_TEXT; |
414 | $request = array($searchtags, $searchterm); | 414 | $request = array($searchtags, $searchterm); |
415 | } | 415 | } |
diff --git a/application/LinkFilter.php b/application/LinkFilter.php index e693b284..d4fe28df 100644 --- a/application/LinkFilter.php +++ b/application/LinkFilter.php | |||
@@ -28,6 +28,11 @@ class LinkFilter | |||
28 | public static $FILTER_DAY = 'FILTER_DAY'; | 28 | public static $FILTER_DAY = 'FILTER_DAY'; |
29 | 29 | ||
30 | /** | 30 | /** |
31 | * @var string Allowed characters for hashtags (regex syntax). | ||
32 | */ | ||
33 | public static $HASHTAG_CHARS = '\p{Pc}\p{N}\p{L}\p{Mn}'; | ||
34 | |||
35 | /** | ||
31 | * @var array all available links. | 36 | * @var array all available links. |
32 | */ | 37 | */ |
33 | private $links; | 38 | private $links; |
@@ -263,8 +268,10 @@ class LinkFilter | |||
263 | for ($i = 0 ; $i < count($searchtags) && $found; $i++) { | 268 | for ($i = 0 ; $i < count($searchtags) && $found; $i++) { |
264 | // Exclusive search, quit if tag found. | 269 | // Exclusive search, quit if tag found. |
265 | // Or, tag not found in the link, quit. | 270 | // Or, tag not found in the link, quit. |
266 | if (($searchtags[$i][0] == '-' && in_array(substr($searchtags[$i], 1), $linktags)) | 271 | if (($searchtags[$i][0] == '-' |
267 | || ($searchtags[$i][0] != '-') && ! in_array($searchtags[$i], $linktags) | 272 | && $this->searchTagAndHashTag(substr($searchtags[$i], 1), $linktags, $link['description'])) |
273 | || ($searchtags[$i][0] != '-') | ||
274 | && ! $this->searchTagAndHashTag($searchtags[$i], $linktags, $link['description']) | ||
268 | ) { | 275 | ) { |
269 | $found = false; | 276 | $found = false; |
270 | } | 277 | } |
@@ -307,6 +314,28 @@ class LinkFilter | |||
307 | } | 314 | } |
308 | 315 | ||
309 | /** | 316 | /** |
317 | * Check if a tag is found in the taglist, or as an hashtag in the link description. | ||
318 | * | ||
319 | * @param string $tag Tag to search. | ||
320 | * @param array $taglist List of tags for the current link. | ||
321 | * @param string $description Link description. | ||
322 | * | ||
323 | * @return bool True if found, false otherwise. | ||
324 | */ | ||
325 | protected function searchTagAndHashTag($tag, $taglist, $description) | ||
326 | { | ||
327 | if (in_array($tag, $taglist)) { | ||
328 | return true; | ||
329 | } | ||
330 | |||
331 | if (preg_match('/(^| )#'. $tag .'([^'. self::$HASHTAG_CHARS .']|$)/mui', $description) > 0) { | ||
332 | return true; | ||
333 | } | ||
334 | |||
335 | return false; | ||
336 | } | ||
337 | |||
338 | /** | ||
310 | * Convert a list of tags (str) to an array. Also | 339 | * Convert a list of tags (str) to an array. Also |
311 | * - handle case sensitivity. | 340 | * - handle case sensitivity. |
312 | * - accepts spaces commas as separator. | 341 | * - accepts spaces commas as separator. |
diff --git a/application/LinkUtils.php b/application/LinkUtils.php index da04ca97..eeca631f 100644 --- a/application/LinkUtils.php +++ b/application/LinkUtils.php | |||
@@ -91,5 +91,80 @@ function count_private($links) | |||
91 | foreach ($links as $link) { | 91 | foreach ($links as $link) { |
92 | $cpt = $link['private'] == true ? $cpt + 1 : $cpt; | 92 | $cpt = $link['private'] == true ? $cpt + 1 : $cpt; |
93 | } | 93 | } |
94 | |||
94 | return $cpt; | 95 | return $cpt; |
95 | } | 96 | } |
97 | |||
98 | /** | ||
99 | * In a string, converts URLs to clickable links. | ||
100 | * | ||
101 | * @param string $text input string. | ||
102 | * @param string $redirector if a redirector is set, use it to gerenate links. | ||
103 | * | ||
104 | * @return string returns $text with all links converted to HTML links. | ||
105 | * | ||
106 | * @see Function inspired from http://www.php.net/manual/en/function.preg-replace.php#85722 | ||
107 | */ | ||
108 | function text2clickable($text, $redirector = '') | ||
109 | { | ||
110 | $regex = '!(((?:https?|ftp|file)://|apt:|magnet:)\S+[[:alnum:]]/?)!si'; | ||
111 | |||
112 | if (empty($redirector)) { | ||
113 | return preg_replace($regex, '<a href="$1">$1</a>', $text); | ||
114 | } | ||
115 | // Redirector is set, urlencode the final URL. | ||
116 | return preg_replace_callback( | ||
117 | $regex, | ||
118 | function ($matches) use ($redirector) { | ||
119 | return '<a href="' . $redirector . urlencode($matches[1]) .'">'. $matches[1] .'</a>'; | ||
120 | }, | ||
121 | $text | ||
122 | ); | ||
123 | } | ||
124 | |||
125 | /** | ||
126 | * Auto-link hashtags. | ||
127 | * | ||
128 | * @param string $description Given description. | ||
129 | * @param string $indexUrl Root URL. | ||
130 | * | ||
131 | * @return string Description with auto-linked hashtags. | ||
132 | */ | ||
133 | function hashtag_autolink($description, $indexUrl = '') | ||
134 | { | ||
135 | /* | ||
136 | * To support unicode: http://stackoverflow.com/a/35498078/1484919 | ||
137 | * \p{Pc} - to match underscore | ||
138 | * \p{N} - numeric character in any script | ||
139 | * \p{L} - letter from any language | ||
140 | * \p{Mn} - any non marking space (accents, umlauts, etc) | ||
141 | */ | ||
142 | $regex = '/(^|\s)#([\p{Pc}\p{N}\p{L}\p{Mn}]+)/mui'; | ||
143 | $replacement = '$1<a href="'. $indexUrl .'?addtag=$2" title="Hashtag $2">#$2</a>'; | ||
144 | return preg_replace($regex, $replacement, $description); | ||
145 | } | ||
146 | |||
147 | /** | ||
148 | * This function inserts where relevant so that multiple spaces are properly displayed in HTML | ||
149 | * even in the absence of <pre> (This is used in description to keep text formatting). | ||
150 | * | ||
151 | * @param string $text input text. | ||
152 | * | ||
153 | * @return string formatted text. | ||
154 | */ | ||
155 | function space2nbsp($text) | ||
156 | { | ||
157 | return preg_replace('/(^| ) /m', '$1 ', $text); | ||
158 | } | ||
159 | |||
160 | /** | ||
161 | * Format Shaarli's description | ||
162 | * | ||
163 | * @param string $description shaare's description. | ||
164 | * @param string $redirector if a redirector is set, use it to gerenate links. | ||
165 | * | ||
166 | * @return string formatted description. | ||
167 | */ | ||
168 | function format_description($description, $redirector = '', $indexUrl = '') { | ||
169 | return nl2br(space2nbsp(hashtag_autolink(text2clickable($description, $redirector), $indexUrl))); | ||
170 | } | ||
diff --git a/application/Utils.php b/application/Utils.php index 9a8ca6d1..7d7eaffd 100644 --- a/application/Utils.php +++ b/application/Utils.php | |||
@@ -198,59 +198,6 @@ function is_session_id_valid($sessionId) | |||
198 | } | 198 | } |
199 | 199 | ||
200 | /** | 200 | /** |
201 | * In a string, converts URLs to clickable links. | ||
202 | * | ||
203 | * @param string $text input string. | ||
204 | * @param string $redirector if a redirector is set, use it to gerenate links. | ||
205 | * | ||
206 | * @return string returns $text with all links converted to HTML links. | ||
207 | * | ||
208 | * @see Function inspired from http://www.php.net/manual/en/function.preg-replace.php#85722 | ||
209 | */ | ||
210 | function text2clickable($text, $redirector) | ||
211 | { | ||
212 | $regex = '!(((?:https?|ftp|file)://|apt:|magnet:)\S+[[:alnum:]]/?)!si'; | ||
213 | |||
214 | if (empty($redirector)) { | ||
215 | return preg_replace($regex, '<a href="$1">$1</a>', $text); | ||
216 | } | ||
217 | // Redirector is set, urlencode the final URL. | ||
218 | return preg_replace_callback( | ||
219 | $regex, | ||
220 | function ($matches) use ($redirector) { | ||
221 | return '<a href="' . $redirector . urlencode($matches[1]) .'">'. $matches[1] .'</a>'; | ||
222 | }, | ||
223 | $text | ||
224 | ); | ||
225 | } | ||
226 | |||
227 | /** | ||
228 | * This function inserts where relevant so that multiple spaces are properly displayed in HTML | ||
229 | * even in the absence of <pre> (This is used in description to keep text formatting). | ||
230 | * | ||
231 | * @param string $text input text. | ||
232 | * | ||
233 | * @return string formatted text. | ||
234 | */ | ||
235 | function space2nbsp($text) | ||
236 | { | ||
237 | return preg_replace('/(^| ) /m', '$1 ', $text); | ||
238 | } | ||
239 | |||
240 | /** | ||
241 | * Format Shaarli's description | ||
242 | * TODO: Move me to ApplicationUtils when it's ready. | ||
243 | * | ||
244 | * @param string $description shaare's description. | ||
245 | * @param string $redirector if a redirector is set, use it to gerenate links. | ||
246 | * | ||
247 | * @return string formatted description. | ||
248 | */ | ||
249 | function format_description($description, $redirector = false) { | ||
250 | return nl2br(space2nbsp(text2clickable($description, $redirector))); | ||
251 | } | ||
252 | |||
253 | /** | ||
254 | * Sniff browser language to set the locale automatically. | 201 | * Sniff browser language to set the locale automatically. |
255 | * Note that is may not work on your server if the corresponding locale is not installed. | 202 | * Note that is may not work on your server if the corresponding locale is not installed. |
256 | * | 203 | * |
diff --git a/plugins/markdown/markdown.php b/plugins/markdown/markdown.php index 5f56ecc2..6b1c1d44 100644 --- a/plugins/markdown/markdown.php +++ b/plugins/markdown/markdown.php | |||
@@ -151,7 +151,44 @@ function hook_markdown_render_editlink($data) | |||
151 | */ | 151 | */ |
152 | function reverse_text2clickable($description) | 152 | function reverse_text2clickable($description) |
153 | { | 153 | { |
154 | return preg_replace('!<a +href="([^ ]*)">[^ ]+</a>!m', '$1', $description); | 154 | $descriptionLines = explode(PHP_EOL, $description); |
155 | $descriptionOut = ''; | ||
156 | $codeBlockOn = false; | ||
157 | $lineCount = 0; | ||
158 | |||
159 | foreach ($descriptionLines as $descriptionLine) { | ||
160 | // Detect line of code | ||
161 | $codeLineOn = preg_match('/^ /', $descriptionLine) > 0; | ||
162 | // Detect and toggle block of code | ||
163 | if (!$codeBlockOn) { | ||
164 | $codeBlockOn = preg_match('/^```/', $descriptionLine) > 0; | ||
165 | } | ||
166 | elseif (preg_match('/^```/', $descriptionLine) > 0) { | ||
167 | $codeBlockOn = false; | ||
168 | } | ||
169 | |||
170 | $hashtagTitle = ' title="Hashtag [^"]+"'; | ||
171 | // Reverse `inline code` hashtags. | ||
172 | $descriptionLine = preg_replace( | ||
173 | '!(`[^`\n]*)<a href="[^ ]*"'. $hashtagTitle .'>([^<]+)</a>([^`\n]*`)!m', | ||
174 | '$1$2$3', | ||
175 | $descriptionLine | ||
176 | ); | ||
177 | |||
178 | // Reverse hashtag links if we're in a code block. | ||
179 | $hashtagFilter = ($codeBlockOn || $codeLineOn) ? $hashtagTitle : ''; | ||
180 | $descriptionLine = preg_replace( | ||
181 | '!<a href="[^ ]*"'. $hashtagFilter .'>([^<]+)</a>!m', | ||
182 | '$1', | ||
183 | $descriptionLine | ||
184 | ); | ||
185 | |||
186 | $descriptionOut .= $descriptionLine; | ||
187 | if ($lineCount++ < count($descriptionLines) - 1) { | ||
188 | $descriptionOut .= PHP_EOL; | ||
189 | } | ||
190 | } | ||
191 | return $descriptionOut; | ||
155 | } | 192 | } |
156 | 193 | ||
157 | /** | 194 | /** |
@@ -226,9 +263,9 @@ function process_markdown($description) | |||
226 | $parsedown = new Parsedown(); | 263 | $parsedown = new Parsedown(); |
227 | 264 | ||
228 | $processedDescription = $description; | 265 | $processedDescription = $description; |
229 | $processedDescription = reverse_text2clickable($processedDescription); | ||
230 | $processedDescription = reverse_nl2br($processedDescription); | 266 | $processedDescription = reverse_nl2br($processedDescription); |
231 | $processedDescription = reverse_space2nbsp($processedDescription); | 267 | $processedDescription = reverse_space2nbsp($processedDescription); |
268 | $processedDescription = reverse_text2clickable($processedDescription); | ||
232 | $processedDescription = unescape($processedDescription); | 269 | $processedDescription = unescape($processedDescription); |
233 | $processedDescription = $parsedown | 270 | $processedDescription = $parsedown |
234 | ->setMarkupEscaped(false) | 271 | ->setMarkupEscaped(false) |
diff --git a/tests/LinkDBTest.php b/tests/LinkDBTest.php index 9c64188f..46956f20 100644 --- a/tests/LinkDBTest.php +++ b/tests/LinkDBTest.php | |||
@@ -256,7 +256,7 @@ class LinkDBTest extends PHPUnit_Framework_TestCase | |||
256 | $link = self::$publicLinkDB->getLinkFromUrl('http://mediagoblin.org/'); | 256 | $link = self::$publicLinkDB->getLinkFromUrl('http://mediagoblin.org/'); |
257 | 257 | ||
258 | $this->assertNotEquals(false, $link); | 258 | $this->assertNotEquals(false, $link); |
259 | $this->assertEquals( | 259 | $this->assertContains( |
260 | 'A free software media publishing platform', | 260 | 'A free software media publishing platform', |
261 | $link['description'] | 261 | $link['description'] |
262 | ); | 262 | ); |
@@ -293,6 +293,7 @@ class LinkDBTest extends PHPUnit_Framework_TestCase | |||
293 | // The DB contains a link with `sTuff` and another one with `stuff` tag. | 293 | // The DB contains a link with `sTuff` and another one with `stuff` tag. |
294 | // They need to be grouped with the first case found (`sTuff`). | 294 | // They need to be grouped with the first case found (`sTuff`). |
295 | 'sTuff' => 2, | 295 | 'sTuff' => 2, |
296 | 'hashtag' => 2, | ||
296 | ), | 297 | ), |
297 | self::$publicLinkDB->allTags() | 298 | self::$publicLinkDB->allTags() |
298 | ); | 299 | ); |
@@ -315,6 +316,7 @@ class LinkDBTest extends PHPUnit_Framework_TestCase | |||
315 | 'sTuff' => 2, | 316 | 'sTuff' => 2, |
316 | '-exclude' => 1, | 317 | '-exclude' => 1, |
317 | '.hidden' => 1, | 318 | '.hidden' => 1, |
319 | 'hashtag' => 2, | ||
318 | ), | 320 | ), |
319 | self::$privateLinkDB->allTags() | 321 | self::$privateLinkDB->allTags() |
320 | ); | 322 | ); |
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 | |||
387 | )) | 387 | )) |
388 | ); | 388 | ); |
389 | } | 389 | } |
390 | |||
391 | /** | ||
392 | * Filter links by #hashtag. | ||
393 | */ | ||
394 | public function testFilterByHashtag() | ||
395 | { | ||
396 | $hashtag = 'hashtag'; | ||
397 | $this->assertEquals( | ||
398 | 3, | ||
399 | count(self::$linkFilter->filter( | ||
400 | LinkFilter::$FILTER_TAG, | ||
401 | $hashtag | ||
402 | )) | ||
403 | ); | ||
404 | |||
405 | $hashtag = 'private'; | ||
406 | $this->assertEquals( | ||
407 | 1, | ||
408 | count(self::$linkFilter->filter( | ||
409 | LinkFilter::$FILTER_TAG, | ||
410 | $hashtag, | ||
411 | false, | ||
412 | true | ||
413 | )) | ||
414 | ); | ||
415 | } | ||
390 | } | 416 | } |
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 | |||
93 | $refDB = new ReferenceLinkDB(); | 93 | $refDB = new ReferenceLinkDB(); |
94 | $this->assertEquals($refDB->countPrivateLinks(), count_private($refDB->getLinks())); | 94 | $this->assertEquals($refDB->countPrivateLinks(), count_private($refDB->getLinks())); |
95 | } | 95 | } |
96 | |||
97 | /** | ||
98 | * Test text2clickable without a redirector being set. | ||
99 | */ | ||
100 | public function testText2clickableWithoutRedirector() | ||
101 | { | ||
102 | $text = 'stuff http://hello.there/is=someone#here otherstuff'; | ||
103 | $expectedText = 'stuff <a href="http://hello.there/is=someone#here">http://hello.there/is=someone#here</a> otherstuff'; | ||
104 | $processedText = text2clickable($text, ''); | ||
105 | $this->assertEquals($expectedText, $processedText); | ||
106 | } | ||
107 | |||
108 | /** | ||
109 | * Test text2clickable a redirector set. | ||
110 | */ | ||
111 | public function testText2clickableWithRedirector() | ||
112 | { | ||
113 | $text = 'stuff http://hello.there/is=someone#here otherstuff'; | ||
114 | $redirector = 'http://redirector.to'; | ||
115 | $expectedText = 'stuff <a href="'. | ||
116 | $redirector . | ||
117 | urlencode('http://hello.there/is=someone#here') . | ||
118 | '">http://hello.there/is=someone#here</a> otherstuff'; | ||
119 | $processedText = text2clickable($text, $redirector); | ||
120 | $this->assertEquals($expectedText, $processedText); | ||
121 | } | ||
122 | |||
123 | /** | ||
124 | * Test testSpace2nbsp. | ||
125 | */ | ||
126 | public function testSpace2nbsp() | ||
127 | { | ||
128 | $text = ' Are you thrilled by flags ?'. PHP_EOL .' Really?'; | ||
129 | $expectedText = ' Are you thrilled by flags ?'. PHP_EOL .' Really?'; | ||
130 | $processedText = space2nbsp($text); | ||
131 | $this->assertEquals($expectedText, $processedText); | ||
132 | } | ||
133 | |||
134 | /** | ||
135 | * Test hashtags auto-link. | ||
136 | */ | ||
137 | public function testHashtagAutolink() | ||
138 | { | ||
139 | $index = 'http://domain.tld/'; | ||
140 | $rawDescription = '#hashtag\n | ||
141 | # nothashtag\n | ||
142 | test#nothashtag #hashtag \#nothashtag\n | ||
143 | test #hashtag #hashtag test #hashtag.test\n | ||
144 | #hashtag #hashtag-nothashtag #hashtag_hashtag\n | ||
145 | What is #ашок anyway?\n | ||
146 | カタカナ #カタカナ」カタカナ\n'; | ||
147 | $autolinkedDescription = hashtag_autolink($rawDescription, $index); | ||
148 | |||
149 | $this->assertContains($this->getHashtagLink('hashtag', $index), $autolinkedDescription); | ||
150 | $this->assertNotContains(' #hashtag', $autolinkedDescription); | ||
151 | $this->assertNotContains('>#nothashtag', $autolinkedDescription); | ||
152 | $this->assertContains($this->getHashtagLink('ашок', $index), $autolinkedDescription); | ||
153 | $this->assertContains($this->getHashtagLink('カタカナ', $index), $autolinkedDescription); | ||
154 | $this->assertContains($this->getHashtagLink('hashtag_hashtag', $index), $autolinkedDescription); | ||
155 | $this->assertNotContains($this->getHashtagLink('hashtag-nothashtag', $index), $autolinkedDescription); | ||
156 | } | ||
157 | |||
158 | /** | ||
159 | * Test hashtags auto-link without index URL. | ||
160 | */ | ||
161 | public function testHashtagAutolinkNoIndex() | ||
162 | { | ||
163 | $rawDescription = 'blabla #hashtag x#nothashtag'; | ||
164 | $autolinkedDescription = hashtag_autolink($rawDescription); | ||
165 | |||
166 | $this->assertContains($this->getHashtagLink('hashtag'), $autolinkedDescription); | ||
167 | $this->assertNotContains(' #hashtag', $autolinkedDescription); | ||
168 | $this->assertNotContains('>#nothashtag', $autolinkedDescription); | ||
169 | } | ||
170 | |||
171 | /** | ||
172 | * Util function to build an hashtag link. | ||
173 | * | ||
174 | * @param string $hashtag Hashtag name. | ||
175 | * @param string $index Index URL. | ||
176 | * | ||
177 | * @return string HTML hashtag link. | ||
178 | */ | ||
179 | private function getHashtagLink($hashtag, $index = '') | ||
180 | { | ||
181 | $hashtagLink = '<a href="'. $index .'?addtag=$1" title="Hashtag $1">#$1</a>'; | ||
182 | return str_replace('$1', $hashtag, $hashtagLink); | ||
183 | } | ||
96 | } | 184 | } |
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 | |||
253 | is_session_id_valid('c0ZqcWF3VFE2NmJBdm1HMVQ0ZHJ3UmZPbTFsNGhkNHI=') | 253 | is_session_id_valid('c0ZqcWF3VFE2NmJBdm1HMVQ0ZHJ3UmZPbTFsNGhkNHI=') |
254 | ); | 254 | ); |
255 | } | 255 | } |
256 | |||
257 | /** | ||
258 | * Test text2clickable without a redirector being set. | ||
259 | */ | ||
260 | public function testText2clickableWithoutRedirector() | ||
261 | { | ||
262 | $text = 'stuff http://hello.there/is=someone#here otherstuff'; | ||
263 | $expectedText = 'stuff <a href="http://hello.there/is=someone#here">http://hello.there/is=someone#here</a> otherstuff'; | ||
264 | $processedText = text2clickable($text, ''); | ||
265 | $this->assertEquals($expectedText, $processedText); | ||
266 | } | ||
267 | |||
268 | /** | ||
269 | * Test text2clickable a redirector set. | ||
270 | */ | ||
271 | public function testText2clickableWithRedirector() | ||
272 | { | ||
273 | $text = 'stuff http://hello.there/is=someone#here otherstuff'; | ||
274 | $redirector = 'http://redirector.to'; | ||
275 | $expectedText = 'stuff <a href="'. | ||
276 | $redirector . | ||
277 | urlencode('http://hello.there/is=someone#here') . | ||
278 | '">http://hello.there/is=someone#here</a> otherstuff'; | ||
279 | $processedText = text2clickable($text, $redirector); | ||
280 | $this->assertEquals($expectedText, $processedText); | ||
281 | } | ||
282 | |||
283 | /** | ||
284 | * Test testSpace2nbsp. | ||
285 | */ | ||
286 | public function testSpace2nbsp() | ||
287 | { | ||
288 | $text = ' Are you thrilled by flags ?'. PHP_EOL .' Really?'; | ||
289 | $expectedText = ' Are you thrilled by flags ?'. PHP_EOL .' Really?'; | ||
290 | $processedText = space2nbsp($text); | ||
291 | $this->assertEquals($expectedText, $processedText); | ||
292 | } | ||
293 | } | 256 | } |
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 | |||
18 | $this->addLink( | 18 | $this->addLink( |
19 | 'Link title: @website', | 19 | 'Link title: @website', |
20 | '?WDWyig', | 20 | '?WDWyig', |
21 | 'Stallman has a beard and is part of the Free Software Foundation (or not). Seriously, read this.', | 21 | 'Stallman has a beard and is part of the Free Software Foundation (or not). Seriously, read this. #hashtag', |
22 | 0, | 22 | 0, |
23 | '20150310_114651', | 23 | '20150310_114651', |
24 | 'sTuff' | 24 | 'sTuff' |
@@ -27,25 +27,25 @@ class ReferenceLinkDB | |||
27 | $this->addLink( | 27 | $this->addLink( |
28 | 'Free as in Freedom 2.0 @website', | 28 | 'Free as in Freedom 2.0 @website', |
29 | 'https://static.fsf.org/nosvn/faif-2.0.pdf', | 29 | 'https://static.fsf.org/nosvn/faif-2.0.pdf', |
30 | 'Richard Stallman and the Free Software Revolution. Read this.', | 30 | 'Richard Stallman and the Free Software Revolution. Read this. #hashtag', |
31 | 0, | 31 | 0, |
32 | '20150310_114633', | 32 | '20150310_114633', |
33 | 'free gnu software stallman -exclude stuff' | 33 | 'free gnu software stallman -exclude stuff hashtag' |
34 | ); | 34 | ); |
35 | 35 | ||
36 | $this->addLink( | 36 | $this->addLink( |
37 | 'MediaGoblin', | 37 | 'MediaGoblin', |
38 | 'http://mediagoblin.org/', | 38 | 'http://mediagoblin.org/', |
39 | 'A free software media publishing platform', | 39 | 'A free software media publishing platform #hashtagOther', |
40 | 0, | 40 | 0, |
41 | '20130614_184135', | 41 | '20130614_184135', |
42 | 'gnu media web .hidden' | 42 | 'gnu media web .hidden hashtag' |
43 | ); | 43 | ); |
44 | 44 | ||
45 | $this->addLink( | 45 | $this->addLink( |
46 | 'w3c-markup-validator', | 46 | 'w3c-markup-validator', |
47 | 'https://dvcs.w3.org/hg/markup-validator/summary', | 47 | 'https://dvcs.w3.org/hg/markup-validator/summary', |
48 | 'Mercurial repository for the W3C Validator', | 48 | 'Mercurial repository for the W3C Validator #private', |
49 | 1, | 49 | 1, |
50 | '20141125_084734', | 50 | '20141125_084734', |
51 | 'css html w3c web Mercurial' | 51 | 'css html w3c web Mercurial' |
@@ -54,7 +54,7 @@ class ReferenceLinkDB | |||
54 | $this->addLink( | 54 | $this->addLink( |
55 | 'UserFriendly - Web Designer', | 55 | 'UserFriendly - Web Designer', |
56 | 'http://ars.userfriendly.org/cartoons/?id=20121206', | 56 | 'http://ars.userfriendly.org/cartoons/?id=20121206', |
57 | 'Naming conventions...', | 57 | 'Naming conventions... #private', |
58 | 0, | 58 | 0, |
59 | '20121206_142300', | 59 | '20121206_142300', |
60 | 'dev cartoon web' | 60 | 'dev cartoon web' |