| [ Index ] |
PHP Cross Reference of Drupal 6 (gatewave) |
[Summary view] [Print] [Text view]
1 <?php 2 // $Id: module.inc,v 1.115.2.5 2010/12/15 14:50:25 goba Exp $ 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 * @param $fixed_list 41 * (Optional) Override the module list with the given modules. Stays until the 42 * next call with $refresh = TRUE. 43 * @return 44 * An associative array whose keys and values are the names of all loaded 45 * modules. 46 */ 47 function module_list($refresh = FALSE, $bootstrap = TRUE, $sort = FALSE, $fixed_list = NULL) { 48 static $list, $sorted_list; 49 50 if ($refresh || $fixed_list) { 51 $list = array(); 52 $sorted_list = NULL; 53 if ($fixed_list) { 54 foreach ($fixed_list as $name => $module) { 55 drupal_get_filename('module', $name, $module['filename']); 56 $list[$name] = $name; 57 } 58 } 59 else { 60 if ($bootstrap) { 61 $result = db_query("SELECT name, filename, throttle FROM {system} WHERE type = 'module' AND status = 1 AND bootstrap = 1 ORDER BY weight ASC, filename ASC"); 62 } 63 else { 64 $result = db_query("SELECT name, filename, throttle FROM {system} WHERE type = 'module' AND status = 1 ORDER BY weight ASC, filename ASC"); 65 } 66 while ($module = db_fetch_object($result)) { 67 if (file_exists($module->filename)) { 68 // Determine the current throttle status and see if the module should be 69 // loaded based on server load. We have to directly access the throttle 70 // variables, since throttle.module may not be loaded yet. 71 $throttle = ($module->throttle && variable_get('throttle_level', 0) > 0); 72 if (!$throttle) { 73 drupal_get_filename('module', $module->name, $module->filename); 74 $list[$module->name] = $module->name; 75 } 76 } 77 } 78 } 79 } 80 if ($sort) { 81 if (!isset($sorted_list)) { 82 $sorted_list = $list; 83 ksort($sorted_list); 84 } 85 return $sorted_list; 86 } 87 return $list; 88 } 89 90 /** 91 * Rebuild the database cache of module files. 92 * 93 * @return 94 * The array of filesystem objects used to rebuild the cache. 95 */ 96 function module_rebuild_cache() { 97 // Get current list of modules 98 $files = drupal_system_listing('\.module$', 'modules', 'name', 0); 99 100 // Extract current files from database. 101 system_get_files_database($files, 'module'); 102 103 ksort($files); 104 105 // Set defaults for module info 106 $defaults = array( 107 'dependencies' => array(), 108 'dependents' => array(), 109 'description' => '', 110 'version' => NULL, 111 'php' => DRUPAL_MINIMUM_PHP, 112 ); 113 114 foreach ($files as $filename => $file) { 115 // Look for the info file. 116 $file->info = drupal_parse_info_file(dirname($file->filename) .'/'. $file->name .'.info'); 117 118 // Skip modules that don't provide info. 119 if (empty($file->info)) { 120 unset($files[$filename]); 121 continue; 122 } 123 // Merge in defaults and save. 124 $files[$filename]->info = $file->info + $defaults; 125 126 // Invoke hook_system_info_alter() to give installed modules a chance to 127 // modify the data in the .info files if necessary. 128 drupal_alter('system_info', $files[$filename]->info, $files[$filename]); 129 130 // Log the critical hooks implemented by this module. 131 $bootstrap = 0; 132 foreach (bootstrap_hooks() as $hook) { 133 if (module_hook($file->name, $hook)) { 134 $bootstrap = 1; 135 break; 136 } 137 } 138 139 // Update the contents of the system table: 140 if (isset($file->status) || (isset($file->old_filename) && $file->old_filename != $file->filename)) { 141 db_query("UPDATE {system} SET info = '%s', name = '%s', filename = '%s', bootstrap = %d WHERE filename = '%s'", serialize($files[$filename]->info), $file->name, $file->filename, $bootstrap, $file->old_filename); 142 } 143 else { 144 // This is a new module. 145 $files[$filename]->status = 0; 146 $files[$filename]->throttle = 0; 147 db_query("INSERT INTO {system} (name, info, type, filename, status, throttle, bootstrap) VALUES ('%s', '%s', '%s', '%s', %d, %d, %d)", $file->name, serialize($files[$filename]->info), 'module', $file->filename, 0, 0, $bootstrap); 148 } 149 } 150 $files = _module_build_dependencies($files); 151 return $files; 152 } 153 154 /** 155 * Find dependencies any level deep and fill in dependents information too. 156 * 157 * If module A depends on B which in turn depends on C then this function will 158 * add C to the list of modules A depends on. This will be repeated until 159 * module A has a list of all modules it depends on. If it depends on itself, 160 * called a circular dependency, that's marked by adding a nonexistent module, 161 * called -circular- to this list of modules. Because this does not exist, 162 * it'll be impossible to switch module A on. 163 * 164 * Also we fill in a dependents array in $file->info. Using the names above, 165 * the dependents array of module B lists A. 166 * 167 * @param $files 168 * The array of filesystem objects used to rebuild the cache. 169 * @return 170 * The same array with dependencies and dependents added where applicable. 171 */ 172 function _module_build_dependencies($files) { 173 do { 174 $new_dependency = FALSE; 175 foreach ($files as $filename => $file) { 176 // We will modify this object (module A, see doxygen for module A, B, C). 177 $file = &$files[$filename]; 178 if (isset($file->info['dependencies']) && is_array($file->info['dependencies'])) { 179 foreach ($file->info['dependencies'] as $dependency_name) { 180 // This is a nonexistent module. 181 if ($dependency_name == '-circular-' || !isset($files[$dependency_name])) { 182 continue; 183 } 184 // $dependency_name is module B (again, see doxygen). 185 $files[$dependency_name]->info['dependents'][$filename] = $filename; 186 $dependency = $files[$dependency_name]; 187 if (isset($dependency->info['dependencies']) && is_array($dependency->info['dependencies'])) { 188 // Let's find possible C modules. 189 foreach ($dependency->info['dependencies'] as $candidate) { 190 if (array_search($candidate, $file->info['dependencies']) === FALSE) { 191 // Is this a circular dependency? 192 if ($candidate == $filename) { 193 // As a module name can not contain dashes, this makes 194 // impossible to switch on the module. 195 $candidate = '-circular-'; 196 // Do not display the message or add -circular- more than once. 197 if (array_search($candidate, $file->info['dependencies']) !== FALSE) { 198 continue; 199 } 200 drupal_set_message(t('%module is part of a circular dependency. This is not supported and you will not be able to switch it on.', array('%module' => $file->info['name'])), 'error'); 201 } 202 else { 203 // We added a new dependency to module A. The next loop will 204 // be able to use this as "B module" thus finding even 205 // deeper dependencies. 206 $new_dependency = TRUE; 207 } 208 $file->info['dependencies'][] = $candidate; 209 } 210 } 211 } 212 } 213 } 214 // Don't forget to break the reference. 215 unset($file); 216 } 217 } while ($new_dependency); 218 return $files; 219 } 220 221 /** 222 * Determine whether a given module exists. 223 * 224 * @param $module 225 * The name of the module (without the .module extension). 226 * @return 227 * TRUE if the module is both installed and enabled. 228 */ 229 function module_exists($module) { 230 $list = module_list(); 231 return array_key_exists($module, $list); 232 } 233 234 /** 235 * Load a module's installation hooks. 236 */ 237 function module_load_install($module) { 238 // Make sure the installation API is available 239 include_once './includes/install.inc'; 240 241 module_load_include('install', $module); 242 } 243 244 /** 245 * Load a module include file. 246 * 247 * Examples: 248 * @code 249 * // Load node.admin.inc from the node module. 250 * module_load_include('inc', 'node', 'node.admin'); 251 * // Load content_types.inc from the node module. 252 * module_load_include('inc', 'node', 'content_types'); 253 * @endcode 254 * 255 * Do not use this function to load an install file. Use module_load_install() 256 * instead. 257 * 258 * @param $type 259 * The include file's type (file extension). 260 * @param $module 261 * The module to which the include file belongs. 262 * @param $name 263 * Optionally, specify the base file name (without the $type extension). 264 * If not set, $module is used. 265 */ 266 function module_load_include($type, $module, $name = NULL) { 267 if (empty($name)) { 268 $name = $module; 269 } 270 271 $file = './'. drupal_get_path('module', $module) ."/$name.$type"; 272 273 if (is_file($file)) { 274 require_once $file; 275 } 276 else { 277 return FALSE; 278 } 279 } 280 281 /** 282 * Load an include file for each of the modules that have been enabled in 283 * the system table. 284 */ 285 function module_load_all_includes($type, $name = NULL) { 286 $modules = module_list(); 287 foreach ($modules as $module) { 288 module_load_include($type, $module, $name); 289 } 290 } 291 292 /** 293 * Enable a given list of modules. 294 * 295 * @param $module_list 296 * An array of module names. 297 */ 298 function module_enable($module_list) { 299 $invoke_modules = array(); 300 foreach ($module_list as $module) { 301 $existing = db_fetch_object(db_query("SELECT status FROM {system} WHERE type = '%s' AND name = '%s'", 'module', $module)); 302 if ($existing->status == 0) { 303 module_load_install($module); 304 db_query("UPDATE {system} SET status = %d, throttle = %d WHERE type = '%s' AND name = '%s'", 1, 0, 'module', $module); 305 drupal_load('module', $module); 306 $invoke_modules[] = $module; 307 } 308 } 309 310 if (!empty($invoke_modules)) { 311 // Refresh the module list to include the new enabled module. 312 module_list(TRUE, FALSE); 313 // Force to regenerate the stored list of hook implementations. 314 module_implements('', FALSE, TRUE); 315 } 316 317 foreach ($invoke_modules as $module) { 318 module_invoke($module, 'enable'); 319 // Check if node_access table needs rebuilding. 320 // We check for the existence of node_access_needs_rebuild() since 321 // at install time, module_enable() could be called while node.module 322 // is not enabled yet. 323 if (function_exists('node_access_needs_rebuild') && !node_access_needs_rebuild() && module_hook($module, 'node_grants')) { 324 node_access_needs_rebuild(TRUE); 325 } 326 } 327 } 328 329 /** 330 * Disable a given set of modules. 331 * 332 * @param $module_list 333 * An array of module names. 334 */ 335 function module_disable($module_list) { 336 $invoke_modules = array(); 337 foreach ($module_list as $module) { 338 if (module_exists($module)) { 339 // Check if node_access table needs rebuilding. 340 if (!node_access_needs_rebuild() && module_hook($module, 'node_grants')) { 341 node_access_needs_rebuild(TRUE); 342 } 343 344 module_load_install($module); 345 module_invoke($module, 'disable'); 346 db_query("UPDATE {system} SET status = %d, throttle = %d WHERE type = '%s' AND name = '%s'", 0, 0, 'module', $module); 347 $invoke_modules[] = $module; 348 } 349 } 350 351 if (!empty($invoke_modules)) { 352 // Refresh the module list to exclude the disabled modules. 353 module_list(TRUE, FALSE); 354 // Force to regenerate the stored list of hook implementations. 355 module_implements('', FALSE, TRUE); 356 } 357 358 // If there remains no more node_access module, rebuilding will be 359 // straightforward, we can do it right now. 360 if (node_access_needs_rebuild() && count(module_implements('node_grants')) == 0) { 361 node_access_rebuild(); 362 } 363 } 364 365 /** 366 * @defgroup hooks Hooks 367 * @{ 368 * Allow modules to interact with the Drupal core. 369 * 370 * Drupal's module system is based on the concept of "hooks". A hook is a PHP 371 * function that is named foo_bar(), where "foo" is the name of the module 372 * (whose filename is thus foo.module) and "bar" is the name of the hook. Each 373 * hook has a defined set of parameters and a specified result type. 374 * 375 * To extend Drupal, a module need simply implement a hook. When Drupal wishes 376 * to allow intervention from modules, it determines which modules implement a 377 * hook and calls that hook in all enabled modules that implement it. 378 * 379 * The available hooks to implement are explained here in the Hooks section of 380 * the developer documentation. The string "hook" is used as a placeholder for 381 * the module name in the hook definitions. For example, if the module file is 382 * called example.module, then hook_help() as implemented by that module would 383 * be defined as example_help(). 384 */ 385 386 /** 387 * Determine whether a module implements a hook. 388 * 389 * @param $module 390 * The name of the module (without the .module extension). 391 * @param $hook 392 * The name of the hook (e.g. "help" or "menu"). 393 * @return 394 * TRUE if the module is both installed and enabled, and the hook is 395 * implemented in that module. 396 */ 397 function module_hook($module, $hook) { 398 return function_exists($module .'_'. $hook); 399 } 400 401 /** 402 * Determine which modules are implementing a hook. 403 * 404 * @param $hook 405 * The name of the hook (e.g. "help" or "menu"). 406 * @param $sort 407 * By default, modules are ordered by weight and filename, settings this option 408 * to TRUE, module list will be ordered by module name. 409 * @param $refresh 410 * For internal use only: Whether to force the stored list of hook 411 * implementations to be regenerated (such as after enabling a new module, 412 * before processing hook_enable). 413 * @return 414 * An array with the names of the modules which are implementing this hook. 415 */ 416 function module_implements($hook, $sort = FALSE, $refresh = FALSE) { 417 static $implementations; 418 419 if ($refresh) { 420 $implementations = array(); 421 return; 422 } 423 424 if (!isset($implementations[$hook])) { 425 $implementations[$hook] = array(); 426 $list = module_list(FALSE, TRUE, $sort); 427 foreach ($list as $module) { 428 if (module_hook($module, $hook)) { 429 $implementations[$hook][] = $module; 430 } 431 } 432 } 433 434 // The explicit cast forces a copy to be made. This is needed because 435 // $implementations[$hook] is only a reference to an element of 436 // $implementations and if there are nested foreaches (due to nested node 437 // API calls, for example), they would both manipulate the same array's 438 // references, which causes some modules' hooks not to be called. 439 // See also http://www.zend.com/zend/art/ref-count.php. 440 return (array)$implementations[$hook]; 441 } 442 443 /** 444 * Invoke a hook in a particular module. 445 * 446 * @param $module 447 * The name of the module (without the .module extension). 448 * @param $hook 449 * The name of the hook to invoke. 450 * @param ... 451 * Arguments to pass to the hook implementation. 452 * @return 453 * The return value of the hook implementation. 454 */ 455 function module_invoke() { 456 $args = func_get_args(); 457 $module = $args[0]; 458 $hook = $args[1]; 459 unset($args[0], $args[1]); 460 $function = $module .'_'. $hook; 461 if (module_hook($module, $hook)) { 462 return call_user_func_array($function, $args); 463 } 464 } 465 /** 466 * Invoke a hook in all enabled modules that implement it. 467 * 468 * @param $hook 469 * The name of the hook to invoke. 470 * @param ... 471 * Arguments to pass to the hook. 472 * @return 473 * An array of return values of the hook implementations. If modules return 474 * arrays from their implementations, those are merged into one array. 475 */ 476 function module_invoke_all() { 477 $args = func_get_args(); 478 $hook = $args[0]; 479 unset($args[0]); 480 $return = array(); 481 foreach (module_implements($hook) as $module) { 482 $function = $module .'_'. $hook; 483 $result = call_user_func_array($function, $args); 484 if (isset($result) && is_array($result)) { 485 $return = array_merge_recursive($return, $result); 486 } 487 else if (isset($result)) { 488 $return[] = $result; 489 } 490 } 491 492 return $return; 493 } 494 495 /** 496 * @} End of "defgroup hooks". 497 */ 498 499 /** 500 * Array of modules required by core. 501 */ 502 function drupal_required_modules() { 503 return array('block', 'filter', 'node', 'system', 'user'); 504 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated: Thu Mar 24 11:18:33 2011 | Cross-referenced by PHPXref 0.7 |