Events

Last updated on
30 November 2019

Drupal 7 will no longer be supported after January 5, 2025. Learn more and find resources for Drupal 7 sites

Modules may add further events, for which actions and conditions may be configured by either the UI or modules.

To do so, you need to implement hook_rules_event_info(). You may put the implementation in your module's MODULE.rules.inc file.

Consider the events provided for the comment module as example:

/**
 * Implementation of hook_rules_event_info().
 */
function rules_comment_event_info() {
  $defaults = array(
    'group' => t('comment'),
    'module' => 'comment',
    'access callback' => 'rules_comment_integration_access',
    'class' => 'RulesCommentEventHandler',
  );
  return array(
    'comment_insert' => $defaults + array(
      'label' => t('After saving a new comment'),
      'variables' => array(
        'comment' => array('type' => 'comment', 'label' => t('created comment')),
      ),
    ),
    'comment_update' => $defaults + array(
      'label' => t('After updating an existing comment'),
      'variables' => array(
        'comment' => array('type' => 'comment', 'label' => t('updated comment')),
        'comment_unchanged' => array('type' => 'comment', 'label' => t('unchanged comment'), 'handler' => 'rules_events_entity_unchanged'),
      ),
    ),
    'comment_presave' => $defaults + array(
      'label' => t('Before saving a comment'),
      'variables' => array(
        'comment' => array('type' => 'comment', 'label' => t('saved comment'), 'skip save' => TRUE),
        'comment_unchanged' => array('type' => 'comment', 'label' => t('unchanged comment'), 'handler' => 'rules_events_entity_unchanged'),
      ),
    ),
    'comment_view' => $defaults + array(
      'label' => t('A comment is viewed'),
      'variables' => array(
        'comment' => array('type' => 'comment', 'label' => t('viewed comment')),
      ),
      'help' => t("Note that if drupal's page cache is enabled, this event won't be generated for pages served from cache."),
    ),
    'comment_delete' => $defaults + array(
      'label' => t('After deleting a comment'),
      'variables' => array(
        'comment' => array('type' => 'comment', 'label' => t('deleted comment')),
      ),
    ),
  );
}

As seen, you have to describe the variables you provide for the event. When invoking the event, you have to pass the variables. For the comment module, the event invocations look like this:

function rules_entity_view($entity, $type, $view_mode, $langcode) {
  switch ($type) {
    case 'comment':
      rules_invoke_event('comment_view--' . $entity->node_type, $entity, $view_mode);
      rules_invoke_event('comment_view', $entity, $view_mode);
      break;
    ...
  }
}

function rules_entity_presave($entity, $type) {
  switch ($type) {
    case 'comment':
      rules_invoke_event('comment_presave--' . $entity->node_type, $entity);
      rules_invoke_event('comment_presave', $entity);
      break;
    ...
  }
}

function rules_entity_update($entity, $type) {
  switch ($type) {
    case 'comment':
      rules_invoke_event('comment_update--' . $entity->node_type, $entity);
      rules_invoke_event('comment_update', $entity);
      break;
    ...
  }
}

function rules_entity_insert($entity, $type) {
  switch ($type) {
    case 'comment':
      rules_invoke_event('comment_insert--' . $entity->node_type, $entity);
      rules_invoke_event('comment_insert', $entity);
      break;
    ...
  }
}

function rules_entity_delete($entity, $type) {
  switch ($type) {
    case 'comment':
      rules_invoke_event('comment_delete--' . $entity->node_type, $entity);
      rules_invoke_event('comment_delete', $entity);
      break;
    ...
  }
}

Usually one also provides a hook for modules - in that case first invoke the hook, then the rules event.

Note that you may also pass an array of variable values, with the variable names as keys. This is done by the rules_invoke_event_by_args function. Example:


function rules_comment_delete($comment) {
  rules_invoke_event_by_args('comment_delete', array('comment' => $comment));
}

Lazy-loading entites / variables

If you want to pass an entity, you may pass an EntityMetadataWrapper object to Rules. In case you do so, Rules uses the passed wrapper instead of creating its own. Passing the wrapper has the benefit, that you may create it with the entity type + id only, thus the entity is lazy loaded on demand.

E.g.:

// Create a wrapper and pass it to Rules.
$comment = entity_metadata_wrapper('comment', $comment_id);
rules_invoke_event('comment_delete', $comment);

Rules also supports lazy-loading variables via a specified handler. For that specify a callback for lazy-loading the variable using the 'handler' key and implement it like this:


function rules_events_variable_foo_load($arguments, $variable_name, $variable_info) {
  // Arguments is the array of variables already passed to the event.
  return $variable;
}

Providing unchanged entities

Rules provides the handler rules_events_entity_unchanged which may be used for providing variables for the unchanged version of an entity that is changed. For using it, just specify the variable for the unchanged entity using the handler and make sure its name matches the name of the updated entity but has '_unchanged' appended. Thus 'comment' would be the updated entity, 'comment_unchanged' the unchanged. Rules implements the logic for keeping track of unchanged entities, such that the handler works for all entities automatically. But note that this handler only works properly if the updated entity has not been saved yet *or* the entity has been loaded with entity_load() before it is saved. Thus in the case the updated entity has been already saved (hook_entity_update/insert) and a module serializes an entity and saves it afterwards on another page load, the handler would fail.

Passing variables by reference

Passing variables by reference is not supported by Rules 2.x - however with PHP 5 this does not matter much for objects. In case you want to allow modifications of an array structure, you need to wrap it manually before passing to rules - use the EntityMetadataArrayObject for that.

Changing variables itself (e.g. changing the the whole object) is not supported for reaction rules / events, but is possible for components. Thus if you need a way for users to alter or even provide a specific variable, consider using a component (e.g. a rule set) for that.

Help improve this page

Page status: No known problems

You can: