diff options
Diffstat (limited to 'application/plugin/PluginManager.php')
-rw-r--r-- | application/plugin/PluginManager.php | 77 |
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 | |||
2 | namespace Shaarli\Plugin; | 3 | namespace Shaarli\Plugin; |
3 | 4 | ||
4 | use Shaarli\Config\ConfigManager; | 5 | use Shaarli\Config\ConfigManager; |
5 | use Shaarli\Plugin\Exception\PluginFileNotFoundException; | 6 | use Shaarli\Plugin\Exception\PluginFileNotFoundException; |
7 | use 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 | } |