Commit eeed9ed8 authored by Dries's avatar Dries
Browse files

- Patch #764558 by Rob Loach, sun, xjm, chx, catch: Remove trigger module from core.

parent 98509c1a
......@@ -10,6 +10,7 @@ Drupal 8.0, xxxx-xx-xx (development version)
modules with similar functionality are available:
* Blog
* Profile
* Trigger
- Removed the Garland theme from core.
- Universally Unique IDentifier (UUID):
* Support for generating and validating UUIDs.
......
......@@ -264,9 +264,6 @@ Tracker module
Translation module
- Francesco Placella 'plach' <http://drupal.org/user/183211>
Trigger module
- ?
Update module
- Derek Wright 'dww' <http://drupal.org/user/46549>
......
......@@ -11,9 +11,7 @@
* Functions that perform an action on a certain system object.
*
* Action functions are declared by modules by implementing hook_action_info().
* Modules can cause action functions to run by calling actions_do(), and
* trigger.module provides a user interface that lets administrators define
* events that cause action functions to run.
* Modules can cause action functions to run by calling actions_do().
*
* Each action function takes two to four arguments:
* - $entity: The object that the action acts on, such as a node, comment, or
......
......@@ -67,6 +67,8 @@ class ActionsConfigurationTestCase extends DrupalWebTestCase {
* Test actions executing in a potential loop, and make sure they abort properly.
*/
class ActionLoopTestCase extends DrupalWebTestCase {
protected $aid;
public static function getInfo() {
return array(
'name' => 'Actions executing in a potentially infinite loop',
......@@ -76,7 +78,7 @@ class ActionLoopTestCase extends DrupalWebTestCase {
}
function setUp() {
parent::setUp('dblog', 'trigger', 'actions_loop_test');
parent::setUp('dblog', 'actions_loop_test');
}
/**
......@@ -86,9 +88,8 @@ class ActionLoopTestCase extends DrupalWebTestCase {
$user = $this->drupalCreateUser(array('administer actions'));
$this->drupalLogin($user);
$hash = drupal_hash_base64('actions_loop_test_log');
$edit = array('aid' => $hash);
$this->drupalPost('admin/structure/trigger/actions_loop_test', $edit, t('Assign'));
$info = actions_loop_test_action_info();
$this->aid = actions_save('actions_loop_test_log', $info['actions_loop_test_log']['type'], array(), $info['actions_loop_test_log']['label']);
// Delete any existing watchdog messages to clear the plethora of
// "Action added" messages from when Drupal was installed.
......@@ -107,7 +108,7 @@ class ActionLoopTestCase extends DrupalWebTestCase {
* times.
*/
protected function triggerActions() {
$this->drupalGet('<front>', array('query' => array('trigger_actions_on_watchdog' => TRUE)));
$this->drupalGet('<front>', array('query' => array('trigger_actions_on_watchdog' => $this->aid)));
$expected = array();
$expected[] = 'Triggering action loop';
for ($i = 1; $i <= variable_get('actions_max_stack', 35); $i++) {
......
<?php
/**
* Implements hook_trigger_info().
*/
function actions_loop_test_trigger_info() {
return array(
'actions_loop_test' => array(
'watchdog' => array(
'label' => t('When a message is logged'),
),
),
);
}
/**
* Implements hook_watchdog().
*/
......@@ -21,9 +8,6 @@ function actions_loop_test_watchdog(array $log_entry) {
if (empty($_GET['trigger_actions_on_watchdog'])) {
return;
}
// Get all the action ids assigned to the trigger on the watchdog hook's
// "run" event.
$aids = trigger_get_assigned_actions('watchdog');
// We can pass in any applicable information in $context. There isn't much in
// this case, but we'll pass in the hook name as the bare minimum.
$context = array(
......@@ -31,7 +15,8 @@ function actions_loop_test_watchdog(array $log_entry) {
);
// Fire the actions on the associated object ($log_entry) and the context
// variable.
actions_do(array_keys($aids), $log_entry, $context);
$aids = (array) $_GET['trigger_actions_on_watchdog'];
actions_do($aids, $log_entry, $context);
}
/**
......
......@@ -3061,7 +3061,7 @@ function system_actions_configure($form, &$form_state, $action = NULL) {
'#title' => t('Label'),
'#default_value' => $edit['actions_label'],
'#maxlength' => '255',
'#description' => t('A unique label for this advanced action. This label will be displayed in the interface of modules that integrate with actions, such as Trigger module.'),
'#description' => t('A unique label for this advanced action. This label will be displayed in the interface of modules that integrate with actions.'),
'#weight' => -10
);
$action_form = $function . '_form';
......
......@@ -3384,9 +3384,7 @@ function hook_file_mimetype_mapping_alter(&$mapping) {
* Declares information about actions.
*
* Any module can define actions, and then call actions_do() to make those
* actions happen in response to events. The trigger module provides a user
* interface for associating actions with module-defined triggers, and it makes
* sure the core triggers fire off actions when their events happen.
* actions happen in response to events.
*
* An action consists of two or three parts:
* - an action definition (returned by this hook)
......@@ -3417,14 +3415,9 @@ function hook_file_mimetype_mapping_alter(&$mapping) {
* declare support for any trigger by returning array('any') for this value.
* - 'behavior': (optional) A machine-readable array of behaviors of this
* action, used to signal additionally required actions that may need to be
* triggered. Currently recognized behaviors by Trigger module:
* - 'changes_property': If an action with this behavior is assigned to a
* trigger other than a "presave" hook, any save actions also assigned to
* this trigger are moved later in the list. If no save action is present,
* one will be added.
* Modules that are processing actions (like Trigger module) should take
* special care for the "presave" hook, in which case a dependent "save"
* action should NOT be invoked.
* triggered. Modules that are processing actions should take special care
* for the "presave" hook, in which case a dependent "save" action should
* NOT be invoked.
*
* @ingroup actions
*/
......@@ -3470,8 +3463,6 @@ function hook_actions_delete($aid) {
*
* Called by actions_list() to allow modules to alter the return values from
* implementations of hook_action_info().
*
* @see trigger_example_action_info_alter()
*/
function hook_action_info_alter(&$actions) {
$actions['node_unpublish_action']['label'] = t('Unpublish and remove from public view.');
......
......@@ -90,7 +90,7 @@ function system_help($path, $arg) {
$output .= '<dt>' . t('Configuring basic site settings') . '</dt>';
$output .= '<dd>' . t('The System module also handles basic configuration options for your site, including <a href="@date-time-settings">Date and time settings</a>, <a href="@file-system">File system settings</a>, <a href="@clean-url">Clean URL support</a>, <a href="@site-info">Site name and other information</a>, and a <a href="@maintenance-mode">Maintenance mode</a> for taking your site temporarily offline.', array('@date-time-settings' => url('admin/config/regional/date-time'), '@file-system' => url('admin/config/media/file-system'), '@clean-url' => url('admin/config/search/clean-urls'), '@site-info' => url('admin/config/system/site-information'), '@maintenance-mode' => url('admin/config/development/maintenance'))) . '</dd>';
$output .= '<dt>' . t('Configuring actions') . '</dt>';
$output .= '<dd>' . t('Actions are individual tasks that the system can do, such as unpublishing a piece of content or banning a user. Modules, such as the <a href="@trigger-help">Trigger module</a>, can fire these actions when certain system events happen; for example, when a new post is added or when a user logs in. Modules may also provide additional actions. Visit the <a href="@actions">Actions page</a> to configure actions.', array('@trigger-help' => url('admin/help/trigger'), '@actions' => url('admin/config/system/actions'))) . '</dd>';
$output .= '<dd>' . t('Actions are individual tasks that the system can do, such as unpublishing a piece of content or banning a user. Other modules can fire these actions when certain system events happen; for example, when a new post is added or when a user logs in. Modules may also provide additional actions. Visit the <a href="@actions">Actions page</a> to configure actions.', array('@actions' => url('admin/config/system/actions'))) . '</dd>';
$output .= '</dl>';
return $output;
case 'admin/index':
......@@ -135,12 +135,9 @@ function system_help($path, $arg) {
case 'admin/config/system/actions/manage':
$output = '';
$output .= '<p>' . t('There are two types of actions: simple and advanced. Simple actions do not require any additional configuration and are listed here automatically. Advanced actions need to be created and configured before they can be used because they have options that need to be specified; for example, sending an e-mail to a specified address or unpublishing content containing certain words. To create an advanced action, select the action from the drop-down list in the advanced action section below and click the <em>Create</em> button.') . '</p>';
if (module_exists('trigger')) {
$output .= '<p>' . t('You may proceed to the <a href="@url">Triggers</a> page to assign these actions to system events.', array('@url' => url('admin/structure/trigger'))) . '</p>';
}
return $output;
case 'admin/config/system/actions/configure':
return t('An advanced action offers additional configuration options which may be filled out below. Changing the <em>Description</em> field is recommended in order to better identify the precise action taking place. This description will be displayed in modules such as the Trigger module when assigning actions to system events, so it is best if it is as descriptive as possible (for example, "Send e-mail to Moderation Team" rather than simply "Send e-mail").');
return t('An advanced action offers additional configuration options which may be filled out below. Changing the <em>Description</em> field is recommended in order to better identify the precise action taking place.');
case 'admin/config/people/ip-blocking':
return '<p>' . t('IP addresses listed here are blocked from your site. Blocked addresses are completely forbidden from accessing the site and instead see a brief message explaining the situation.') . '</p>';
case 'admin/reports/status':
......
name = "Trigger Test"
description = "Support module for Trigger tests."
package = Testing
core = 8.x
hidden = TRUE
<?php
/**
* @file
* Mock module to aid in testing trigger.module.
*/
/**
* Implements hook_action_info().
*/
function trigger_test_action_info() {
// Register an action that can be assigned to the trigger "cron".
return array(
'trigger_test_system_cron_action' => array(
'type' => 'system',
'label' => t('Cron test action'),
'configurable' => FALSE,
'triggers' => array('cron'),
),
'trigger_test_system_cron_conf_action' => array(
'type' => 'system',
'label' => t('Cron test configurable action'),
'configurable' => TRUE,
'triggers' => array('cron'),
),
'trigger_test_generic_action' => array(
'type' => 'system',
'label' => t('Generic test action'),
'configurable' => FALSE,
'triggers' => array(
'taxonomy_term_insert',
'taxonomy_term_update',
'taxonomy_delete',
'comment_insert',
'comment_update',
'comment_delete',
'user_insert',
'user_update',
'user_delete',
'user_login',
'user_logout',
'user_view',
),
),
'trigger_test_generic_any_action' => array(
'type' => 'system',
'label' => t('Generic test action for any trigger'),
'configurable' => FALSE,
'triggers' => array('any'),
),
);
}
/**
* Implements hook_trigger_info().
*/
function trigger_test_trigger_info() {
// Register triggers that this module provides. The first is an additional
// node trigger and the second is our own, which should create a new tab
// on the trigger assignment page.
return array(
'node' => array(
'node_triggertest' => array(
'label' => t('A test trigger is fired'),
),
),
'trigger_test' => array(
'trigger_test_triggertest' => array(
'label' => t('Another test trigger is fired'),
),
),
);
}
/**
* Action fired during the "cron run" trigger test.
*/
function trigger_test_system_cron_action() {
// Indicate successful execution by setting a persistent variable.
variable_set('trigger_test_system_cron_action', TRUE);
}
/**
* Implement a configurable Drupal action.
*/
function trigger_test_system_cron_conf_action($object, $context) {
// Indicate successful execution by incrementing a persistent variable.
$value = variable_get('trigger_test_system_cron_conf_action', 0) + 1;
variable_set('trigger_test_system_cron_conf_action', $value);
}
/**
* Form for configurable test action.
*/
function trigger_test_system_cron_conf_action_form($context) {
if (!isset($context['subject'])) {
$context['subject'] = '';
}
$form['subject'] = array(
'#type' => 'textfield',
'#default_value' => $context['subject'],
);
return $form;
}
/**
* Form submission handler for configurable test action.
*/
function trigger_test_system_cron_conf_action_submit($form, $form_state) {
$form_values = $form_state['values'];
// Process the HTML form to store configuration. The keyed array that
// we return will be serialized to the database.
$params = array(
'subject' => $form_values['subject'],
);
return $params;
}
/**
* Action fired during the "taxonomy", "comment", and "user" trigger tests.
*/
function trigger_test_generic_action($context) {
// Indicate successful execution by setting a persistent variable.
variable_set('trigger_test_generic_action', TRUE);
}
/**
* Action fired during the additional trigger tests.
*/
function trigger_test_generic_any_action($context) {
// Indicate successful execution by setting a persistent variable.
variable_set('trigger_test_generic_any_action', variable_get('trigger_test_generic_any_action', 0) + 1);
}
<?php
/**
* @file
* Admin page callbacks for the trigger module.
*/
/**
* Builds the form that allows users to assign actions to triggers.
*
* @param $module_to_display
* Which tab of triggers to display. E.g., 'node' for all
* node-related triggers.
* @return
* HTML form.
*/
function trigger_assign($module_to_display = NULL) {
// If no type is specified we default to node actions, since they
// are the most common.
if (!isset($module_to_display)) {
drupal_goto('admin/structure/trigger/node');
}
$build = array();
$trigger_info = module_invoke_all('trigger_info');
drupal_alter('trigger_info', $trigger_info);
foreach ($trigger_info as $module => $hooks) {
if ($module == $module_to_display) {
foreach ($hooks as $hook => $description) {
$form_id = 'trigger_' . $hook . '_assign_form';
$build[$form_id] = drupal_get_form($form_id, $module, $hook, $description['label']);
}
}
}
return $build;
}
/**
* Confirm removal of an assigned action.
*
* @param $module
* The tab of triggers the user will be directed to after successful
* removal of the action, or if the confirmation form is cancelled.
* @param $hook
* @param $aid
* The action ID.
* @ingroup forms
* @see trigger_unassign_submit()
*/
function trigger_unassign($form, $form_state, $module, $hook = NULL, $aid = NULL) {
if (!($hook && $aid)) {
drupal_goto('admin/structure/trigger');
}
$form['hook'] = array(
'#type' => 'value',
'#value' => $hook,
);
$form['module'] = array(
'#type' => 'value',
'#value' => $module,
);
$form['aid'] = array(
'#type' => 'value',
'#value' => $aid,
);
$action = actions_function_lookup($aid);
$actions = actions_get_all_actions();
$destination = 'admin/structure/trigger/' . $module;
return confirm_form($form,
t('Are you sure you want to unassign the action %title?', array('%title' => $actions[$action]['label'])),
$destination,
t('You can assign it again later if you wish.'),
t('Unassign'), t('Cancel')
);
}
/**
* Submit callback for trigger_unassign() form.
*/
function trigger_unassign_submit($form, &$form_state) {
if ($form_state['values']['confirm'] == 1) {
$aid = actions_function_lookup($form_state['values']['aid']);
db_delete('trigger_assignments')
->condition('hook', $form_state['values']['hook'])
->condition('aid', $aid)
->execute();
$actions = actions_get_all_actions();
watchdog('actions', 'Action %action has been unassigned.', array('%action' => $actions[$aid]['label']));
drupal_set_message(t('Action %action has been unassigned.', array('%action' => $actions[$aid]['label'])));
$form_state['redirect'] = 'admin/structure/trigger/' . $form_state['values']['module'];
}
else {
drupal_goto('admin/structure/trigger');
}
}
/**
* Returns the form for assigning an action to a trigger.
*
* @param $module
* The name of the trigger group, e.g., 'node'.
* @param $hook
* The name of the trigger hook, e.g., 'node_insert'.
* @param $label
* A plain English description of what this trigger does.
*
* @ingoup forms
* @see trigger_assign_form_validate()
* @see trigger_assign_form_submit()
*/
function trigger_assign_form($form, $form_state, $module, $hook, $label) {
$form['module'] = array(
'#type' => 'hidden',
'#value' => $module,
);
$form['hook'] = array(
'#type' => 'hidden',
'#value' => $hook,
);
// All of these forms use the same validate and submit functions.
$form['#validate'][] = 'trigger_assign_form_validate';
$form['#submit'][] = 'trigger_assign_form_submit';
$options = array();
$functions = array();
// Restrict the options list to actions that declare support for this hook.
foreach (actions_list() as $func => $metadata) {
if (isset($metadata['triggers']) && array_intersect(array($hook, 'any'), $metadata['triggers'])) {
$functions[] = $func;
}
}
foreach (actions_actions_map(actions_get_all_actions()) as $aid => $action) {
if (in_array($action['callback'], $functions)) {
$options[$action['type']][$aid] = $action['label'];
}
}
$form[$hook] = array(
'#type' => 'fieldset',
// !description is correct, since these labels are passed through t() in
// hook_trigger_info().
'#title' => t('Trigger: !description', array('!description' => $label)),
'#theme' => 'trigger_display',
);
// Retrieve actions that are already assigned to this hook combination.
$actions = trigger_get_assigned_actions($hook);
$form[$hook]['assigned']['#type'] = 'value';
$form[$hook]['assigned']['#value'] = array();
foreach ($actions as $aid => $info) {
// If action is defined unassign it, otherwise offer to delete all orphaned
// actions.
$hash = drupal_hash_base64($aid, TRUE);
if (actions_function_lookup($hash)) {
$form[$hook]['assigned']['#value'][$aid] = array(
'label' => $info['label'],
'link' => l(t('unassign'), "admin/structure/trigger/unassign/$module/$hook/$hash"),
);
}
else {
// Link to system_actions_remove_orphans() to do the clean up.
$form[$hook]['assigned']['#value'][$aid] = array(
'label' => $info['label'],
'link' => l(t('Remove orphaned actions'), "admin/config/system/actions/orphan"),
);
}
}
$form[$hook]['parent'] = array(
'#type' => 'container',
'#attributes' => array('class' => array('container-inline')),
);
// List possible actions that may be assigned.
if (count($options) != 0) {
$form[$hook]['parent']['aid'] = array(
'#type' => 'select',
'#title' => t('List of trigger actions when !description', array('!description' => $label)),
'#title_display' => 'invisible',
'#options' => $options,
'#empty_option' => t('Choose an action'),
);
$form[$hook]['parent']['submit'] = array(
'#type' => 'submit',
'#value' => t('Assign')
);
}
else {
$form[$hook]['none'] = array(
'#markup' => t('No actions available for this trigger. <a href="@link">Add action</a>.', array('@link' => url('admin/config/system/actions/manage')))
);
}
return $form;
}
/**
* Validation function for trigger_assign_form().
*
* Makes sure that the user is not re-assigning an action to an event.
*/
function trigger_assign_form_validate($form, $form_state) {
$form_values = $form_state['values'];
if (!empty($form_values['aid'])) {
$aid = actions_function_lookup($form_values['aid']);
$aid_exists = db_query("SELECT aid FROM {trigger_assignments} WHERE hook = :hook AND aid = :aid", array(
':hook' => $form_values['hook'],
':aid' => $aid,
))->fetchField();
if ($aid_exists) {
form_set_error($form_values['hook'], t('The action you chose is already assigned to that trigger.'));
}
}
}
/**
* Submit function for trigger_assign_form().
*/
function trigger_assign_form_submit($form, &$form_state) {
if (!empty($form_state['values']['aid'])) {
$aid = actions_function_lookup($form_state['values']['aid']);
$weight = db_query("SELECT MAX(weight) FROM {trigger_assignments} WHERE hook = :hook", array(':hook' => $form_state['values']['hook']))->fetchField();
// Insert the new action.
db_insert('trigger_assignments')
->fields(array(
'hook' => $form_state['values']['hook'],
'aid' => $aid,
'weight' => $weight + 1,
))
->execute();
// If we are not configuring an action for a "presave" hook and this action
// changes an object property, then we need to save the object, so the
// property change will persist.
$actions = actions_list();
if (strpos($form_state['values']['hook'], 'presave') === FALSE && isset($actions[$aid]['behavior']) && in_array('changes_property', $actions[$aid]['behavior'])) {
// Determine the corresponding save action name for this action.
$save_action = strtok($aid, '_') . '_save_action';
// If no corresponding save action exists, we need to bail out.
if (!isset($actions[$save_action])) {
throw new Exception(t('Missing/undefined save action (%save_aid) for %aid action.', array('%save_aid' => $aid, '%aid' => $aid)));
}
// Delete previous save action if it exists, and re-add it using a higher
// weight.
$save_action_assigned = db_query("SELECT aid FROM {trigger_assignments} WHERE hook = :hook AND aid = :aid", array(':hook' => $form_state['values']['hook'], ':aid' => $save_action))->fetchField();
if ($save_action_assigned) {
db_delete('trigger_assignments')
->condition('hook', $form_state['values']['hook'])
->condition('aid', $save_action)
->execute();
}
db_insert('trigger_assignments')
->fields(array(
'hook' => $form_state['values']['hook'],
'aid' => $save_action,
'weight' => $weight + 2,
))
->execute();
// If no save action existed before, inform the user about it.
if (!$save_action_assigned) {
drupal_set_message(t('The %label action has been appended, which is required to save the property change.', array('%label' => $actions[$save_action]['label'])));
}
// Otherwise, just inform about the new weight.
else {
drupal_set_message(t('The %label action was moved to save the property change.', array('%label' => $actions[$save_action]['label'])));
}
}
}
}
/**
* Returns HTML for the form showing actions assigned to a trigger.
*
* @param $variables
* An associative array containing:
* - element: The fieldset including all assigned actions.
*
* @ingroup themeable
*/
function theme_trigger_display($variables) {