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 * Plugins meta files extension.
38 * @var string $META_EXT
40 public static $META_EXT = 'meta';
43 * Private constructor: new instances not allowed.
45 private function __construct()
50 * Cloning isn't allowed either.
54 private function __clone()
59 * Return existing instance of PluginManager, or create it.
61 * @return PluginManager instance.
63 public static function getInstance()
65 if (!(self
::$instance instanceof self
)) {
66 self
::$instance = new self();
69 return self
::$instance;
73 * Load plugins listed in $authorizedPlugins.
75 * @param array $authorizedPlugins Names of plugin authorized to be loaded.
79 public function load($authorizedPlugins)
81 $this->authorizedPlugins
= $authorizedPlugins;
83 $dirs = glob(self
::$PLUGINS_PATH . '/*', GLOB_ONLYDIR
);
84 $dirnames = array_map('basename', $dirs);
85 foreach ($this->authorizedPlugins
as $plugin) {
86 $index = array_search($plugin, $dirnames);
88 // plugin authorized, but its folder isn't listed
89 if ($index === false) {
94 $this->loadPlugin($dirs[$index], $plugin);
96 catch (PluginFileNotFoundException
$e) {
97 error_log($e->getMessage());
103 * Execute all plugins registered hook.
105 * @param string $hook name of the hook to trigger.
106 * @param array $data list of data to manipulate passed by reference.
107 * @param array $params additional parameters such as page target.
111 public function executeHooks($hook, &$data, $params = array())
113 if (!empty($params['target'])) {
114 $data['_PAGE_'] = $params['target'];
117 if (isset($params['loggedin'])) {
118 $data['_LOGGEDIN_'] = $params['loggedin'];
121 foreach ($this->loadedPlugins
as $plugin) {
122 $hookFunction = $this->buildHookName($hook, $plugin);
124 if (function_exists($hookFunction)) {
125 $data = call_user_func($hookFunction, $data);
131 * Load a single plugin from its files.
132 * Add them in $loadedPlugins if successful.
134 * @param string $dir plugin's directory.
135 * @param string $pluginName plugin's name.
138 * @throws PluginFileNotFoundException - plugin files not found.
140 private function loadPlugin($dir, $pluginName)
143 throw new PluginFileNotFoundException($pluginName);
146 $pluginFilePath = $dir . '/' . $pluginName . '.php';
147 if (!is_file($pluginFilePath)) {
148 throw new PluginFileNotFoundException($pluginName);
151 include_once $pluginFilePath;
153 $this->loadedPlugins
[] = $pluginName;
157 * Construct normalize hook name for a specific plugin.
160 * hook_<plugin_name>_<hook_name>
162 * @param string $hook hook name.
163 * @param string $pluginName plugin name.
165 * @return string - plugin's hook name.
167 public function buildHookName($hook, $pluginName)
169 return 'hook_' . $pluginName . '_' . $hook;
173 * Retrieve plugins metadata from *.meta (INI) files into an array.
175 * - plugin description [description]
176 * - parameters split with ';' [parameters]
178 * Respects plugins order from settings.
180 * @return array plugins metadata.
182 public function getPluginsMeta()
185 $dirs = glob(self
::$PLUGINS_PATH . '/*', GLOB_ONLYDIR
| GLOB_MARK
);
187 // Browse all plugin directories.
188 foreach ($dirs as $pluginDir) {
189 $plugin = basename($pluginDir);
190 $metaFile = $pluginDir . $plugin . '.' . self
::$META_EXT;
191 if (!is_file($metaFile) || !is_readable($metaFile)) {
195 $metaData[$plugin] = parse_ini_file($metaFile);
196 $metaData[$plugin]['order'] = array_search($plugin, $this->authorizedPlugins
);
198 // Read parameters and format them into an array.
199 if (isset($metaData[$plugin]['parameters'])) {
200 $params = explode(';', $metaData[$plugin]['parameters']);
204 $metaData[$plugin]['parameters'] = array();
205 foreach ($params as $param) {
210 $metaData[$plugin]['parameters'][$param] = '';
219 * Class PluginFileNotFoundException
221 * Raise when plugin files can't be found.
223 class PluginFileNotFoundException
extends Exception
226 * Construct exception with plugin name.
229 * @param string $pluginName name of the plugin not found
231 public function __construct($pluginName)
233 $this->message
= 'Plugin "'. $pluginName .'" files not found.';