initial import from onelab svn codebase
[plewww.git] / includes / module.inc
1 <?php
2 // $Id: module.inc 144 2007-03-28 07:52:20Z thierry $
3
4 /**
5  * @file
6  * API for loading and interacting with Drupal modules.
7  */
8
9 /**
10  * Load all the modules that have been enabled in the system table.
11  */
12 function module_load_all() {
13   foreach (module_list(TRUE, FALSE) as $module) {
14     drupal_load('module', $module);
15   }
16 }
17
18 /**
19  * Call a function repeatedly with each module in turn as an argument.
20  */
21 function module_iterate($function, $argument = '') {
22   foreach (module_list() as $name) {
23     $function($name, $argument);
24   }
25 }
26
27 /**
28  * Collect a list of all loaded modules. During the bootstrap, return only
29  * vital modules. See bootstrap.inc
30  *
31  * @param $refresh
32  *   Whether to force the module list to be regenerated (such as after the
33  *   administrator has changed the system settings).
34  * @param $bootstrap
35  *   Whether to return the reduced set of modules loaded in "bootstrap mode"
36  *   for cached pages. See bootstrap.inc.
37  * @param $sort
38  *   By default, modules are ordered by weight and filename, settings this option
39  *   to TRUE, module list will be ordered by module name.
40  * @return
41  *   An associative array whose keys and values are the names of all loaded
42  *   modules.
43  */
44 function module_list($refresh = FALSE, $bootstrap = TRUE, $sort = FALSE) {
45   static $list, $sorted_list;
46
47   if ($refresh) {
48     $list = array();
49     $sorted_list = NULL;
50   }
51
52   if (!$list) {
53     $list = array('filter' => 'filter', 'node' => 'node', 'system' => 'system', 'user' => 'user', 'watchdog' => 'watchdog');
54     if ($bootstrap) {
55       $result = db_query("SELECT name, filename, throttle, bootstrap FROM {system} WHERE type = 'module' AND status = 1 AND bootstrap = 1 ORDER BY weight ASC, filename ASC");
56     }
57     else {
58       $result = db_query("SELECT name, filename, throttle, bootstrap FROM {system} WHERE type = 'module' AND status = 1 ORDER BY weight ASC, filename ASC");
59     }
60     while ($module = db_fetch_object($result)) {
61       if (file_exists($module->filename)) {
62         // Determine the current throttle status and see if the module should be
63         // loaded based on server load. We have to directly access the throttle
64         // variables, since throttle.module may not be loaded yet.
65         $throttle = ($module->throttle && variable_get('throttle_level', 0) > 0);
66         if (!$throttle) {
67           drupal_get_filename('module', $module->name, $module->filename);
68           $list[$module->name] = $module->name;
69         }
70       }
71     }
72   }
73   if ($sort) {
74     if (!isset($sorted_list)) {
75       $sorted_list = $list;
76       ksort($sorted_list);
77     }
78     return $sorted_list;
79   }
80   return $list;
81 }
82
83 /**
84  * Determine whether a given module exists.
85  *
86  * @param $module
87  *   The name of the module (without the .module extension).
88  * @return
89  *   TRUE if the module is both installed and enabled.
90  */
91 function module_exist($module) {
92   $list = module_list();
93   return array_key_exists($module, $list);
94 }
95
96 /**
97  * @defgroup hooks Hooks
98  * @{
99  * Allow modules to interact with the Drupal core.
100  *
101  * Drupal's module system is based on the concept of "hooks". A hook is a PHP
102  * function that is named foo_bar(), where "foo" is the name of the module (whose
103  * filename is thus foo.module) and "bar" is the name of the hook. Each hook has
104  * a defined set of parameters and a specified result type.
105  *
106  * To extend Drupal, a module need simply implement a hook. When Drupal wishes to
107  * allow intervention from modules, it determines which modules implement a hook
108  * and call that hook in all enabled modules that implement it.
109  *
110  * The available hooks to implement are explained here in the Hooks section of
111  * the developer documentation. The string "hook" is used as a placeholder for
112  * the module name is the hook definitions. For example, if the module file is
113  * called example.module, then hook_help() as implemented by that module would be
114  * defined as example_help().
115  */
116
117 /**
118  * Determine whether a module implements a hook.
119  *
120  * @param $module
121  *   The name of the module (without the .module extension).
122  * @param $hook
123  *   The name of the hook (e.g. "help" or "menu").
124  * @return
125  *   TRUE if the module is both installed and enabled, and the hook is
126  *   implemented in that module.
127  */
128 function module_hook($module, $hook) {
129   return function_exists($module .'_'. $hook);
130 }
131
132 /**
133  * Determine which modules are implementing a hook.
134  *
135  * @param $hook
136  *   The name of the hook (e.g. "help" or "menu").
137  * @param $sort
138  *   By default, modules are ordered by weight and filename, settings this option
139  *   to TRUE, module list will be ordered by module name.
140  * @return
141  *   An array with the names of the modules which are implementing this hook.
142  */
143 function module_implements($hook, $sort = FALSE) {
144   static $implementations;
145
146   if (!isset($implementations[$hook])) {
147     $implementations[$hook] = array();
148     $list = module_list(FALSE, TRUE, $sort);
149     foreach ($list as $module) {
150       if (module_hook($module, $hook)) {
151         $implementations[$hook][] = $module;
152       }
153     }
154   }
155
156   // The explicit cast forces a copy to be made.  This is needed because
157   // $implementations[$hook] is only a reference to an element of
158   // $implementations and if there are nested foreaches (due to nested node
159   // API calls, for example), they would both manipulate the same array's
160   // references, which causes some modules' hooks not to be called.
161   // See also http://www.zend.com/zend/art/ref-count.php.
162   return (array)$implementations[$hook];
163 }
164
165 /**
166  * Invoke a hook in a particular module.
167  *
168  * @param $module
169  *   The name of the module (without the .module extension).
170  * @param $hook
171  *   The name of the hook to invoke.
172  * @param ...
173  *   Arguments to pass to the hook implementation.
174  * @return
175  *   The return value of the hook implementation.
176  */
177 function module_invoke() {
178   $args = func_get_args();
179   $module = array_shift($args);
180   $hook = array_shift($args);
181   $function = $module .'_'. $hook;
182   if (module_hook($module, $hook)) {
183     return call_user_func_array($function, $args);
184   }
185 }
186 /**
187  * Invoke a hook in all enabled modules that implement it.
188  *
189  * @param $hook
190  *   The name of the hook to invoke.
191  * @param ...
192  *   Arguments to pass to the hook.
193  * @return
194  *   An array of return values of the hook implementations. If modules return
195  *   arrays from their implementations, those are merged into one array.
196  */
197 function module_invoke_all() {
198   $args = func_get_args();
199   $hook = array_shift($args);
200   $return = array();
201   foreach (module_implements($hook) as $module) {
202     $function = $module .'_'. $hook;
203     $result = call_user_func_array($function, $args);
204     if (isset($result) && is_array($result)) {
205       $return = array_merge($return, $result);
206     }
207     else if (isset($result)) {
208       $return[] = $result;
209     }
210   }
211
212   return $return;
213 }
214
215 /**
216  * @} End of "defgroup hooks".
217  */
218
219