=== modified file 'includes/bootstrap.inc' --- includes/bootstrap.inc 2008-09-20 20:22:23 +0000 +++ includes/bootstrap.inc 2008-09-26 22:35:29 +0000 @@ -825,7 +825,7 @@ function watchdog($type, $message, $vari ); // Call the logging hooks to log/process the message - foreach (module_implements('watchdog', TRUE) as $module) { + foreach (module_implements('watchdog') as $module) { module_invoke($module, 'watchdog', $log_message); } } @@ -1435,31 +1435,6 @@ function registry_rebuild() { } /** - * Save hook implementations cache. - * - * @param $hook - * Array with the hook name and list of modules that implement it. - * @param $write_to_persistent_cache - * Whether to write to the persistent cache. - */ -function registry_cache_hook_implementations($hook, $write_to_persistent_cache = FALSE) { - static $implementations; - - if ($hook) { - // Newer is always better, so overwrite anything that's come before. - $implementations[$hook['hook']] = $hook['modules']; - } - - if ($write_to_persistent_cache === TRUE) { - // Only write this to cache if the implementations data we are going to cache - // is different to what we loaded earlier in the request. - if ($implementations != module_implements()) { - cache_set('hooks', $implementations, 'cache_registry'); - } - } -} - -/** * Save the files required by the registry for this path. */ function registry_cache_path_files() { === modified file 'includes/common.inc' --- includes/common.inc 2008-09-20 20:22:23 +0000 +++ includes/common.inc 2008-09-26 22:35:29 +0000 @@ -648,7 +648,7 @@ function _drupal_get_last_caller($backtr // The first trace is the call itself. // It gives us the line and the file of the last call. $call = $backtrace[0]; - + // The second call give us the function where the call originated. if (isset($backtrace[1])) { if (isset($backtrace[1]['class'])) { @@ -1531,7 +1531,7 @@ function drupal_page_footer() { module_invoke_all('exit'); - registry_cache_hook_implementations(FALSE, TRUE); + module_implements(MODULE_IMPLEMENTS_WRITE_CACHE); registry_cache_path_files(); } === modified file 'includes/menu.inc' --- includes/menu.inc 2008-09-22 03:19:43 +0000 +++ includes/menu.inc 2008-09-26 22:35:29 +0000 @@ -1730,7 +1730,7 @@ function menu_router_build($reset = FALS // We need to manually call each module so that we can know which module // a given item came from. $callbacks = array(); - foreach (module_implements('menu', NULL, TRUE) as $module) { + foreach (module_implements('menu') as $module) { $router_items = call_user_func($module . '_menu'); if (isset($router_items) && is_array($router_items)) { foreach (array_keys($router_items) as $path) { @@ -1888,7 +1888,7 @@ function _menu_delete_item($item, $force * - plid The mlid of the parent. * - router_path The path of the relevant router item. * @return - * The mlid of the saved menu link, or FALSE if the menu link could not be + * The mlid of the saved menu link, or FALSE if the menu link could not be * saved. */ function menu_link_save(&$item) { === modified file 'includes/module.inc' --- includes/module.inc 2008-09-20 20:22:23 +0000 +++ includes/module.inc 2008-09-26 22:39:04 +0000 @@ -7,6 +7,17 @@ */ /** + * 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() { @@ -380,48 +391,118 @@ function module_hook($module, $hook) { * Determine which modules are implementing a hook. * * @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. - * @param $refresh - * For internal use only: Whether to force the stored list of 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). Note that if $refresh is TRUE this function - * will always return NULL. + * before processing hook_enable). + * MODULE_IMPLEMENTS_WRITE_CACHE: write the stored list of hook + * implementations into the cache_registry table. * @return * An array with the names of the modules which are implementing this hook. - * If $hook is NULL then it will return the implementation cache. + * All enabled modules are taken into consideration and the files containing + * the implementations are loaded as necessary. */ -function module_implements($hook = NULL, $sort = FALSE, $refresh = FALSE) { - static $implementations = array(); +function module_implements($hook) { + static $implementations = array(), $loaded = array(), $cache; - if (!isset($hook)) { - return $implementations; + if (defined('MAINTENANCE_MODE')) { + return _module_implements_maintenance($hook); } - if ($refresh) { + if ($hook == MODULE_IMPLEMENTS_CLEAR_CACHE) { $implementations = array(); + $loaded = array(); + cache_clear_all('hooks', 'cache_registry'); + return; } - if (!defined('MAINTENANCE_MODE') && empty($implementations) && ($cache = cache_get('hooks', 'cache_registry'))) { + if ($hook == MODULE_IMPLEMENTS_WRITE_CACHE) { + // Only write this to cache if the implementations data we are going to cache + // is different to what we loaded earlier in the request. + if (!$refresh && $cache && $implementations != $cache->data) { + cache_set('hooks', $implementations, 'cache_registry'); + } + return; + } + + if (empty($implementations) && ($cache = cache_get('hooks', 'cache_registry'))) { $implementations = $cache->data; } - if ($hook) { - if (!isset($implementations[$hook])) { - $implementations[$hook] = array(); - foreach (module_list() as $module) { - if (module_hook($module, $hook)) { - $implementations[$hook][] = $module; - } - } + if (empty($loaded[$hook])) { + if (isset($implementations[$hook])) { + _module_implements_check($implementations, $hook); } - registry_cache_hook_implementations(array('hook' => $hook, 'modules' => $implementations[$hook])); + else { + $implementations[$hook] = _module_implements_build($hook); + } + $loaded[$hook] = TRUE; + } - return $implementations[$hook]; + return $implementations[$hook]; +} + +/** + * This is the maintenance version of module_implements. + * + * @param $hook + * The name of the hook (e.g. "help" or "menu"). + * @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) { + $implementations = array(); + foreach (module_list() as $module) { + $function = $module . '_' . $hook; + if (function_exists($function)) { + $implementations[] = $module; + } + } + return $implementations; +} + +/** + * Checks whether the functions implementationing a hook are in memory. + * + * @param $implementations + * The cached implementations. + * @param $hook + * The name of the hook. + */ +function _module_implements_check($implementations, $hook) { + foreach ($implementations[$hook] as $module) { + $function = $module . '_' . $hook; + // Though drupal_function_exists itself checks function_exists, + // most of the time the function will exist because of the per router path + // hook cache so we can save lots of calls to drupal_function_exists. + if (!function_exists($function)) { + drupal_function_exists($function); + } } } /** + * Collects the implementations of a hook from the registry table. + * + * @param $hook + * The name of the hook. + * @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_build($hook) { + $return = array(); + $result = db_query("SELECT name, filename, module FROM {registry} WHERE type = 'function' AND hook = '%s'", $hook); + while ($function = db_fetch_object($result)) { + $return[] = $function->module; + // We need to load the relevant file for this function. + drupal_function_exists($function->name); + } + return $return; +} + + +/** * Invoke a hook in a particular module. * * @param $module === modified file 'includes/registry.inc' --- includes/registry.inc 2008-09-20 20:22:23 +0000 +++ includes/registry.inc 2008-09-26 22:36:49 +0000 @@ -45,7 +45,7 @@ function _registry_rebuild() { if ($module->status) { $dir = dirname($module->filename); foreach ($module->info['files'] as $file) { - $files["$dir/$file"] = array(); + $files["$dir/$file"] = array('module' => $module->name); } } } @@ -67,6 +67,7 @@ function _registry_rebuild() { } _registry_parse_files($files); + module_implements(MODULE_IMPLEMENTS_CLEAR_CACHE); cache_clear_all('*', 'cache_registry', TRUE); } @@ -84,7 +85,7 @@ function registry_get_parsed_files() { * Parse all files that have changed since the registry was last built, and save their function and class listings. * * @param $files - * The list of files to check and parse. + * The list of files to check and parse. */ function _registry_parse_files($files) { $changed_files = array(); @@ -95,7 +96,7 @@ function _registry_parse_files($files) { if ($new_file || $md5 != $file['md5']) { // We update the md5 after we've saved the files resources rather than here, so if we // don't make it through this rebuild, the next run will reparse the file. - _registry_parse_file($filename, $contents); + _registry_parse_file($filename, $contents, isset($file['module']) ? $file['module'] : ''); $file['md5'] = $md5; db_merge('registry_file') ->key(array('filename' => $filename)) @@ -109,11 +110,13 @@ function _registry_parse_files($files) { * Parse a file and save its function and class listings. * * @param $filename - * Name of the file we are going to parse. + * Name of the file we are going to parse. * @param $contents - * Contents of the file we are going to parse as a string. + * Contents of the file we are going to parse as a string. + * @param $module + * Name of the module (optional) this file belongs to. */ -function _registry_parse_file($filename, $contents) { +function _registry_parse_file($filename, $contents, $module = '') { static $map = array(T_FUNCTION => 'function', T_CLASS => 'class', T_INTERFACE => 'interface'); // Delete registry entries for this file, so we can insert the new resources. db_delete('registry')->condition('filename', $filename)->execute(); @@ -123,6 +126,18 @@ function _registry_parse_file($filename, if (is_array($token) && isset($map[$token[0]])) { $type = $map[$token[0]]; if ($resource_name = _registry_get_resource_name($tokens, $type)) { + $hook = ''; + if ($type == 'function' && !empty($module)) { + $n = strlen($module); + if (substr($resource_name, 0, $n) == $module) { + $hook = substr($resource_name, $n + 1); + } + } + $fields = array( + 'filename' => $filename, + 'module' => $module, + 'hook' => $hook, + ); // Because some systems, such as cache, currently use duplicate function // names in separate files an insert query cannot be used here as it // would cause a key constraint violation. Instead we use a merge query. @@ -132,7 +147,7 @@ function _registry_parse_file($filename, // filename instead of another. // TODO: Convert this back to an insert query after all duplicate // function names have been purged from Drupal. - db_merge('registry')->key(array('name' => $resource_name, 'type' => $type))->fields(array('filename' => $filename))->execute(); + db_merge('registry')->key(array('name' => $resource_name, 'type' => $type))->fields($fields)->execute(); // We skip the body because classes may contain functions. _registry_skip_body($tokens); === modified file 'index.php' --- index.php 2008-09-20 20:22:23 +0000 +++ index.php 2008-09-26 22:35:29 +0000 @@ -19,6 +19,7 @@ define('DRUPAL_ROOT', dirname(realpath(_ require_once DRUPAL_ROOT . '/includes/bootstrap.inc'; drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL); + $return = menu_execute_active_handler(); // Menu status constants are integers; page content is a string. === modified file 'modules/aggregator/aggregator.info' --- modules/aggregator/aggregator.info 2008-05-15 21:27:32 +0000 +++ modules/aggregator/aggregator.info 2008-09-26 22:35:29 +0000 @@ -8,3 +8,4 @@ core = 7.x files[] = aggregator.module files[] = aggregator.admin.inc files[] = aggregator.pages.inc +files[] = aggregator.install === modified file 'modules/block/block.info' --- modules/block/block.info 2008-05-15 21:30:02 +0000 +++ modules/block/block.info 2008-09-26 22:35:29 +0000 @@ -7,3 +7,4 @@ version = VERSION core = 7.x files[] = block.module files[] = block.admin.inc +files[] = block.install === modified file 'modules/blogapi/blogapi.info' --- modules/blogapi/blogapi.info 2008-05-13 18:13:43 +0000 +++ modules/blogapi/blogapi.info 2008-09-26 22:35:29 +0000 @@ -6,3 +6,4 @@ package = Core - optional version = VERSION core = 7.x files[] = blogapi.module +files[] = blogapi.install === modified file 'modules/book/book.info' --- modules/book/book.info 2008-05-15 21:19:24 +0000 +++ modules/book/book.info 2008-09-26 22:35:29 +0000 @@ -8,3 +8,4 @@ core = 7.x files[] = book.module files[] = book.admin.inc files[] = book.pages.inc +files[] = book.install === modified file 'modules/color/color.info' --- modules/color/color.info 2008-05-19 19:36:41 +0000 +++ modules/color/color.info 2008-09-26 22:35:29 +0000 @@ -6,3 +6,4 @@ package = Core - optional version = VERSION core = 7.x files[] = color.module +files[] = color.install === modified file 'modules/comment/comment.info' --- modules/comment/comment.info 2008-05-14 13:12:40 +0000 +++ modules/comment/comment.info 2008-09-26 22:35:29 +0000 @@ -8,3 +8,4 @@ core = 7.x files[] = comment.module files[] = comment.admin.inc files[] = comment.pages.inc +files[] = comment.install === modified file 'modules/contact/contact.info' --- modules/contact/contact.info 2008-05-06 12:18:44 +0000 +++ modules/contact/contact.info 2008-09-26 22:35:29 +0000 @@ -7,3 +7,4 @@ core = 7.x files[] = contact.module files[] = contact.admin.inc files[] = contact.pages.inc +files[] = contact.install === modified file 'modules/dblog/dblog.info' --- modules/dblog/dblog.info 2008-05-06 12:18:44 +0000 +++ modules/dblog/dblog.info 2008-09-26 22:35:29 +0000 @@ -6,3 +6,4 @@ version = VERSION core = 7.x files[] = dblog.module files[] = dblog.admin.inc +files[] = dblog.install === modified file 'modules/filter/filter.info' --- modules/filter/filter.info 2008-08-09 12:41:22 +0000 +++ modules/filter/filter.info 2008-09-26 22:35:29 +0000 @@ -7,3 +7,4 @@ core = 7.x files[] = filter.module files[] = filter.admin.inc files[] = filter.pages.inc +files[] = filter.install === modified file 'modules/forum/forum.info' --- modules/forum/forum.info 2008-08-03 18:29:29 +0000 +++ modules/forum/forum.info 2008-09-26 22:35:29 +0000 @@ -9,3 +9,4 @@ core = 7.x files[] = forum.module files[] = forum.admin.inc files[] = forum.pages.inc +files[] = forum.install === modified file 'modules/locale/locale.info' --- modules/locale/locale.info 2008-05-06 12:18:44 +0000 +++ modules/locale/locale.info 2008-09-26 22:35:29 +0000 @@ -5,3 +5,4 @@ package = Core - optional version = VERSION core = 7.x files[] = locale.module +files[] = locale.install === modified file 'modules/menu/menu.info' --- modules/menu/menu.info 2008-05-06 12:18:44 +0000 +++ modules/menu/menu.info 2008-09-26 22:35:29 +0000 @@ -6,3 +6,4 @@ version = VERSION core = 7.x files[] = menu.module files[] = menu.admin.inc +files[] = menu.install === modified file 'modules/node/node.info' --- modules/node/node.info 2008-05-06 12:18:44 +0000 +++ modules/node/node.info 2008-09-26 22:35:29 +0000 @@ -8,3 +8,4 @@ files[] = node.module files[] = content_types.inc files[] = node.admin.inc files[] = node.pages.inc +files[] = node.install === modified file 'modules/openid/openid.info' --- modules/openid/openid.info 2008-05-06 12:18:44 +0000 +++ modules/openid/openid.info 2008-09-26 22:35:29 +0000 @@ -8,3 +8,4 @@ files[] = openid.module files[] = openid.inc files[] = openid.pages.inc files[] = xrds.inc +files[] = openid.install === modified file 'modules/php/php.info' --- modules/php/php.info 2008-05-06 12:18:44 +0000 +++ modules/php/php.info 2008-09-26 22:35:29 +0000 @@ -5,3 +5,4 @@ package = Core - optional version = VERSION core = 7.x files[] = php.module +files[] = php.install === modified file 'modules/poll/poll.info' --- modules/poll/poll.info 2008-05-06 12:18:44 +0000 +++ modules/poll/poll.info 2008-09-26 22:35:29 +0000 @@ -6,3 +6,4 @@ version = VERSION core = 7.x files[] = poll.module files[] = poll.pages.inc +files[] = poll.install === modified file 'modules/profile/profile.info' --- modules/profile/profile.info 2008-05-06 12:18:44 +0000 +++ modules/profile/profile.info 2008-09-26 22:35:29 +0000 @@ -7,3 +7,4 @@ core = 7.x files[] = profile.module files[] = profile.admin.inc files[] = profile.pages.inc +files[] = profile.install === modified file 'modules/search/search.info' --- modules/search/search.info 2008-05-06 12:18:44 +0000 +++ modules/search/search.info 2008-09-26 22:35:29 +0000 @@ -7,3 +7,4 @@ core = 7.x files[] = search.module files[] = search.admin.inc files[] = search.pages.inc +files[] = search.install === modified file 'modules/simpletest/simpletest.info' --- modules/simpletest/simpletest.info 2008-05-06 12:18:44 +0000 +++ modules/simpletest/simpletest.info 2008-09-26 22:35:29 +0000 @@ -5,3 +5,4 @@ package = Core - optional version = VERSION core = 7.x files[] = simpletest.module +files[] = simpletest.install === modified file 'modules/simpletest/tests/database_test.info' --- modules/simpletest/tests/database_test.info 2008-08-31 11:43:41 +0000 +++ modules/simpletest/tests/database_test.info 2008-09-26 22:35:29 +0000 @@ -4,5 +4,6 @@ description = "Support module for Databa core = 7.x package = Testing files[] = database_test.module +files[] = database_test.install version = VERSION hidden = TRUE === modified file 'modules/statistics/statistics.info' --- modules/statistics/statistics.info 2008-05-06 12:18:44 +0000 +++ modules/statistics/statistics.info 2008-09-26 22:35:29 +0000 @@ -7,3 +7,4 @@ core = 7.x files[] = statistics.module files[] = statistics.admin.inc files[] = statistics.pages.inc +files[] = statistics.install === modified file 'modules/system/system.info' --- modules/system/system.info 2008-07-08 01:08:15 +0000 +++ modules/system/system.info 2008-09-26 22:35:29 +0000 @@ -7,3 +7,4 @@ core = 7.x files[] = system.module files[] = system.admin.inc files[] = image.gd.inc +files[] = system.install === modified file 'modules/system/system.install' --- modules/system/system.install 2008-09-20 20:22:23 +0000 +++ modules/system/system.install 2008-09-26 22:35:29 +0000 @@ -1091,6 +1091,20 @@ function system_schema() { 'length' => 255, 'not null' => TRUE, ), + 'module' => array( + 'description' => t('Name of the module the file belongs to.'), + 'type' => 'varchar', + 'length' => 255, + 'not null' => TRUE, + 'default' => '' + ), + 'hook' => array( + 'description' => t('Name of the hook this function implements, if any.'), + 'type' => 'varchar', + 'length' => 255, + 'not null' => TRUE, + 'default' => '' + ), ), 'primary key' => array('name', 'type'), ); @@ -2927,9 +2941,11 @@ function system_update_7006() { db_drop_field($ret, 'menu_router', 'file'); $schema['registry'] = array( 'fields' => array( - 'name' => array('type' => 'varchar', 'length' => 255, 'not null' => TRUE, 'default' => ''), - 'type' => array('type' => 'varchar', 'length' => 9, 'not null' => TRUE, 'default' => ''), - 'filename' => array('type' => 'varchar', 'length' => 255, 'not null' => TRUE, 'default' => ''), + 'name' => array('type' => 'varchar', 'length' => 255, 'not null' => TRUE, 'default' => ''), + 'type' => array('type' => 'varchar', 'length' => 9, 'not null' => TRUE, 'default' => ''), + 'filename' => array('type' => 'varchar', 'length' => 255, 'not null' => TRUE, 'default' => ''), + 'module' => array('type' => 'varchar', 'length' => 255, 'not null' => TRUE, 'default' => ''), + 'hook' => array('type' => 'varchar', 'length' => 255, 'not null' => TRUE, 'default' => ''), ), 'primary key' => array('name', 'type'), ); === modified file 'modules/taxonomy/taxonomy.info' --- modules/taxonomy/taxonomy.info 2008-05-06 12:18:44 +0000 +++ modules/taxonomy/taxonomy.info 2008-09-26 22:35:29 +0000 @@ -7,3 +7,4 @@ core = 7.x files[] = taxonomy.module files[] = taxonomy.admin.inc files[] = taxonomy.pages.inc +files[] = taxonomy.install === modified file 'modules/trigger/trigger.info' --- modules/trigger/trigger.info 2008-05-06 12:18:44 +0000 +++ modules/trigger/trigger.info 2008-09-26 22:35:29 +0000 @@ -6,3 +6,4 @@ version = VERSION core = 7.x files[] = trigger.module files[] = trigger.admin.inc +files[] = trigger.install === modified file 'modules/update/update.info' --- modules/update/update.info 2008-05-06 12:18:44 +0000 +++ modules/update/update.info 2008-09-26 22:35:29 +0000 @@ -9,3 +9,4 @@ files[] = update.compare.inc files[] = update.fetch.inc files[] = update.report.inc files[] = update.settings.inc +files[] = update.install === modified file 'modules/upload/upload.info' --- modules/upload/upload.info 2008-05-06 12:18:44 +0000 +++ modules/upload/upload.info 2008-09-26 22:35:29 +0000 @@ -6,3 +6,4 @@ version = VERSION core = 7.x files[] = upload.module files[] = upload.admin.inc +files[] = upload.install === modified file 'modules/user/user.info' --- modules/user/user.info 2008-05-06 12:18:44 +0000 +++ modules/user/user.info 2008-09-26 22:35:29 +0000 @@ -7,3 +7,4 @@ core = 7.x files[] = user.module files[] = user.admin.inc files[] = user.pages.inc +files[] = user.install