3 * FusionForge plugin system
5 * Copyright 2002-2017, Roland Mas
6 * Copyright 2014,2021, Franck Villaume - TrivialDev
7 * http://fusionforge.org
9 * This file is part of FusionForge. FusionForge is free software;
10 * you can redistribute it and/or modify it under the terms of the
11 * GNU General Public License as published by the Free Software
12 * Foundation; either version 2 of the Licence, or (at your option)
15 * FusionForge is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License along
21 * with FusionForge; if not, write to the Free Software Foundation, Inc.,
22 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25 class PluginManager extends FFError {
27 var $plugins_to_hooks;
28 var $hooks_to_plugins;
29 var $returned_values = array();
30 var $plugins_data = array();
32 function __construct() {
33 parent::__construct();
34 $this->plugins_objects = array();
35 $this->plugins_to_hooks = array();
36 $this->hooks_to_plugins = array();
38 //to work with Codendi files
39 static function instance() {
40 global $PLUGINMANAGER_OBJ;
41 if (!isset($PLUGINMANAGER_OBJ) || !$PLUGINMANAGER_OBJ) {
42 $PLUGINMANAGER_OBJ = new PluginManager;
44 return $PLUGINMANAGER_OBJ;
48 * getPlugins() - get a list of installed plugins
50 * @return array hash of plugin id => plugin names
52 function getPlugins() {
53 $this->plugins_data = array();
54 $res = db_query_params('SELECT plugin_id, plugin_name FROM plugins ORDER BY plugin_name',
56 $rows = db_numrows($res);
57 for ($i=0; $i<$rows; $i++) {
58 $plugin_id = db_result($res, $i, 'plugin_id');
59 $this->plugins_data[$plugin_id] = db_result($res, $i, 'plugin_name');
61 return $this->plugins_data;
65 * GetPluginObject() - get a particular plugin object
67 * @param string $pluginname name of plugin
68 * @return object|bool plugin object or false if not available
70 function GetPluginObject($pluginname) {
71 if (!isset($this->plugins_objects[$pluginname])) {
74 return $this->plugins_objects[$pluginname];
77 //Added for Codendi compatibility
78 function getPluginByName($pluginname) {
79 return @$this->plugins_objects[$pluginname];
83 * PluginIsInstalled() - is a plugin installed?
85 * @param string $pluginname name of plugin
86 * @return bool true if installed
88 function PluginIsInstalled($pluginname) {
89 $plugins_names = $this->getPlugins();
90 foreach ($plugins_names as $p_name) {
91 if ($p_name == $pluginname) {
99 * isPluginAvailable() - is a plugin available?
101 * @param string $plugin name of plugin
102 * @return bool true if installed
104 function isPluginAvailable($plugin) {
105 $pluginname = $plugin->GetName();
106 $plugins_names = $this->getPlugins();
107 foreach ($plugins_names as $p_name) {
108 if ($p_name == $pluginname) {
114 function activate($pluginname) {
115 $query_exists = 'SELECT plugin_id, plugin_name FROM plugins WHERE plugin_name=$1';
116 $res = db_query_params($query_exists, array($pluginname));
117 if (db_numrows($res) == 0) {
118 db_query_params('INSERT INTO plugins (plugin_name,plugin_desc) VALUES ($1,$2)',
119 array($pluginname, "This is the $pluginname plugin"));
122 $res = db_query_params($query_exists, array($pluginname));
123 if (db_numrows($res) == 1) {
124 $plugin_id = db_result($res, 0, 'plugin_id');
125 $this->plugins_data[$plugin_id] = db_result($res,0,'plugin_name');
132 function deactivate($pluginname) {
133 $res = db_query_params('DELETE FROM plugins WHERE plugin_name = $1', array($pluginname));
137 if (!isset($this->plugins_data)) {
138 $this->plugins_data = array();
140 foreach ($this->plugins_data as $i => $n) {
141 if ($n == $pluginname) {
146 unset($this->plugins_data[$p_id]);
152 * LoadPlugin() - load a specific plugin
154 * @param string $p_name plugin name
157 function LoadPlugin($p_name) {
158 global $gfplugins, $gfcommon, $gfwww;
160 $include_path = forge_get_config('plugins_path');
161 $filename = $include_path . '/'. $p_name . "/common/".$p_name."-init.php";
162 if (file_exists($filename)) {
163 require_once ($filename);
165 $filename = $include_path . '/'. $p_name . "/common/".$p_name."Plugin.class.php";
166 if (file_exists($filename)) {
167 require_once($filename);
168 $p_class = $p_name.'Plugin';
169 register_plugin(new $p_class);
176 * LoadPlugins() - load available plugins
179 function LoadPlugins() {
180 $plugins_names = $this->getPlugins();
181 foreach ($plugins_names as $p_id => $p_name) {
182 if (!$this->LoadPlugin($p_name)) {
183 // we can't find the plugin so we remove it from the array
184 unset($this->plugins_data[$p_id]);
191 * SetupHooks() - setup all hooks for installed plugins
194 function SetupHooks() {
195 $this->hooks_to_plugins = array();
196 foreach ($this->plugins_to_hooks as $p_name => $hook_list) {
197 foreach ($hook_list as $hook_name) {
198 if (!isset($this->hooks_to_plugins[$hook_name])) {
199 $this->hooks_to_plugins[$hook_name] = array();
201 $this->hooks_to_plugins[$hook_name][] = $p_name;
208 * RegisterPlugin() - register a plugin
210 * @param object $pluginobject an object of a subclass of the Plugin class
213 function RegisterPlugin($pluginobject) {
214 if (!$pluginobject->GetName()) {
215 exit_error(_("Some plugin did not provide a name. I'd gladly tell you which one, but obviously I cannot. Sorry."),'');
217 $p_name = $pluginobject->GetName();
218 $this->plugins_objects[$p_name] =& $pluginobject;
219 $this->plugins_to_hooks[$p_name] = array_unique($pluginobject->GetHooks());
224 * RunHooks() - call hooks from a particular point
226 * @param string $hookname - name of the hook
227 * @param array $params - array of extra parameters
229 * @return bool, true if all returned true.
231 function RunHooks($hookname, & $params) {
233 $this->returned_values[$hookname] = array();
234 if (isset($this->hooks_to_plugins[$hookname])) {
235 $p_list = $this->hooks_to_plugins[$hookname];
236 foreach ($p_list as $p_name) {
237 $p_obj = $this->plugins_objects[$p_name];
238 if (method_exists($p_obj, $hookname)) {
239 $returned = $p_obj->$hookname($params);
241 $returned = $p_obj->CallHook($hookname, $params);
243 $this->returned_values[$hookname][$p_name] = $returned;
244 $result = $result && $returned;
247 // Return true only if all the plugins have returned true.
251 function getReturnedValues($hookname) {
252 return $this->returned_values[$hookname];
255 function getReturnedValuesAsString($hookname) {
258 if (isset($this->returned_values[$hookname])) {
259 foreach ($this->returned_values[$hookname] as $value) {
268 * CountHookListeners() - number of listeners on a particular hook
270 * @param string $hookname name of the hook
271 * @return int nb of listeners for this hookname
273 function CountHookListeners($hookname) {
274 if (isset($this->hooks_to_plugins[$hookname])) {
275 $p_list = $this->hooks_to_plugins[$hookname];
276 return count($p_list);
283 * GetHookListeners() - list of plugins listening on a particular hook
285 * @param string $hookname name of the hook
286 * @return array array of plugin names, listening for this hookname
288 function GetHookListeners($hookname) {
289 if (isset($this->hooks_to_plugins[$hookname])) {
290 return $this->hooks_to_plugins[$hookname];
296 function isPluginAllowedForProject($p, $group_id) {
297 $Group = group_get_object($group_id);
298 return $Group->usesPlugin($p->getName());
303 * plugin_manager_get_object() - get the PluginManager object
305 * @return PluginManager the PluginManager object
307 function &plugin_manager_get_object() {
308 global $PLUGINMANAGER_OBJ;
309 if (!isset($PLUGINMANAGER_OBJ) || !$PLUGINMANAGER_OBJ) {
310 $PLUGINMANAGER_OBJ = new PluginManager;
312 return $PLUGINMANAGER_OBJ;
316 * plugin_get_object() - get a particular Plugin object
318 * @param string $pluginname - a plugin name
319 * @return Plugin The Plugin object
321 function &plugin_get_object($pluginname) {
322 global $PLUGINMANAGER_OBJ;
323 $result = $PLUGINMANAGER_OBJ->Getpluginobject($pluginname);
328 * register_plugin() - register a plugin
330 * @param pluginobject - an object of a subclass of the Plugin class
333 function register_plugin($pluginobject) {
334 $pm =&plugin_manager_get_object();
335 return $pm->RegisterPlugin($pluginobject);
339 * plugin_hook() - run a set of hooks
341 * @param string $hookname - name of the hook
342 * @param array $params - parameters for the hook
345 function plugin_hook($hookname, $params = array()) {
346 $pm =& plugin_manager_get_object();
347 return $pm->RunHooks($hookname, $params);
351 * plugin_hook_by_reference() - run a set of hooks with params passed by reference
353 * @param string $hookname - name of the hook
354 * @param array $params - parameters for the hook
357 function plugin_hook_by_reference($hookname, &$params) {
358 $pm =& plugin_manager_get_object();
359 return $pm->RunHooks($hookname, $params);
363 * plugin_hook_listeners() - count the number of listeners on a hook
365 * @param string $hookname - name of the hook
368 function plugin_hook_listeners($hookname) {
369 $pm =& plugin_manager_get_object();
370 return $pm->CountHookListeners($hookname);
374 * setup_plugin_manager() - initialise the plugin infrastructure
377 function setup_plugin_manager() {
378 $pm =& plugin_manager_get_object();
386 // c-file-style: "bsd"