Total Complexity | 162 |
Total Lines | 1120 |
Duplicated Lines | 0 % |
Changes | 0 |
Complex classes like PluginManager often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use PluginManager, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
18 | class PluginManager { |
||
19 | // True if the Plugin framework is enabled |
||
20 | public $enabled; |
||
21 | |||
22 | // The path to the folder which contains the plugins |
||
23 | public $pluginpath; |
||
24 | |||
25 | // The path to the folder which holds the configuration for the plugins |
||
26 | // This folder has same structure as $this->pluginpath |
||
27 | public $pluginconfigpath; |
||
28 | |||
29 | // List of all plugins and their data |
||
30 | public $plugindata; |
||
31 | |||
32 | // List of the plugins in the order in which |
||
33 | // they should be loaded |
||
34 | public $pluginorder; |
||
35 | |||
36 | /** |
||
37 | * List of all hooks registered by plugins. |
||
38 | * [eventID][] = plugin. |
||
39 | */ |
||
40 | public $hooks; |
||
41 | |||
42 | /** |
||
43 | * List of all plugin objects |
||
44 | * [pluginname] = pluginObj. |
||
45 | */ |
||
46 | public $plugins; |
||
47 | |||
48 | /** |
||
49 | * List of all provided modules |
||
50 | * [modulename] = moduleFile. |
||
51 | */ |
||
52 | public $modules; |
||
53 | |||
54 | /** |
||
55 | * List of all provided notifiers |
||
56 | * [notifiername] = notifierFile. |
||
57 | */ |
||
58 | public $notifiers; |
||
59 | |||
60 | /** |
||
61 | * List of sessiondata from plugins. |
||
62 | * [pluginname] = sessiondata. |
||
63 | */ |
||
64 | public $sessionData; |
||
65 | |||
66 | /** |
||
67 | * Mapping for the XML 'load' attribute values |
||
68 | * on the <serverfile>, <clientfile> or <resourcefile> element |
||
69 | * to the corresponding define. |
||
70 | */ |
||
71 | public $loadMap = [ |
||
72 | 'release' => LOAD_RELEASE, |
||
73 | 'debug' => LOAD_DEBUG, |
||
74 | 'source' => LOAD_SOURCE, |
||
75 | ]; |
||
76 | |||
77 | /** |
||
78 | * Mapping for the XML 'type' attribute values |
||
79 | * on the <serverfile> element to the corresponding define. |
||
80 | */ |
||
81 | public $typeMap = [ |
||
82 | 'plugin' => TYPE_PLUGIN, |
||
83 | 'module' => TYPE_MODULE, |
||
84 | 'notifier' => TYPE_NOTIFIER, |
||
85 | ]; |
||
86 | |||
87 | /** |
||
88 | * Mapping for the XML 'type' attribute values |
||
89 | * on the <depends> element to the corresponding define. |
||
90 | */ |
||
91 | public $dependMap = [ |
||
92 | 'depends' => DEPEND_DEPENDS, |
||
93 | 'requires' => DEPEND_REQUIRES, |
||
94 | 'recommends' => DEPEND_RECOMMENDS, |
||
95 | 'suggests' => DEPEND_SUGGESTS, |
||
96 | ]; |
||
97 | |||
98 | /** |
||
99 | * Constructor. |
||
100 | * |
||
101 | * @param mixed $enable |
||
102 | */ |
||
103 | public function __construct($enable = ENABLE_PLUGINS) { |
||
115 | } |
||
116 | } |
||
117 | |||
118 | /** |
||
119 | * pluginsEnabled. |
||
120 | * |
||
121 | * Checks whether the plugins have been enabled by checking if the proper |
||
122 | * configuration keys are set. |
||
123 | * |
||
124 | * @return bool returns true when plugins enabled, false when not |
||
125 | */ |
||
126 | public function pluginsEnabled() { |
||
127 | return $this->enabled; |
||
128 | } |
||
129 | |||
130 | /** |
||
131 | * detectPlugins. |
||
132 | * |
||
133 | * Detecting the installed plugins either by using the already ready data |
||
134 | * from the state object or otherwise read in all the data and write it into |
||
135 | * the state. |
||
136 | * |
||
137 | * @param string $disabled the list of plugins to disable, this list is separated |
||
138 | * by the ';' character |
||
139 | */ |
||
140 | public function detectPlugins($disabled = '') { |
||
197 | } |
||
198 | |||
199 | /** |
||
200 | * readPluginFolder. |
||
201 | * |
||
202 | * Read all subfolders of the directory referenced to by $this->pluginpath, |
||
203 | * for each subdir, we $this->processPlugin it as a plugin. |
||
204 | * |
||
205 | * @param $disabledPlugins Array The list of disabled plugins, the subfolders |
||
206 | * named as any of the strings inside this list will not be processed |
||
207 | * |
||
208 | * @returns Array The object containing all the processed plugins. The object is a key-value' |
||
209 | * object where the key is the unique name of the plugin, and the value the parsed data. |
||
210 | */ |
||
211 | public function readPluginFolder($disabledPlugins) { |
||
212 | $data = []; |
||
213 | |||
214 | $pluginsdir = opendir($this->pluginpath); |
||
215 | if ($pluginsdir) { |
||
216 | while (($plugin = readdir($pluginsdir)) !== false) { |
||
217 | if ($plugin != '.' && $plugin != '..' && !in_array($plugin, $disabledPlugins)) { |
||
218 | if (is_dir($this->pluginpath . DIRECTORY_SEPARATOR . $plugin)) { |
||
219 | if (is_file($this->pluginpath . DIRECTORY_SEPARATOR . $plugin . DIRECTORY_SEPARATOR . 'manifest.xml')) { |
||
220 | $processed = $this->processPlugin($plugin); |
||
221 | $data[$processed['pluginname']] = $processed; |
||
222 | } |
||
223 | } |
||
224 | } |
||
225 | } |
||
226 | |||
227 | closedir($pluginsdir); |
||
228 | } |
||
229 | |||
230 | return $data; |
||
231 | } |
||
232 | |||
233 | /** |
||
234 | * validatePluginRequirements. |
||
235 | * |
||
236 | * Go over the parsed $this->plugindata and check if all requirements are met. |
||
237 | * This means that for each plugin which defined a "depends" or "requires" plugin |
||
238 | * we check if those plugins are present on the system. If some dependencies are |
||
239 | * not met, the plugin is removed from $this->plugindata. |
||
240 | * |
||
241 | * @return bool False if the $this->plugindata was modified by this function |
||
242 | */ |
||
243 | public function validatePluginRequirements() { |
||
244 | $modified = false; |
||
245 | |||
246 | do { |
||
247 | $success = true; |
||
248 | |||
249 | foreach ($this->plugindata as $pluginname => &$plugin) { |
||
250 | // Check if the plugin had any dependencies |
||
251 | // declared in the manifest. If not, they are obviously |
||
252 | // met. Otherwise we have to check the type of dependencies |
||
253 | // which were declared. |
||
254 | if ($plugin['dependencies']) { |
||
255 | // We only care about the 'depends' and 'requires' |
||
256 | // dependency types. All others are not blocking. |
||
257 | foreach ($plugin['dependencies'][DEPEND_DEPENDS] as &$depends) { |
||
258 | if (!$this->pluginExists($depends['plugin'])) { |
||
259 | if (DEBUG_PLUGINS) { |
||
260 | dump('[PLUGIN ERROR] Plugin "' . $pluginname . '" requires "' . $depends['plugin'] . '" which could not be found'); |
||
261 | } |
||
262 | unset($this->plugindata[$pluginname]); |
||
263 | // Indicate failure, as we have removed a plugin, and the requirements |
||
264 | // must be rechecked. |
||
265 | $success = false; |
||
266 | // Indicate that the plugindata was modified. |
||
267 | $modified = true; |
||
268 | } |
||
269 | } |
||
270 | |||
271 | foreach ($plugin['dependencies'][DEPEND_REQUIRES] as &$depends) { |
||
272 | if (!$this->pluginExists($depends['plugin'])) { |
||
273 | if (DEBUG_PLUGINS) { |
||
274 | dump('[PLUGIN ERROR] Plugin "' . $pluginname . '" requires "' . $depends['plugin'] . '" which could not be found'); |
||
275 | } |
||
276 | unset($this->plugindata[$pluginname]); |
||
277 | // Indicate failure, as we have removed a plugin, and the requirements |
||
278 | // must be rechecked. |
||
279 | $success = false; |
||
280 | // Indicate that the plugindata was modified. |
||
281 | $modified = true; |
||
282 | } |
||
283 | } |
||
284 | } |
||
285 | } |
||
286 | |||
287 | // If a plugin was removed because of a failed dependency or requirement, |
||
288 | // then we have to redo the cycle, because another plugin might have depended |
||
289 | // on the removed plugin. |
||
290 | } |
||
291 | while (!$success); |
||
292 | |||
293 | return !$modified; |
||
294 | } |
||
295 | |||
296 | /** |
||
297 | * buildPluginDependencyOrder. |
||
298 | * |
||
299 | * Go over the parsed $this->plugindata and create a ordered list of the plugins, resembling |
||
300 | * the order in which those plugins should be loaded. This goes over all plugins to read |
||
301 | * the 'dependencies' data and ordering those plugins based on the DEPEND_DEPENDS dependency type. |
||
302 | * |
||
303 | * In case of circular dependencies, the $this->plugindata object might be altered to remove |
||
304 | * the plugin which the broken dependencies. |
||
305 | * |
||
306 | * @return array The array of plugins in the order of which they should be loaded |
||
307 | */ |
||
308 | public function buildPluginDependencyOrder() { |
||
309 | $plugins = array_keys($this->plugindata); |
||
310 | $ordered = []; |
||
311 | $failedCount = 0; |
||
312 | |||
313 | // We are going to keep it quite simple, we keep looping over the $plugins |
||
314 | // array until it is empty. Each time we find a plugin for which all dependencies |
||
315 | // are met, we can put it on the $ordered list. If we have looped over the list twice, |
||
316 | // without updated the $ordered list in any way, then we have found a circular dependency |
||
317 | // and we cannot resolve the plugins correctly. |
||
318 | while (!empty($plugins)) { |
||
319 | $pluginname = array_shift($plugins); |
||
320 | $plugin = $this->plugindata[$pluginname]; |
||
321 | $accepted = true; |
||
322 | |||
323 | // Go over all dependencies to see if they have been met. |
||
324 | if ($plugin['dependencies']) { |
||
325 | for ($i = 0, $len = count($plugin['dependencies'][DEPEND_DEPENDS]); $i < $len; ++$i) { |
||
326 | $dependency = $plugin['dependencies'][DEPEND_DEPENDS][$i]; |
||
327 | if (array_search($dependency['plugin'], $ordered) === false) { |
||
328 | $accepted = false; |
||
329 | break; |
||
330 | } |
||
331 | } |
||
332 | } |
||
333 | |||
334 | if ($accepted) { |
||
335 | // The dependencies for this plugin have been met, we can push |
||
336 | // the plugin into the tree. |
||
337 | $ordered[] = $pluginname; |
||
338 | |||
339 | // Reset the $failedCount property, this ensures that we can keep |
||
340 | // looping because other plugins with previously unresolved dependencies |
||
341 | // could possible be resolved. |
||
342 | $failedCount = 0; |
||
343 | } |
||
344 | else { |
||
345 | // The dependencies for this plugin have not been met, we push |
||
346 | // the plugin back to the list and we will retry later when the |
||
347 | // $ordered list contains more items. |
||
348 | $plugins[] = $pluginname; |
||
349 | |||
350 | // Increase the $failedCount property, this prevents that we could go into |
||
351 | // an infinite loop when a circular dependency was defined. |
||
352 | ++$failedCount; |
||
353 | } |
||
354 | |||
355 | // If the $failedCount matches the the number of items in the $plugins array, |
||
356 | // it means that all unordered plugins have unmet dependencies. This could only |
||
357 | // happen for circular dependencies. In that case we will refuse to load those plugins. |
||
358 | if ($failedCount === count($plugins)) { |
||
359 | foreach ($plugins as $plugin) { |
||
360 | if (DEBUG_PLUGINS) { |
||
361 | dump('[PLUGIN ERROR] Circular dependency detected for plugin "' . $plugin . '"'); |
||
362 | } |
||
363 | unset($this->plugindata[$plugin]); |
||
364 | } |
||
365 | break; |
||
366 | } |
||
367 | } |
||
368 | |||
369 | return $ordered; |
||
370 | } |
||
371 | |||
372 | /** |
||
373 | * initPlugins. |
||
374 | * |
||
375 | * This function includes the server plugin classes, instantiate and |
||
376 | * initialize them. |
||
377 | * |
||
378 | * @param number $load One of LOAD_RELEASE, LOAD_DEBUG, LOAD_SOURCE. This will filter |
||
379 | * the files based on the 'load' attribute. |
||
380 | */ |
||
381 | public function initPlugins($load = LOAD_RELEASE) { |
||
382 | if (!$this->pluginsEnabled()) { |
||
383 | return false; |
||
384 | } |
||
385 | |||
386 | $files = $this->getServerFiles($load); |
||
387 | foreach ($files['server'] as $file) { |
||
388 | include_once $file; |
||
389 | } |
||
390 | |||
391 | // Include the root files of all the plugins and instantiate the plugin |
||
392 | foreach ($this->pluginorder as $plugName) { |
||
393 | $pluginClassName = 'Plugin' . $plugName; |
||
394 | if (class_exists($pluginClassName)) { |
||
395 | $this->plugins[$plugName] = new $pluginClassName(); |
||
396 | $this->plugins[$plugName]->setPluginName($plugName); |
||
397 | $this->plugins[$plugName]->init(); |
||
398 | } |
||
399 | } |
||
400 | |||
401 | $this->modules = $files['modules']; |
||
402 | $this->notifiers = $files['notifiers']; |
||
403 | } |
||
404 | |||
405 | /** |
||
406 | * processPlugin. |
||
407 | * |
||
408 | * Read in the manifest and get the files that need to be included |
||
409 | * for placing hooks, defining modules, etc. |
||
410 | * |
||
411 | * @param $dirname string name of the directory of the plugin |
||
412 | * |
||
413 | * @return array The plugin data read from the given directory |
||
414 | */ |
||
415 | public function processPlugin($dirname) { |
||
416 | // Read XML manifest file of plugin |
||
417 | $handle = fopen($this->pluginpath . DIRECTORY_SEPARATOR . $dirname . DIRECTORY_SEPARATOR . 'manifest.xml', 'rb'); |
||
418 | $xml = ''; |
||
419 | if ($handle) { |
||
420 | while (!feof($handle)) { |
||
421 | $xml .= fread($handle, 4096); |
||
422 | } |
||
423 | fclose($handle); |
||
424 | } |
||
425 | |||
426 | $plugindata = $this->extractPluginDataFromXML($xml, $dirname); |
||
427 | if ($plugindata) { |
||
428 | // Apply the name to the object |
||
429 | $plugindata['pluginname'] = $dirname; |
||
430 | } |
||
431 | else { |
||
432 | if (DEBUG_PLUGINS) { |
||
433 | dump('[PLUGIN ERROR] Plugin "' . $dirname . '" has an invalid manifest.'); |
||
434 | } |
||
435 | } |
||
436 | |||
437 | return $plugindata; |
||
438 | } |
||
439 | |||
440 | /** |
||
441 | * loadSessionData. |
||
442 | * |
||
443 | * Loads sessiondata of the plugins from disk. |
||
444 | * To improve performance the data is only loaded if a |
||
445 | * plugin requests (reads or saves) the data. |
||
446 | * |
||
447 | * @param $pluginname string Identifier of the plugin |
||
448 | */ |
||
449 | public function loadSessionData($pluginname) { |
||
450 | // lazy reading of sessionData |
||
451 | if (!$this->sessionData) { |
||
452 | $sessState = new State('plugin_sessiondata'); |
||
453 | $sessState->open(); |
||
454 | $this->sessionData = $sessState->read("sessionData"); |
||
455 | if (!isset($this->sessionData) || $this->sessionData == "") { |
||
456 | $this->sessionData = []; |
||
457 | } |
||
458 | $sessState->close(); |
||
459 | } |
||
460 | if ($this->pluginExists($pluginname)) { |
||
461 | if (!isset($this->sessionData[$pluginname])) { |
||
462 | $this->sessionData[$pluginname] = []; |
||
463 | } |
||
464 | $this->plugins[$pluginname]->setSessionData($this->sessionData[$pluginname]); |
||
465 | } |
||
466 | } |
||
467 | |||
468 | /** |
||
469 | * saveSessionData. |
||
470 | * |
||
471 | * Saves sessiondata of the plugins to the disk. |
||
472 | * |
||
473 | * @param $pluginname string Identifier of the plugin |
||
474 | */ |
||
475 | public function saveSessionData($pluginname) { |
||
476 | if ($this->pluginExists($pluginname)) { |
||
477 | $this->sessionData[$pluginname] = $this->plugins[$pluginname]->getSessionData(); |
||
478 | } |
||
479 | if ($this->sessionData) { |
||
480 | $sessState = new State('plugin_sessiondata'); |
||
481 | $sessState->open(); |
||
482 | $sessState->write("sessionData", $this->sessionData); |
||
483 | $sessState->close(); |
||
484 | } |
||
485 | } |
||
486 | |||
487 | /** |
||
488 | * pluginExists. |
||
489 | * |
||
490 | * Checks if plugin exists. |
||
491 | * |
||
492 | * @param $pluginname string Identifier of the plugin |
||
493 | * |
||
494 | * @return bool true when plugin exists, false when it does not |
||
495 | */ |
||
496 | public function pluginExists($pluginname) { |
||
497 | if (isset($this->plugindata[$pluginname])) { |
||
498 | return true; |
||
499 | } |
||
500 | |||
501 | return false; |
||
502 | } |
||
503 | |||
504 | /** |
||
505 | * getModuleFilePath. |
||
506 | * |
||
507 | * Obtain the filepath of the given modulename |
||
508 | * |
||
509 | * @param $modulename string Identifier of the modulename |
||
510 | * |
||
511 | * @return string The path to the file for the module |
||
512 | */ |
||
513 | public function getModuleFilePath($modulename) { |
||
514 | return $this->modules[$modulename] ?? false; |
||
515 | } |
||
516 | |||
517 | /** |
||
518 | * getNotifierFilePath. |
||
519 | * |
||
520 | * Obtain the filepath of the given notifiername |
||
521 | * |
||
522 | * @param $notifiername string Identifier of the notifiername |
||
523 | * |
||
524 | * @return string The path to the file for the notifier |
||
525 | */ |
||
526 | public function getNotifierFilePath($notifiername) { |
||
527 | return $this->notifiers[$notifiername] ?? false; |
||
528 | } |
||
529 | |||
530 | /** |
||
531 | * registerHook. |
||
532 | * |
||
533 | * This function allows the plugin to register their hooks. |
||
534 | * |
||
535 | * @param $eventID string Identifier of the event where this hook must be triggered |
||
536 | * @param $pluginName string Name of the plugin that is registering this hook |
||
537 | */ |
||
538 | public function registerHook($eventID, $pluginName) { |
||
539 | $this->hooks[$eventID][$pluginName] = $pluginName; |
||
540 | } |
||
541 | |||
542 | /** |
||
543 | * triggerHook. |
||
544 | * |
||
545 | * This function will call all the registered hooks when their event is triggered. |
||
546 | * |
||
547 | * @param $eventID string Identifier of the event that has just been triggered |
||
548 | * @param $data mixed (Optional) Usually an array of data that the callback function can modify |
||
549 | * |
||
550 | * @return mixed data that has been changed by plugins |
||
551 | */ |
||
552 | public function triggerHook($eventID, $data = []) { |
||
560 | } |
||
561 | |||
562 | /** |
||
563 | * getPluginVersion. |
||
564 | * |
||
565 | * Function is used to prepare version information array from plugindata. |
||
566 | * |
||
567 | * @return array the array of plugins version information |
||
568 | */ |
||
569 | public function getPluginsVersion() { |
||
570 | $versionInfo = []; |
||
571 | foreach ($this->plugindata as $pluginName => $data) { |
||
572 | $versionInfo[$pluginName] = $data["version"]; |
||
573 | } |
||
574 | |||
575 | return $versionInfo; |
||
576 | } |
||
577 | |||
578 | /** |
||
579 | * getServerFilesForComponent. |
||
580 | * |
||
581 | * Called by getServerFiles() to return the list of files which are provided |
||
582 | * for the given component in a particular plugin. |
||
583 | * The paths which are returned start at the root of the webapp. |
||
584 | * |
||
585 | * This function might call itself recursively if it couldn't find any files for |
||
586 | * the given $load type. If no 'source' files are found, it will obtain the 'debug' |
||
587 | * files, if that too files it will fallback to 'release' files. If the latter is |
||
588 | * not found either, no files are returned. |
||
589 | * |
||
590 | * @param string $pluginname The name of the plugin (this is used in the pathname) |
||
591 | * @param array $component The component to read the serverfiles from |
||
592 | * @param number $load One of LOAD_RELEASE, LOAD_DEBUG, LOAD_SOURCE. This will filter |
||
593 | * the files based on the 'load' attribute. |
||
594 | * |
||
595 | * @return array list of paths to the files in this component |
||
596 | */ |
||
597 | public function getServerFilesForComponent($pluginname, $component, $load) { |
||
598 | $componentfiles = [ |
||
599 | 'server' => [], |
||
600 | 'modules' => [], |
||
601 | 'notifiers' => [], |
||
602 | ]; |
||
603 | |||
604 | foreach ($component['serverfiles'][$load] as &$file) { |
||
605 | switch ($file['type']) { |
||
606 | case TYPE_CONFIG: |
||
607 | $componentfiles['server'][] = $this->pluginconfigpath . DIRECTORY_SEPARATOR . $pluginname . DIRECTORY_SEPARATOR . $file['file']; |
||
608 | break; |
||
609 | |||
610 | case TYPE_PLUGIN: |
||
611 | $componentfiles['server'][] = $this->pluginpath . DIRECTORY_SEPARATOR . $pluginname . DIRECTORY_SEPARATOR . $file['file']; |
||
612 | break; |
||
613 | |||
614 | case TYPE_MODULE: |
||
615 | $componentfiles['modules'][$file['module']] = $this->pluginpath . DIRECTORY_SEPARATOR . $pluginname . DIRECTORY_SEPARATOR . $file['file']; |
||
616 | break; |
||
617 | |||
618 | case TYPE_NOTIFIER: |
||
619 | $componentfiles['notifiers'][$file['notifier']] = $this->pluginpath . DIRECTORY_SEPARATOR . $pluginname . DIRECTORY_SEPARATOR . $file['file']; |
||
620 | break; |
||
621 | } |
||
622 | } |
||
623 | unset($file); |
||
624 | |||
625 | return $componentfiles; |
||
626 | } |
||
627 | |||
628 | /** |
||
629 | * getServerFiles. |
||
630 | * |
||
631 | * Returning an array of paths to files that need to be included. |
||
632 | * The paths which are returned start at the root of the webapp. |
||
633 | * |
||
634 | * This calls getServerFilesForComponent() to obtain the files |
||
635 | * for each component inside the requested plugin |
||
636 | * |
||
637 | * @param number $load One of LOAD_RELEASE, LOAD_DEBUG, LOAD_SOURCE. This will filter |
||
638 | * the files based on the 'load' attribute. |
||
639 | * |
||
640 | * @return array list of paths to files |
||
641 | */ |
||
642 | public function getServerFiles($load = LOAD_RELEASE) { |
||
643 | $files = [ |
||
644 | 'server' => [], |
||
645 | 'modules' => [], |
||
646 | 'notifiers' => [], |
||
647 | ]; |
||
648 | |||
649 | foreach ($this->pluginorder as $pluginname) { |
||
650 | $plugin = &$this->plugindata[$pluginname]; |
||
651 | foreach ($plugin['components'] as &$component) { |
||
652 | if (!empty($component['serverfiles'][$load])) { |
||
653 | $componentfiles = $this->getServerFilesForComponent($pluginname, $component, $load); |
||
654 | } |
||
655 | elseif ($load === LOAD_SOURCE && !empty($component['serverfiles'][LOAD_DEBUG])) { |
||
656 | $componentfiles = $this->getServerFilesForComponent($pluginname, $component, LOAD_DEBUG); |
||
657 | } |
||
658 | elseif ($load !== LOAD_RELEASE && !empty($component['serverfiles'][LOAD_RELEASE])) { |
||
659 | $componentfiles = $this->getServerFilesForComponent($pluginname, $component, LOAD_RELEASE); |
||
660 | } // else tough luck, at least release should be present |
||
661 | |||
662 | if (isset($componentfiles)) { |
||
663 | $files['server'] = array_merge($files['server'], $componentfiles['server']); |
||
664 | $files['modules'] = array_merge($files['modules'], $componentfiles['modules']); |
||
665 | $files['notifiers'] = array_merge($files['notifiers'], $componentfiles['notifiers']); |
||
666 | unset($componentfiles); |
||
667 | } |
||
668 | } |
||
669 | unset($component); |
||
670 | } |
||
671 | unset($plugin); |
||
672 | |||
673 | return $files; |
||
674 | } |
||
675 | |||
676 | /** |
||
677 | * getClientFilesForComponent. |
||
678 | * |
||
679 | * Called by getClientFiles() to return the list of files which are provided |
||
680 | * for the given component in a particular plugin. |
||
681 | * The paths which are returned start at the root of the webapp. |
||
682 | * |
||
683 | * This function might call itself recursively if it couldn't find any files for |
||
684 | * the given $load type. If no 'source' files are found, it will obtain the 'debug' |
||
685 | * files, if that too files it will fallback to 'release' files. If the latter is |
||
686 | * not found either, no files are returned. |
||
687 | * |
||
688 | * @param string $pluginname The name of the plugin (this is used in the pathname) |
||
689 | * @param array $component The component to read the clientfiles from |
||
690 | * @param number $load One of LOAD_RELEASE, LOAD_DEBUG, LOAD_SOURCE. This will filter |
||
691 | * the files based on the 'load' attribute. |
||
692 | * |
||
693 | * @return array list of paths to the files in this component |
||
694 | */ |
||
695 | public function getClientFilesForComponent($pluginname, $component, $load) { |
||
704 | } |
||
705 | |||
706 | /** |
||
707 | * getClientFiles. |
||
708 | * |
||
709 | * Returning an array of paths to files that need to be included. |
||
710 | * The paths which are returned start at the root of the webapp. |
||
711 | * |
||
712 | * This calls getClientFilesForComponent() to obtain the files |
||
713 | * for each component inside each plugin. |
||
714 | * |
||
715 | * @param number $load One of LOAD_RELEASE, LOAD_DEBUG, LOAD_SOURCE. This will filter |
||
716 | * the files based on the 'load' attribute. |
||
717 | * |
||
718 | * @return array list of paths to files |
||
719 | */ |
||
720 | public function getClientFiles($load = LOAD_RELEASE) { |
||
721 | $files = []; |
||
722 | |||
723 | foreach ($this->pluginorder as $pluginname) { |
||
724 | $plugin = &$this->plugindata[$pluginname]; |
||
725 | foreach ($plugin['components'] as &$component) { |
||
726 | if (!empty($component['clientfiles'][$load])) { |
||
727 | $componentfiles = $this->getClientFilesForComponent($pluginname, $component, $load); |
||
728 | } |
||
729 | elseif ($load === LOAD_SOURCE && !empty($component['clientfiles'][LOAD_DEBUG])) { |
||
730 | $componentfiles = $this->getClientFilesForComponent($pluginname, $component, LOAD_DEBUG); |
||
731 | } |
||
732 | elseif ($load !== LOAD_RELEASE && !empty($component['clientfiles'][LOAD_RELEASE])) { |
||
733 | $componentfiles = $this->getClientFilesForComponent($pluginname, $component, LOAD_RELEASE); |
||
734 | } // else tough luck, at least release should be present |
||
735 | |||
736 | if (isset($componentfiles)) { |
||
737 | $files = array_merge($files, $componentfiles); |
||
738 | unset($componentfiles); |
||
739 | } |
||
740 | } |
||
741 | unset($component); |
||
742 | } |
||
743 | unset($plugin); |
||
744 | |||
745 | return $files; |
||
746 | } |
||
747 | |||
748 | /** |
||
749 | * getResourceFilesForComponent. |
||
750 | * |
||
751 | * Called by getResourceFiles() to return the list of files which are provided |
||
752 | * for the given component in a particular plugin. |
||
753 | * The paths which are returned start at the root of the webapp. |
||
754 | * |
||
755 | * This function might call itself recursively if it couldn't find any files for |
||
756 | * the given $load type. If no 'source' files are found, it will obtain the 'debug' |
||
757 | * files, if that too files it will fallback to 'release' files. If the latter is |
||
758 | * not found either, no files are returned. |
||
759 | * |
||
760 | * @param string $pluginname The name of the plugin (this is used in the pathname) |
||
761 | * @param array $component The component to read the resourcefiles from |
||
762 | * @param number $load One of LOAD_RELEASE, LOAD_DEBUG, LOAD_SOURCE. This will filter |
||
763 | * the files based on the 'load' attribute. |
||
764 | * |
||
765 | * @return array list of paths to the files in this component |
||
766 | */ |
||
767 | public function getResourceFilesForComponent($pluginname, $component, $load) { |
||
768 | $componentfiles = []; |
||
769 | |||
770 | foreach ($component['resourcefiles'][$load] as &$file) { |
||
771 | $componentfiles[] = $this->pluginpath . DIRECTORY_SEPARATOR . $pluginname . DIRECTORY_SEPARATOR . $file['file']; |
||
772 | } |
||
773 | unset($file); |
||
774 | |||
775 | return $componentfiles; |
||
776 | } |
||
777 | |||
778 | /** |
||
779 | * getResourceFiles. |
||
780 | * |
||
781 | * Returning an array of paths to files that need to be included. |
||
782 | * The paths which are returned start at the root of the webapp. |
||
783 | * |
||
784 | * This calls getResourceFilesForComponent() to obtain the files |
||
785 | * for each component inside each plugin. |
||
786 | * |
||
787 | * @param number $load One of LOAD_RELEASE, LOAD_DEBUG, LOAD_SOURCE. This will filter |
||
788 | * the files based on the 'load' attribute. |
||
789 | * |
||
790 | * @return array list of paths to files |
||
791 | */ |
||
792 | public function getResourceFiles($load = LOAD_RELEASE) { |
||
793 | $files = []; |
||
794 | |||
795 | foreach ($this->pluginorder as $pluginname) { |
||
796 | $plugin = &$this->plugindata[$pluginname]; |
||
797 | foreach ($plugin['components'] as &$component) { |
||
798 | if (!empty($component['resourcefiles'][$load])) { |
||
799 | $componentfiles = $this->getResourceFilesForComponent($pluginname, $component, $load); |
||
800 | } |
||
801 | elseif ($load === LOAD_SOURCE && !empty($component['resourcefiles'][LOAD_DEBUG])) { |
||
802 | $componentfiles = $this->getResourceFilesForComponent($pluginname, $component, LOAD_DEBUG); |
||
803 | } |
||
804 | elseif ($load !== LOAD_RELEASE && !empty($component['resourcefiles'][LOAD_RELEASE])) { |
||
805 | $componentfiles = $this->getResourceFilesForComponent($pluginname, $component, LOAD_RELEASE); |
||
806 | } // else tough luck, at least release should be present |
||
807 | |||
808 | if (isset($componentfiles)) { |
||
809 | $files = array_merge($files, $componentfiles); |
||
810 | unset($componentfiles); |
||
811 | } |
||
812 | } |
||
813 | unset($component); |
||
814 | } |
||
815 | unset($plugin); |
||
816 | |||
817 | return $files; |
||
818 | } |
||
819 | |||
820 | /** |
||
821 | * getTranslationFilePaths. |
||
822 | * |
||
823 | * Returning an array of paths to to the translations files. This will be |
||
824 | * used by the gettext functionality. |
||
825 | * |
||
826 | * @return array list of paths to translations |
||
827 | */ |
||
828 | public function getTranslationFilePaths() { |
||
843 | } |
||
844 | |||
845 | /** |
||
846 | * extractPluginDataFromXML. |
||
847 | * |
||
848 | * Extracts all the data from the Plugin XML manifest. |
||
849 | * |
||
850 | * @param $xml string XML manifest of plugin |
||
851 | * @param $dirname string name of the directory of the plugin |
||
852 | * |
||
853 | * @return array data from XML converted into array that the PluginManager can use |
||
854 | */ |
||
855 | public function extractPluginDataFromXML($xml, $dirname) { |
||
1077 | } |
||
1078 | |||
1079 | /** |
||
1080 | * Expands a string that contains a semicolon separated list of plugins. |
||
1081 | * All wildcards (*) will be resolved. |
||
1082 | * |
||
1083 | * @param mixed $pluginList |
||
1084 | */ |
||
1085 | public function expandPluginList($pluginList) { |
||
1113 | } |
||
1114 | |||
1115 | /** |
||
1116 | * Finds all plugins that match the given string name (that contains one or |
||
1117 | * more wildcards). |
||
1118 | * |
||
1119 | * @param string $pluginNameWithWildcard A plugin identifying string that |
||
1120 | * contains a wildcard character (*) |
||
1121 | * |
||
1122 | * @return array An array with the names of the plugins that are identified by |
||
1123 | * $pluginNameWithWildcard |
||
1124 | */ |
||
1125 | private function _expandPluginNameWithWildcard($pluginNameWithWildcard) { |
||
1140 |
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.
Consider making the comparison explicit by using
empty(..)
or! empty(...)
instead.