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
Comment #2
klausiDo you have rules_test module enabled which defines the rules_test_log action?
Comment #3
Torenware CreditAttribution: Torenware as a volunteer commentedIIRC -- 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.
Comment #4
klausiOK, closing for now, please report back in case you still have problems.