diff options
author | ArthurHoaro <arthur@hoa.ro> | 2019-07-06 12:34:02 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-07-06 12:34:02 +0200 |
commit | c03c90a13e1356ca9cf40cc664547c49305cb24b (patch) | |
tree | bf7ce75b0c93a95d8e7a805b1ebfbe8d90a9565a | |
parent | 5d8a958d5d139337546bb3f4091a6ef7592ea752 (diff) | |
parent | 6a4872520cbbc012b5a8358cd50c78844afe8d07 (diff) | |
download | Shaarli-c03c90a13e1356ca9cf40cc664547c49305cb24b.tar.gz Shaarli-c03c90a13e1356ca9cf40cc664547c49305cb24b.tar.zst Shaarli-c03c90a13e1356ca9cf40cc664547c49305cb24b.zip |
Merge pull request #1313 from ArthurHoaro/feature/desc-retrieval
Automatically retrieve description for new bookmarks
-rw-r--r-- | application/bookmark/LinkUtils.php | 85 | ||||
-rw-r--r-- | application/config/ConfigManager.php | 1 | ||||
-rw-r--r-- | doc/md/Shaarli-configuration.md | 2 | ||||
-rw-r--r-- | inc/languages/fr/LC_MESSAGES/shaarli.po | 128 | ||||
-rw-r--r-- | index.php | 5 | ||||
-rw-r--r-- | tests/bookmark/LinkUtilsTest.php | 204 | ||||
-rw-r--r-- | tpl/default/configure.html | 16 | ||||
-rw-r--r-- | tpl/vintage/configure.html | 8 |
8 files changed, 374 insertions, 75 deletions
diff --git a/application/bookmark/LinkUtils.php b/application/bookmark/LinkUtils.php index 35a5b290..77eb2d95 100644 --- a/application/bookmark/LinkUtils.php +++ b/application/bookmark/LinkUtils.php | |||
@@ -7,13 +7,25 @@ use Shaarli\Bookmark\LinkDB; | |||
7 | * | 7 | * |
8 | * @param string $charset to extract from the downloaded page (reference) | 8 | * @param string $charset to extract from the downloaded page (reference) |
9 | * @param string $title to extract from the downloaded page (reference) | 9 | * @param string $title to extract from the downloaded page (reference) |
10 | * @param string $description to extract from the downloaded page (reference) | ||
11 | * @param string $keywords to extract from the downloaded page (reference) | ||
12 | * @param bool $retrieveDescription Automatically tries to retrieve description and keywords from HTML content | ||
10 | * @param string $curlGetInfo Optionally overrides curl_getinfo function | 13 | * @param string $curlGetInfo Optionally overrides curl_getinfo function |
11 | * | 14 | * |
12 | * @return Closure | 15 | * @return Closure |
13 | */ | 16 | */ |
14 | function get_curl_download_callback(&$charset, &$title, $curlGetInfo = 'curl_getinfo') | 17 | function get_curl_download_callback( |
15 | { | 18 | &$charset, |
19 | &$title, | ||
20 | &$description, | ||
21 | &$keywords, | ||
22 | $retrieveDescription, | ||
23 | $curlGetInfo = 'curl_getinfo' | ||
24 | ) { | ||
16 | $isRedirected = false; | 25 | $isRedirected = false; |
26 | $currentChunk = 0; | ||
27 | $foundChunk = null; | ||
28 | |||
17 | /** | 29 | /** |
18 | * cURL callback function for CURLOPT_WRITEFUNCTION (called during the download). | 30 | * cURL callback function for CURLOPT_WRITEFUNCTION (called during the download). |
19 | * | 31 | * |
@@ -25,7 +37,18 @@ function get_curl_download_callback(&$charset, &$title, $curlGetInfo = 'curl_get | |||
25 | * | 37 | * |
26 | * @return int|bool length of $data or false if we need to stop the download | 38 | * @return int|bool length of $data or false if we need to stop the download |
27 | */ | 39 | */ |
28 | return function (&$ch, $data) use ($curlGetInfo, &$charset, &$title, &$isRedirected) { | 40 | return function (&$ch, $data) use ( |
41 | $retrieveDescription, | ||
42 | $curlGetInfo, | ||
43 | &$charset, | ||
44 | &$title, | ||
45 | &$description, | ||
46 | &$keywords, | ||
47 | &$isRedirected, | ||
48 | &$currentChunk, | ||
49 | &$foundChunk | ||
50 | ) { | ||
51 | $currentChunk++; | ||
29 | $responseCode = $curlGetInfo($ch, CURLINFO_RESPONSE_CODE); | 52 | $responseCode = $curlGetInfo($ch, CURLINFO_RESPONSE_CODE); |
30 | if (!empty($responseCode) && in_array($responseCode, [301, 302])) { | 53 | if (!empty($responseCode) && in_array($responseCode, [301, 302])) { |
31 | $isRedirected = true; | 54 | $isRedirected = true; |
@@ -50,9 +73,34 @@ function get_curl_download_callback(&$charset, &$title, $curlGetInfo = 'curl_get | |||
50 | } | 73 | } |
51 | if (empty($title)) { | 74 | if (empty($title)) { |
52 | $title = html_extract_title($data); | 75 | $title = html_extract_title($data); |
76 | $foundChunk = ! empty($title) ? $currentChunk : $foundChunk; | ||
77 | } | ||
78 | if ($retrieveDescription && empty($description)) { | ||
79 | $description = html_extract_tag('description', $data); | ||
80 | $foundChunk = ! empty($description) ? $currentChunk : $foundChunk; | ||
53 | } | 81 | } |
82 | if ($retrieveDescription && empty($keywords)) { | ||
83 | $keywords = html_extract_tag('keywords', $data); | ||
84 | if (! empty($keywords)) { | ||
85 | $foundChunk = $currentChunk; | ||
86 | // Keywords use the format tag1, tag2 multiple words, tag | ||
87 | // So we format them to match Shaarli's separator and glue multiple words with '-' | ||
88 | $keywords = implode(' ', array_map(function($keyword) { | ||
89 | return implode('-', preg_split('/\s+/', trim($keyword))); | ||
90 | }, explode(',', $keywords))); | ||
91 | } | ||
92 | } | ||
93 | |||
54 | // We got everything we want, stop the download. | 94 | // We got everything we want, stop the download. |
55 | if (!empty($responseCode) && !empty($contentType) && !empty($charset) && !empty($title)) { | 95 | // If we already found either the title, description or keywords, |
96 | // it's highly unlikely that we'll found the other metas further than | ||
97 | // in the same chunk of data or the next one. So we also stop the download after that. | ||
98 | if ((!empty($responseCode) && !empty($contentType) && !empty($charset)) && $foundChunk !== null | ||
99 | && (! $retrieveDescription | ||
100 | || $foundChunk < $currentChunk | ||
101 | || (!empty($title) && !empty($description) && !empty($keywords)) | ||
102 | ) | ||
103 | ) { | ||
56 | return false; | 104 | return false; |
57 | } | 105 | } |
58 | 106 | ||
@@ -111,6 +159,35 @@ function html_extract_charset($html) | |||
111 | } | 159 | } |
112 | 160 | ||
113 | /** | 161 | /** |
162 | * Extract meta tag from HTML content in either: | ||
163 | * - OpenGraph: <meta property="og:[tag]" ...> | ||
164 | * - Meta tag: <meta name="[tag]" ...> | ||
165 | * | ||
166 | * @param string $tag Name of the tag to retrieve. | ||
167 | * @param string $html HTML content where to look for charset. | ||
168 | * | ||
169 | * @return bool|string Charset string if found, false otherwise. | ||
170 | */ | ||
171 | function html_extract_tag($tag, $html) | ||
172 | { | ||
173 | $propertiesKey = ['property', 'name', 'itemprop']; | ||
174 | $properties = implode('|', $propertiesKey); | ||
175 | // Try to retrieve OpenGraph image. | ||
176 | $ogRegex = '#<meta[^>]+(?:'. $properties .')=["\']?(?:og:)?'. $tag .'["\'\s][^>]*content=["\']?(.*?)["\'/>]#'; | ||
177 | // If the attributes are not in the order property => content (e.g. Github) | ||
178 | // New regex to keep this readable... more or less. | ||
179 | $ogRegexReverse = '#<meta[^>]+content=["\']([^"\']+)[^>]+(?:'. $properties .')=["\']?(?:og)?:'. $tag .'["\'\s/>]#'; | ||
180 | |||
181 | if (preg_match($ogRegex, $html, $matches) > 0 | ||
182 | || preg_match($ogRegexReverse, $html, $matches) > 0 | ||
183 | ) { | ||
184 | return $matches[1]; | ||
185 | } | ||
186 | |||
187 | return false; | ||
188 | } | ||
189 | |||
190 | /** | ||
114 | * Count private links in given linklist. | 191 | * Count private links in given linklist. |
115 | * | 192 | * |
116 | * @param array|Countable $links Linklist. | 193 | * @param array|Countable $links Linklist. |
diff --git a/application/config/ConfigManager.php b/application/config/ConfigManager.php index 30993928..c95e6800 100644 --- a/application/config/ConfigManager.php +++ b/application/config/ConfigManager.php | |||
@@ -365,6 +365,7 @@ class ConfigManager | |||
365 | $this->setEmpty('general.links_per_page', 20); | 365 | $this->setEmpty('general.links_per_page', 20); |
366 | $this->setEmpty('general.enabled_plugins', self::$DEFAULT_PLUGINS); | 366 | $this->setEmpty('general.enabled_plugins', self::$DEFAULT_PLUGINS); |
367 | $this->setEmpty('general.default_note_title', 'Note: '); | 367 | $this->setEmpty('general.default_note_title', 'Note: '); |
368 | $this->setEmpty('general.retrieve_description', false); | ||
368 | 369 | ||
369 | $this->setEmpty('updates.check_updates', false); | 370 | $this->setEmpty('updates.check_updates', false); |
370 | $this->setEmpty('updates.check_updates_branch', 'stable'); | 371 | $this->setEmpty('updates.check_updates_branch', 'stable'); |
diff --git a/doc/md/Shaarli-configuration.md b/doc/md/Shaarli-configuration.md index a931ab1e..664e36dd 100644 --- a/doc/md/Shaarli-configuration.md +++ b/doc/md/Shaarli-configuration.md | |||
@@ -56,6 +56,8 @@ _These settings should not be edited_ | |||
56 | - **timezone**: See [the list of supported timezones](http://php.net/manual/en/timezones.php). | 56 | - **timezone**: See [the list of supported timezones](http://php.net/manual/en/timezones.php). |
57 | - **enabled_plugins**: List of enabled plugins. | 57 | - **enabled_plugins**: List of enabled plugins. |
58 | - **default_note_title**: Default title of a new note. | 58 | - **default_note_title**: Default title of a new note. |
59 | - **retrieve_description** (boolean): If set to true, for every new links Shaarli will try | ||
60 | to retrieve the description and keywords from the HTML meta tags. | ||
59 | 61 | ||
60 | ### Security | 62 | ### Security |
61 | 63 | ||
diff --git a/inc/languages/fr/LC_MESSAGES/shaarli.po b/inc/languages/fr/LC_MESSAGES/shaarli.po index c2c73b29..611296f1 100644 --- a/inc/languages/fr/LC_MESSAGES/shaarli.po +++ b/inc/languages/fr/LC_MESSAGES/shaarli.po | |||
@@ -1,8 +1,8 @@ | |||
1 | msgid "" | 1 | msgid "" |
2 | msgstr "" | 2 | msgstr "" |
3 | "Project-Id-Version: Shaarli\n" | 3 | "Project-Id-Version: Shaarli\n" |
4 | "POT-Creation-Date: 2019-05-25 16:37+0200\n" | 4 | "POT-Creation-Date: 2019-07-06 12:14+0200\n" |
5 | "PO-Revision-Date: 2019-05-25 16:37+0200\n" | 5 | "PO-Revision-Date: 2019-07-06 12:17+0200\n" |
6 | "Last-Translator: \n" | 6 | "Last-Translator: \n" |
7 | "Language-Team: Shaarli\n" | 7 | "Language-Team: Shaarli\n" |
8 | "Language: fr_FR\n" | 8 | "Language: fr_FR\n" |
@@ -252,7 +252,7 @@ msgstr "404 Introuvable" | |||
252 | msgid "Couldn't retrieve updater class methods." | 252 | msgid "Couldn't retrieve updater class methods." |
253 | msgstr "Impossible de récupérer les méthodes de la classe Updater." | 253 | msgstr "Impossible de récupérer les méthodes de la classe Updater." |
254 | 254 | ||
255 | #: application/updater/Updater.php:526 index.php:1033 | 255 | #: application/updater/Updater.php:526 index.php:1034 |
256 | msgid "" | 256 | msgid "" |
257 | "You have enabled or changed thumbnails mode. <a href=\"?do=thumbs_update" | 257 | "You have enabled or changed thumbnails mode. <a href=\"?do=thumbs_update" |
258 | "\">Please synchronize them</a>." | 258 | "\">Please synchronize them</a>." |
@@ -337,8 +337,8 @@ msgid "You are not supposed to change a password on an Open Shaarli." | |||
337 | msgstr "" | 337 | msgstr "" |
338 | "Vous n'êtes pas censé modifier le mot de passe d'un Shaarli en mode ouvert." | 338 | "Vous n'êtes pas censé modifier le mot de passe d'un Shaarli en mode ouvert." |
339 | 339 | ||
340 | #: index.php:957 index.php:1007 index.php:1092 index.php:1122 index.php:1232 | 340 | #: index.php:957 index.php:1007 index.php:1094 index.php:1124 index.php:1234 |
341 | #: index.php:1279 | 341 | #: index.php:1281 |
342 | msgid "Wrong token." | 342 | msgid "Wrong token." |
343 | msgstr "Jeton invalide." | 343 | msgstr "Jeton invalide." |
344 | 344 | ||
@@ -356,64 +356,64 @@ msgstr "Votre mot de passe a été modifié" | |||
356 | msgid "Change password" | 356 | msgid "Change password" |
357 | msgstr "Modifier le mot de passe" | 357 | msgstr "Modifier le mot de passe" |
358 | 358 | ||
359 | #: index.php:1053 | 359 | #: index.php:1054 |
360 | msgid "Configuration was saved." | 360 | msgid "Configuration was saved." |
361 | msgstr "La configuration a été sauvegardée." | 361 | msgstr "La configuration a été sauvegardée." |
362 | 362 | ||
363 | #: index.php:1076 tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:24 | 363 | #: index.php:1078 tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:24 |
364 | msgid "Configure" | 364 | msgid "Configure" |
365 | msgstr "Configurer" | 365 | msgstr "Configurer" |
366 | 366 | ||
367 | #: index.php:1086 tmp/changetag.b91ef64efc3688266305ea9b42e5017e.rtpl.php:13 | 367 | #: index.php:1088 tmp/changetag.b91ef64efc3688266305ea9b42e5017e.rtpl.php:13 |
368 | #: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:36 | 368 | #: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:36 |
369 | msgid "Manage tags" | 369 | msgid "Manage tags" |
370 | msgstr "Gérer les tags" | 370 | msgstr "Gérer les tags" |
371 | 371 | ||
372 | #: index.php:1105 | 372 | #: index.php:1107 |
373 | #, php-format | 373 | #, php-format |
374 | msgid "The tag was removed from %d link." | 374 | msgid "The tag was removed from %d link." |
375 | msgid_plural "The tag was removed from %d links." | 375 | msgid_plural "The tag was removed from %d links." |
376 | msgstr[0] "Le tag a été supprimé de %d lien." | 376 | msgstr[0] "Le tag a été supprimé de %d lien." |
377 | msgstr[1] "Le tag a été supprimé de %d liens." | 377 | msgstr[1] "Le tag a été supprimé de %d liens." |
378 | 378 | ||
379 | #: index.php:1106 | 379 | #: index.php:1108 |
380 | #, php-format | 380 | #, php-format |
381 | msgid "The tag was renamed in %d link." | 381 | msgid "The tag was renamed in %d link." |
382 | msgid_plural "The tag was renamed in %d links." | 382 | msgid_plural "The tag was renamed in %d links." |
383 | msgstr[0] "Le tag a été renommé dans %d lien." | 383 | msgstr[0] "Le tag a été renommé dans %d lien." |
384 | msgstr[1] "Le tag a été renommé dans %d liens." | 384 | msgstr[1] "Le tag a été renommé dans %d liens." |
385 | 385 | ||
386 | #: index.php:1113 tmp/addlink.b91ef64efc3688266305ea9b42e5017e.rtpl.php:13 | 386 | #: index.php:1115 tmp/addlink.b91ef64efc3688266305ea9b42e5017e.rtpl.php:13 |
387 | msgid "Shaare a new link" | 387 | msgid "Shaare a new link" |
388 | msgstr "Partager un nouveau lien" | 388 | msgstr "Partager un nouveau lien" |
389 | 389 | ||
390 | #: index.php:1342 tmp/linklist.b91ef64efc3688266305ea9b42e5017e.rtpl.php:169 | 390 | #: index.php:1344 tmp/linklist.b91ef64efc3688266305ea9b42e5017e.rtpl.php:169 |
391 | msgid "Edit" | 391 | msgid "Edit" |
392 | msgstr "Modifier" | 392 | msgstr "Modifier" |
393 | 393 | ||
394 | #: index.php:1342 index.php:1413 | 394 | #: index.php:1344 index.php:1416 |
395 | #: tmp/page.header.b91ef64efc3688266305ea9b42e5017e.rtpl.php:26 | 395 | #: tmp/page.header.b91ef64efc3688266305ea9b42e5017e.rtpl.php:26 |
396 | #: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:26 | 396 | #: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:26 |
397 | msgid "Shaare" | 397 | msgid "Shaare" |
398 | msgstr "Shaare" | 398 | msgstr "Shaare" |
399 | 399 | ||
400 | #: index.php:1382 | 400 | #: index.php:1385 |
401 | msgid "Note: " | 401 | msgid "Note: " |
402 | msgstr "Note : " | 402 | msgstr "Note : " |
403 | 403 | ||
404 | #: index.php:1421 | 404 | #: index.php:1424 |
405 | msgid "Invalid link ID provided" | 405 | msgid "Invalid link ID provided" |
406 | msgstr "" | 406 | msgstr "" |
407 | 407 | ||
408 | #: index.php:1441 tmp/export.b91ef64efc3688266305ea9b42e5017e.rtpl.php:65 | 408 | #: index.php:1444 tmp/export.b91ef64efc3688266305ea9b42e5017e.rtpl.php:65 |
409 | msgid "Export" | 409 | msgid "Export" |
410 | msgstr "Exporter" | 410 | msgstr "Exporter" |
411 | 411 | ||
412 | #: index.php:1503 tmp/import.b91ef64efc3688266305ea9b42e5017e.rtpl.php:83 | 412 | #: index.php:1506 tmp/import.b91ef64efc3688266305ea9b42e5017e.rtpl.php:83 |
413 | msgid "Import" | 413 | msgid "Import" |
414 | msgstr "Importer" | 414 | msgstr "Importer" |
415 | 415 | ||
416 | #: index.php:1513 | 416 | #: index.php:1516 |
417 | #, php-format | 417 | #, php-format |
418 | msgid "" | 418 | msgid "" |
419 | "The file you are trying to upload is probably bigger than what this " | 419 | "The file you are trying to upload is probably bigger than what this " |
@@ -423,20 +423,20 @@ msgstr "" | |||
423 | "le serveur web peut accepter (%s). Merci de l'envoyer en parties plus " | 423 | "le serveur web peut accepter (%s). Merci de l'envoyer en parties plus " |
424 | "légères." | 424 | "légères." |
425 | 425 | ||
426 | #: index.php:1558 tmp/pluginsadmin.b91ef64efc3688266305ea9b42e5017e.rtpl.php:26 | 426 | #: index.php:1561 tmp/pluginsadmin.b91ef64efc3688266305ea9b42e5017e.rtpl.php:26 |
427 | #: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:22 | 427 | #: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:22 |
428 | msgid "Plugin administration" | 428 | msgid "Plugin administration" |
429 | msgstr "Administration des plugins" | 429 | msgstr "Administration des plugins" |
430 | 430 | ||
431 | #: index.php:1612 tmp/thumbnails.b91ef64efc3688266305ea9b42e5017e.rtpl.php:14 | 431 | #: index.php:1615 tmp/thumbnails.b91ef64efc3688266305ea9b42e5017e.rtpl.php:14 |
432 | msgid "Thumbnails update" | 432 | msgid "Thumbnails update" |
433 | msgstr "Mise à jour des miniatures" | 433 | msgstr "Mise à jour des miniatures" |
434 | 434 | ||
435 | #: index.php:1778 | 435 | #: index.php:1781 |
436 | msgid "Search: " | 436 | msgid "Search: " |
437 | msgstr "Recherche : " | 437 | msgstr "Recherche : " |
438 | 438 | ||
439 | #: index.php:1821 | 439 | #: index.php:1824 |
440 | #, php-format | 440 | #, php-format |
441 | msgid "" | 441 | msgid "" |
442 | "<pre>Sessions do not seem to work correctly on your server.<br>Make sure the " | 442 | "<pre>Sessions do not seem to work correctly on your server.<br>Make sure the " |
@@ -455,7 +455,7 @@ msgstr "" | |||
455 | "des cookies. Nous vous recommandons d'accéder à votre serveur depuis son " | 455 | "des cookies. Nous vous recommandons d'accéder à votre serveur depuis son " |
456 | "adresse IP ou un <em>Fully Qualified Domain Name</em>.<br>" | 456 | "adresse IP ou un <em>Fully Qualified Domain Name</em>.<br>" |
457 | 457 | ||
458 | #: index.php:1831 | 458 | #: index.php:1834 |
459 | msgid "Click to try again." | 459 | msgid "Click to try again." |
460 | msgstr "Cliquer ici pour réessayer." | 460 | msgstr "Cliquer ici pour réessayer." |
461 | 461 | ||
@@ -592,7 +592,7 @@ msgstr "Mauvaise réponse du hub %s" | |||
592 | msgid "Enable PubSubHubbub feed publishing." | 592 | msgid "Enable PubSubHubbub feed publishing." |
593 | msgstr "Active la publication de flux vers PubSubHubbub." | 593 | msgstr "Active la publication de flux vers PubSubHubbub." |
594 | 594 | ||
595 | #: plugins/qrcode/qrcode.php:73 plugins/wallabag/wallabag.php:68 | 595 | #: plugins/qrcode/qrcode.php:72 plugins/wallabag/wallabag.php:68 |
596 | msgid "For each link, add a QRCode icon." | 596 | msgid "For each link, add a QRCode icon." |
597 | msgstr "Pour chaque lien, ajouter une icône de QRCode." | 597 | msgstr "Pour chaque lien, ajouter une icône de QRCode." |
598 | 598 | ||
@@ -679,6 +679,34 @@ msgstr "Vous pouvez aussi modifier les tags dans la" | |||
679 | msgid "tag list" | 679 | msgid "tag list" |
680 | msgstr "liste des tags" | 680 | msgstr "liste des tags" |
681 | 681 | ||
682 | #: tmp/configure.90100d2eaf5d3705e14b9b4f78ecddc9.rtpl.php:143 | ||
683 | #: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:312 | ||
684 | #: tmp/export.b91ef64efc3688266305ea9b42e5017e.rtpl.php:31 | ||
685 | msgid "All" | ||
686 | msgstr "Tous" | ||
687 | |||
688 | #: tmp/configure.90100d2eaf5d3705e14b9b4f78ecddc9.rtpl.php:147 | ||
689 | #: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:316 | ||
690 | msgid "Only common media hosts" | ||
691 | msgstr "Seulement les hébergeurs de média connus" | ||
692 | |||
693 | #: tmp/configure.90100d2eaf5d3705e14b9b4f78ecddc9.rtpl.php:151 | ||
694 | #: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:320 | ||
695 | msgid "None" | ||
696 | msgstr "Aucune" | ||
697 | |||
698 | #: tmp/configure.90100d2eaf5d3705e14b9b4f78ecddc9.rtpl.php:158 | ||
699 | #: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:297 | ||
700 | msgid "You need to enable the extension <code>php-gd</code> to use thumbnails." | ||
701 | msgstr "" | ||
702 | "Vous devez activer l'extension <code>php-gd</code> pour utiliser les " | ||
703 | "miniatures." | ||
704 | |||
705 | #: tmp/configure.90100d2eaf5d3705e14b9b4f78ecddc9.rtpl.php:162 | ||
706 | #| msgid "Enable thumbnails" | ||
707 | msgid "Synchonize thumbnails" | ||
708 | msgstr "" | ||
709 | |||
682 | #: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:29 | 710 | #: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:29 |
683 | msgid "title" | 711 | msgid "title" |
684 | msgstr "titre" | 712 | msgstr "titre" |
@@ -762,50 +790,41 @@ msgid "Notify me when a new release is ready" | |||
762 | msgstr "Me notifier lorsqu'une nouvelle version est disponible" | 790 | msgstr "Me notifier lorsqu'une nouvelle version est disponible" |
763 | 791 | ||
764 | #: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:247 | 792 | #: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:247 |
793 | msgid "Automatically retrieve description for new bookmarks" | ||
794 | msgstr "Récupérer automatiquement la description" | ||
795 | |||
796 | #: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:248 | ||
797 | msgid "Shaarli will try to retrieve the description from meta HTML headers" | ||
798 | msgstr "" | ||
799 | "Shaarli essaiera de récupérer la description depuis les balises HTML meta " | ||
800 | "dans les entêtes" | ||
801 | |||
802 | #: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:263 | ||
765 | #: tmp/install.b91ef64efc3688266305ea9b42e5017e.rtpl.php:169 | 803 | #: tmp/install.b91ef64efc3688266305ea9b42e5017e.rtpl.php:169 |
766 | msgid "Enable REST API" | 804 | msgid "Enable REST API" |
767 | msgstr "Activer l'API REST" | 805 | msgstr "Activer l'API REST" |
768 | 806 | ||
769 | #: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:248 | 807 | #: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:264 |
770 | #: tmp/install.b91ef64efc3688266305ea9b42e5017e.rtpl.php:170 | 808 | #: tmp/install.b91ef64efc3688266305ea9b42e5017e.rtpl.php:170 |
771 | msgid "Allow third party software to use Shaarli such as mobile application" | 809 | msgid "Allow third party software to use Shaarli such as mobile application" |
772 | msgstr "" | 810 | msgstr "" |
773 | "Permet aux applications tierces d'utiliser Shaarli, par exemple les " | 811 | "Permet aux applications tierces d'utiliser Shaarli, par exemple les " |
774 | "applications mobiles" | 812 | "applications mobiles" |
775 | 813 | ||
776 | #: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:263 | 814 | #: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:279 |
777 | msgid "API secret" | 815 | msgid "API secret" |
778 | msgstr "Clé d'API secrète" | 816 | msgstr "Clé d'API secrète" |
779 | 817 | ||
780 | #: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:277 | 818 | #: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:293 |
781 | msgid "Enable thumbnails" | 819 | msgid "Enable thumbnails" |
782 | msgstr "Activer les miniatures" | 820 | msgstr "Activer les miniatures" |
783 | 821 | ||
784 | #: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:281 | 822 | #: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:301 |
785 | msgid "You need to enable the extension <code>php-gd</code> to use thumbnails." | ||
786 | msgstr "" | ||
787 | "Vous devez activer l'extension <code>php-gd</code> pour utiliser les " | ||
788 | "miniatures." | ||
789 | |||
790 | #: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:285 | ||
791 | #: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:56 | 823 | #: tmp/tools.b91ef64efc3688266305ea9b42e5017e.rtpl.php:56 |
792 | msgid "Synchronize thumbnails" | 824 | msgid "Synchronize thumbnails" |
793 | msgstr "Synchroniser les miniatures" | 825 | msgstr "Synchroniser les miniatures" |
794 | 826 | ||
795 | #: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:296 | 827 | #: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:328 |
796 | #: tmp/export.b91ef64efc3688266305ea9b42e5017e.rtpl.php:31 | ||
797 | msgid "All" | ||
798 | msgstr "Tous" | ||
799 | |||
800 | #: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:300 | ||
801 | msgid "Only common media hosts" | ||
802 | msgstr "Seulement les hébergeurs de média connus" | ||
803 | |||
804 | #: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:304 | ||
805 | msgid "None" | ||
806 | msgstr "Aucune" | ||
807 | |||
808 | #: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:312 | ||
809 | #: tmp/editlink.b91ef64efc3688266305ea9b42e5017e.rtpl.php:72 | 828 | #: tmp/editlink.b91ef64efc3688266305ea9b42e5017e.rtpl.php:72 |
810 | #: tmp/pluginsadmin.b91ef64efc3688266305ea9b42e5017e.rtpl.php:139 | 829 | #: tmp/pluginsadmin.b91ef64efc3688266305ea9b42e5017e.rtpl.php:139 |
811 | #: tmp/pluginsadmin.b91ef64efc3688266305ea9b42e5017e.rtpl.php:199 | 830 | #: tmp/pluginsadmin.b91ef64efc3688266305ea9b42e5017e.rtpl.php:199 |
@@ -1149,17 +1168,13 @@ msgstr "Déconnexion" | |||
1149 | 1168 | ||
1150 | #: tmp/page.header.b91ef64efc3688266305ea9b42e5017e.rtpl.php:150 | 1169 | #: tmp/page.header.b91ef64efc3688266305ea9b42e5017e.rtpl.php:150 |
1151 | #: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:150 | 1170 | #: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:150 |
1152 | #, fuzzy | ||
1153 | #| msgid "Public" | ||
1154 | msgid "Set public" | 1171 | msgid "Set public" |
1155 | msgstr "Publics" | 1172 | msgstr "Rendre public" |
1156 | 1173 | ||
1157 | #: tmp/page.header.b91ef64efc3688266305ea9b42e5017e.rtpl.php:155 | 1174 | #: tmp/page.header.b91ef64efc3688266305ea9b42e5017e.rtpl.php:155 |
1158 | #: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:155 | 1175 | #: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:155 |
1159 | #, fuzzy | ||
1160 | #| msgid "Private" | ||
1161 | msgid "Set private" | 1176 | msgid "Set private" |
1162 | msgstr "Privé" | 1177 | msgstr "Rendre privé" |
1163 | 1178 | ||
1164 | #: tmp/page.header.b91ef64efc3688266305ea9b42e5017e.rtpl.php:187 | 1179 | #: tmp/page.header.b91ef64efc3688266305ea9b42e5017e.rtpl.php:187 |
1165 | #: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:187 | 1180 | #: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:187 |
@@ -1409,11 +1424,6 @@ msgstr "" | |||
1409 | "Glisser ce lien dans votre barre de favoris ou cliquer droit dessus et « " | 1424 | "Glisser ce lien dans votre barre de favoris ou cliquer droit dessus et « " |
1410 | "Ajouter aux favoris »" | 1425 | "Ajouter aux favoris »" |
1411 | 1426 | ||
1412 | #, fuzzy | ||
1413 | #~| msgid "Enable thumbnails" | ||
1414 | #~ msgid "Synchonize thumbnails" | ||
1415 | #~ msgstr "Activer les miniatures" | ||
1416 | |||
1417 | #~ msgid "" | 1427 | #~ msgid "" |
1418 | #~ "You need to browse your Shaarli over <strong>HTTPS</strong> to use this " | 1428 | #~ "You need to browse your Shaarli over <strong>HTTPS</strong> to use this " |
1419 | #~ "functionality." | 1429 | #~ "functionality." |
@@ -1015,6 +1015,7 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager, | |||
1015 | $conf->set('general.timezone', $tz); | 1015 | $conf->set('general.timezone', $tz); |
1016 | $conf->set('general.title', escape($_POST['title'])); | 1016 | $conf->set('general.title', escape($_POST['title'])); |
1017 | $conf->set('general.header_link', escape($_POST['titleLink'])); | 1017 | $conf->set('general.header_link', escape($_POST['titleLink'])); |
1018 | $conf->set('general.retrieve_description', !empty($_POST['retrieveDescription'])); | ||
1018 | $conf->set('resource.theme', escape($_POST['theme'])); | 1019 | $conf->set('resource.theme', escape($_POST['theme'])); |
1019 | $conf->set('security.session_protection_disabled', !empty($_POST['disablesessionprotection'])); | 1020 | $conf->set('security.session_protection_disabled', !empty($_POST['disablesessionprotection'])); |
1020 | $conf->set('privacy.default_private_links', !empty($_POST['privateLinkByDefault'])); | 1021 | $conf->set('privacy.default_private_links', !empty($_POST['privateLinkByDefault'])); |
@@ -1063,6 +1064,7 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager, | |||
1063 | ); | 1064 | ); |
1064 | $PAGE->assign('continents', $continents); | 1065 | $PAGE->assign('continents', $continents); |
1065 | $PAGE->assign('cities', $cities); | 1066 | $PAGE->assign('cities', $cities); |
1067 | $PAGE->assign('retrieve_description', $conf->get('general.retrieve_description')); | ||
1066 | $PAGE->assign('private_links_default', $conf->get('privacy.default_private_links', false)); | 1068 | $PAGE->assign('private_links_default', $conf->get('privacy.default_private_links', false)); |
1067 | $PAGE->assign('session_protection_disabled', $conf->get('security.session_protection_disabled', false)); | 1069 | $PAGE->assign('session_protection_disabled', $conf->get('security.session_protection_disabled', false)); |
1068 | $PAGE->assign('enable_rss_permalinks', $conf->get('feed.rss_permalinks', false)); | 1070 | $PAGE->assign('enable_rss_permalinks', $conf->get('feed.rss_permalinks', false)); |
@@ -1364,13 +1366,14 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager, | |||
1364 | // If this is an HTTP(S) link, we try go get the page to extract | 1366 | // If this is an HTTP(S) link, we try go get the page to extract |
1365 | // the title (otherwise we will to straight to the edit form.) | 1367 | // the title (otherwise we will to straight to the edit form.) |
1366 | if (empty($title) && strpos(get_url_scheme($url), 'http') !== false) { | 1368 | if (empty($title) && strpos(get_url_scheme($url), 'http') !== false) { |
1369 | $retrieveDescription = $conf->get('general.retrieve_description'); | ||
1367 | // Short timeout to keep the application responsive | 1370 | // Short timeout to keep the application responsive |
1368 | // The callback will fill $charset and $title with data from the downloaded page. | 1371 | // The callback will fill $charset and $title with data from the downloaded page. |
1369 | get_http_response( | 1372 | get_http_response( |
1370 | $url, | 1373 | $url, |
1371 | $conf->get('general.download_timeout', 30), | 1374 | $conf->get('general.download_timeout', 30), |
1372 | $conf->get('general.download_max_size', 4194304), | 1375 | $conf->get('general.download_max_size', 4194304), |
1373 | get_curl_download_callback($charset, $title) | 1376 | get_curl_download_callback($charset, $title, $description, $tags, $retrieveDescription) |
1374 | ); | 1377 | ); |
1375 | if (! empty($title) && strtolower($charset) != 'utf-8') { | 1378 | if (! empty($title) && strtolower($charset) != 'utf-8') { |
1376 | $title = mb_convert_encoding($title, 'utf-8', $charset); | 1379 | $title = mb_convert_encoding($title, 'utf-8', $charset); |
diff --git a/tests/bookmark/LinkUtilsTest.php b/tests/bookmark/LinkUtilsTest.php index 25fb3043..78cb8f2a 100644 --- a/tests/bookmark/LinkUtilsTest.php +++ b/tests/bookmark/LinkUtilsTest.php | |||
@@ -2,14 +2,16 @@ | |||
2 | 2 | ||
3 | namespace Shaarli\Bookmark; | 3 | namespace Shaarli\Bookmark; |
4 | 4 | ||
5 | use PHPUnit\Framework\TestCase; | ||
5 | use ReferenceLinkDB; | 6 | use ReferenceLinkDB; |
7 | use Shaarli\Config\ConfigManager; | ||
6 | 8 | ||
7 | require_once 'tests/utils/CurlUtils.php'; | 9 | require_once 'tests/utils/CurlUtils.php'; |
8 | 10 | ||
9 | /** | 11 | /** |
10 | * Class LinkUtilsTest. | 12 | * Class LinkUtilsTest. |
11 | */ | 13 | */ |
12 | class LinkUtilsTest extends \PHPUnit\Framework\TestCase | 14 | class LinkUtilsTest extends TestCase |
13 | { | 15 | { |
14 | /** | 16 | /** |
15 | * Test html_extract_title() when the title is found. | 17 | * Test html_extract_title() when the title is found. |
@@ -76,11 +78,56 @@ class LinkUtilsTest extends \PHPUnit\Framework\TestCase | |||
76 | } | 78 | } |
77 | 79 | ||
78 | /** | 80 | /** |
81 | * Test html_extract_tag() when the tag <meta name= is found. | ||
82 | */ | ||
83 | public function testHtmlExtractExistentNameTag() | ||
84 | { | ||
85 | $description = 'Bob and Alice share cookies.'; | ||
86 | $html = '<html><meta>stuff2</meta><meta name="description" content="' . $description . '"/></html>'; | ||
87 | $this->assertEquals($description, html_extract_tag('description', $html)); | ||
88 | } | ||
89 | |||
90 | /** | ||
91 | * Test html_extract_tag() when the tag <meta name= is not found. | ||
92 | */ | ||
93 | public function testHtmlExtractNonExistentNameTag() | ||
94 | { | ||
95 | $html = '<html><meta>stuff2</meta><meta name="image" content="img"/></html>'; | ||
96 | $this->assertFalse(html_extract_tag('description', $html)); | ||
97 | } | ||
98 | |||
99 | /** | ||
100 | * Test html_extract_tag() when the tag <meta property="og: is found. | ||
101 | */ | ||
102 | public function testHtmlExtractExistentOgTag() | ||
103 | { | ||
104 | $description = 'Bob and Alice share cookies.'; | ||
105 | $html = '<html><meta>stuff2</meta><meta property="og:description" content="' . $description . '"/></html>'; | ||
106 | $this->assertEquals($description, html_extract_tag('description', $html)); | ||
107 | } | ||
108 | |||
109 | /** | ||
110 | * Test html_extract_tag() when the tag <meta property="og: is not found. | ||
111 | */ | ||
112 | public function testHtmlExtractNonExistentOgTag() | ||
113 | { | ||
114 | $html = '<html><meta>stuff2</meta><meta name="image" content="img"/></html>'; | ||
115 | $this->assertFalse(html_extract_tag('description', $html)); | ||
116 | } | ||
117 | |||
118 | /** | ||
79 | * Test the download callback with valid value | 119 | * Test the download callback with valid value |
80 | */ | 120 | */ |
81 | public function testCurlDownloadCallbackOk() | 121 | public function testCurlDownloadCallbackOk() |
82 | { | 122 | { |
83 | $callback = get_curl_download_callback($charset, $title, 'ut_curl_getinfo_ok'); | 123 | $callback = get_curl_download_callback( |
124 | $charset, | ||
125 | $title, | ||
126 | $desc, | ||
127 | $keywords, | ||
128 | false, | ||
129 | 'ut_curl_getinfo_ok' | ||
130 | ); | ||
84 | $data = [ | 131 | $data = [ |
85 | 'HTTP/1.1 200 OK', | 132 | 'HTTP/1.1 200 OK', |
86 | 'Server: GitHub.com', | 133 | 'Server: GitHub.com', |
@@ -90,7 +137,9 @@ class LinkUtilsTest extends \PHPUnit\Framework\TestCase | |||
90 | 'end' => 'th=device-width">' | 137 | 'end' => 'th=device-width">' |
91 | . '<title>Refactoring · GitHub</title>' | 138 | . '<title>Refactoring · GitHub</title>' |
92 | . '<link rel="search" type="application/opensea', | 139 | . '<link rel="search" type="application/opensea', |
93 | '<title>ignored</title>', | 140 | '<title>ignored</title>' |
141 | . '<meta name="description" content="desc" />' | ||
142 | . '<meta name="keywords" content="key1,key2" />', | ||
94 | ]; | 143 | ]; |
95 | foreach ($data as $key => $line) { | 144 | foreach ($data as $key => $line) { |
96 | $ignore = null; | 145 | $ignore = null; |
@@ -102,6 +151,8 @@ class LinkUtilsTest extends \PHPUnit\Framework\TestCase | |||
102 | } | 151 | } |
103 | $this->assertEquals('utf-8', $charset); | 152 | $this->assertEquals('utf-8', $charset); |
104 | $this->assertEquals('Refactoring · GitHub', $title); | 153 | $this->assertEquals('Refactoring · GitHub', $title); |
154 | $this->assertEmpty($desc); | ||
155 | $this->assertEmpty($keywords); | ||
105 | } | 156 | } |
106 | 157 | ||
107 | /** | 158 | /** |
@@ -109,13 +160,22 @@ class LinkUtilsTest extends \PHPUnit\Framework\TestCase | |||
109 | */ | 160 | */ |
110 | public function testCurlDownloadCallbackOkNoCharset() | 161 | public function testCurlDownloadCallbackOkNoCharset() |
111 | { | 162 | { |
112 | $callback = get_curl_download_callback($charset, $title, 'ut_curl_getinfo_no_charset'); | 163 | $callback = get_curl_download_callback( |
164 | $charset, | ||
165 | $title, | ||
166 | $desc, | ||
167 | $keywords, | ||
168 | false, | ||
169 | 'ut_curl_getinfo_no_charset' | ||
170 | ); | ||
113 | $data = [ | 171 | $data = [ |
114 | 'HTTP/1.1 200 OK', | 172 | 'HTTP/1.1 200 OK', |
115 | 'end' => 'th=device-width">' | 173 | 'end' => 'th=device-width">' |
116 | . '<title>Refactoring · GitHub</title>' | 174 | . '<title>Refactoring · GitHub</title>' |
117 | . '<link rel="search" type="application/opensea', | 175 | . '<link rel="search" type="application/opensea', |
118 | '<title>ignored</title>', | 176 | '<title>ignored</title>' |
177 | . '<meta name="description" content="desc" />' | ||
178 | . '<meta name="keywords" content="key1,key2" />', | ||
119 | ]; | 179 | ]; |
120 | foreach ($data as $key => $line) { | 180 | foreach ($data as $key => $line) { |
121 | $ignore = null; | 181 | $ignore = null; |
@@ -123,6 +183,8 @@ class LinkUtilsTest extends \PHPUnit\Framework\TestCase | |||
123 | } | 183 | } |
124 | $this->assertEmpty($charset); | 184 | $this->assertEmpty($charset); |
125 | $this->assertEquals('Refactoring · GitHub', $title); | 185 | $this->assertEquals('Refactoring · GitHub', $title); |
186 | $this->assertEmpty($desc); | ||
187 | $this->assertEmpty($keywords); | ||
126 | } | 188 | } |
127 | 189 | ||
128 | /** | 190 | /** |
@@ -130,14 +192,23 @@ class LinkUtilsTest extends \PHPUnit\Framework\TestCase | |||
130 | */ | 192 | */ |
131 | public function testCurlDownloadCallbackOkHtmlCharset() | 193 | public function testCurlDownloadCallbackOkHtmlCharset() |
132 | { | 194 | { |
133 | $callback = get_curl_download_callback($charset, $title, 'ut_curl_getinfo_no_charset'); | 195 | $callback = get_curl_download_callback( |
196 | $charset, | ||
197 | $title, | ||
198 | $desc, | ||
199 | $keywords, | ||
200 | false, | ||
201 | 'ut_curl_getinfo_no_charset' | ||
202 | ); | ||
134 | $data = [ | 203 | $data = [ |
135 | 'HTTP/1.1 200 OK', | 204 | 'HTTP/1.1 200 OK', |
136 | '<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />', | 205 | '<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />', |
137 | 'end' => 'th=device-width">' | 206 | 'end' => 'th=device-width">' |
138 | . '<title>Refactoring · GitHub</title>' | 207 | . '<title>Refactoring · GitHub</title>' |
139 | . '<link rel="search" type="application/opensea', | 208 | . '<link rel="search" type="application/opensea', |
140 | '<title>ignored</title>', | 209 | '<title>ignored</title>' |
210 | . '<meta name="description" content="desc" />' | ||
211 | . '<meta name="keywords" content="key1,key2" />', | ||
141 | ]; | 212 | ]; |
142 | foreach ($data as $key => $line) { | 213 | foreach ($data as $key => $line) { |
143 | $ignore = null; | 214 | $ignore = null; |
@@ -149,6 +220,8 @@ class LinkUtilsTest extends \PHPUnit\Framework\TestCase | |||
149 | } | 220 | } |
150 | $this->assertEquals('utf-8', $charset); | 221 | $this->assertEquals('utf-8', $charset); |
151 | $this->assertEquals('Refactoring · GitHub', $title); | 222 | $this->assertEquals('Refactoring · GitHub', $title); |
223 | $this->assertEmpty($desc); | ||
224 | $this->assertEmpty($keywords); | ||
152 | } | 225 | } |
153 | 226 | ||
154 | /** | 227 | /** |
@@ -156,7 +229,14 @@ class LinkUtilsTest extends \PHPUnit\Framework\TestCase | |||
156 | */ | 229 | */ |
157 | public function testCurlDownloadCallbackOkNoTitle() | 230 | public function testCurlDownloadCallbackOkNoTitle() |
158 | { | 231 | { |
159 | $callback = get_curl_download_callback($charset, $title, 'ut_curl_getinfo_ok'); | 232 | $callback = get_curl_download_callback( |
233 | $charset, | ||
234 | $title, | ||
235 | $desc, | ||
236 | $keywords, | ||
237 | false, | ||
238 | 'ut_curl_getinfo_ok' | ||
239 | ); | ||
160 | $data = [ | 240 | $data = [ |
161 | 'HTTP/1.1 200 OK', | 241 | 'HTTP/1.1 200 OK', |
162 | 'end' => 'th=device-width">Refactoring · GitHub<link rel="search" type="application/opensea', | 242 | 'end' => 'th=device-width">Refactoring · GitHub<link rel="search" type="application/opensea', |
@@ -168,6 +248,8 @@ class LinkUtilsTest extends \PHPUnit\Framework\TestCase | |||
168 | } | 248 | } |
169 | $this->assertEquals('utf-8', $charset); | 249 | $this->assertEquals('utf-8', $charset); |
170 | $this->assertEmpty($title); | 250 | $this->assertEmpty($title); |
251 | $this->assertEmpty($desc); | ||
252 | $this->assertEmpty($keywords); | ||
171 | } | 253 | } |
172 | 254 | ||
173 | /** | 255 | /** |
@@ -175,7 +257,14 @@ class LinkUtilsTest extends \PHPUnit\Framework\TestCase | |||
175 | */ | 257 | */ |
176 | public function testCurlDownloadCallbackInvalidContentType() | 258 | public function testCurlDownloadCallbackInvalidContentType() |
177 | { | 259 | { |
178 | $callback = get_curl_download_callback($charset, $title, 'ut_curl_getinfo_ct_ko'); | 260 | $callback = get_curl_download_callback( |
261 | $charset, | ||
262 | $title, | ||
263 | $desc, | ||
264 | $keywords, | ||
265 | false, | ||
266 | 'ut_curl_getinfo_ct_ko' | ||
267 | ); | ||
179 | $ignore = null; | 268 | $ignore = null; |
180 | $this->assertFalse($callback($ignore, '')); | 269 | $this->assertFalse($callback($ignore, '')); |
181 | $this->assertEmpty($charset); | 270 | $this->assertEmpty($charset); |
@@ -187,7 +276,14 @@ class LinkUtilsTest extends \PHPUnit\Framework\TestCase | |||
187 | */ | 276 | */ |
188 | public function testCurlDownloadCallbackInvalidResponseCode() | 277 | public function testCurlDownloadCallbackInvalidResponseCode() |
189 | { | 278 | { |
190 | $callback = get_curl_download_callback($charset, $title, 'ut_curl_getinfo_rc_ko'); | 279 | $callback = $callback = get_curl_download_callback( |
280 | $charset, | ||
281 | $title, | ||
282 | $desc, | ||
283 | $keywords, | ||
284 | false, | ||
285 | 'ut_curl_getinfo_rc_ko' | ||
286 | ); | ||
191 | $ignore = null; | 287 | $ignore = null; |
192 | $this->assertFalse($callback($ignore, '')); | 288 | $this->assertFalse($callback($ignore, '')); |
193 | $this->assertEmpty($charset); | 289 | $this->assertEmpty($charset); |
@@ -199,7 +295,14 @@ class LinkUtilsTest extends \PHPUnit\Framework\TestCase | |||
199 | */ | 295 | */ |
200 | public function testCurlDownloadCallbackInvalidContentTypeAndResponseCode() | 296 | public function testCurlDownloadCallbackInvalidContentTypeAndResponseCode() |
201 | { | 297 | { |
202 | $callback = get_curl_download_callback($charset, $title, 'ut_curl_getinfo_rs_ct_ko'); | 298 | $callback = $callback = get_curl_download_callback( |
299 | $charset, | ||
300 | $title, | ||
301 | $desc, | ||
302 | $keywords, | ||
303 | false, | ||
304 | 'ut_curl_getinfo_rs_ct_ko' | ||
305 | ); | ||
203 | $ignore = null; | 306 | $ignore = null; |
204 | $this->assertFalse($callback($ignore, '')); | 307 | $this->assertFalse($callback($ignore, '')); |
205 | $this->assertEmpty($charset); | 308 | $this->assertEmpty($charset); |
@@ -207,6 +310,85 @@ class LinkUtilsTest extends \PHPUnit\Framework\TestCase | |||
207 | } | 310 | } |
208 | 311 | ||
209 | /** | 312 | /** |
313 | * Test the download callback with valid value, and retrieve_description option enabled. | ||
314 | */ | ||
315 | public function testCurlDownloadCallbackOkWithDesc() | ||
316 | { | ||
317 | $callback = get_curl_download_callback( | ||
318 | $charset, | ||
319 | $title, | ||
320 | $desc, | ||
321 | $keywords, | ||
322 | true, | ||
323 | 'ut_curl_getinfo_ok' | ||
324 | ); | ||
325 | $data = [ | ||
326 | 'HTTP/1.1 200 OK', | ||
327 | 'Server: GitHub.com', | ||
328 | 'Date: Sat, 28 Oct 2017 12:01:33 GMT', | ||
329 | 'Content-Type: text/html; charset=utf-8', | ||
330 | 'Status: 200 OK', | ||
331 | 'th=device-width">' | ||
332 | . '<title>Refactoring · GitHub</title>' | ||
333 | . '<link rel="search" type="application/opensea', | ||
334 | 'end' => '<title>ignored</title>' | ||
335 | . '<meta name="description" content="link desc" />' | ||
336 | . '<meta name="keywords" content="key1,key2" />', | ||
337 | ]; | ||
338 | foreach ($data as $key => $line) { | ||
339 | $ignore = null; | ||
340 | $expected = $key !== 'end' ? strlen($line) : false; | ||
341 | $this->assertEquals($expected, $callback($ignore, $line)); | ||
342 | if ($expected === false) { | ||
343 | break; | ||
344 | } | ||
345 | } | ||
346 | $this->assertEquals('utf-8', $charset); | ||
347 | $this->assertEquals('Refactoring · GitHub', $title); | ||
348 | $this->assertEquals('link desc', $desc); | ||
349 | $this->assertEquals('key1 key2', $keywords); | ||
350 | } | ||
351 | |||
352 | /** | ||
353 | * Test the download callback with valid value, and retrieve_description option enabled, | ||
354 | * but no desc or keyword defined in the page. | ||
355 | */ | ||
356 | public function testCurlDownloadCallbackOkWithDescNotFound() | ||
357 | { | ||
358 | $callback = get_curl_download_callback( | ||
359 | $charset, | ||
360 | $title, | ||
361 | $desc, | ||
362 | $keywords, | ||
363 | true, | ||
364 | 'ut_curl_getinfo_ok' | ||
365 | ); | ||
366 | $data = [ | ||
367 | 'HTTP/1.1 200 OK', | ||
368 | 'Server: GitHub.com', | ||
369 | 'Date: Sat, 28 Oct 2017 12:01:33 GMT', | ||
370 | 'Content-Type: text/html; charset=utf-8', | ||
371 | 'Status: 200 OK', | ||
372 | 'th=device-width">' | ||
373 | . '<title>Refactoring · GitHub</title>' | ||
374 | . '<link rel="search" type="application/opensea', | ||
375 | 'end' => '<title>ignored</title>', | ||
376 | ]; | ||
377 | foreach ($data as $key => $line) { | ||
378 | $ignore = null; | ||
379 | $expected = $key !== 'end' ? strlen($line) : false; | ||
380 | $this->assertEquals($expected, $callback($ignore, $line)); | ||
381 | if ($expected === false) { | ||
382 | break; | ||
383 | } | ||
384 | } | ||
385 | $this->assertEquals('utf-8', $charset); | ||
386 | $this->assertEquals('Refactoring · GitHub', $title); | ||
387 | $this->assertEmpty($desc); | ||
388 | $this->assertEmpty($keywords); | ||
389 | } | ||
390 | |||
391 | /** | ||
210 | * Test count_private. | 392 | * Test count_private. |
211 | */ | 393 | */ |
212 | public function testCountPrivateLinks() | 394 | public function testCountPrivateLinks() |
diff --git a/tpl/default/configure.html b/tpl/default/configure.html index 7a87c05d..83033624 100644 --- a/tpl/default/configure.html +++ b/tpl/default/configure.html | |||
@@ -215,6 +215,22 @@ | |||
215 | <div class="pure-g"> | 215 | <div class="pure-g"> |
216 | <div class="pure-u-lg-{$ratioLabel} pure-u-{$ratioLabelMobile}"> | 216 | <div class="pure-u-lg-{$ratioLabel} pure-u-{$ratioLabelMobile}"> |
217 | <div class="form-label"> | 217 | <div class="form-label"> |
218 | <label for="retrieveDescription"> | ||
219 | <span class="label-name">{'Automatically retrieve description for new bookmarks'|t}</span><br> | ||
220 | <span class="label-desc">{'Shaarli will try to retrieve the description from meta HTML headers'|t}</span> | ||
221 | </label> | ||
222 | </div> | ||
223 | </div> | ||
224 | <div class="pure-u-lg-{$ratioInput} pure-u-{$ratioInputMobile}"> | ||
225 | <div class="form-input"> | ||
226 | <input type="checkbox" name="retrieveDescription" id="retrieveDescription" | ||
227 | {if="$retrieve_description"}checked{/if}/> | ||
228 | </div> | ||
229 | </div> | ||
230 | </div> | ||
231 | <div class="pure-g"> | ||
232 | <div class="pure-u-lg-{$ratioLabel} pure-u-{$ratioLabelMobile}"> | ||
233 | <div class="form-label"> | ||
218 | <label for="enableApi"> | 234 | <label for="enableApi"> |
219 | <span class="label-name">{'Enable REST API'|t}</span><br> | 235 | <span class="label-name">{'Enable REST API'|t}</span><br> |
220 | <span class="label-desc">{'Allow third party software to use Shaarli such as mobile application'|t}</span> | 236 | <span class="label-desc">{'Allow third party software to use Shaarli such as mobile application'|t}</span> |
diff --git a/tpl/vintage/configure.html b/tpl/vintage/configure.html index f1892fa1..160286a5 100644 --- a/tpl/vintage/configure.html +++ b/tpl/vintage/configure.html | |||
@@ -107,6 +107,14 @@ | |||
107 | </td> | 107 | </td> |
108 | </tr> | 108 | </tr> |
109 | <tr> | 109 | <tr> |
110 | <td valign="top"><b>Automatically retrieve description for new bookmarks:</b></td> | ||
111 | <td> | ||
112 | <input type="checkbox" name="retrieveDescription" id="retrieveDescription" | ||
113 | {if="$retrieve_description"}checked{/if}/> | ||
114 | <label for="retrieveDescription"> Shaarli will try to retrieve the description from meta HTML headers</label> | ||
115 | </td> | ||
116 | </tr> | ||
117 | <tr> | ||
110 | <td valign="top"><b>Enable REST API</b></td> | 118 | <td valign="top"><b>Enable REST API</b></td> |
111 | <td> | 119 | <td> |
112 | <input type="checkbox" name="enableApi" id="enableApi" | 120 | <input type="checkbox" name="enableApi" id="enableApi" |