123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242 |
- <?php
- /**
- * Class PluginManager
- *
- * Use to manage, load and execute plugins.
- */
- class PluginManager
- {
- /**
- * List of authorized plugins from configuration file.
- * @var array $authorizedPlugins
- */
- private $authorizedPlugins;
- /**
- * List of loaded plugins.
- * @var array $loadedPlugins
- */
- private $loadedPlugins = array();
- /**
- * @var ConfigManager Configuration Manager instance.
- */
- protected $conf;
- /**
- * @var array List of plugin errors.
- */
- protected $errors;
- /**
- * Plugins subdirectory.
- * @var string $PLUGINS_PATH
- */
- public static $PLUGINS_PATH = 'plugins';
- /**
- * Plugins meta files extension.
- * @var string $META_EXT
- */
- public static $META_EXT = 'meta';
- /**
- * Constructor.
- *
- * @param ConfigManager $conf Configuration Manager instance.
- */
- public function __construct(&$conf)
- {
- $this->conf = $conf;
- $this->errors = array();
- }
- /**
- * Load plugins listed in $authorizedPlugins.
- *
- * @param array $authorizedPlugins Names of plugin authorized to be loaded.
- *
- * @return void
- */
- public function load($authorizedPlugins)
- {
- $this->authorizedPlugins = $authorizedPlugins;
- $dirs = glob(self::$PLUGINS_PATH . '/*', GLOB_ONLYDIR);
- $dirnames = array_map('basename', $dirs);
- foreach ($this->authorizedPlugins as $plugin) {
- $index = array_search($plugin, $dirnames);
- // plugin authorized, but its folder isn't listed
- if ($index === false) {
- continue;
- }
- try {
- $this->loadPlugin($dirs[$index], $plugin);
- }
- catch (PluginFileNotFoundException $e) {
- error_log($e->getMessage());
- }
- }
- }
- /**
- * Execute all plugins registered hook.
- *
- * @param string $hook name of the hook to trigger.
- * @param array $data list of data to manipulate passed by reference.
- * @param array $params additional parameters such as page target.
- *
- * @return void
- */
- public function executeHooks($hook, &$data, $params = array())
- {
- if (!empty($params['target'])) {
- $data['_PAGE_'] = $params['target'];
- }
- if (isset($params['loggedin'])) {
- $data['_LOGGEDIN_'] = $params['loggedin'];
- }
- foreach ($this->loadedPlugins as $plugin) {
- $hookFunction = $this->buildHookName($hook, $plugin);
- if (function_exists($hookFunction)) {
- $data = call_user_func($hookFunction, $data, $this->conf);
- }
- }
- }
- /**
- * Load a single plugin from its files.
- * Call the init function if it exists, and collect errors.
- * Add them in $loadedPlugins if successful.
- *
- * @param string $dir plugin's directory.
- * @param string $pluginName plugin's name.
- *
- * @return void
- * @throws PluginFileNotFoundException - plugin files not found.
- */
- private function loadPlugin($dir, $pluginName)
- {
- if (!is_dir($dir)) {
- throw new PluginFileNotFoundException($pluginName);
- }
- $pluginFilePath = $dir . '/' . $pluginName . '.php';
- if (!is_file($pluginFilePath)) {
- throw new PluginFileNotFoundException($pluginName);
- }
- $conf = $this->conf;
- include_once $pluginFilePath;
- $initFunction = $pluginName . '_init';
- if (function_exists($initFunction)) {
- $errors = call_user_func($initFunction, $this->conf);
- if (!empty($errors)) {
- $this->errors = array_merge($this->errors, $errors);
- }
- }
- $this->loadedPlugins[] = $pluginName;
- }
- /**
- * Construct normalize hook name for a specific plugin.
- *
- * Format:
- * hook_<plugin_name>_<hook_name>
- *
- * @param string $hook hook name.
- * @param string $pluginName plugin name.
- *
- * @return string - plugin's hook name.
- */
- public function buildHookName($hook, $pluginName)
- {
- return 'hook_' . $pluginName . '_' . $hook;
- }
- /**
- * Retrieve plugins metadata from *.meta (INI) files into an array.
- * Metadata contains:
- * - plugin description [description]
- * - parameters split with ';' [parameters]
- *
- * Respects plugins order from settings.
- *
- * @return array plugins metadata.
- */
- public function getPluginsMeta()
- {
- $metaData = array();
- $dirs = glob(self::$PLUGINS_PATH . '/*', GLOB_ONLYDIR | GLOB_MARK);
- // Browse all plugin directories.
- foreach ($dirs as $pluginDir) {
- $plugin = basename($pluginDir);
- $metaFile = $pluginDir . $plugin . '.' . self::$META_EXT;
- if (!is_file($metaFile) || !is_readable($metaFile)) {
- continue;
- }
- $metaData[$plugin] = parse_ini_file($metaFile);
- $metaData[$plugin]['order'] = array_search($plugin, $this->authorizedPlugins);
- // Read parameters and format them into an array.
- if (isset($metaData[$plugin]['parameters'])) {
- $params = explode(';', $metaData[$plugin]['parameters']);
- } else {
- $params = array();
- }
- $metaData[$plugin]['parameters'] = array();
- foreach ($params as $param) {
- if (empty($param)) {
- continue;
- }
- $metaData[$plugin]['parameters'][$param]['value'] = '';
- // Optional parameter description in parameter.PARAM_NAME=
- if (isset($metaData[$plugin]['parameter.'. $param])) {
- $metaData[$plugin]['parameters'][$param]['desc'] = $metaData[$plugin]['parameter.'. $param];
- }
- }
- }
- return $metaData;
- }
- /**
- * Return the list of encountered errors.
- *
- * @return array List of errors (empty array if none exists).
- */
- public function getErrors()
- {
- return $this->errors;
- }
- }
- /**
- * Class PluginFileNotFoundException
- *
- * Raise when plugin files can't be found.
- */
- class PluginFileNotFoundException extends Exception
- {
- /**
- * Construct exception with plugin name.
- * Generate message.
- *
- * @param string $pluginName name of the plugin not found
- */
- public function __construct($pluginName)
- {
- $this->message = 'Plugin "'. $pluginName .'" files not found.';
- }
- }
|