Providing actions/conditions via classes

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

Since Rules 2.4 it's possible to implement actions or conditions via classes - in alternative to the existing functional/info hook based way. In a class based implementation each possible callback is present as method on the action/condition class, whereas there are two special methods every class requires: A static getInfo() method and an execute() method for actually executing the condition/action.

Citing the in-code documentation from RulesActionHandlerInterface:

 * In addition to the interface an execute() and a static getInfo() method must
 * be implemented. The static getInfo() method has to return the info as
 * returned by hook_rules_action_info() but including an additional 'name' key,
 * specifying the plugin name.
 * The execute method is the equivalent to the usual execution callback and
 * gets the parameters passed as specified in the info array.

Implementation

Let's have a look at an example, the node type condition:

/**
 * Condition: Check for selected content types
 */
class RulesNodeConditionType extends RulesNodeConditionBase {

  /**
   * Defines the condition.
   */
  public static function getInfo() {
    $info = self::defaults() + array(
      'name' => 'node_is_of_type',
      'label' => t('Content is of type'),
      'help' => t('Evaluates to TRUE if the given content is of one of the selected content types.'),
    );
    $info['parameter']['type'] = array(
      'type' => 'list<text>',
      'label' => t('Content types'),
      'options list' => 'node_type_get_names',
      'description' => t('The content type(s) to check for.'),
      'restriction' => 'input',
    );
    return $info;
  }

  /**
   * Executes the condition.
   */
  public function execute($node, $types) {
    return in_array($node->type, $types);
  }

  /**
   * Provides the content type of a node as asserted metadata.
   */
  public function assertions() {
    return array('node' => array('bundle' => $this->element->settings['type']));
  }
}

As you can see, it has everything need to declare the condition in one place: the info + the execution method. Also, the condition implements the (optional) 'assertions' callback, which maps 1:1 to a class method. As for the callbacks, check RulesPluginHandlerInterface for details on possible callbacks/methods.

Discovery

Next, rules needs to find the class for your action/condition to pick it up. This works as documented at rules_discover_plugins():

 * Class based plugin handlers must be loaded when rules caches are rebuilt,
 * such that they get discovered properly. You have the following options:
 *  - Put it into a regular module file (discouraged)
 *  - Put it into your module.rules.inc file
 *  - Put it in any file and declare it using hook_rules_file_info()
 *  - Put it in any file and declare it using hook_rules_directory()
 *
 * In addition to that, the class must be loadable via regular class
 * auto-loading, thus put the file holding the class in your info file or use
 * another class-loader.

So putting it into a module.rules.inc file is enough, or put it in any file and declare it using hook_rules_file_info() + declare the file in your module's info file. Of course, you need to clear caches to trigger Rules' discovery.

Help improve this page

Page status: No known problems

You can: