eca-1.0.x-dev/modules/form/src/Plugin/ECA/Condition/FormFieldValue.php
modules/form/src/Plugin/ECA/Condition/FormFieldValue.php
<?php
namespace Drupal\eca_form\Plugin\ECA\Condition;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\eca\Attribute\EcaCondition;
use Drupal\eca\Plugin\ECA\Condition\ConditionInterface;
use Drupal\eca\Plugin\ECA\Condition\StringComparisonBase;
use Drupal\eca\Plugin\FormFieldPluginTrait;
/**
* Compares a submitted form field value.
*/
#[EcaCondition(
id: 'eca_form_field_value',
label: new TranslatableMarkup('Form field: compare submitted value'),
description: new TranslatableMarkup('Compares a submitted form field value.'),
version_introduced: '1.0.0',
)]
class FormFieldValue extends StringComparisonBase {
use FormFieldPluginTrait;
/**
* The configured and expected field value.
*
* @var string|null
*/
protected ?string $expectedValue = NULL;
/**
* The current value in the form.
*
* @var string|null
*/
protected ?string $currentValue = NULL;
/**
* {@inheritdoc}
*
* The left value must not be replaced with Tokens, as this may be arbitrary
* user input, including from untrusted users.
*/
protected static bool $replaceTokens = FALSE;
/**
* {@inheritdoc}
*/
public function reset(): ConditionInterface {
$this->expectedValue = NULL;
$this->currentValue = NULL;
return parent::reset();
}
/**
* {@inheritdoc}
*/
protected function getLeftValue(): string {
return $this->currentValue ?? $this->getCurrentValue();
}
/**
* {@inheritdoc}
*/
protected function getRightValue(): string {
return $this->getExpectedValue();
}
/**
* Get the configured and tokenized value as expected field value.
*
* @return string
* The expected field value.
*/
protected function getExpectedValue(): string {
if (!isset($this->expectedValue)) {
$this->expectedValue = (string) $this->tokenService->replaceClear($this->configuration['field_value']);
}
return $this->expectedValue;
}
/**
* Get the current form value.
*
* @return string|null
* The current value. May be NULL if no value exists.
*/
protected function getCurrentValue(): ?string {
if (!$this->getCurrentFormState()) {
// Since the StringComparisonBase always compares string values, we want
// to make sure, that the evaluation will return FALSE when there is no
// current form state available.
return '_FORM_STATE_IS_MISSING_';
}
$original_field_name = $this->configuration['field_name'];
$this->configuration['field_name'] = (string) $this->tokenService->replace($original_field_name);
$value = $this->getSubmittedValue();
if (is_array($value)) {
// When the field contains multiple values, we evaluate against
// every single item and stick with the first match found. If no match
// was found, we stick with the first found value, that mostly would then
// finally evaluate to be false.
$first_val = NULL;
$matched_val = NULL;
$negated = $this->isNegated();
$this->configuration['negate'] = FALSE;
array_walk_recursive($value, function ($v, $k) use (&$first_val, &$matched_val) {
// This check includes a considering of integer 0 as unchecked checkbox.
// @see \Drupal\Core\Render\Element\Checkboxes::getCheckedCheckboxes()
if (is_scalar($v) && ($v !== 0) && trim((string) $v) !== '') {
if (!isset($first_val)) {
$first_val = $v;
}
if (!isset($matched_val)) {
$this->currentValue = $v;
if ($this->evaluate()) {
$matched_val = $v;
}
}
}
});
$this->expectedValue = NULL;
$this->configuration['negate'] = $negated;
$value = $matched_val ?? $first_val;
}
// Restoring the original config entry.
$this->configuration['field_name'] = $original_field_name;
if (is_scalar($value) || is_null($value)) {
$value = trim((string) $value);
}
else {
return '_VALUE_NOT_RESOLVABLE_TO_STRING_';
}
return $value;
}
/**
* {@inheritdoc}
*/
public function defaultConfiguration(): array {
return [
'field_value' => '',
] + $this->defaultFormFieldConfiguration() + parent::defaultConfiguration();
}
/**
* {@inheritdoc}
*/
public function buildConfigurationForm(array $form, FormStateInterface $form_state): array {
$form['field_value'] = [
'#type' => 'textarea',
'#title' => $this->t('Field value'),
'#description' => $this->t('The field value to compare.'),
'#default_value' => $this->configuration['field_value'],
'#weight' => -70,
'#eca_token_replacement' => TRUE,
];
$form = $this->buildFormFieldConfigurationForm($form, $form_state);
return parent::buildConfigurationForm($form, $form_state);
}
/**
* {@inheritdoc}
*/
public function validateConfigurationForm(array &$form, FormStateInterface $form_state): void {
$this->validateFormFieldConfigurationForm($form, $form_state);
parent::validateConfigurationForm($form, $form_state);
}
/**
* {@inheritdoc}
*/
public function submitConfigurationForm(array &$form, FormStateInterface $form_state): void {
$this->configuration['field_value'] = $form_state->getValue('field_value');
$this->submitFormFieldConfigurationForm($form, $form_state);
parent::submitConfigurationForm($form, $form_state);
}
}
