eca-1.0.x-dev/src/Service/Conditions.php
src/Service/Conditions.php
<?php
namespace Drupal\eca\Service;
use Drupal\Component\Plugin\Exception\ContextException;
use Drupal\Component\Plugin\Exception\PluginException;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Extension\ModuleExtensionList;
use Drupal\Core\Language\LanguageManagerInterface;
use Drupal\Core\Logger\LoggerChannelInterface;
use Drupal\eca\ErrorHandlerTrait;
use Drupal\eca\Plugin\ECA\Condition\ConditionInterface;
use Drupal\eca\PluginManager\Condition;
use Drupal\eca\Token\TokenInterface;
use Symfony\Contracts\EventDispatcher\Event;
/**
* Service class for condition plugins in ECA.
*/
class Conditions {
use ErrorHandlerTrait;
use ServiceTrait;
/**
* ECA condition plugin manager.
*
* @var \Drupal\eca\PluginManager\Condition
*/
protected Condition $conditionManager;
/**
* Logger channel service.
*
* @var \Drupal\Core\Logger\LoggerChannelInterface
*/
protected LoggerChannelInterface $logger;
/**
* Entity type manager service.
*
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
*/
protected EntityTypeManagerInterface $entityTypeManager;
/**
* Language manager service.
*
* @var \Drupal\Core\Language\LanguageManagerInterface
*/
protected LanguageManagerInterface $languageManager;
/**
* ECA token service.
*
* @var \Drupal\eca\Token\TokenInterface
*/
protected TokenInterface $token;
/**
* The module extension manager.
*
* @var \Drupal\Core\Extension\ModuleExtensionList
*/
protected ModuleExtensionList $extensionManager;
/**
* Conditions constructor.
*
* @param \Drupal\eca\PluginManager\Condition $condition_manager
* The ECA condition plugin manager.
* @param \Drupal\Core\Logger\LoggerChannelInterface $logger
* The logger channel service.
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
* The entity type manager service.
* @param \Drupal\Core\Language\LanguageManagerInterface $language_manager
* The language manager service.
* @param \Drupal\eca\Token\TokenInterface $token
* The ECA token service.
* @param \Drupal\Core\Extension\ModuleExtensionList $extension_manager
* The module extension manager.
*/
public function __construct(Condition $condition_manager, LoggerChannelInterface $logger, EntityTypeManagerInterface $entity_type_manager, LanguageManagerInterface $language_manager, TokenInterface $token, ModuleExtensionList $extension_manager) {
$this->conditionManager = $condition_manager;
$this->logger = $logger;
$this->entityTypeManager = $entity_type_manager;
$this->languageManager = $language_manager;
$this->token = $token;
$this->extensionManager = $extension_manager;
}
/**
* Returns a sorted list of condition plugins.
*
* @return \Drupal\eca\Plugin\ECA\Condition\ConditionInterface[]
* The sorted list of conditions.
*/
public function conditions(): array {
static $conditions;
if ($conditions === NULL) {
$this->enableExtendedErrorHandling('Collecting all available conditions');
$conditions = [];
foreach ($this->conditionManager->getDefinitions() as $plugin_id => $definition) {
if ($condition = $this->createInstance($plugin_id)) {
$conditions[] = $condition;
}
}
$this->resetExtendedErrorHandling();
$this->sortPlugins($conditions, $this->extensionManager);
}
return $conditions;
}
/**
* Get a condition plugin by id.
*
* @param string $plugin_id
* The id of the condition plugin to be returned.
* @param array $configuration
* The optional configuration array.
*
* @return \Drupal\eca\Plugin\ECA\Condition\ConditionInterface|null
* The condition plugin.
*/
public function createInstance(string $plugin_id, array $configuration = []): ?ConditionInterface {
try {
/**
* @var \Drupal\eca\Plugin\ECA\Condition\ConditionInterface $condition
*/
$condition = $this->conditionManager->createInstance($plugin_id, $configuration);
}
// @phpstan-ignore catch.neverThrown
catch (\Exception | \Throwable $e) {
$condition = NULL;
$this->logger->error('The condition plugin %pluginid can not be initialized. ECA is ignoring this condition. The issue with this condition: %msg', [
'%pluginid' => $plugin_id,
'%msg' => $e->getMessage(),
]);
}
return $condition;
}
/**
* Asserts the condition identified by $condition_id in context of an event.
*
* @param \Symfony\Contracts\EventDispatcher\Event $event
* The event in which context the conditions needs to be asserted.
* @param string|bool|null $condition_id
* The ID of the condition to be asserted or FALSE, if the sequence flow
* does not have any condition.
* @param array|null $condition
* An array containing the plugin ID of the condition to be asserted and
* the field values of the plugin configuration.
* @param array $context
* An array with context settings of events and successors for building
* meaningful log messages.
*
* @return bool
* TRUE, if the condition can be asserted, FALSE otherwise.
*/
public function assertCondition(Event $event, string|bool|null $condition_id, ?array $condition, array $context): bool {
if (empty($condition_id)) {
$this->logger->info('Unconditional %successorlabel (%successorid) from ECA %ecalabel (%ecaid) for event %event.', $context);
return TRUE;
}
$context['%conditionid'] = $condition_id;
if ($condition === NULL) {
$this->logger->error('Non existent condition %conditionid for %successorlabel from ECA %ecalabel (%ecaid) for event %event.', $context);
return FALSE;
}
try {
/**
* @var \Drupal\eca\Plugin\ECA\Condition\ConditionInterface $plugin
*/
$plugin = $this->conditionManager->createInstance($condition['plugin'], $condition['configuration'] ?? []);
}
catch (PluginException $e) {
// Deliberately ignored, handled below already.
}
if (isset($plugin)) {
// If a config value is an array, we may receive a string from the
// modeller and have to convert this into an array.
$pluginConfig = $plugin->getConfiguration();
$defaultConfig = $plugin->defaultConfiguration();
foreach ($pluginConfig as $key => $value) {
if (isset($defaultConfig[$key]) && is_array($defaultConfig[$key])) {
$pluginConfig[$key] = explode(',', $value);
}
}
$plugin->setConfiguration($pluginConfig);
$plugin->setEvent($event);
/** @var \Drupal\Core\Plugin\Context\ContextDefinition $definition */
foreach ($plugin->getPluginDefinition()['context_definitions'] ?? [] as $key => $definition) {
// If the field for this context is filled by the model, then use that.
// Otherwise fall back to the entity of the original event of the
// current process.
if (empty($pluginConfig[$key])) {
switch ($definition->getDataType()) {
case 'language':
$token = $this->languageManager->getCurrentLanguage();
break;
default:
$token = 'entity';
}
}
else {
$token = $pluginConfig[$key];
}
if (is_string($token)) {
$data = $this->token->getTokenData($token);
}
else {
$data = $token;
}
try {
$plugin->setContextValue($key, $data);
}
catch (ContextException $e) {
$this->logger->error('Invalid context data for condition %conditionid for %successorlabel from ECA %ecalabel (%ecaid) for event %event.', $context);
}
}
if ($plugin->reset()->evaluate()) {
$this->logger->info('Asserted condition %conditionid for %successorlabel from ECA %ecalabel (%ecaid) for event %event.', $context);
return TRUE;
}
$this->logger->info('Not asserting condition %conditionid for %successorlabel from ECA %ecalabel (%ecaid) for event %event.', $context);
}
else {
$this->logger->error('Invalid condition %conditionid for %successorlabel from ECA %ecalabel (%ecaid) for event %event.', $context);
}
return FALSE;
}
}
