Commit 4d202740 authored by webchick's avatar webchick

#253569 by aaron, agentrickard, and Dave Reid: Add hook_modules_X to allow...

#253569 by aaron, agentrickard, and Dave Reid: Add hook_modules_X to allow modules to react when other modules are enabled, disabled, installed, or uninstalled.
parent 11074d91
......@@ -506,7 +506,10 @@ function drupal_install_modules($module_list = array()) {
} while ($moved);
asort($module_list);
$module_list = array_keys($module_list);
array_filter($module_list, '_drupal_install_module');
$modules_installed = array_filter($module_list, '_drupal_install_module');
if (!empty($modules_installed)) {
module_invoke_all('modules_installed', $modules_installed);
}
module_enable($module_list);
}
......@@ -574,46 +577,52 @@ function drupal_install_system() {
module_rebuild_cache();
}
/**
* Calls the uninstall function and updates the system table for a given module.
*
* @param $module
* The machine name of the module to uninstall.
*/
function drupal_uninstall_module($module) {
// First, retrieve all the module's menu paths from db.
drupal_load('module', $module);
$paths = module_invoke($module, 'menu');
// Uninstall the module(s).
module_load_install($module);
module_invoke($module, 'uninstall');
// Now remove the menu links for all paths declared by this module.
if (!empty($paths)) {
$paths = array_keys($paths);
// Clean out the names of load functions.
foreach ($paths as $index => $path) {
$parts = explode('/', $path, MENU_MAX_PARTS);
foreach ($parts as $k => $part) {
if (preg_match('/^%[a-z_]*$/', $part)) {
$parts[$k] = '%';
* @param $module_list
* The modules to uninstall.
*/
function drupal_uninstall_modules($module_list = array()) {
foreach ($module_list as $module) {
// First, retrieve all the module's menu paths from db.
drupal_load('module', $module);
$paths = module_invoke($module, 'menu');
// Uninstall the module.
module_load_install($module);
module_invoke($module, 'uninstall');
// Now remove the menu links for all paths declared by this module.
if (!empty($paths)) {
$paths = array_keys($paths);
// Clean out the names of load functions.
foreach ($paths as $index => $path) {
$parts = explode('/', $path, MENU_MAX_PARTS);
foreach ($parts as $k => $part) {
if (preg_match('/^%[a-z_]*$/', $part)) {
$parts[$k] = '%';
}
}
$paths[$index] = implode('/', $parts);
}
$paths[$index] = implode('/', $parts);
}
$placeholders = implode(', ', array_fill(0, count($paths), "'%s'"));
$placeholders = implode(', ', array_fill(0, count($paths), "'%s'"));
$result = db_query('SELECT * FROM {menu_links} WHERE router_path IN (' . $placeholders . ') AND external = 0 ORDER BY depth DESC', $paths);
// Remove all such items. Starting from those with the greatest depth will
// minimize the amount of re-parenting done by menu_link_delete().
while ($item = db_fetch_array($result)) {
_menu_delete_item($item, TRUE);
$result = db_query('SELECT * FROM {menu_links} WHERE router_path IN (' . $placeholders . ') AND external = 0 ORDER BY depth DESC', $paths);
// Remove all such items. Starting from those with the greatest depth will
// minimize the amount of re-parenting done by menu_link_delete().
while ($item = db_fetch_array($result)) {
_menu_delete_item($item, TRUE);
}
}
drupal_set_installed_schema_version($module, SCHEMA_UNINSTALLED);
}
drupal_set_installed_schema_version($module, SCHEMA_UNINSTALLED);
if (!empty($module_list)) {
// Call hook_module_uninstall to let other modules act
module_invoke_all('modules_uninstalled', $module_list);
}
}
/**
......
......@@ -297,6 +297,12 @@ function module_enable($module_list) {
node_access_needs_rebuild(TRUE);
}
}
if (!empty($invoke_modules)) {
// Invoke the hook_module_enable after all the modules have been
// enabled.
module_invoke_all('modules_enabled', $invoke_modules);
}
}
/**
......@@ -322,6 +328,9 @@ function module_disable($module_list) {
}
if (!empty($invoke_modules)) {
// 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, FALSE);
// Force to regenerate the stored list of hook implementations.
......
......@@ -84,3 +84,39 @@ function system_test_redirect_invalid_scheme() {
function system_test_destination() {
return 'The destination: ' . drupal_get_destination();
}
/**
* Implementation of hook_modules_installed().
*/
function system_test_modules_installed($modules) {
if (in_array('aggregator', $modules)) {
drupal_set_message(t('hook_modules_installed fired for aggregator'));
}
}
/**
* Implementation of hook_modules_enabled().
*/
function system_test_modules_enabled($modules) {
if (in_array('aggregator', $modules)) {
drupal_set_message(t('hook_modules_enabled fired for aggregator'));
}
}
/**
* Implementation of hook_modules_disabled().
*/
function system_test_modules_disabled($modules) {
if (in_array('aggregator', $modules)) {
drupal_set_message(t('hook_modules_disabled fired for aggregator'));
}
}
/**
* Implementation of hook_modules_uninstalled().
*/
function system_test_modules_uninstalled($modules) {
if (in_array('aggregator', $modules)) {
drupal_set_message(t('hook_modules_uninstalled fired for aggregator'));
}
}
......@@ -1083,9 +1083,8 @@ function system_modules_uninstall_submit($form, &$form_state) {
if (!empty($form['#confirmed'])) {
// Call the uninstall routine for each selected module.
foreach (array_filter($form_state['values']['uninstall']) as $module => $value) {
drupal_uninstall_module($module);
}
$modules = array_keys($form_state['values']['uninstall']);
drupal_uninstall_modules($modules);
drupal_set_message(t('The selected modules have been uninstalled.'));
unset($form_state['storage']);
......
......@@ -19,7 +19,7 @@ class EnableDisableCoreTestCase extends DrupalWebTestCase {
* Implementation of setUp().
*/
function setUp() {
parent::setUp();
parent::setUp('system_test');
$this->admin_user = $this->drupalCreateUser(array('access administration pages', 'administer site configuration'));
$this->drupalLogin($this->admin_user);
......@@ -28,17 +28,22 @@ class EnableDisableCoreTestCase extends DrupalWebTestCase {
/**
* Enable a module, check the database for related tables, disable module,
* check for related tables, unistall module, check for related tables.
* Also check for invocation of the hook_module_action hook.
*/
function testEnableDisable() {
// Enable aggregator, and check tables.
$this->assertModules(array('aggregator'), FALSE);
$this->assertTableCount('aggregator', FALSE);
// Install (and enable) aggregator module.
$edit = array();
$edit['modules[Core][aggregator][enable]'] = 'aggregator';
$this->drupalPost('admin/build/modules', $edit, t('Save configuration'));
$this->assertText(t('The configuration options have been saved.'), t('Modules status has been updated.'));
// Check that hook_modules_installed and hook_modules_enabled hooks were invoked and check tables.
$this->assertText(t('hook_modules_installed fired for aggregator'), t('hook_modules_installed fired.'));
$this->assertText(t('hook_modules_enabled fired for aggregator'), t('hook_modules_enabled fired.'));
$this->assertModules(array('aggregator'), TRUE);
$this->assertTableCount('aggregator', TRUE);
......@@ -48,9 +53,12 @@ class EnableDisableCoreTestCase extends DrupalWebTestCase {
$this->drupalPost('admin/build/modules', $edit, t('Save configuration'));
$this->assertText(t('The configuration options have been saved.'), t('Modules status has been updated.'));
// Check that hook_modules_disabled hook was invoked and check tables.
$this->assertText(t('hook_modules_disabled fired for aggregator'), t('hook_modules_disabled fired.'));
$this->assertModules(array('aggregator'), FALSE);
$this->assertTableCount('aggregator', TRUE);
// Uninstall the module.
$edit = array();
$edit['uninstall[aggregator]'] = 'aggregator';
$this->drupalPost('admin/build/modules/uninstall', $edit, t('Uninstall'));
......@@ -58,6 +66,8 @@ class EnableDisableCoreTestCase extends DrupalWebTestCase {
$this->drupalPost(NULL, NULL, t('Uninstall'));
$this->assertText(t('The selected modules have been uninstalled.'), t('Modules status has been updated.'));
// Check that hook_modules_uninstalled hook was invoked and check tables.
$this->assertText(t('hook_modules_uninstalled fired for aggregator'), t('hook_modules_uninstalled fired.'));
$this->assertModules(array('aggregator'), FALSE);
$this->assertTableCount('aggregator', FALSE);
}
......
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