Skip to content
Snippets Groups Projects
Commit 1980f991 authored by Jürgen Haas's avatar Jürgen Haas
Browse files

Issue #3271473 by jurgenhaas, mxh: StringComparisonBase doesn’t work consistently yet

parent f22aa429
No related branches found
Tags 4.8.1
No related merge requests found
......@@ -18,14 +18,14 @@ class EcaState extends StringComparisonBase {
/**
* {@inheritdoc}
*/
protected function getFirstValue(): string {
protected function getLeftValue(): string {
return $this->state->get($this->configuration['key'], '');
}
/**
* {@inheritdoc}
*/
protected function getSecondValue(): string {
protected function getRightValue(): string {
return $this->configuration['value'];
}
......
......@@ -18,15 +18,15 @@ class ScalarComparison extends StringComparisonBase {
/**
* {@inheritdoc}
*/
protected function getFirstValue(): string {
return $this->configuration['right'] ?? '';
protected function getLeftValue(): string {
return $this->configuration['left'] ?? '';
}
/**
* {@inheritdoc}
*/
protected function getSecondValue(): string {
return $this->configuration['left'] ?? '';
protected function getRightValue(): string {
return $this->configuration['right'] ?? '';
}
/**
......@@ -43,16 +43,16 @@ class ScalarComparison extends StringComparisonBase {
* {@inheritdoc}
*/
public function buildConfigurationForm(array $form, FormStateInterface $form_state): array {
$form['right'] = [
$form['left'] = [
'#type' => 'textarea',
'#title' => $this->t('First value'),
'#default_value' => $this->getSecondValue(),
'#default_value' => $this->getLeftValue(),
'#weight' => -10,
];
$form['left'] = [
$form['right'] = [
'#type' => 'textarea',
'#title' => $this->t('Second value'),
'#default_value' => $this->getFirstValue(),
'#default_value' => $this->getRightValue(),
'#weight' => -8,
];
return parent::buildConfigurationForm($form, $form_state);
......
<?php
namespace Drupal\Tests\eca_base\Kernel;
use Drupal\eca\Plugin\ECA\Condition\StringComparisonBase;
use Drupal\eca\PluginManager\Condition;
use Drupal\eca\Service\Conditions;
use Drupal\KernelTests\KernelTestBase;
/**
* Kernel tests for the "eca_scalar" condition plugin.
*
* @group eca
* @group eca_base
*/
class CompareScalarTest extends KernelTestBase {
protected static $modules = [
'eca',
'eca_base',
];
/**
* @var \Drupal\eca\PluginManager\Condition|null
*/
protected ?Condition $conditionManager;
/**
* {@inheritdoc}
*/
public function setUp(): void {
parent::setUp();
$this->installConfig(static::$modules);
$this->conditionManager = \Drupal::service('plugin.manager.eca.condition');
}
/**
* Tests scalar value comparison.
*
* @dataProvider stringDataProvider
* @dataProvider integerDataProvider
*/
public function testScalarValues($left, $right, $operator, $type, $case, $negate, $message): void {
// Configure default settings for condition.
$config = [
'left' => $left,
'right' => $right,
'operator' => $operator,
'type' => $type,
'case' => $case,
'negate' => $negate,
];
/** @var \Drupal\eca_base\Plugin\ECA\Condition\ScalarComparison $condition */
$condition = $this->conditionManager->createInstance('eca_scalar', $config);
$this->assertTrue($condition->evaluate(), $message);
}
/**
* Provides multiple string test cases for the testScalarValues method.
*
* @return array
* The string test cases.
*/
public function stringDataProvider(): array {
return [
[
'my test string',
'my test string',
StringComparisonBase::COMPARE_EQUALS,
StringComparisonBase::COMPARE_TYPE_VALUE,
Conditions::OPTION_NO,
Conditions::OPTION_NO,
'Left equals right value.',
],
[
'my test string',
'my test string',
StringComparisonBase::COMPARE_EQUALS,
StringComparisonBase::COMPARE_TYPE_VALUE,
Conditions::OPTION_YES,
Conditions::OPTION_NO,
'Left equals (case sensitiv) right value.',
],
[
'my test string',
'My Test String',
StringComparisonBase::COMPARE_EQUALS,
StringComparisonBase::COMPARE_TYPE_VALUE,
Conditions::OPTION_YES,
Conditions::OPTION_YES,
'Left does not equal (case sensitiv) right value.',
],
[
'my test string',
'my test',
StringComparisonBase::COMPARE_BEGINS_WITH,
StringComparisonBase::COMPARE_TYPE_VALUE,
Conditions::OPTION_NO,
Conditions::OPTION_NO,
'Left begins with right value.',
],
[
'my test string',
'test string',
StringComparisonBase::COMPARE_ENDS_WITH,
StringComparisonBase::COMPARE_TYPE_VALUE,
Conditions::OPTION_NO,
Conditions::OPTION_NO,
'Left ends with right value.',
],
[
'my test string',
'test',
StringComparisonBase::COMPARE_CONTAINS,
StringComparisonBase::COMPARE_TYPE_VALUE,
Conditions::OPTION_NO,
Conditions::OPTION_NO,
'Left contains right value.',
],
[
'my test string',
'a test string',
StringComparisonBase::COMPARE_GREATERTHAN,
StringComparisonBase::COMPARE_TYPE_VALUE,
Conditions::OPTION_NO,
Conditions::OPTION_NO,
'Left is greater than right value.',
],
[
'my test string',
'your test string',
StringComparisonBase::COMPARE_LESSTHAN,
StringComparisonBase::COMPARE_TYPE_VALUE,
Conditions::OPTION_NO,
Conditions::OPTION_NO,
'Left is less than right value.',
],
[
'my test string',
'my test string',
StringComparisonBase::COMPARE_ATMOST,
StringComparisonBase::COMPARE_TYPE_VALUE,
Conditions::OPTION_NO,
Conditions::OPTION_NO,
'Left is at most the equal right value.',
],
[
'my test string',
'your test string',
StringComparisonBase::COMPARE_ATMOST,
StringComparisonBase::COMPARE_TYPE_VALUE,
Conditions::OPTION_NO,
Conditions::OPTION_NO,
'Left is at most right value.',
],
[
'my test string',
'my test string',
StringComparisonBase::COMPARE_ATLEAST,
StringComparisonBase::COMPARE_TYPE_VALUE,
Conditions::OPTION_NO,
Conditions::OPTION_NO,
'Left is at least the equal right value.',
],
[
'my test string',
'a test string',
StringComparisonBase::COMPARE_ATLEAST,
StringComparisonBase::COMPARE_TYPE_VALUE,
Conditions::OPTION_NO,
Conditions::OPTION_NO,
'Left is at least right value.',
],
];
}
/**
* Provides multiple integer test cases for the testScalarValues method.
*
* @return array
* The integer test cases.
*/
public function integerDataProvider(): array {
return [
[
5,
5,
StringComparisonBase::COMPARE_EQUALS,
StringComparisonBase::COMPARE_TYPE_NUMERIC,
Conditions::OPTION_NO,
Conditions::OPTION_NO,
'Left and right are equal.',
],
[
5,
4,
StringComparisonBase::COMPARE_GREATERTHAN,
StringComparisonBase::COMPARE_TYPE_NUMERIC,
Conditions::OPTION_NO,
Conditions::OPTION_NO,
'Left is great than right value.',
],
];
}
}
......@@ -69,16 +69,9 @@ class EntityFieldValue extends StringComparisonBase {
/**
* {@inheritdoc}
*/
protected function getFirstValue(): string {
return $this->getExpectedValue();
}
/**
* {@inheritdoc}
*/
protected function getSecondValue(): string {
protected function getLeftValue(): string {
$target_value = $this->targetValue ?? $this->getTargetValue();
if (NULL === $target_value && $this->getFirstValue() === '') {
if (NULL === $target_value && $this->getRightValue() === '') {
// Since the StringComparisonBase always compares string values, we want
// to make sure, that the evaluation will return FALSE for the very rare
// situation, that an empty string is expected to be contained.
......@@ -87,6 +80,13 @@ class EntityFieldValue extends StringComparisonBase {
return $target_value ?? '';
}
/**
* {@inheritdoc}
*/
protected function getRightValue(): string {
return $this->getExpectedValue();
}
/**
* Get the configured and tokenized field name.
*
......
<?php
namespace Drupal\Tests\eca_content\Kernel;
use Drupal\eca\Plugin\ECA\Condition\StringComparisonBase;
use Drupal\eca\PluginManager\Condition;
use Drupal\eca\Service\Conditions;
use Drupal\KernelTests\KernelTestBase;
use Drupal\node\Entity\Node;
use Drupal\node\NodeInterface;
use Drupal\user\Entity\User;
/**
* Kernel tests for the "eca_entity_field_value" condition plugin.
*
* @group eca
* @group eca_content
*/
class CompareFieldValueTest extends KernelTestBase {
protected static $modules = [
'system',
'user',
'field',
'text',
'node',
'eca',
'eca_content',
];
/**
* {@inheritdoc}
*/
public function setUp(): void {
parent::setUp();
$this->installEntitySchema('user');
$this->installEntitySchema('node');
$this->installSchema('node', ['node_access']);
$this->installConfig(static::$modules);
User::create(['uid' => 1, 'name' => 'admin'])->save();
}
/**
* Evaluates the given test values with a fresh condition plugin.
*
* @param \Drupal\eca\PluginManager\Condition $condition_manager
* @param \Drupal\node\NodeInterface $node
* @param array $defaults
* @param array $test_values
*
* @return void
*/
private function evaluate(Condition $condition_manager, NodeInterface $node, array $defaults, array $test_values): void {
$message = $test_values['message'];
unset($test_values['message']);
/** @var \Drupal\eca_content\Plugin\ECA\Condition\EntityFieldValue $condition */
$condition = $condition_manager->createInstance('eca_entity_field_value', $test_values + $defaults);
$condition->setContextValue('entity', $node);
$this->assertTrue($condition->evaluate(), $message);
}
/**
* Tests single string field comparison.
*/
public function testNodeTitle(): void {
/** @var \Drupal\eca\PluginManager\Condition $condition_manager */
$condition_manager = \Drupal::service('plugin.manager.eca.condition');
/** @var \Drupal\node\NodeInterface $node */
$node = Node::create([
'type' => 'article',
'uid' => 1,
'title' => 'First article',
]);
$node->save();
// Configure default settings for condition.
$defaults = [
'field_name' => 'title',
'type' => StringComparisonBase::COMPARE_TYPE_VALUE,
'case' => Conditions::OPTION_NO,
'negate' => Conditions::OPTION_NO,
];
// Configure test values.
$tests = [
[
'expected_value' => 'First article',
'operator' => StringComparisonBase::COMPARE_EQUALS,
'message' => 'Title equals expected value.',
],
[
'expected_value' => 'First',
'operator' => StringComparisonBase::COMPARE_BEGINS_WITH,
'message' => 'Title begins with expected value.',
],
[
'expected_value' => 'article',
'operator' => StringComparisonBase::COMPARE_ENDS_WITH,
'message' => 'Title ends with expected value.',
],
[
'expected_value' => 't a',
'operator' => StringComparisonBase::COMPARE_CONTAINS,
'message' => 'Title contains expected value.',
],
[
'expected_value' => 'An article',
'operator' => StringComparisonBase::COMPARE_GREATERTHAN,
'message' => 'Title is greater than expected value.',
],
[
'expected_value' => 'Second article',
'operator' => StringComparisonBase::COMPARE_LESSTHAN,
'message' => 'Title is less than expected value.',
],
[
'expected_value' => 'First article',
'operator' => StringComparisonBase::COMPARE_ATMOST,
'message' => 'Title is at most the equal expected value.',
],
[
'expected_value' => 'Second article',
'operator' => StringComparisonBase::COMPARE_ATMOST,
'message' => 'Title is at most expected value.',
],
[
'expected_value' => 'First article',
'operator' => StringComparisonBase::COMPARE_ATLEAST,
'message' => 'Title is at least the equal expected value.',
],
[
'expected_value' => 'An article',
'operator' => StringComparisonBase::COMPARE_ATLEAST,
'message' => 'Title is at least expected value.',
],
];
// Test all the combinations.
foreach ($tests as $test) {
$this->evaluate($condition_manager, $node, $defaults, $test);
}
}
}
......@@ -19,7 +19,7 @@ class FormFieldValue extends StringComparisonBase {
/**
* {@inheritdoc}
*/
protected function getFirstValue(): string {
protected function getLeftValue(): string {
if ($this->event instanceof FormBase) {
$formState = $this->event->getFormState();
if ($formState->hasValue($this->configuration['field_name'])) {
......@@ -32,7 +32,7 @@ class FormFieldValue extends StringComparisonBase {
/**
* {@inheritdoc}
*/
protected function getSecondValue(): string {
protected function getRightValue(): string {
return $this->configuration['field_value'];
}
......
......@@ -22,14 +22,14 @@ class RouteMatch extends StringComparisonBase {
/**
* {@inheritdoc}
*/
protected function getFirstValue(): string {
protected function getLeftValue(): string {
return $this->getRouteMatch()->getRouteName() ?? '';
}
/**
* {@inheritdoc}
*/
protected function getSecondValue(): string {
protected function getRightValue(): string {
return $this->configuration['route'];
}
......
......@@ -34,18 +34,18 @@ abstract class StringComparisonBase extends ConditionBase implements OptionsInte
protected static bool $replaceTokens = TRUE;
/**
* Get the first string value for comparison.
* Get the left/first string value for comparison.
*
* @return string
*/
abstract protected function getFirstValue(): string;
abstract protected function getLeftValue(): string;
/**
* Get the second string value for comparison.
* Get the right/second string value for comparison.
*
* @return string
*/
abstract protected function getSecondValue(): string;
abstract protected function getRightValue(): string;
/**
* Get the selected comparison operator.
......@@ -82,22 +82,22 @@ abstract class StringComparisonBase extends ConditionBase implements OptionsInte
*/
final public function evaluate(): bool {
if (static::$replaceTokens) {
$value1 = $this->tokenServices->replaceClear($this->getFirstValue());
$value2 = $this->tokenServices->replaceClear($this->getSecondValue());
$leftValue = $this->tokenServices->replaceClear($this->getLeftValue());
$rightValue = $this->tokenServices->replaceClear($this->getRightValue());
}
else {
$value1 = $this->getFirstValue();
$value2 = $this->getSecondValue();
$leftValue = $this->getLeftValue();
$rightValue = $this->getRightValue();
}
if (!$this->caseSensitive()) {
$value1 = mb_strtolower($value1);
$value2 = mb_strtolower($value2);
$leftValue = mb_strtolower($leftValue);
$rightValue = mb_strtolower($rightValue);
}
switch ($this->getType()) {
case static::COMPARE_TYPE_NUMERIC:
if (!is_numeric($value1) || !is_numeric($value2)) {
if (!is_numeric($leftValue) || !is_numeric($rightValue)) {
return FALSE;
}
break;
......@@ -105,18 +105,18 @@ abstract class StringComparisonBase extends ConditionBase implements OptionsInte
case static::COMPARE_TYPE_LEXICAL:
// Prepend the value with a constant character to force string
// comparison, even if values were numeric.
$value1 = 'a' . $value1;
$value2 = 'a' . $value2;
$leftValue = 'a' . $leftValue;
$rightValue = 'a' . $rightValue;
break;
case static::COMPARE_TYPE_NATURAL:
$value1 = strnatcmp($value1, $value2);
$value2 = 0;
$leftValue = 0;
$rightValue = strnatcmp($rightValue, $leftValue);
break;
case static::COMPARE_TYPE_COUNT:
$value1 = mb_strlen($value1);
$value2 = mb_strlen($value2);
$leftValue = mb_strlen($leftValue);
$rightValue = mb_strlen($rightValue);
break;
}
......@@ -124,35 +124,35 @@ abstract class StringComparisonBase extends ConditionBase implements OptionsInte
switch ($this->getOperator()) {
case static::COMPARE_EQUALS:
$result = $value1 === $value2;
$result = $leftValue === $rightValue;
break;
case static::COMPARE_BEGINS_WITH:
$result = mb_strpos($value2, $value1) === 0;
$result = mb_strpos($leftValue, $rightValue) === 0;
break;
case static::COMPARE_ENDS_WITH:
$result = mb_strpos($value2, $value1) === (mb_strlen($value2) - mb_strlen($value1));
$result = mb_strpos($leftValue, $rightValue) === (mb_strlen($leftValue) - mb_strlen($rightValue));
break;
case static::COMPARE_CONTAINS:
$result = mb_strpos($value2, $value1) !== FALSE;
$result = mb_strpos($leftValue, $rightValue) !== FALSE;
break;
case static::COMPARE_GREATERTHAN:
$result = $value2 > $value1;
$result = $leftValue > $rightValue;
break;
case static::COMPARE_LESSTHAN:
$result = $value2 < $value1;
$result = $leftValue < $rightValue;
break;
case static::COMPARE_ATMOST:
$result = $value2 <= $value1;
$result = $leftValue <= $rightValue;
break;
case static::COMPARE_ATLEAST:
$result = $value2 >= $value1;
$result = $leftValue >= $rightValue;
break;
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment