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