diff options
-rw-r--r-- | includes/install.core.inc | 3 | ||||
-rw-r--r-- | includes/install.inc | 25 | ||||
-rw-r--r-- | includes/module.inc | 80 | ||||
-rw-r--r-- | modules/node/node.module | 11 | ||||
-rw-r--r-- | modules/rdf/rdf.install | 5 | ||||
-rw-r--r-- | modules/shortcut/shortcut.install | 9 | ||||
-rw-r--r-- | modules/simpletest/tests/module.test | 40 | ||||
-rw-r--r-- | modules/simpletest/tests/module_test.install | 43 | ||||
-rw-r--r-- | modules/system/system.module | 2 |
9 files changed, 144 insertions, 74 deletions
diff --git a/includes/install.core.inc b/includes/install.core.inc index 8fcb5ca71..7c4bc1057 100644 --- a/includes/install.core.inc +++ b/includes/install.core.inc @@ -1493,8 +1493,7 @@ function install_finished(&$install_state) { * Batch callback for batch installation of modules. */ function _install_module_batch($module, $module_name, &$context) { - _drupal_install_module($module); - // We enable the installed module right away, so that the module will be + // Install and enable the module right away, so that the module will be // loaded by drupal_bootstrap in subsequent batch requests, and other // modules possibly depending on it can safely perform their installation // steps. diff --git a/includes/install.inc b/includes/install.inc index c3e0536c3..17225f562 100644 --- a/includes/install.inc +++ b/includes/install.inc @@ -542,31 +542,6 @@ function drupal_verify_profile($install_state) { } /** - * Callback to install an individual install profile module. - * - * Used during installation to install modules one at a time and then - * enable them, or to install a number of modules at one time - * from admin/modules. - * - * @param $module - * The machine name of the module to install. - * @return - * TRUE if the module got installed. - */ -function _drupal_install_module($module) { - if (drupal_get_installed_schema_version($module, TRUE) == SCHEMA_UNINSTALLED) { - drupal_load('module', $module); - drupal_install_schema($module); - // Now allow the module to perform install tasks. - module_invoke($module, 'install'); - $versions = drupal_get_schema_versions($module); - drupal_set_installed_schema_version($module, $versions ? max($versions) : SCHEMA_INSTALLED); - system_list_reset(); - return TRUE; - } -} - -/** * Manually include all files for the active database. * * Because we have no registry yet, we need to manually include the diff --git a/includes/module.inc b/includes/module.inc index 313f71253..f5f66d7e9 100644 --- a/includes/module.inc +++ b/includes/module.inc @@ -336,63 +336,69 @@ function module_enable($module_list, $enable_dependencies = TRUE, $disable_modul $module_list = array_keys($module_list); } - $invoke_modules = array(); - - // Required for _drupal_install_module(). + // Required for module installation checks. include_once DRUPAL_ROOT . '/includes/install.inc'; - // Try to install the enabled modules and collect which were installed. - // $module_list is not changed and already installed modules are ignored. - $modules_installed = array_filter($module_list, '_drupal_install_module'); + + $modules_installed = array(); + $modules_enabled = array(); foreach ($module_list as $module) { + // Only process modules that are not already enabled. $existing = db_query("SELECT status FROM {system} WHERE type = :type AND name = :name", array( ':type' => 'module', ':name' => $module)) ->fetchObject(); if ($existing->status == 0) { + // Load the module's code. + drupal_load('module', $module); module_load_install($module); + + // Update the database and module list to reflect the new module. This + // needs to be done first so that the module's hook implementations, + // hook_schema() in particular, can be called while it is being + // installed. db_update('system') ->fields(array('status' => 1)) ->condition('type', 'module') ->condition('name', $module) ->execute(); - drupal_load('module', $module); - $invoke_modules[] = $module; - watchdog('system', '%module module enabled.', array('%module' => $module), WATCHDOG_INFO); - } - } + // Refresh the module list to include it. + system_list_reset(); + module_list(TRUE); + module_implements('', FALSE, TRUE); + _system_update_bootstrap_status(); + // Update the registry to include it. + registry_update(); + // Refresh the schema to include it. + drupal_get_schema(NULL, TRUE); + + // Now install the module if necessary. + if (drupal_get_installed_schema_version($module, TRUE) == SCHEMA_UNINSTALLED) { + drupal_install_schema($module); + // Allow the module to perform install tasks. + module_invoke($module, 'install'); + $versions = drupal_get_schema_versions($module); + drupal_set_installed_schema_version($module, $versions ? max($versions) : SCHEMA_INSTALLED); + // Record the fact that it was installed. + $modules_installed[] = $module; + } - if (!empty($invoke_modules)) { - // Refresh the module list to exclude the disabled modules. - system_list_reset(); - module_list(TRUE); - module_implements('', FALSE, TRUE); - // Update the registry to include the new enabled module. - registry_update(); - // Refresh the schema to include the new enabled module. - drupal_get_schema(NULL, TRUE); + // Enable the module. + module_invoke($module, 'enable'); - // If any modules were newly installed, execute the hook for them. - if (!$disable_modules_installed_hook && !empty($modules_installed)) { - module_invoke_all('modules_installed', $modules_installed); + // Record the fact that it was enabled. + $modules_enabled[] = $module; + watchdog('system', '%module module enabled.', array('%module' => $module), WATCHDOG_INFO); } - _system_update_bootstrap_status(); } - foreach ($invoke_modules as $module) { - module_invoke($module, 'enable'); - // Check if node_access table needs rebuilding. - // 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 (function_exists('node_access_needs_rebuild') && !node_access_needs_rebuild() && module_hook($module, 'node_grants')) { - node_access_needs_rebuild(TRUE); - } + // If any modules were newly installed, invoke hook_modules_installed(). + if (!$disable_modules_installed_hook && !empty($modules_installed)) { + module_invoke_all('modules_installed', $modules_installed); } - if (!empty($invoke_modules)) { - // Invoke hook_modules_enabled after all the modules have been - // enabled. - module_invoke_all('modules_enabled', $invoke_modules); + // If any modules were newly enabled, invoke hook_modules_enabled(). + if (!empty($modules_enabled)) { + module_invoke_all('modules_enabled', $modules_enabled); } return TRUE; diff --git a/modules/node/node.module b/modules/node/node.module index 9e6b76045..36cc76dcd 100644 --- a/modules/node/node.module +++ b/modules/node/node.module @@ -3536,6 +3536,17 @@ function node_requirements($phase) { } /** + * Implements hook_modules_enabled(). + */ +function node_modules_enabled($modules) { + // Check if any of the newly enabled modules require the node_access table to + // be rebuilt. + if (!node_access_needs_rebuild() && array_intersect($modules, module_implements('node_grants'))) { + node_access_needs_rebuild(TRUE); + } +} + +/** * Controller class for nodes. * * This extends the DrupalDefaultEntityController class, adding required diff --git a/modules/rdf/rdf.install b/modules/rdf/rdf.install index ec553fcda..905c24771 100644 --- a/modules/rdf/rdf.install +++ b/modules/rdf/rdf.install @@ -43,8 +43,9 @@ function rdf_schema() { * Implements hook_install(). */ function rdf_install() { - // The installer does not trigger hook_modules_installed(), so it needs to be - // triggered manually for modules defining RDF mappings. + // Collect any RDF mappings that were declared by modules installed before + // this one. $modules = module_implements('rdf_mapping'); rdf_modules_installed($modules); } + diff --git a/modules/shortcut/shortcut.install b/modules/shortcut/shortcut.install index 634ee51fb..5c49322ee 100644 --- a/modules/shortcut/shortcut.install +++ b/modules/shortcut/shortcut.install @@ -7,14 +7,9 @@ */ /** - * Implements hook_enable(). + * Implements hook_install(). */ -function shortcut_enable() { - if (shortcut_set_load(SHORTCUT_DEFAULT_SET_NAME)) { - // Quit out; this module has already been installed before. - return; - } - +function shortcut_install() { $t = get_t(); // Create an initial default shortcut set. $shortcut_set = new StdClass(); diff --git a/modules/simpletest/tests/module.test b/modules/simpletest/tests/module.test index 242910c7f..31c0bb028 100644 --- a/modules/simpletest/tests/module.test +++ b/modules/simpletest/tests/module.test @@ -126,13 +126,50 @@ class ModuleUnitTest extends DrupalWebTestCase { } /** + * Unit tests for module installation. + */ +class ModuleInstallTestCase extends DrupalWebTestCase { + public static function getInfo() { + return array( + 'name' => 'Module installation', + 'description' => 'Tests the installation of modules.', + 'group' => 'Module', + ); + } + + function setUp() { + parent::setUp('module_test'); + } + + /** + * Test that calls to drupal_write_record() work during module installation. + * + * This is a useful function to test because modules often use it to insert + * initial data in their database tables when they are being installed or + * enabled. Furthermore, drupal_write_record() relies on the module schema + * information being available, so this also checks that the data from one of + * the module's hook implementations, in particular hook_schema(), is + * properly available during this time. Therefore, this test helps ensure + * that modules are fully functional while Drupal is installing and enabling + * them. + */ + function testDrupalWriteRecord() { + // Check for data that was inserted using drupal_write_record() while the + // 'module_test' module was being installed and enabled. + $data = db_query("SELECT data FROM {module_test}")->fetchCol(); + $this->assertTrue(in_array('Data inserted in hook_install()', $data), t('Data inserted using drupal_write_record() in hook_install() is correctly saved.')); + $this->assertTrue(in_array('Data inserted in hook_enable()', $data), t('Data inserted using drupal_write_record() in hook_enable() is correctly saved.')); + } +} + +/** * Unit tests for module uninstallation and related hooks. */ class ModuleUninstallTestCase extends DrupalWebTestCase { public static function getInfo() { return array( 'name' => 'Module uninstallation', - 'description' => 'Checks module uninstallation', + 'description' => 'Tests the uninstallation of modules.', 'group' => 'Module', ); } @@ -147,6 +184,7 @@ class ModuleUninstallTestCase extends DrupalWebTestCase { function testUserPermsUninstalled() { // Uninstalls the module_test module, so hook_modules_uninstalled() // is executed. + module_disable(array('module_test')); drupal_uninstall_modules(array('module_test')); // Are the perms defined by module_test removed from {role_permission}. diff --git a/modules/simpletest/tests/module_test.install b/modules/simpletest/tests/module_test.install new file mode 100644 index 000000000..5f8e76b70 --- /dev/null +++ b/modules/simpletest/tests/module_test.install @@ -0,0 +1,43 @@ +<?php +// $Id$ + +/** + * @file + * Install, update and uninstall functions for the module_test module. + */ + +/** + * Implements hook_schema(). + */ +function module_test_schema() { + $schema['module_test'] = array( + 'description' => 'Dummy table to test the behavior of hook_schema() during module installation.', + 'fields' => array( + 'data' => array( + 'type' => 'varchar', + 'length' => 255, + 'not null' => TRUE, + 'default' => '', + 'description' => 'An example data column for the module.', + ), + ), + ); + return $schema; +} + +/** + * Implements hook_install(). + */ +function module_test_install() { + $record = array('data' => 'Data inserted in hook_install()'); + drupal_write_record('module_test', $record); +} + +/** + * Implements hook_enable(). + */ +function module_test_enable() { + $record = array('data' => 'Data inserted in hook_enable()'); + drupal_write_record('module_test', $record); +} + diff --git a/modules/system/system.module b/modules/system/system.module index 18ada5af7..f598fc590 100644 --- a/modules/system/system.module +++ b/modules/system/system.module @@ -2226,6 +2226,8 @@ function _system_update_bootstrap_status() { $query->condition('name', $bootstrap_modules, 'NOT IN'); } $query->execute(); + // Reset the cached list of bootstrap modules. + system_list_reset(); } /** |