Default rules

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

Providing default rules may serve as a simple way for modules to provide some default functionality, which users may override. Also it's useful for versioning rule configurations in code using the usual version control system or to build feature-like modules.

Modules may provide default rules using hook_default_rules_configuration(). For optimizing the memory footprint, you may put the hook implementation in the include file MODULE.rules_defaults.inc - this file will not be automatically loaded into memory on each page view (as it would if the hook were defined in MODULE.module), but Rules will load this include file when needed. Be sure to prefix the default rules with your module name to avoid name collisions.

Consider the example based on the code in the rules_test module (found in the tests directory in the Rules distribution):

/**
 * Implements hook_default_rules_configuration().
 */
function rules_test_default_rules_configuration() {
  $rule = rules_reaction_rule();
  $rule->label = 'example default rule';
  // Add rules tags.
  $rule->tags = array('Admin', 'Tag2');
  $rule->active = FALSE;
  $rule->event('node_update')
       ->condition(rules_condition('data_is', array('data:select' => 'node:status', 'value' => TRUE))->negate())
       ->condition('data_is', array('data:select' => 'node:type', 'value' => 'page'))
       ->action('drupal_message', array('message' => 'A node has been updated.'));

  $configs['rules_test_default_1'] = $rule;

  return $configs;
}

As seen, the hook has to return an array of rule configurations keyed by configuration name. This technique allows that any type of configuration may be provided, including components.
Configurations in code may be overridden by the user, whereas those overrides are stored in the database. To avoid that you may set $rule_config->status = ENTITY_FIXED;. Read more about exportable entities (=> rule configurations) here.

Managing your exported rules in code

You can also export every rule individually into its own file and check these in to git. (This makes changes to individual rules easier to see and manage). The files can be placed into a /rules/ folder inside your custom module, and each one can end in a .rule extension.

Then, you can place a single function inside the file mymodule.rules_defaults.inc in mymodule. In that function you can loop through all the files, and import each rule.

Here's an example of the mymodule.rules_defaults.inc file:

/**
 * Implements hook_default_rules_configuration().
 */
function mymodule_default_rules_configuration() {
  $config = array();

  $rules_path = drupal_get_path('module', 'mymodule') . '/rules';
  $files = file_scan_directory($rules_path, '/\.rule$/');

  foreach ($files as $filepath => $file) {
    require $filepath;
    if (isset($rule)) {
      $config['mymodule_' . $file->name] = rules_import($rule);
    }
  }

  return $config;
}

And here's an example of a something_or_other.rule file (don't forget the opening php tag!):

/**
 * Rule exported to code: auto_alias_product_type.
 */

$rule =
  '{ "auto_alias_product_type" : {
      "LABEL" : "Auto alias for new product type",
      "PLUGIN" : "reaction rule",
      "REQUIRES" : [ "rules", "path", "entity" ],
      "ON" : [ "commerce_product_insert" ],
      "DO" : [
        { "path_alias" : {
            "source" : "classes\/[commerce-product:product-id]",
            "alias" : "classes\/[commerce-product:title]"
          }
        }
      ]
    }
  }';

After exporting a rule you may notice it has a setting "OWNER" : "rules", and you may think it's a good idea to put your own module there instead of 'rules'. If you do so, the rule won't appear in the rules UI, and you'll spend hours wondering why. Just leave it be.

If you wish to put each default rule in its own file, create a directory (called, say, rules) within your module, put each rule in its own file using MACHINENAME.json as the filename and use this:

/**
* Implements hook_default_rules_configuration().
*
* Must be placed in MODULE.rules_defaults.inc
*/
function MODULE_default_rules_configuration() {
  $rules = array();
  foreach (glob(__DIR__ . '/rules/*.json') as $rule_filename) {
    $rule_name = basename($rule_filename, '.json');
    $rules[$rule_name] = rules_import(file_get_contents($rule_filename));
  }
  return $rules;
}

Note: __DIR__ requires php 5.3.

Help improve this page

Page status: No known problems

You can: