Evaluate filter group operators (and/or)
[MAILPOET-5218]
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
namespace MailPoet\Automation\Engine\Control;
|
||||
|
||||
use MailPoet\Automation\Engine\Data\Filter as FilterData;
|
||||
use MailPoet\Automation\Engine\Data\FilterGroup;
|
||||
use MailPoet\Automation\Engine\Data\StepRunArgs;
|
||||
use MailPoet\Automation\Engine\Exceptions;
|
||||
use MailPoet\Automation\Engine\Registry;
|
||||
@@ -19,18 +20,33 @@ class FilterHandler {
|
||||
|
||||
public function matchesFilters(StepRunArgs $args): bool {
|
||||
$filters = $args->getStep()->getFilters();
|
||||
$groups = $filters ? $filters->getGroups() : [];
|
||||
foreach ($groups as $group) {
|
||||
foreach ($group->getFilters() as $filter) {
|
||||
$value = $args->getFieldValue($filter->getFieldKey());
|
||||
if (!$this->matchesFilter($filter, $value)) {
|
||||
return false;
|
||||
}
|
||||
if (!$filters) {
|
||||
return true;
|
||||
}
|
||||
|
||||
foreach ($filters->getGroups() as $group) {
|
||||
if ($this->matchesGroup($group, $args)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private function matchesGroup(FilterGroup $group, StepRunArgs $args): bool {
|
||||
$operator = $group->getOperator();
|
||||
foreach ($group->getFilters() as $filter) {
|
||||
$value = $args->getFieldValue($filter->getFieldKey());
|
||||
$matches = $this->matchesFilter($filter, $value);
|
||||
if ($operator === FilterGroup::OPERATOR_AND && !$matches) {
|
||||
return false;
|
||||
}
|
||||
if ($operator === FilterGroup::OPERATOR_OR && $matches) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return $operator === FilterGroup::OPERATOR_AND;
|
||||
}
|
||||
|
||||
/** @param mixed $value */
|
||||
private function matchesFilter(FilterData $data, $value): bool {
|
||||
$filter = $this->registry->getFilter($data->getFieldType());
|
||||
|
@@ -59,6 +59,32 @@ class FilterHandlerTest extends MailPoetUnitTest {
|
||||
$this->assertSame($expectation, $result);
|
||||
}
|
||||
|
||||
/** @dataProvider dataForTestItEvaluatesGroupOperators */
|
||||
public function testItEvaluatesGroupOperators(FilterGroup $group, bool $expectation): void {
|
||||
$filters = new Filters('and', [$group]);
|
||||
$step = new Step('step', Step::TYPE_TRIGGER, 'test:step', [], [], $filters);
|
||||
$subject = $this->createSubject('subject', [
|
||||
new Field('test:field-string', Field::TYPE_STRING, 'Test field string', function () {
|
||||
return 'abc';
|
||||
}),
|
||||
]);
|
||||
|
||||
$stepRunArgs = new StepRunArgs(
|
||||
$this->createMock(Automation::class),
|
||||
$this->createMock(AutomationRun::class),
|
||||
$step,
|
||||
[new SubjectEntry($subject, new SubjectData($subject->getKey(), []))]
|
||||
);
|
||||
|
||||
$registry = Stub::make(Registry::class, [
|
||||
'filters' => [Field::TYPE_STRING => $this->createFilter(Field::TYPE_STRING)],
|
||||
]);
|
||||
|
||||
$handler = new FilterHandler($registry);
|
||||
$result = $handler->matchesFilters($stepRunArgs);
|
||||
$this->assertSame($expectation, $result);
|
||||
}
|
||||
|
||||
public function dataForTestItFilters(): array {
|
||||
return [
|
||||
// no filters
|
||||
@@ -94,6 +120,41 @@ class FilterHandlerTest extends MailPoetUnitTest {
|
||||
];
|
||||
}
|
||||
|
||||
public function dataForTestItEvaluatesGroupOperators(): array {
|
||||
return [
|
||||
[
|
||||
new FilterGroup('g1', 'and', [
|
||||
new FilterData('f1', Field::TYPE_STRING, 'test:field-string', '', ['value' => 'abc']),
|
||||
new FilterData('f2', Field::TYPE_STRING, 'test:field-string', '', ['value' => 'abc']),
|
||||
new FilterData('f3', Field::TYPE_STRING, 'test:field-string', '', ['value' => 'abc']),
|
||||
]),
|
||||
true,
|
||||
],
|
||||
[
|
||||
new FilterGroup('g2', 'and', [
|
||||
new FilterData('f1', Field::TYPE_STRING, 'test:field-string', '', ['value' => 'abc']),
|
||||
new FilterData('f2', Field::TYPE_STRING, 'test:field-string', '', ['value' => 'xyz']),
|
||||
]),
|
||||
false,
|
||||
],
|
||||
[
|
||||
new FilterGroup('g3', 'or', [
|
||||
new FilterData('f1', Field::TYPE_STRING, 'test:field-string', '', ['value' => 'def']),
|
||||
new FilterData('f2', Field::TYPE_STRING, 'test:field-string', '', ['value' => 'abc']),
|
||||
new FilterData('f2', Field::TYPE_STRING, 'test:field-string', '', ['value' => 'xyz']),
|
||||
]),
|
||||
true,
|
||||
],
|
||||
[
|
||||
new FilterGroup('g4', 'or', [
|
||||
new FilterData('f1', Field::TYPE_STRING, 'test:field-string', '', ['value' => 'def']),
|
||||
new FilterData('f2', Field::TYPE_STRING, 'test:field-string', '', ['value' => 'xyz']),
|
||||
]),
|
||||
false,
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/** @return Subject<Payload> */
|
||||
private function createSubject(string $key, array $fields): Subject {
|
||||
return new class($key, $fields) implements Subject {
|
||||
|
Reference in New Issue
Block a user