Index: includes/actions.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/actions.inc,v retrieving revision 1.17 diff -u -p -r1.17 actions.inc --- includes/actions.inc 15 Sep 2008 16:07:47 -0000 1.17 +++ includes/actions.inc 16 Sep 2008 17:48:31 -0000 @@ -78,12 +78,16 @@ function actions_do($action_ids, $object foreach ($actions as $action_id => $params) { if (is_numeric($action_id)) { // Configurable actions need parameters. $function = $params['callback']; - $context = array_merge($context, $params); - $result[$action_id] = $function($object, $context, $a1, $a2); + if (drupal_function_exists($function)) { + $context = array_merge($context, $params); + $result[$action_id] = $function($object, $context, $a1, $a2); + } } // Singleton action; $action_id is the function name. else { - $result[$action_id] = $action_id($object, $context, $a1, $a2); + if (drupal_function_exists($action_id)) { + $result[$action_id] = $action_id($object, $context, $a1, $a2); + } } } } @@ -93,12 +97,16 @@ function actions_do($action_ids, $object if (is_numeric($action_ids)) { $action = db_fetch_object(db_query("SELECT * FROM {actions} WHERE aid = '%s'", $action_ids)); $function = $action->callback; - $context = array_merge($context, unserialize($action->parameters)); - $result[$action_ids] = $function($object, $context, $a1, $a2); + if (drupal_function_exists($function)) { + $context = array_merge($context, unserialize($action->parameters)); + $result[$action_ids] = $function($object, $context, $a1, $a2); + } } // Singleton action; $action_ids is the function name. else { - $result[$action_ids] = $action_ids($object, $context, $a1, $a2); + if (drupal_function_exists($action_ids)) { + $result[$action_ids] = $action_ids($object, $context, $a1, $a2); + } } } return $result; @@ -235,8 +243,8 @@ function actions_function_lookup($hash) } } - // Must be an instance; must check database. - $aid = db_result(db_query("SELECT aid FROM {actions} WHERE MD5(aid) = '%s' AND parameters <> ''", $hash)); + // Must be an instance or an orphaned action; must check database. + $aid = db_result(db_query("SELECT aid FROM {actions} WHERE MD5(aid) = '%s'", $hash)); return $aid; } @@ -247,11 +255,18 @@ function actions_function_lookup($hash) * This is necessary so that actions that do not require configuration can * receive action IDs. This is not necessarily the best approach, * but it is the most straightforward. + * + * @param $delete_orphans + * If TRUE, any actions that exist in the database but are no longer found + * in the code (for example, because the module that provides them has + * been disabled) will be deleted. + * + * @return + * If $delete_orphans is FALSE, array of orphaned action callbacks. + * If $delete_orphans is TRUE, an array of actions that were deleted. */ -function actions_synchronize($actions_in_code = array(), $delete_orphans = FALSE) { - if (!$actions_in_code) { - $actions_in_code = actions_list(TRUE); - } +function actions_synchronize($delete_orphans = FALSE) { + $actions_in_code = actions_list(TRUE); $actions_in_db = array(); $result = db_query("SELECT * FROM {actions} WHERE parameters = ''"); while ($action = db_fetch_object($result)) { @@ -288,17 +303,21 @@ function actions_synchronize($actions_in $orphans = implode(', ', $orphaned); if ($delete_orphans) { + $deleted = array(); $placeholders = implode(', ', $placeholder); $results = db_query("SELECT a.aid, a.description FROM {actions} a WHERE callback IN ($placeholders)", $orphaned); while ($action = db_fetch_object($results)) { actions_delete($action->aid); - watchdog('actions', "Removed orphaned action '%action' from database.", array('%action' => filter_xss_admin($action->description))); + $deleted[] = $action; + watchdog('actions', "Removed orphaned action '%action' from database.", array('%action' => check_plain($action->description))); } + return $deleted; } else { - $link = l(t('Remove orphaned actions'), 'admin/build/actions/orphan'); + $link = l(t('Remove orphaned actions'), 'admin/settings/actions/orphan'); $count = count($actions_in_db); watchdog('actions', format_plural($count, 'One orphaned action (%orphans) exists in the actions table. !link', '@count orphaned actions (%orphans) exist in the actions table. !link'), array('@count' => $count, '%orphans' => $orphans, '!link' => $link), WATCHDOG_WARNING); + return $orphaned; } } } Index: modules/system/system.module =================================================================== RCS file: /cvs/drupal/drupal/modules/system/system.module,v retrieving revision 1.619 diff -u -p -r1.619 system.module --- modules/system/system.module 15 Sep 2008 08:49:40 -0000 1.619 +++ modules/system/system.module 16 Sep 2008 17:48:33 -0000 @@ -1483,8 +1483,16 @@ function system_action_info() { */ function system_actions_manage() { $output = ''; + + // Warn user of any orphaned actions. + $orphans = actions_synchronize(); + $count = count($orphans); + $link = l(t('Remove orphaned actions'), 'admin/settings/actions/orphan'); + if ($orphans) { + drupal_set_message(t(format_plural($count, 'One orphaned action (%orphans) exists in the actions table. !link', '@count orphaned actions (%orphans) exist in the actions table. !link'), array('@count' => $count, '%orphans' => implode(', ', $orphans), '!link' => $link)), 'error', FALSE); + } + $actions = actions_list(); - actions_synchronize($actions); $actions_map = actions_actions_map($actions); $options = array(t('Choose an advanced action')); $unconfigurable = array(); @@ -1717,28 +1725,21 @@ function system_actions_delete_form_subm $action = actions_load($aid); actions_delete($aid); $description = check_plain($action->description); + drupal_set_message(t('Action %action was deleted.', array('%action' => $description))); watchdog('user', 'Deleted action %aid (%action)', array('%aid' => $aid, '%action' => $description)); - drupal_set_message(t('Action %action was deleted', array('%action' => $description))); $form_state['redirect'] = 'admin/settings/actions/manage'; } /** - * Post-deletion operations for deleting action orphans. - * - * @param $orphaned - * An array of orphaned actions. - */ -function system_action_delete_orphans_post($orphaned) { - foreach ($orphaned as $callback) { - drupal_set_message(t("Deleted orphaned action (%action).", array('%action' => $callback))); - } -} - -/** * Remove actions that are in the database but not supported by any enabled module. */ function system_actions_remove_orphans() { - actions_synchronize(actions_list(), TRUE); + if ($deleted = actions_synchronize(TRUE)) { + foreach ($deleted as $action) { + $description = check_plain($action->description); + drupal_set_message(t("Orphaned action %action was deleted.", array('%action' => $description))); + } + } drupal_goto('admin/settings/actions/manage'); } Index: modules/trigger/trigger.admin.inc =================================================================== RCS file: /cvs/drupal/drupal/modules/trigger/trigger.admin.inc,v retrieving revision 1.7 diff -u -p -r1.7 trigger.admin.inc --- modules/trigger/trigger.admin.inc 16 Jul 2008 21:59:28 -0000 1.7 +++ modules/trigger/trigger.admin.inc 16 Sep 2008 17:48:33 -0000 @@ -24,6 +24,14 @@ function trigger_assign($type = NULL) { $type = 'nodeapi'; } + // Warn user of any orphaned actions. + $orphans = actions_synchronize(); + $count = count($orphans); + $link = l(t('Remove orphaned actions'), 'admin/settings/actions/orphan'); + if ($orphans) { + drupal_set_message(t(format_plural($count, 'One orphaned action (%orphans) exists in the actions table. !link', '@count orphaned actions (%orphans) exist in the actions table. !link'), array('@count' => $count, '%orphans' => implode(', ', $orphans), '!link' => $link)), 'error', FALSE); + } + $output = ''; $hooks = module_invoke_all('hook_info'); foreach ($hooks as $module => $hook) { Index: modules/trigger/trigger.install =================================================================== RCS file: /cvs/drupal/drupal/modules/trigger/trigger.install,v retrieving revision 1.5 diff -u -p -r1.5 trigger.install --- modules/trigger/trigger.install 28 Dec 2007 12:02:52 -0000 1.5 +++ modules/trigger/trigger.install 16 Sep 2008 17:48:33 -0000 @@ -9,7 +9,7 @@ function trigger_install() { drupal_install_schema('trigger'); // Do initial synchronization of actions in code and the database. - actions_synchronize(actions_list()); + actions_synchronize(); } /**