8

I want to provide an update for my custom module, which also has some rules provided via hook_default_rules_configuration.

Now, how can I update those existing rules? Can I re-import them? Override them somehow? I cant find anything about this in the documentary or an respective hook.

There seems to be a hook to respond to rules being updated, so I guess there must be a way to provide updates for custom rules...

At first I thought it was hook_default_rules_configuration_alter but it doesnt seem to work as expected since I just want to import JSON.

For instance, using views I can simply load all .inc files and save them via views_save_view like in this question - isnt there a similar way in rules?

2 Answers 2

7

You can export the rules configuration via the Rules UI and then implement hook_default_rules_configuration_alter() like this:

/**
 * Implements hook_default_rules_configuration_alter().
 */
function MODULENAME_default_rules_configuration_alter(&$data) {
  if (isset($data['commerce_cart_add_to_cart_message'])) {
    $data['commerce_cart_add_to_cart_message'] = entity_import('rules_config', '{ "commerce_cart_add_to_cart_message" : {
        "LABEL" : "Display an Add to Cart message",
        "PLUGIN" : "reaction rule",
        "OWNER" : "rules",
        "TAGS" : [ "Commerce Cart" ],
        "REQUIRES" : [ "rules", "commerce_cart" ],
        "ON" : { "commerce_cart_product_add" : [] },
        "IF" : [
          { "data_is" : { "data" : [ "commerce-order:commerce-nocart" ], "value" : "0" } }
        ],
        "DO" : [
          { "commerce_cart_add_to_cart_message" : { "commerce_product" : [ "commerce-product" ] } }
        ]
      }
    }');
  }
}

Just change the instances of $data['commerce_cart_add_to_cart_message'] to use your rule machine name and replace the export string with your own.

You can also use rules_import() instead of entity_import(). Either is acceptable.

Since the rules module loads default rules from code into the database and from then on loads them from the database, it won't immediately pick up your override. To make it do so navigate to the Rules UI and revert the rule. It will revert back to the default code, which will be your override.

To programmatically revert a rule you can do this (again replacing the rule machine name):

if ($rules_config = rules_config_load('commerce_cart_add_to_cart_message')) {
  $rules_config->delete();
}

An example usage of that may be to do it during an update function for a custom module.

It may seem wring to be deleting it but delete and revert are equivalent for rules that are provided by code because delete means delete from the database. If this was a rule created via the UI then it would be gone, however a rule from code will just delete from the DB and then read in again from the code.

Unfortunately there are currently only drush commands for enable/disable of rules. There is a feature request for a delete/revert command at https://www.drupal.org/node/2507187

6
  • that is exactly what I tried but it did not seem to work. I'll give it another try.
    – Alex
    Aug 4, 2015 at 12:56
  • I added a part at the end about reverting. Possibly that is the missing info.
    – rooby
    Aug 4, 2015 at 13:11
  • interesting point! so when I update my rules in hook_default_rules_configuration i can revert the rules so any updates are applied. that is smart, but: can I force a revert per rule? can I do this programmatically?
    – Alex
    Aug 4, 2015 at 13:14
  • Yep, I added info to the bottom of the answer.
    – rooby
    Aug 4, 2015 at 13:30
  • I came to a very similar conclusion by looking into ui.forms.inc, function rules_ui_confirm_operation_apply. Here you can also enable and disable. Thanks for your great help! I will try around a little and accept your answer in a minute
    – Alex
    Aug 4, 2015 at 13:32
2

To update module's rules programmatically you can load them and change them. Example of removing single action:

$rule = rules_config_load("some_rule");
foreach ($rule->actions() as $action) {
  if (strpos($action->getPluginName(), 'drupal_message') !== FALSE) {
    $action->delete();
  }
}
$rule->save();

If it's one time change, add it into hook_update.

See: RulesPlugin for API.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.