diff options
author | ArthurHoaro <arthur@hoa.ro> | 2018-07-28 09:41:29 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-07-28 09:41:29 +0200 |
commit | ad5f47adbaee1eef85e90950ab8a45fe82959924 (patch) | |
tree | d23a186661db00d36cb2b2287a7bf890fbc62cfb /application | |
parent | 8fdd65b88412a0db28c723a486650c434fe5668c (diff) | |
parent | 7b4fea0e39be9e74e9aef13e73af9bbd2b1a6397 (diff) | |
download | Shaarli-ad5f47adbaee1eef85e90950ab8a45fe82959924.tar.gz Shaarli-ad5f47adbaee1eef85e90950ab8a45fe82959924.tar.zst Shaarli-ad5f47adbaee1eef85e90950ab8a45fe82959924.zip |
Merge pull request #687 from ArthurHoaro/web-thumb
Use web-thumbnailer to retrieve thumbnails
Diffstat (limited to 'application')
-rw-r--r-- | application/PageBuilder.php | 37 | ||||
-rw-r--r-- | application/Router.php | 12 | ||||
-rw-r--r-- | application/Thumbnailer.php | 127 | ||||
-rw-r--r-- | application/Updater.php | 36 | ||||
-rw-r--r-- | application/config/ConfigManager.php | 56 |
5 files changed, 258 insertions, 10 deletions
diff --git a/application/PageBuilder.php b/application/PageBuilder.php index a4483870..b1abe0d0 100644 --- a/application/PageBuilder.php +++ b/application/PageBuilder.php | |||
@@ -1,6 +1,7 @@ | |||
1 | <?php | 1 | <?php |
2 | 2 | ||
3 | use Shaarli\Config\ConfigManager; | 3 | use Shaarli\Config\ConfigManager; |
4 | use Shaarli\Thumbnailer; | ||
4 | 5 | ||
5 | /** | 6 | /** |
6 | * This class is in charge of building the final page. | 7 | * This class is in charge of building the final page. |
@@ -22,10 +23,20 @@ class PageBuilder | |||
22 | protected $conf; | 23 | protected $conf; |
23 | 24 | ||
24 | /** | 25 | /** |
26 | * @var array $_SESSION | ||
27 | */ | ||
28 | protected $session; | ||
29 | |||
30 | /** | ||
25 | * @var LinkDB $linkDB instance. | 31 | * @var LinkDB $linkDB instance. |
26 | */ | 32 | */ |
27 | protected $linkDB; | 33 | protected $linkDB; |
28 | 34 | ||
35 | /** | ||
36 | * @var null|string XSRF token | ||
37 | */ | ||
38 | protected $token; | ||
39 | |||
29 | /** @var bool $isLoggedIn Whether the user is logged in **/ | 40 | /** @var bool $isLoggedIn Whether the user is logged in **/ |
30 | protected $isLoggedIn = false; | 41 | protected $isLoggedIn = false; |
31 | 42 | ||
@@ -33,14 +44,17 @@ class PageBuilder | |||
33 | * PageBuilder constructor. | 44 | * PageBuilder constructor. |
34 | * $tpl is initialized at false for lazy loading. | 45 | * $tpl is initialized at false for lazy loading. |
35 | * | 46 | * |
36 | * @param ConfigManager $conf Configuration Manager instance (reference). | 47 | * @param ConfigManager $conf Configuration Manager instance (reference). |
37 | * @param LinkDB $linkDB instance. | 48 | * @param array $session $_SESSION array |
38 | * @param string $token Session token | 49 | * @param LinkDB $linkDB instance. |
50 | * @param string $token Session token | ||
51 | * @param bool $isLoggedIn | ||
39 | */ | 52 | */ |
40 | public function __construct(&$conf, $linkDB = null, $token = null, $isLoggedIn = false) | 53 | public function __construct(&$conf, $session, $linkDB = null, $token = null, $isLoggedIn = false) |
41 | { | 54 | { |
42 | $this->tpl = false; | 55 | $this->tpl = false; |
43 | $this->conf = $conf; | 56 | $this->conf = $conf; |
57 | $this->session = $session; | ||
44 | $this->linkDB = $linkDB; | 58 | $this->linkDB = $linkDB; |
45 | $this->token = $token; | 59 | $this->token = $token; |
46 | $this->isLoggedIn = $isLoggedIn; | 60 | $this->isLoggedIn = $isLoggedIn; |
@@ -105,6 +119,19 @@ class PageBuilder | |||
105 | if ($this->linkDB !== null) { | 119 | if ($this->linkDB !== null) { |
106 | $this->tpl->assign('tags', $this->linkDB->linksCountPerTag()); | 120 | $this->tpl->assign('tags', $this->linkDB->linksCountPerTag()); |
107 | } | 121 | } |
122 | |||
123 | $this->tpl->assign( | ||
124 | 'thumbnails_enabled', | ||
125 | $this->conf->get('thumbnails.mode', Thumbnailer::MODE_NONE) !== Thumbnailer::MODE_NONE | ||
126 | ); | ||
127 | $this->tpl->assign('thumbnails_width', $this->conf->get('thumbnails.width')); | ||
128 | $this->tpl->assign('thumbnails_height', $this->conf->get('thumbnails.height')); | ||
129 | |||
130 | if (! empty($_SESSION['warnings'])) { | ||
131 | $this->tpl->assign('global_warnings', $_SESSION['warnings']); | ||
132 | unset($_SESSION['warnings']); | ||
133 | } | ||
134 | |||
108 | // To be removed with a proper theme configuration. | 135 | // To be removed with a proper theme configuration. |
109 | $this->tpl->assign('conf', $this->conf); | 136 | $this->tpl->assign('conf', $this->conf); |
110 | } | 137 | } |
diff --git a/application/Router.php b/application/Router.php index 4df0387c..bf86b884 100644 --- a/application/Router.php +++ b/application/Router.php | |||
@@ -7,6 +7,8 @@ | |||
7 | */ | 7 | */ |
8 | class Router | 8 | class Router |
9 | { | 9 | { |
10 | public static $AJAX_THUMB_UPDATE = 'ajax_thumb_update'; | ||
11 | |||
10 | public static $PAGE_LOGIN = 'login'; | 12 | public static $PAGE_LOGIN = 'login'; |
11 | 13 | ||
12 | public static $PAGE_PICWALL = 'picwall'; | 14 | public static $PAGE_PICWALL = 'picwall'; |
@@ -47,6 +49,8 @@ class Router | |||
47 | 49 | ||
48 | public static $PAGE_SAVE_PLUGINSADMIN = 'save_pluginadmin'; | 50 | public static $PAGE_SAVE_PLUGINSADMIN = 'save_pluginadmin'; |
49 | 51 | ||
52 | public static $PAGE_THUMBS_UPDATE = 'thumbs_update'; | ||
53 | |||
50 | public static $GET_TOKEN = 'token'; | 54 | public static $GET_TOKEN = 'token'; |
51 | 55 | ||
52 | /** | 56 | /** |
@@ -101,6 +105,14 @@ class Router | |||
101 | return self::$PAGE_FEED_RSS; | 105 | return self::$PAGE_FEED_RSS; |
102 | } | 106 | } |
103 | 107 | ||
108 | if (startsWith($query, 'do='. self::$PAGE_THUMBS_UPDATE)) { | ||
109 | return self::$PAGE_THUMBS_UPDATE; | ||
110 | } | ||
111 | |||
112 | if (startsWith($query, 'do='. self::$AJAX_THUMB_UPDATE)) { | ||
113 | return self::$AJAX_THUMB_UPDATE; | ||
114 | } | ||
115 | |||
104 | // At this point, only loggedin pages. | 116 | // At this point, only loggedin pages. |
105 | if (!$loggedIn) { | 117 | if (!$loggedIn) { |
106 | return self::$PAGE_LINKLIST; | 118 | return self::$PAGE_LINKLIST; |
diff --git a/application/Thumbnailer.php b/application/Thumbnailer.php new file mode 100644 index 00000000..7d0d9c33 --- /dev/null +++ b/application/Thumbnailer.php | |||
@@ -0,0 +1,127 @@ | |||
1 | <?php | ||
2 | |||
3 | namespace Shaarli; | ||
4 | |||
5 | use Shaarli\Config\ConfigManager; | ||
6 | use WebThumbnailer\Exception\WebThumbnailerException; | ||
7 | use WebThumbnailer\WebThumbnailer; | ||
8 | use WebThumbnailer\Application\ConfigManager as WTConfigManager; | ||
9 | |||
10 | /** | ||
11 | * Class Thumbnailer | ||
12 | * | ||
13 | * Utility class used to retrieve thumbnails using web-thumbnailer dependency. | ||
14 | */ | ||
15 | class Thumbnailer | ||
16 | { | ||
17 | const COMMON_MEDIA_DOMAINS = [ | ||
18 | 'imgur.com', | ||
19 | 'flickr.com', | ||
20 | 'youtube.com', | ||
21 | 'wikimedia.org', | ||
22 | 'redd.it', | ||
23 | 'gfycat.com', | ||
24 | 'media.giphy.com', | ||
25 | 'twitter.com', | ||
26 | 'twimg.com', | ||
27 | 'instagram.com', | ||
28 | 'pinterest.com', | ||
29 | 'pinterest.fr', | ||
30 | 'tumblr.com', | ||
31 | 'deviantart.com', | ||
32 | ]; | ||
33 | |||
34 | const MODE_ALL = 'all'; | ||
35 | const MODE_COMMON = 'common'; | ||
36 | const MODE_NONE = 'none'; | ||
37 | |||
38 | /** | ||
39 | * @var WebThumbnailer instance. | ||
40 | */ | ||
41 | protected $wt; | ||
42 | |||
43 | /** | ||
44 | * @var ConfigManager instance. | ||
45 | */ | ||
46 | protected $conf; | ||
47 | |||
48 | /** | ||
49 | * Thumbnailer constructor. | ||
50 | * | ||
51 | * @param ConfigManager $conf instance. | ||
52 | */ | ||
53 | public function __construct($conf) | ||
54 | { | ||
55 | $this->conf = $conf; | ||
56 | |||
57 | if (! $this->checkRequirements()) { | ||
58 | $this->conf->set('thumbnails.enabled', false); | ||
59 | $this->conf->write(true); | ||
60 | // TODO: create a proper error handling system able to catch exceptions... | ||
61 | die(t('php-gd extension must be loaded to use thumbnails. Thumbnails are now disabled. Please reload the page.')); | ||
62 | } | ||
63 | |||
64 | $this->wt = new WebThumbnailer(); | ||
65 | WTConfigManager::addFile('inc/web-thumbnailer.json'); | ||
66 | $this->wt->maxWidth($this->conf->get('thumbnails.width')) | ||
67 | ->maxHeight($this->conf->get('thumbnails.height')) | ||
68 | ->crop(true) | ||
69 | ->debug($this->conf->get('dev.debug', false)); | ||
70 | } | ||
71 | |||
72 | /** | ||
73 | * Retrieve a thumbnail for given URL | ||
74 | * | ||
75 | * @param string $url where to look for a thumbnail. | ||
76 | * | ||
77 | * @return bool|string The thumbnail relative cache file path, or false if none has been found. | ||
78 | */ | ||
79 | public function get($url) | ||
80 | { | ||
81 | if ($this->conf->get('thumbnails.mode') === self::MODE_COMMON | ||
82 | && ! $this->isCommonMediaOrImage($url) | ||
83 | ) { | ||
84 | return false; | ||
85 | } | ||
86 | |||
87 | try { | ||
88 | return $this->wt->thumbnail($url); | ||
89 | } catch (WebThumbnailerException $e) { | ||
90 | // Exceptions are only thrown in debug mode. | ||
91 | error_log(get_class($e) . ': ' . $e->getMessage()); | ||
92 | } | ||
93 | return false; | ||
94 | } | ||
95 | |||
96 | /** | ||
97 | * We check weather the given URL is from a common media domain, | ||
98 | * or if the file extension is an image. | ||
99 | * | ||
100 | * @param string $url to check | ||
101 | * | ||
102 | * @return bool true if it's an image or from a common media domain, false otherwise. | ||
103 | */ | ||
104 | public function isCommonMediaOrImage($url) | ||
105 | { | ||
106 | foreach (self::COMMON_MEDIA_DOMAINS as $domain) { | ||
107 | if (strpos($url, $domain) !== false) { | ||
108 | return true; | ||
109 | } | ||
110 | } | ||
111 | |||
112 | if (endsWith($url, '.jpg') || endsWith($url, '.png') || endsWith($url, '.jpeg')) { | ||
113 | return true; | ||
114 | } | ||
115 | |||
116 | return false; | ||
117 | } | ||
118 | |||
119 | /** | ||
120 | * Make sure that requirements are match to use thumbnails: | ||
121 | * - php-gd is loaded | ||
122 | */ | ||
123 | protected function checkRequirements() | ||
124 | { | ||
125 | return extension_loaded('gd'); | ||
126 | } | ||
127 | } | ||
diff --git a/application/Updater.php b/application/Updater.php index dece2c02..c2aa1568 100644 --- a/application/Updater.php +++ b/application/Updater.php | |||
@@ -2,6 +2,7 @@ | |||
2 | use Shaarli\Config\ConfigJson; | 2 | use Shaarli\Config\ConfigJson; |
3 | use Shaarli\Config\ConfigPhp; | 3 | use Shaarli\Config\ConfigPhp; |
4 | use Shaarli\Config\ConfigManager; | 4 | use Shaarli\Config\ConfigManager; |
5 | use Shaarli\Thumbnailer; | ||
5 | 6 | ||
6 | /** | 7 | /** |
7 | * Class Updater. | 8 | * Class Updater. |
@@ -31,6 +32,11 @@ class Updater | |||
31 | protected $isLoggedIn; | 32 | protected $isLoggedIn; |
32 | 33 | ||
33 | /** | 34 | /** |
35 | * @var array $_SESSION | ||
36 | */ | ||
37 | protected $session; | ||
38 | |||
39 | /** | ||
34 | * @var ReflectionMethod[] List of current class methods. | 40 | * @var ReflectionMethod[] List of current class methods. |
35 | */ | 41 | */ |
36 | protected $methods; | 42 | protected $methods; |
@@ -42,13 +48,17 @@ class Updater | |||
42 | * @param LinkDB $linkDB LinkDB instance. | 48 | * @param LinkDB $linkDB LinkDB instance. |
43 | * @param ConfigManager $conf Configuration Manager instance. | 49 | * @param ConfigManager $conf Configuration Manager instance. |
44 | * @param boolean $isLoggedIn True if the user is logged in. | 50 | * @param boolean $isLoggedIn True if the user is logged in. |
51 | * @param array $session $_SESSION (by reference) | ||
52 | * | ||
53 | * @throws ReflectionException | ||
45 | */ | 54 | */ |
46 | public function __construct($doneUpdates, $linkDB, $conf, $isLoggedIn) | 55 | public function __construct($doneUpdates, $linkDB, $conf, $isLoggedIn, &$session = []) |
47 | { | 56 | { |
48 | $this->doneUpdates = $doneUpdates; | 57 | $this->doneUpdates = $doneUpdates; |
49 | $this->linkDB = $linkDB; | 58 | $this->linkDB = $linkDB; |
50 | $this->conf = $conf; | 59 | $this->conf = $conf; |
51 | $this->isLoggedIn = $isLoggedIn; | 60 | $this->isLoggedIn = $isLoggedIn; |
61 | $this->session = &$session; | ||
52 | 62 | ||
53 | // Retrieve all update methods. | 63 | // Retrieve all update methods. |
54 | $class = new ReflectionClass($this); | 64 | $class = new ReflectionClass($this); |
@@ -480,6 +490,30 @@ class Updater | |||
480 | } | 490 | } |
481 | 491 | ||
482 | $this->conf->write($this->isLoggedIn); | 492 | $this->conf->write($this->isLoggedIn); |
493 | return true; | ||
494 | } | ||
495 | |||
496 | /** | ||
497 | * * Move thumbnails management to WebThumbnailer, coming with new settings. | ||
498 | */ | ||
499 | public function updateMethodWebThumbnailer() | ||
500 | { | ||
501 | if ($this->conf->exists('thumbnails.mode')) { | ||
502 | return true; | ||
503 | } | ||
504 | |||
505 | $thumbnailsEnabled = $this->conf->get('thumbnail.enable_thumbnails', true); | ||
506 | $this->conf->set('thumbnails.mode', $thumbnailsEnabled ? Thumbnailer::MODE_ALL : Thumbnailer::MODE_NONE); | ||
507 | $this->conf->set('thumbnails.width', 125); | ||
508 | $this->conf->set('thumbnails.height', 90); | ||
509 | $this->conf->remove('thumbnail'); | ||
510 | $this->conf->write(true); | ||
511 | |||
512 | if ($thumbnailsEnabled) { | ||
513 | $this->session['warnings'][] = t( | ||
514 | 'You have enabled or changed thumbnails mode. <a href="?do=thumbs_update">Please synchronize them</a>.' | ||
515 | ); | ||
516 | } | ||
483 | 517 | ||
484 | return true; | 518 | return true; |
485 | } | 519 | } |
diff --git a/application/config/ConfigManager.php b/application/config/ConfigManager.php index 82f4a368..32aaea48 100644 --- a/application/config/ConfigManager.php +++ b/application/config/ConfigManager.php | |||
@@ -148,6 +148,33 @@ class ConfigManager | |||
148 | } | 148 | } |
149 | 149 | ||
150 | /** | 150 | /** |
151 | * Remove a config element from the config file. | ||
152 | * | ||
153 | * @param string $setting Asked setting, keys separated with dots. | ||
154 | * @param bool $write Write the new setting in the config file, default false. | ||
155 | * @param bool $isLoggedIn User login state, default false. | ||
156 | * | ||
157 | * @throws \Exception Invalid | ||
158 | */ | ||
159 | public function remove($setting, $write = false, $isLoggedIn = false) | ||
160 | { | ||
161 | if (empty($setting) || ! is_string($setting)) { | ||
162 | throw new \Exception(t('Invalid setting key parameter. String expected, got: '). gettype($setting)); | ||
163 | } | ||
164 | |||
165 | // During the ConfigIO transition, map legacy settings to the new ones. | ||
166 | if ($this->configIO instanceof ConfigPhp && isset(ConfigPhp::$LEGACY_KEYS_MAPPING[$setting])) { | ||
167 | $setting = ConfigPhp::$LEGACY_KEYS_MAPPING[$setting]; | ||
168 | } | ||
169 | |||
170 | $settings = explode('.', $setting); | ||
171 | self::removeConfig($settings, $this->loadedConfig); | ||
172 | if ($write) { | ||
173 | $this->write($isLoggedIn); | ||
174 | } | ||
175 | } | ||
176 | |||
177 | /** | ||
151 | * Check if a settings exists. | 178 | * Check if a settings exists. |
152 | * | 179 | * |
153 | * Supports nested settings with dot separated keys. | 180 | * Supports nested settings with dot separated keys. |
@@ -272,7 +299,7 @@ class ConfigManager | |||
272 | * | 299 | * |
273 | * @param array $settings Ordered array which contains keys to find. | 300 | * @param array $settings Ordered array which contains keys to find. |
274 | * @param mixed $value | 301 | * @param mixed $value |
275 | * @param array $conf Loaded settings, then sub-array. | 302 | * @param array $conf Loaded settings, then sub-array. |
276 | * | 303 | * |
277 | * @return mixed Found setting or NOT_FOUND flag. | 304 | * @return mixed Found setting or NOT_FOUND flag. |
278 | */ | 305 | */ |
@@ -290,6 +317,27 @@ class ConfigManager | |||
290 | } | 317 | } |
291 | 318 | ||
292 | /** | 319 | /** |
320 | * Recursive function which find asked setting in the loaded config and deletes it. | ||
321 | * | ||
322 | * @param array $settings Ordered array which contains keys to find. | ||
323 | * @param array $conf Loaded settings, then sub-array. | ||
324 | * | ||
325 | * @return mixed Found setting or NOT_FOUND flag. | ||
326 | */ | ||
327 | protected static function removeConfig($settings, &$conf) | ||
328 | { | ||
329 | if (!is_array($settings) || count($settings) == 0) { | ||
330 | return self::$NOT_FOUND; | ||
331 | } | ||
332 | |||
333 | $setting = array_shift($settings); | ||
334 | if (count($settings) > 0) { | ||
335 | return self::removeConfig($settings, $conf[$setting]); | ||
336 | } | ||
337 | unset($conf[$setting]); | ||
338 | } | ||
339 | |||
340 | /** | ||
293 | * Set a bunch of default values allowing Shaarli to start without a config file. | 341 | * Set a bunch of default values allowing Shaarli to start without a config file. |
294 | */ | 342 | */ |
295 | protected function setDefaultValues() | 343 | protected function setDefaultValues() |
@@ -333,12 +381,12 @@ class ConfigManager | |||
333 | // default state of the 'remember me' checkbox of the login form | 381 | // default state of the 'remember me' checkbox of the login form |
334 | $this->setEmpty('privacy.remember_user_default', true); | 382 | $this->setEmpty('privacy.remember_user_default', true); |
335 | 383 | ||
336 | $this->setEmpty('thumbnail.enable_thumbnails', true); | ||
337 | $this->setEmpty('thumbnail.enable_localcache', true); | ||
338 | |||
339 | $this->setEmpty('redirector.url', ''); | 384 | $this->setEmpty('redirector.url', ''); |
340 | $this->setEmpty('redirector.encode_url', true); | 385 | $this->setEmpty('redirector.encode_url', true); |
341 | 386 | ||
387 | $this->setEmpty('thumbnails.width', '125'); | ||
388 | $this->setEmpty('thumbnails.height', '90'); | ||
389 | |||
342 | $this->setEmpty('translation.language', 'auto'); | 390 | $this->setEmpty('translation.language', 'auto'); |
343 | $this->setEmpty('translation.mode', 'php'); | 391 | $this->setEmpty('translation.mode', 'php'); |
344 | $this->setEmpty('translation.extensions', []); | 392 | $this->setEmpty('translation.extensions', []); |