Since I've been working on event dispatch scripts, I've been going back and forth with klausi on some issues I've found.

klausi just added a new test, EventIntegrationTest::testUserLoginEvent(). When run via PHPUnit, the test does run, and it passes.

Since it's the best example of building a reaction rule we have right now, and my other event dispatch scripts are now failing, I figured the first step was to use klausi's example, and run a test script based on his newer code.

Problem. It also fails. Roughly the same way as my test scripts.

Here's the stack trace:

vagrant@drupalvm2:/var/www/tests$ drush @d8 scr verify-event-dispatch.php
exception 'Drupal\Component\Plugin\Exception\ContextException' with message 'The message context is not a valid context.'[error]
in /var/www/drupal/core/lib/Drupal/Component/Plugin/ContextAwarePluginBase.php:71
Stack trace:
#0 /var/www/drupal/core/lib/Drupal/Core/Plugin/ContextAwarePluginBase.php(39):
Drupal\Component\Plugin\ContextAwarePluginBase->getContextDefinition('message')
#1 /var/www/drupal/core/lib/Drupal/Component/Plugin/ContextAwarePluginBase.php(120):
Drupal\Core\Plugin\ContextAwarePluginBase->getContext('message')
#2 /var/www/drupal/modules/custom/rules/tests/modules/rules_test/src/Plugin/RulesAction/TestLogAction.php(71):
Drupal\Component\Plugin\ContextAwarePluginBase->getContextValue('message')
#3 /var/www/drupal/modules/custom/rules/src/Plugin/RulesExpression/RulesAction.php(104):
Drupal\rules_test\Plugin\RulesAction\TestLogAction->execute()
#4 /var/www/drupal/modules/custom/rules/src/Plugin/RulesExpression/ActionSet.php(109):
Drupal\rules\Plugin\RulesExpression\RulesAction->executeWithState(Object(Drupal\rules\Engine\RulesState))
#5 /var/www/drupal/modules/custom/rules/src/Plugin/RulesExpression/Rule.php(97):
Drupal\rules\Plugin\RulesExpression\ActionSet->executeWithState(Object(Drupal\rules\Engine\RulesState))
#6 /var/www/drupal/modules/custom/rules/src/Engine/ExpressionBase.php(75):
Drupal\rules\Plugin\RulesExpression\Rule->executeWithState(Object(Drupal\rules\Engine\RulesState))
#7 /var/www/drupal/modules/custom/rules/src/EventSubscriber/GenericEventSubscriber.php(94):
Drupal\rules\Engine\ExpressionBase->execute()
#8 /var/www/drupal/core/lib/Drupal/Component/EventDispatcher/ContainerAwareEventDispatcher.php(116):
Drupal\rules\EventSubscriber\GenericEventSubscriber->onRulesEvent(Object(Drupal\rules\Event\UserLoginEvent),
'rules_user_logi...', Object(Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher))
#9 /var/www/drupal/modules/custom/rules/rules.module(23):
Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher->dispatch('rules_user_logi...',
Object(Drupal\rules\Event\UserLoginEvent))
#10 /var/www/tests/verify-event-dispatch.php(41): rules_user_login(Object(Drupal\user\Entity\User))
#11 /usr/local/share/drush/commands/core/core.drush.inc(1165): include('/var/www/tests/...')
#12 [internal function]: drush_core_php_script('verify-event-di...')

The test script looks like this, very similar to klausi's code:


use Drupal\rules\Context\ContextConfig;
use Drupal\rules\Engine\ExpressionBase;
use Drupal\user\Entity\User;


$expressionManager = \Drupal::service('plugin.manager.rules_expression');
$logger = \Drupal::service('logger.channel.rules');
$storage = \Drupal::service('entity.manager')->getStorage('rules_reaction_rule');

$rule_name = 'test_rule';

$old = $storage->load($rule_name);
if (!empty($old))
  $old->delete();


$rule = $expressionManager->createInstance('rules_reaction_rule', ['event' => 'rules_user_login']);
$rule->addCondition('rules_test_true');
$rule->addAction('rules_test_log',
  ContextConfig::create()
    ->map('message', 'account:name:0:value')
);

$config_entity = $storage->create([
  'id' => $rule_name,
  'expression_id' => 'rules_reaction_rule',
  'event' => 'rules_user_login',
  'configuration' => $rule->getConfiguration(),
]);
$config_entity->save();

// Rebuild the container so that the newly configured event gets picked up.
//$this->container->get('kernel')->rebuildContainer();
// The logger instance has changed, refresh it.
//$this->logger = $this->container->get('logger.channel.rules');

$account = User::create(['name' => 'test_user']);
// Invoke the hook manually which should trigger the rule.
rules_user_login($account);


print "after execution:\n";
$logs = $logger->getLogs();
print_r($logs);

I've commented out the container rebuild, because the event is picked up w/o problem (and I'm not sure how normal code would do that anyway). rules_user_login() triggers the event, and we crash inside of it, when the rules_test_log action looks for context passed to it, and finds that the context is MISSING. This brings up the

'Drupal\Component\Plugin\Exception\ContextException' with message 'The message context is not a valid context.'

I'm not sure why we pass when running phpunit (xdebug does not work well with phpunit's process model), but when debugging from drush, I'm definitely losing the context in RulesAction::executeWithState() (line 96 in rules/src/Plugin/RulesExpression/RulesAction.php). While "account" is in the RulesState's variable list, the context mapper never grabs the context.

I'm not sure how best to validate how we're doing context mapping, but I'm pretty sure we need to test it more. This is at least the third issue I've found with it.

Comments

Torenware created an issue. See original summary.

klausi’s picture

Category: Bug report » Support request
Status: Active » Postponed (maintainer needs more info)

Do you have rules_test module enabled which defines the rules_test_log action?

Torenware’s picture

IIRC -- this bug's pretty old -- my test code was running via drush, and I had the rule test module enabled (this required me to do a little sym linking so the module loader would find it).

I'm not sure if this would still be a problem, since the code base has changed a lot since September of last year.

klausi’s picture

Status: Postponed (maintainer needs more info) » Closed (works as designed)

OK, closing for now, please report back in case you still have problems.