summaryrefslogtreecommitdiff
path: root/includes/module.inc
diff options
context:
space:
mode:
Diffstat (limited to 'includes/module.inc')
-rw-r--r--includes/module.inc159
1 files changed, 45 insertions, 114 deletions
diff --git a/includes/module.inc b/includes/module.inc
index 0c3f9202d..3a5609a00 100644
--- a/includes/module.inc
+++ b/includes/module.inc
@@ -6,24 +6,15 @@
* API for loading and interacting with Drupal modules.
*/
-/**
- * Pass this to module_implements when its cache needs to be written.
- */
-define('MODULE_IMPLEMENTS_WRITE_CACHE', -1);
-
-/**
- * Pass this to module_implements when its cache needs to be cleared.
- */
-define('MODULE_IMPLEMENTS_CLEAR_CACHE', -2);
-
/**
* Load all the modules that have been enabled in the system table.
*/
-function module_load_all() {
- foreach (module_list(TRUE) as $module) {
+function module_load_all($bootstrap = FALSE) {
+ foreach (module_list(TRUE, $bootstrap) as $module) {
drupal_load('module', $module);
}
+ module_implements('', FALSE, TRUE);
}
/**
@@ -33,6 +24,9 @@ function module_load_all() {
* @param $refresh
* Whether to force the module list to be regenerated (such as after the
* administrator has changed the system settings).
+ * @param $bootstrap
+ * Whether to return the reduced set of modules loaded in "bootstrap mode"
+ * for cached pages. See bootstrap.inc.
* @param $sort
* By default, modules are ordered by weight and module name. Set this option
* to TRUE to return a module list ordered only by module name.
@@ -43,7 +37,7 @@ function module_load_all() {
* An associative array whose keys and values are the names of all loaded
* modules.
*/
-function module_list($refresh = FALSE, $sort = FALSE, $fixed_list = NULL) {
+function module_list($refresh = FALSE, $bootstrap = FALSE, $sort = FALSE, $fixed_list = NULL) {
static $list = array(), $sorted_list;
if (empty($list) || $refresh || $fixed_list) {
@@ -61,7 +55,12 @@ function module_list($refresh = FALSE, $sort = FALSE, $fixed_list = NULL) {
// Drupal installations, which might have modules installed in different
// locations in the file system. The ordering here must also be
// consistent with the one used in module_implements().
- $result = db_query("SELECT name, filename FROM {system} WHERE type = 'module' AND status = 1 ORDER BY weight ASC, name ASC");
+ if ($bootstrap) {
+ $result = db_query("SELECT name, filename FROM {system} WHERE type = 'module' AND status = 1 AND bootstrap = 1 ORDER BY weight ASC, name ASC");
+ }
+ else {
+ $result = db_query("SELECT name, filename FROM {system} WHERE type = 'module' AND status = 1 ORDER BY weight ASC, name ASC");
+ }
foreach ($result as $module) {
if (file_exists($module->filename)) {
drupal_get_filename('module', $module->name, $module->filename);
@@ -164,7 +163,7 @@ function module_load_include($type, $module, $name = NULL) {
$name = $module;
}
- if (drupal_function_exists('drupal_get_path')) {
+ if (function_exists('drupal_get_path')) {
$file = DRUPAL_ROOT . '/' . drupal_get_path('module', $module) . "/$name.$type";
if (is_file($file)) {
require_once $file;
@@ -218,8 +217,9 @@ function module_enable($module_list, $disable_modules_installed_hook = FALSE) {
}
if (!empty($invoke_modules)) {
- // Refresh the module list to include the new enabled module.
+ // Refresh the module list to exclude the disabled modules.
module_list(TRUE);
+ module_implements('', FALSE, TRUE);
// Force to regenerate the stored list of hook implementations.
registry_rebuild();
@@ -235,7 +235,7 @@ function module_enable($module_list, $disable_modules_installed_hook = FALSE) {
// We check for the existence of node_access_needs_rebuild() since
// at install time, module_enable() could be called while node.module
// is not enabled yet.
- if (drupal_function_exists('node_access_needs_rebuild') && !node_access_needs_rebuild() && module_hook($module, 'node_grants')) {
+ if (function_exists('node_access_needs_rebuild') && !node_access_needs_rebuild() && module_hook($module, 'node_grants')) {
node_access_needs_rebuild(TRUE);
}
}
@@ -275,11 +275,12 @@ function module_disable($module_list) {
}
if (!empty($invoke_modules)) {
+ // Refresh the module list to exclude the disabled modules.
+ module_list(TRUE);
+ module_implements('', FALSE, TRUE);
// Invoke hook_module_disable before disabling modules,
// so we can still call module hooks to get information.
module_invoke_all('modules_disabled', $invoke_modules);
- // Refresh the module list to exclude the disabled modules.
- module_list(TRUE);
// Force to regenerate the stored list of hook implementations.
registry_rebuild();
}
@@ -324,119 +325,49 @@ function module_disable($module_list) {
* implemented in that module.
*/
function module_hook($module, $hook) {
- $function = $module . '_' . $hook;
- return function_exists($function) || drupal_function_exists($function);
+ return function_exists($module . '_' . $hook);
}
/**
* Determine which modules are implementing a hook.
*
* @param $hook
- * The name of the hook (e.g. "help" or "menu"). Special cases:
- * MODULE_IMPLEMENTS_CLEAR_CACHE: Force the stored list of hook
- * implementations to be regenerated (such as after enabling a new module,
- * before processing hook_enable).
- * MODULE_IMPLEMENTS_WRITE_CACHE: Write the stored list of hook
- * implementations into the cache_registry table.
+ * The name of the hook (e.g. "help" or "menu").
* @param $sort
- * By default, modules are ordered by weight and module name. By setting this
- * option to TRUE, modules will be ordered by module name.
+ * By default, modules are ordered by weight and filename, settings this option
+ * to TRUE, module list will be ordered by module name.
+ * @param $refresh
+ * For internal use only: Whether to force the stored list of hook
+ * implementations to be regenerated (such as after enabling a new module,
+ * before processing hook_enable).
* @return
* An array with the names of the modules which are implementing this hook.
- * All enabled modules are taken into consideration and the files containing
- * the implementations are loaded as necessary.
*/
-function module_implements($hook, $sort = FALSE) {
- static $implementations = array(), $sorted_implementations = array(), $loaded = array(), $cached_hooks = 0, $maintenance;
-
- // Use a static variable for maintenance mode to avoid the overhead of
- // calling defined() each time the function is called.
- if (!isset($maintenance)) {
- $maintenance = defined('MAINTENANCE_MODE');
- }
+function module_implements($hook, $sort = FALSE, $refresh = FALSE) {
+ static $implementations;
- if ($maintenance) {
- return _module_implements_maintenance($hook, $sort);
- }
- if ($hook === MODULE_IMPLEMENTS_CLEAR_CACHE) {
+ if ($refresh) {
$implementations = array();
- $sorted_implementations = array();
- $loaded = array();
- $cached_hooks = 0;
- cache_clear_all('hooks', 'cache_registry');
- return;
- }
- if ($hook === MODULE_IMPLEMENTS_WRITE_CACHE) {
- // Only write this to cache if we loaded new implementations.
- if (count($implementations) > $cached_hooks) {
- cache_set('hooks', $implementations, 'cache_registry');
- }
return;
}
- if (!isset($loaded[$hook])) {
- if (empty($implementations) && ($cache = cache_get('hooks', 'cache_registry'))) {
- $implementations = $cache->data;
- $cached_hooks = count($implementations);
- }
- if (!isset($implementations[$hook])) {
- // The module name (rather than the filename) is used as the fallback
- // weighting in order to guarantee consistent behavior across different
- // Drupal installations, which might have modules installed in different
- // locations in the file system. The ordering here must also be
- // consistent with the one used in module_list().
- $implementations[$hook] = db_query("SELECT module FROM {registry} WHERE type = 'function' AND suffix = :hook ORDER BY weight, module", array(':hook' => $hook))->fetchCol();
- }
- foreach ($implementations[$hook] as $module) {
- $function = $module . '_' . $hook;
- if (!function_exists($function)) {
- drupal_function_exists($function);
+ if (!isset($implementations[$hook])) {
+ $implementations[$hook] = array();
+ $list = module_list(FALSE, FALSE, $sort);
+ foreach ($list as $module) {
+ if (module_hook($module, $hook)) {
+ $implementations[$hook][] = $module;
}
}
- $loaded[$hook] = TRUE;
}
- if ($sort) {
- if (!isset($sorted_implementations[$hook])) {
- $sorted_implementations[$hook] = $implementations[$hook];
- sort($sorted_implementations[$hook]);
- }
- return $sorted_implementations[$hook];
- }
- else {
- return $implementations[$hook];
- }
-}
-
-/**
- * This is the maintenance version of module_implements for internal use only.
- *
- * This function is called whenever MAINTENANCE_MODE is defined and is a
- * safe code path for Drupal installation or upgrade because it does not use
- * the database, instead it uses module_list. @see module_list $fixed_list on
- * how to make module_list also DB independent.
- *
- * @param $hook
- * The name of the hook (e.g. "help" or "menu").
- * @param $sort
- * By default, modules are ordered by weight and filename, settings this
- * option to TRUE, module list will be ordered by module name.
- * @return
- * An array with the names of the modules which are implementing this hook.
- * Only enabled and already loaded modules are taken into consideration.
- */
-function _module_implements_maintenance($hook, $sort = FALSE) {
- $implementations = array();
- foreach (module_list() as $module) {
- $function = $module . '_' . $hook;
- if (function_exists($function)) {
- $implementations[] = $module;
- }
- if ($sort) {
- sort($implementations);
- }
- }
- return $implementations;
+ // The explicit cast forces a copy to be made. This is needed because
+ // $implementations[$hook] is only a reference to an element of
+ // $implementations and if there are nested foreaches (due to nested node
+ // API calls, for example), they would both manipulate the same array's
+ // references, which causes some modules' hooks not to be called.
+ // See also http://www.zend.com/zend/art/ref-count.php.
+ return (array)$implementations[$hook];
}
/**
@@ -478,7 +409,7 @@ function module_invoke_all() {
$return = array();
foreach (module_implements($hook) as $module) {
$function = $module . '_' . $hook;
- if (drupal_function_exists($function)) {
+ if (function_exists($function)) {
$result = call_user_func_array($function, $args);
if (isset($result) && is_array($result)) {
$return = array_merge_recursive($return, $result);