aboutsummaryrefslogtreecommitdiffhomepage
path: root/application/plugin/PluginManager.php
diff options
context:
space:
mode:
Diffstat (limited to 'application/plugin/PluginManager.php')
-rw-r--r--application/plugin/PluginManager.php77
1 files changed, 71 insertions, 6 deletions
diff --git a/application/plugin/PluginManager.php b/application/plugin/PluginManager.php
index da66dea3..7fc0cb04 100644
--- a/application/plugin/PluginManager.php
+++ b/application/plugin/PluginManager.php
@@ -1,8 +1,10 @@
1<?php 1<?php
2
2namespace Shaarli\Plugin; 3namespace Shaarli\Plugin;
3 4
4use Shaarli\Config\ConfigManager; 5use Shaarli\Config\ConfigManager;
5use Shaarli\Plugin\Exception\PluginFileNotFoundException; 6use Shaarli\Plugin\Exception\PluginFileNotFoundException;
7use Shaarli\Plugin\Exception\PluginInvalidRouteException;
6 8
7/** 9/**
8 * Class PluginManager 10 * Class PluginManager
@@ -23,7 +25,15 @@ class PluginManager
23 * 25 *
24 * @var array $loadedPlugins 26 * @var array $loadedPlugins
25 */ 27 */
26 private $loadedPlugins = array(); 28 private $loadedPlugins = [];
29
30 /** @var array List of registered routes. Contains keys:
31 * - `method`: HTTP method, GET/POST/PUT/PATCH/DELETE
32 * - `route` (path): without prefix, e.g. `/up/{variable}`
33 * It will be later prefixed by `/plugin/<plugin name>/`.
34 * - `callable` string, function name or FQN class's method, e.g. `demo_plugin_custom_controller`.
35 */
36 protected $registeredRoutes = [];
27 37
28 /** 38 /**
29 * @var ConfigManager Configuration Manager instance. 39 * @var ConfigManager Configuration Manager instance.
@@ -57,7 +67,7 @@ class PluginManager
57 public function __construct(&$conf) 67 public function __construct(&$conf)
58 { 68 {
59 $this->conf = $conf; 69 $this->conf = $conf;
60 $this->errors = array(); 70 $this->errors = [];
61 } 71 }
62 72
63 /** 73 /**
@@ -85,6 +95,9 @@ class PluginManager
85 $this->loadPlugin($dirs[$index], $plugin); 95 $this->loadPlugin($dirs[$index], $plugin);
86 } catch (PluginFileNotFoundException $e) { 96 } catch (PluginFileNotFoundException $e) {
87 error_log($e->getMessage()); 97 error_log($e->getMessage());
98 } catch (\Throwable $e) {
99 $error = $plugin . t(' [plugin incompatibility]: ') . $e->getMessage();
100 $this->errors = array_unique(array_merge($this->errors, [$error]));
88 } 101 }
89 } 102 }
90 } 103 }
@@ -98,7 +111,7 @@ class PluginManager
98 * 111 *
99 * @return void 112 * @return void
100 */ 113 */
101 public function executeHooks($hook, &$data, $params = array()) 114 public function executeHooks($hook, &$data, $params = [])
102 { 115 {
103 $metadataParameters = [ 116 $metadataParameters = [
104 'target' => '_PAGE_', 117 'target' => '_PAGE_',
@@ -165,6 +178,22 @@ class PluginManager
165 } 178 }
166 } 179 }
167 180
181 $registerRouteFunction = $pluginName . '_register_routes';
182 $routes = null;
183 if (function_exists($registerRouteFunction)) {
184 $routes = call_user_func($registerRouteFunction);
185 }
186
187 if ($routes !== null) {
188 foreach ($routes as $route) {
189 if (static::validateRouteRegistration($route)) {
190 $this->registeredRoutes[$pluginName][] = $route;
191 } else {
192 throw new PluginInvalidRouteException($pluginName);
193 }
194 }
195 }
196
168 $this->loadedPlugins[] = $pluginName; 197 $this->loadedPlugins[] = $pluginName;
169 } 198 }
170 199
@@ -196,7 +225,7 @@ class PluginManager
196 */ 225 */
197 public function getPluginsMeta() 226 public function getPluginsMeta()
198 { 227 {
199 $metaData = array(); 228 $metaData = [];
200 $dirs = glob(self::$PLUGINS_PATH . '/*', GLOB_ONLYDIR | GLOB_MARK); 229 $dirs = glob(self::$PLUGINS_PATH . '/*', GLOB_ONLYDIR | GLOB_MARK);
201 230
202 // Browse all plugin directories. 231 // Browse all plugin directories.
@@ -217,9 +246,9 @@ class PluginManager
217 if (isset($metaData[$plugin]['parameters'])) { 246 if (isset($metaData[$plugin]['parameters'])) {
218 $params = explode(';', $metaData[$plugin]['parameters']); 247 $params = explode(';', $metaData[$plugin]['parameters']);
219 } else { 248 } else {
220 $params = array(); 249 $params = [];
221 } 250 }
222 $metaData[$plugin]['parameters'] = array(); 251 $metaData[$plugin]['parameters'] = [];
223 foreach ($params as $param) { 252 foreach ($params as $param) {
224 if (empty($param)) { 253 if (empty($param)) {
225 continue; 254 continue;
@@ -237,6 +266,14 @@ class PluginManager
237 } 266 }
238 267
239 /** 268 /**
269 * @return array List of registered custom routes by plugins.
270 */
271 public function getRegisteredRoutes(): array
272 {
273 return $this->registeredRoutes;
274 }
275
276 /**
240 * Return the list of encountered errors. 277 * Return the list of encountered errors.
241 * 278 *
242 * @return array List of errors (empty array if none exists). 279 * @return array List of errors (empty array if none exists).
@@ -245,4 +282,32 @@ class PluginManager
245 { 282 {
246 return $this->errors; 283 return $this->errors;
247 } 284 }
285
286 /**
287 * Checks whether provided input is valid to register a new route.
288 * It must contain keys `method`, `route`, `callable` (all strings).
289 *
290 * @param string[] $input
291 *
292 * @return bool
293 */
294 protected static function validateRouteRegistration(array $input): bool
295 {
296 if (
297 !array_key_exists('method', $input)
298 || !in_array(strtoupper($input['method']), ['GET', 'PUT', 'PATCH', 'POST', 'DELETE'])
299 ) {
300 return false;
301 }
302
303 if (!array_key_exists('route', $input) || !preg_match('#^[a-z\d/\.\-_]+$#', $input['route'])) {
304 return false;
305 }
306
307 if (!array_key_exists('callable', $input)) {
308 return false;
309 }
310
311 return true;
312 }
248} 313}