Commit f6b166ff authored by Dries's avatar Dries

- Patch #620298 by David_Rothstein: schema not available in hook_install().

parent bc70eaeb
...@@ -1493,8 +1493,7 @@ function install_finished(&$install_state) { ...@@ -1493,8 +1493,7 @@ function install_finished(&$install_state) {
* Batch callback for batch installation of modules. * Batch callback for batch installation of modules.
*/ */
function _install_module_batch($module, $module_name, &$context) { function _install_module_batch($module, $module_name, &$context) {
_drupal_install_module($module); // Install and enable the module right away, so that the module will be
// We enable the installed module right away, so that the module will be
// loaded by drupal_bootstrap in subsequent batch requests, and other // loaded by drupal_bootstrap in subsequent batch requests, and other
// modules possibly depending on it can safely perform their installation // modules possibly depending on it can safely perform their installation
// steps. // steps.
......
...@@ -541,31 +541,6 @@ function drupal_verify_profile($install_state) { ...@@ -541,31 +541,6 @@ function drupal_verify_profile($install_state) {
return $requirements; return $requirements;
} }
/**
* 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. * Manually include all files for the active database.
* *
......
...@@ -336,63 +336,69 @@ function module_enable($module_list, $enable_dependencies = TRUE, $disable_modul ...@@ -336,63 +336,69 @@ function module_enable($module_list, $enable_dependencies = TRUE, $disable_modul
$module_list = array_keys($module_list); $module_list = array_keys($module_list);
} }
$invoke_modules = array(); // Required for module installation checks.
// Required for _drupal_install_module().
include_once DRUPAL_ROOT . '/includes/install.inc'; 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();
$modules_installed = array_filter($module_list, '_drupal_install_module'); $modules_enabled = array();
foreach ($module_list as $module) { 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( $existing = db_query("SELECT status FROM {system} WHERE type = :type AND name = :name", array(
':type' => 'module', ':type' => 'module',
':name' => $module)) ':name' => $module))
->fetchObject(); ->fetchObject();
if ($existing->status == 0) { if ($existing->status == 0) {
// Load the module's code.
drupal_load('module', $module);
module_load_install($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') db_update('system')
->fields(array('status' => 1)) ->fields(array('status' => 1))
->condition('type', 'module') ->condition('type', 'module')
->condition('name', $module) ->condition('name', $module)
->execute(); ->execute();
drupal_load('module', $module); // Refresh the module list to include it.
$invoke_modules[] = $module; system_list_reset();
watchdog('system', '%module module enabled.', array('%module' => $module), WATCHDOG_INFO); 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)) { // Enable the module.
// Refresh the module list to exclude the disabled modules. module_invoke($module, 'enable');
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);
// If any modules were newly installed, execute the hook for them. // Record the fact that it was enabled.
if (!$disable_modules_installed_hook && !empty($modules_installed)) { $modules_enabled[] = $module;
module_invoke_all('modules_installed', $modules_installed); watchdog('system', '%module module enabled.', array('%module' => $module), WATCHDOG_INFO);
} }
_system_update_bootstrap_status();
} }
foreach ($invoke_modules as $module) { // If any modules were newly installed, invoke hook_modules_installed().
module_invoke($module, 'enable'); if (!$disable_modules_installed_hook && !empty($modules_installed)) {
// Check if node_access table needs rebuilding. module_invoke_all('modules_installed', $modules_installed);
// 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 (!empty($invoke_modules)) { // If any modules were newly enabled, invoke hook_modules_enabled().
// Invoke hook_modules_enabled after all the modules have been if (!empty($modules_enabled)) {
// enabled. module_invoke_all('modules_enabled', $modules_enabled);
module_invoke_all('modules_enabled', $invoke_modules);
} }
return TRUE; return TRUE;
......
...@@ -3535,6 +3535,17 @@ function node_requirements($phase) { ...@@ -3535,6 +3535,17 @@ function node_requirements($phase) {
return $requirements; return $requirements;
} }
/**
* 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. * Controller class for nodes.
* *
......
...@@ -43,8 +43,9 @@ function rdf_schema() { ...@@ -43,8 +43,9 @@ function rdf_schema() {
* Implements hook_install(). * Implements hook_install().
*/ */
function rdf_install() { function rdf_install() {
// The installer does not trigger hook_modules_installed(), so it needs to be // Collect any RDF mappings that were declared by modules installed before
// triggered manually for modules defining RDF mappings. // this one.
$modules = module_implements('rdf_mapping'); $modules = module_implements('rdf_mapping');
rdf_modules_installed($modules); rdf_modules_installed($modules);
} }
...@@ -7,14 +7,9 @@ ...@@ -7,14 +7,9 @@
*/ */
/** /**
* Implements hook_enable(). * Implements hook_install().
*/ */
function shortcut_enable() { function shortcut_install() {
if (shortcut_set_load(SHORTCUT_DEFAULT_SET_NAME)) {
// Quit out; this module has already been installed before.
return;
}
$t = get_t(); $t = get_t();
// Create an initial default shortcut set. // Create an initial default shortcut set.
$shortcut_set = new StdClass(); $shortcut_set = new StdClass();
......
...@@ -125,6 +125,43 @@ class ModuleUnitTest extends DrupalWebTestCase { ...@@ -125,6 +125,43 @@ 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. * Unit tests for module uninstallation and related hooks.
*/ */
...@@ -132,7 +169,7 @@ class ModuleUninstallTestCase extends DrupalWebTestCase { ...@@ -132,7 +169,7 @@ class ModuleUninstallTestCase extends DrupalWebTestCase {
public static function getInfo() { public static function getInfo() {
return array( return array(
'name' => 'Module uninstallation', 'name' => 'Module uninstallation',
'description' => 'Checks module uninstallation', 'description' => 'Tests the uninstallation of modules.',
'group' => 'Module', 'group' => 'Module',
); );
} }
...@@ -147,6 +184,7 @@ class ModuleUninstallTestCase extends DrupalWebTestCase { ...@@ -147,6 +184,7 @@ class ModuleUninstallTestCase extends DrupalWebTestCase {
function testUserPermsUninstalled() { function testUserPermsUninstalled() {
// Uninstalls the module_test module, so hook_modules_uninstalled() // Uninstalls the module_test module, so hook_modules_uninstalled()
// is executed. // is executed.
module_disable(array('module_test'));
drupal_uninstall_modules(array('module_test')); drupal_uninstall_modules(array('module_test'));
// Are the perms defined by module_test removed from {role_permission}. // Are the perms defined by module_test removed from {role_permission}.
......
<?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);
}
...@@ -2226,6 +2226,8 @@ function _system_update_bootstrap_status() { ...@@ -2226,6 +2226,8 @@ function _system_update_bootstrap_status() {
$query->condition('name', $bootstrap_modules, 'NOT IN'); $query->condition('name', $bootstrap_modules, 'NOT IN');
} }
$query->execute(); $query->execute();
// Reset the cached list of bootstrap modules.
system_list_reset();
} }
/** /**
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment