6 * Use to manage, load and execute plugins.
8 * Using Singleton design pattern.
13 * PluginManager singleton instance.
14 * @var PluginManager $instance
16 private static $instance;
19 * List of authorized plugins from configuration file.
20 * @var array $authorizedPlugins
22 private $authorizedPlugins;
25 * List of loaded plugins.
26 * @var array $loadedPlugins
28 private $loadedPlugins = array();
31 * Plugins subdirectory.
32 * @var string $PLUGINS_PATH
34 public static $PLUGINS_PATH = 'plugins';
37 * Private constructor: new instances not allowed.
39 private function __construct()
44 * Cloning isn't allowed either.
48 private function __clone()
53 * Return existing instance of PluginManager, or create it.
55 * @return PluginManager instance.
57 public static function getInstance()
59 if (!(self
::$instance instanceof self
)) {
60 self
::$instance = new self();
63 return self
::$instance;
67 * Load plugins listed in $authorizedPlugins.
69 * @param array $authorizedPlugins Names of plugin authorized to be loaded.
73 public function load($authorizedPlugins)
75 $this->authorizedPlugins
= $authorizedPlugins;
77 $dirs = glob(self
::$PLUGINS_PATH . '/*', GLOB_ONLYDIR
);
78 $dirnames = array_map('basename', $dirs);
79 foreach ($this->authorizedPlugins
as $plugin) {
80 $index = array_search($plugin, $dirnames);
82 // plugin authorized, but its folder isn't listed
83 if ($index === false) {
88 $this->loadPlugin($dirs[$index], $plugin);
90 catch (PluginFileNotFoundException
$e) {
91 error_log($e->getMessage());
97 * Execute all plugins registered hook.
99 * @param string $hook name of the hook to trigger.
100 * @param array $data list of data to manipulate passed by reference.
101 * @param array $params additional parameters such as page target.
105 public function executeHooks($hook, &$data, $params = array())
107 if (!empty($params['target'])) {
108 $data['_PAGE_'] = $params['target'];
111 if (isset($params['loggedin'])) {
112 $data['_LOGGEDIN_'] = $params['loggedin'];
115 foreach ($this->loadedPlugins
as $plugin) {
116 $hookFunction = $this->buildHookName($hook, $plugin);
118 if (function_exists($hookFunction)) {
119 $data = call_user_func($hookFunction, $data);
125 * Load a single plugin from its files.
126 * Add them in $loadedPlugins if successful.
128 * @param string $dir plugin's directory.
129 * @param string $pluginName plugin's name.
132 * @throws PluginFileNotFoundException - plugin files not found.
134 private function loadPlugin($dir, $pluginName)
137 throw new PluginFileNotFoundException($pluginName);
140 $pluginFilePath = $dir . '/' . $pluginName . '.php';
141 if (!is_file($pluginFilePath)) {
142 throw new PluginFileNotFoundException($pluginName);
145 include_once $pluginFilePath;
147 $this->loadedPlugins
[] = $pluginName;
151 * Construct normalize hook name for a specific plugin.
154 * hook_<plugin_name>_<hook_name>
156 * @param string $hook hook name.
157 * @param string $pluginName plugin name.
159 * @return string - plugin's hook name.
161 public function buildHookName($hook, $pluginName)
163 return 'hook_' . $pluginName . '_' . $hook;
168 * Class PluginFileNotFoundException
170 * Raise when plugin files can't be found.
172 class PluginFileNotFoundException
extends Exception
175 * Construct exception with plugin name.
178 * @param string $pluginName name of the plugin not found
180 public function __construct($pluginName)
182 $this->message
= 'Plugin "'. $pluginName .'" files not found.';