Index: database/database.mysql =================================================================== RCS file: /cvs/drupal/drupal/database/database.mysql,v retrieving revision 1.191 diff -u -r1.191 database.mysql --- database/database.mysql 29 Jul 2005 07:26:49 -0000 1.191 +++ database/database.mysql 31 Jul 2005 15:05:05 -0000 @@ -617,6 +617,7 @@ status int(2) NOT NULL default '0', throttle tinyint(1) DEFAULT '0' NOT NULL, bootstrap int(2) NOT NULL default '0', + hooks varchar(255) NOT NULL default '', PRIMARY KEY (filename) ) TYPE=MyISAM; Index: database/updates.inc =================================================================== RCS file: /cvs/drupal/drupal/database/updates.inc,v retrieving revision 1.122 diff -u -r1.122 updates.inc --- database/updates.inc 29 Jul 2005 20:31:04 -0000 1.122 +++ database/updates.inc 31 Jul 2005 15:05:12 -0000 @@ -118,7 +118,8 @@ "2005-05-11" => "update_139", "2005-05-12" => "update_140", "2005-05-22" => "update_141", - "2005-07-29" => "update_142" + "2005-07-29" => "update_142", + "2005-07-31" => "update_143" ); function update_32() { @@ -2518,6 +2519,12 @@ return $ret; } +function update_143() { + $ret = array(); + $ret[] = update_sql("ALTER TABLE {system} ADD COLUMN hooks varchar(255) NOT NULL default ''"); + return $ret; +} + function update_sql($sql) { $edit = $_POST["edit"]; $result = db_query($sql); Index: includes/module.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/module.inc,v retrieving revision 1.68 diff -u -r1.68 module.inc --- includes/module.inc 29 Jul 2005 07:09:30 -0000 1.68 +++ includes/module.inc 31 Jul 2005 15:05:12 -0000 @@ -10,11 +10,11 @@ * Initialize all modules. */ function module_init() { - // Load all the modules that have been enabled in the system table. - foreach (module_list(TRUE, FALSE) as $module) { - drupal_load('module', $module); - } + // Preload all the modules that have been enabled in the system table. + module_list(TRUE, FALSE); module_invoke_all('init'); + // Load locale if enabled + module_load('locale'); } /** @@ -49,11 +49,15 @@ if (!$list) { $list = array('filter' => 'filter', 'system' => 'system', 'user' => 'user', 'watchdog' => 'watchdog'); + // Load system modules + foreach($list as $name) { + module_load($name, TRUE); + } if ($bootstrap) { - $result = db_query("SELECT name, filename, throttle, bootstrap FROM {system} WHERE type = 'module' AND status = 1 AND bootstrap = 1"); + $result = db_query("SELECT name, filename, throttle, bootstrap, hooks FROM {system} WHERE type = 'module' AND status = 1 AND bootstrap = 1"); } else { - $result = db_query("SELECT name, filename, throttle, bootstrap FROM {system} WHERE type = 'module' AND status = 1"); + $result = db_query("SELECT name, filename, throttle, bootstrap, hooks FROM {system} WHERE type = 'module' AND status = 1"); } while ($module = db_fetch_object($result)) { if (file_exists($module->filename)) { @@ -64,6 +68,8 @@ if (!$throttle) { drupal_get_filename('module', $module->name, $module->filename); $list[$module->name] = $module->name; + $module->hooks = $module->hooks ? explode(';',$module->hooks) : array(); + module_info($module->name, $module); } } } @@ -73,6 +79,47 @@ } /** + * This is the real module loader + * + * @param $name + * Name of the module to be loaded + * @param $system + * Whether it is a system module, to be always loaded + * @return + * TRUE if the module is successfully loaded. + */ +function module_load($name, $system = FALSE){ + static $loaded = array(); + + if(array_key_exists($name, $loaded)) { + return $loaded[$name]; + } elseif($system || module_info($name)) { + return $loaded[$name] = drupal_load('module', $name); + } else { + // Module is not enabled nor a system module + return $loaded[$name] = FALSE; + } +} + +/** + * Maintains info about enabled modules + * + * @param $name + * Name of the module + * @param $data + * An object containing module info to be set for that module + * @return + * An object containing module info + */ +function module_info($name, $data = NULL){ + static $info = array(); + if($data){ + return $info[$name] = $data; + } elseif(array_key_exists($name, $info)) { + return $info[$name]; + } +} +/** * Determine whether a given module exists. * * @param $module @@ -118,7 +165,11 @@ * implemented in that module. */ function module_hook($module, $hook) { - return function_exists($module .'_'. $hook); + if($info = module_info($module)) { + return in_array($hook, $info->hooks); + } else { + return function_exists($module .'_'. $hook); + } } /** @@ -162,9 +213,10 @@ $module = array_shift($args); $hook = array_shift($args); $function = $module .'_'. $hook; - if (module_hook($module, $hook)) { + module_load($module); + if (function_exists($function)) { return call_user_func_array($function, $args); - } + } } /** * Invoke a hook in all enabled modules that implement it. @@ -182,6 +234,7 @@ $hook = array_shift($args); $return = array(); foreach (module_implements($hook) as $module) { + module_load($module); $function = $module .'_'. $hook; $result = call_user_func_array($function, $args); if (is_array($result)) { @@ -196,6 +249,15 @@ } /** + * Lists all hooks for modules + */ + +function _module_list_hooks(){ + return array('access', 'auth', 'block', 'comment', 'cron', 'db_rewrite_sql', 'delete', 'exit', 'filter', 'filter_tips', 'footer', + 'form', 'help', 'info', 'init', 'insert', 'link', 'load', 'menu', 'nodeapi', 'node_grants', 'node_name', 'node_types', + 'onload', 'perm', 'ping', 'search', 'search_item', 'search_preprocess', 'settings', 'taxonomy', 'textarea', 'update', 'update_index', 'user', 'validate', 'view', 'xmlrpc'); +} +/** * @} End of "defgroup hooks". */ Index: modules/system.module =================================================================== RCS file: /cvs/drupal/drupal/modules/system.module,v retrieving revision 1.220 diff -u -r1.220 system.module --- modules/system.module 26 Jul 2005 01:56:31 -0000 1.220 +++ modules/system.module 31 Jul 2005 15:05:15 -0000 @@ -477,10 +477,17 @@ break; } } + // log remaining hooks + $hooks = array(); + foreach (_module_list_hooks() as $hook){ + if(function_exists($file->name.'_'.$hook)) { + $hooks[]= $hook; + } + } // Update the contents of the system table: db_query("DELETE FROM {system} WHERE name = '%s' AND type = '%s'", $file->name, 'module'); - db_query("INSERT INTO {system} (name, description, type, filename, status, throttle, bootstrap) VALUES ('%s', '%s', '%s', '%s', %d, %d, %d)", $file->name, $file->description, 'module', $file->filename, $file->status, $file->throttle, $bootstrap); + db_query("INSERT INTO {system} (name, description, type, filename, status, throttle, bootstrap, hooks) VALUES ('%s', '%s', '%s', '%s', %d, %d, %d, '%s')", $file->name, $file->description, 'module', $file->filename, $file->status, $file->throttle, $bootstrap, implode(';',$hooks)); $row = array($file->name, $file->description, array('data' => (in_array($file->name, $required) ? form_hidden("status][$file->name", 1) . t('required') : form_checkbox('', "status][$file->name", 1, $file->status)), 'align' => 'center')); if (module_exist('throttle')) { @@ -505,6 +512,8 @@ // Make certain that the default theme is enabled to avoid user error if (($edit['type'] == 'theme') && ($edit['theme_default'] == $name)) { $status = 1; + } else { + } db_query("UPDATE {system} SET status = %d, throttle = %d WHERE type = '%s' AND name = '%s'", $status, $edit['throttle'][$name], $edit['type'], $name);