Is there currently an API for adding an event to a ReactionRule?

Currently Drupal\rules\Plugin\RulesExpression\ReactionRule does not have a specific API for this; you have ->addCondition() and ->addAction() (which are inherited from Drupal\rules\Plugin\RulesExpression\Rule), but there does not appear to be any supported way to add an event directly, or to directly manipulate context information used to either define the event, or map from the event context into the RuleState.

I can do this indirectly by converting a ReactionRule into its exported definition, modifying the definition array, and creating a new ReactionRule from the modified array. I'm not sure how future proof this is :-)

I know that some of this stuff will get implemented when the UI gets further along, but I'd like to encourage folks to get some of the lower level stuff exposed a bit earlier than that.

Comments

Torenware created an issue. See original summary.

Torenware’s picture

It turns out that none of the methods I tried initially actually work. Specifically, trying to add an "event" key to the configuration array does not work.

After mulling over the sources of the current Rules UI code, I have a provisional answer to this that appears to work.

Core idea: ReactionRule and RulesComponent are config entities. As part of their declaration, they list the fields they "know" about. For ReactionRule,

/**
 * Reaction rule configuration entity to persistently store configuration.
 *
 * @ConfigEntityType(
 *   id = "rules_reaction_rule",
 *   label = @Translation("Reaction Rule"),
 *   handlers = {
 *     "storage" = "Drupal\rules\Entity\ReactionRuleStorage",
 *     "list_builder" = "Drupal\rules\Entity\Controller\RulesReactionListBuilder",
 *     "form" = {
 *        "add" = "\Drupal\rules\Entity\ReactionRuleAddForm",
 *        "edit" = "\Drupal\rules\Entity\ReactionRuleEditForm",
 *        "delete" = "\Drupal\Core\Entity\EntityDeleteForm"
 *      }
 *   },
 *   admin_permission = "administer rules",
 *   config_prefix = "reaction",
 *   entity_keys = {
 *     "id" = "id",
 *     "label" = "label",
 *     "status" = "status"
 *   },
 *   config_export = {
 *     "id",
 *     "label",
 *     "event",
 *     "module",
 *     "description",
 *     "tag",
 *     "core",
 *     "expression_id",
 *     "configuration",
 *   },
 *   links = {
 *     "collection" = "/admin/config/workflow/rules",
 *     "edit-form" = "/admin/config/workflow/rules/reactions/edit/{rules_reaction_rule}",
 *     "delete-form" = "/admin/config/workflow/rules/reactions/delete/{rules_reaction_rule}"
 *   }
 * )
 */

The sub-key "config-export" seems to define the list of keys known to the system. When the "Add Reaction Rule" form is submitted, the values of the FormState object get transferred in EntityForm::copyFormValuesToEntity(), using the entity's set() function:

    foreach ($values as $key => $value) {
      $entity->set($key, $value);
    }

Calling "set()" on a ReactionRule does indeed work; AFAICT, it's the only thing I've tried that actually works. Specifically, the RulesStorageManager will correctly transfer the events to the settings system, as needed for Rules to find an event at run time.

I'm not sure if more specific API would be better; there are some restrictions doing this; it won't work on some entities. But it will work on ConfigEntities like ours.

klausi’s picture

Status: Active » Fixed

The API looks something like this (taken from EventIntegrationTest):

    $rule = $this->expressionManager->createRule();
    $rule->addCondition('rules_test_true');
    $rule->addAction('rules_test_log',
      ContextConfig::create()
        ->map('message', 'account.name.0.value')
    );

    $config_entity = $this->storage->create([
      'id' => 'test_rule',
      'events' => [['event_name' => 'rules_user_login']],
      'expression' => $rule->getConfiguration(),
    ]);
    $config_entity->save();

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.