Last updated December 23, 2014. Created on August 16, 2010.
Edited by DanChadwick, jpoesen, jenlampton, mitchell. Log in to edit this page.

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 MODULE.rules_defaults.inc - which is automatically picked up. Be sure to prefix the default rules with your module name to avoid name collisions.

Consider the example taken from the testing module:

<?php
/**
 * Implements hook_default_rules_configuration().
 */
function rules_test_default_rules_configuration() {
 
$rule = rules_reaction_rule();
 
$rule->label = 'example default rule';
 
$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:

<?php
/**
 * 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!):

<?php
/**
 * 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:

<?php
/**
* 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.

Looking for support? Visit the Drupal.org forums, or join #drupal-support in IRC.

Comments

tcmug’s picture

You can use rules_import() to create the $rule from any exported code you have.

    $rule = rules_import($data);
    $configs[$rule->name] = $rule;
TechNikh’s picture

Thanks tcmug.

Here is an example code. http://drupalcode.org/project/commerce_stock.git/blob_plain/eddda60f384d...

/**
* @file
* Default rule configurations for Commerce Stock.
*/
function commerce_stock_default_rules_configuration() {
  $rules_decrement_stock_completing_order = '{ "rules_decrement_stock_completing_order" : {
      "LABEL" : "Decrease stock when completing the order process",
      "PLUGIN" : "reaction rule",
      "REQUIRES" : [ "commerce_stock", "commerce_checkout" ],
      "ON" : [ "commerce_checkout_complete" ],
      "DO" : [
        { "LOOP" : {
            "USING" : { "list" : [ "commerce_order:commerce-line-items" ] },
            "DO" : [
              { "commerce_stock_decrease_by_line_item" : { "commerce_line_item" : [ "list-item" ] } }
            ]
          }
        }
      ]
    }
  }';
  $configs['rules_decrement_stock_completing_order'] = rules_import($rules_decrement_stock_completing_order);

  return $configs;
}

Cheers,
TechNikh

In 30 seconds set up Automated Visual testing of your website. Zero coding. https://drupal.org/project/drulenium
Ever dreamed of styling your view, We have a solution for you. https://drupal.org/project/views_stylizer

jenlampton’s picture

I handle my rule exports very similar to this comment on the Drupal 6 documentation. I'll add some code examples to the docs page above. Hope this helps someone until ctools exports are integrated :)

jonathan1055’s picture

When writing hook_default_rules_configuration() it took me a while to find out how to define a parameter as a 'data selection' value not a plain text value. You need ':select' in the array key after your parameter name. Otherwise the value is treated as pain text. Here is my code from the Scheduler module:

<?php
$rule
->action('scheduler_set_publish_date_action',
              array(
'node:select' => 'scheduler-node', 'date:select' => 'scheduler-publish-on-date'));
             
// The keys required above are 'node' and 'date', which are the names defined in scheduler_rules_action_info()
              // followed by :select to specify data selection instead of plain text values.
?>

This was not immediately obvious in the documentation I had read, but I found it by reading examples of others, and trying it out.

Jonathan