diff --git a/mailpoet/lib/Automation/Integrations/Core/CoreIntegration.php b/mailpoet/lib/Automation/Integrations/Core/CoreIntegration.php index 8a1f0855e2..87f696a190 100644 --- a/mailpoet/lib/Automation/Integrations/Core/CoreIntegration.php +++ b/mailpoet/lib/Automation/Integrations/Core/CoreIntegration.php @@ -23,6 +23,7 @@ class CoreIntegration implements Integration { $registry->addFilter(new Filters\NumberFilter()); $registry->addFilter(new Filters\IntegerFilter()); $registry->addFilter(new Filters\StringFilter()); + $registry->addFilter(new Filters\EnumFilter()); $registry->addFilter(new Filters\EnumArrayFilter()); } } diff --git a/mailpoet/lib/Automation/Integrations/Core/Filters/EnumFilter.php b/mailpoet/lib/Automation/Integrations/Core/Filters/EnumFilter.php new file mode 100644 index 0000000000..cde3f88e96 --- /dev/null +++ b/mailpoet/lib/Automation/Integrations/Core/Filters/EnumFilter.php @@ -0,0 +1,51 @@ + __('is any of', 'mailpoet'), + self::IS_NONE_OF => __('is none of', 'mailpoet'), + ]; + } + + public function getArgsSchema(): ObjectSchema { + return Builder::object([ + 'value' => Builder::oneOf([ + Builder::array(Builder::string())->minItems(1), + Builder::array(Builder::integer())->minItems(1), + ])->required(), + ]); + } + + public function matches(FilterData $data, $value): bool { + $filterValue = $data->getArgs()['value'] ?? null; + if (!is_scalar($value) || !is_array($filterValue)) { + return false; + } + + $filterValue = array_unique($filterValue, SORT_REGULAR); + switch ($data->getCondition()) { + case self::IS_ANY_OF: + return in_array($value, $filterValue, true); + case self::IS_NONE_OF: + return !in_array($value, $filterValue, true); + default: + return false; + } + } +} diff --git a/mailpoet/tests/unit/Automation/Integration/Core/Filters/EnumFilterTest.php b/mailpoet/tests/unit/Automation/Integration/Core/Filters/EnumFilterTest.php new file mode 100644 index 0000000000..f4c5728a3f --- /dev/null +++ b/mailpoet/tests/unit/Automation/Integration/Core/Filters/EnumFilterTest.php @@ -0,0 +1,93 @@ +assertSame('enum', $filter->getFieldType()); + + $this->assertSame([ + 'is-any-of' => 'is any of', + 'is-none-of' => 'is none of', + ], $filter->getConditions()); + + $this->assertSame([ + 'type' => 'object', + 'properties' => [ + 'value' => [ + 'oneOf' => [ + ['type' => 'array', 'items' => ['type' => 'string'], 'minItems' => 1], + ['type' => 'array', 'items' => ['type' => 'integer'], 'minItems' => 1], + ], + 'required' => true, + ], + ], + ], $filter->getArgsSchema()->toArray()); + } + + public function testInvalidValues(): void { + $this->assertNotMatches('is-any-of', [], null); + $this->assertNotMatches('is-any-of', [], 123); + $this->assertNotMatches('is-any-of', [], 'abc'); + $this->assertNotMatches('is-any-of', [], new stdClass()); + $this->assertNotMatches('is-any-of', [], true); + $this->assertNotMatches('is-any-of', [], false); + $this->assertNotMatches('is-any-of', [1], [1]); + + $this->assertNotMatches('is-any-of', null, 1); + $this->assertNotMatches('is-any-of', 123, 1); + $this->assertNotMatches('is-any-of', 'abc', 1); + $this->assertNotMatches('is-any-of', new stdClass(), 1); + $this->assertNotMatches('is-any-of', true, 1); + $this->assertNotMatches('is-any-of', false, 1); + $this->assertNotMatches('is-any-of', 1, 1); + } + + public function testMatchesAnyCondition(): void { + $this->assertMatches('is-any-of', [1], 1); + $this->assertMatches('is-any-of', [1, 1, 1], 1); + $this->assertMatches('is-any-of', [1, 2, 3], 1); + $this->assertMatches('is-any-of', [1, 2, 3], 3); + $this->assertMatches('is-any-of', ['abc', 'def'], 'abc'); + $this->assertNotMatches('is-any-of', [], 1); + $this->assertNotMatches('is-any-of', [1], 0); + $this->assertNotMatches('is-any-of', [1, 2, 3], 7); + $this->assertNotMatches('is-any-of', ['abc', 'def'], 'xyz'); + } + + public function testMatchesNoneCondition(): void { + $this->assertMatches('is-none-of', [], 1); + $this->assertMatches('is-none-of', [1], 2); + $this->assertMatches('is-none-of', [1, 2, 3], 7); + $this->assertMatches('is-none-of', [1, 1, 1], 2); + $this->assertMatches('is-none-of', ['abc', 'def'], 'xyz'); + $this->assertNotMatches('is-none-of', [1], 1); + $this->assertNotMatches('is-none-of', [1, 2, 3], 2); + $this->assertNotMatches('is-none-of', [1, 1, 1], 1); + $this->assertNotMatches('is-none-of', ['abc', 'def'], 'def'); + } + + public function testUnknownCondition(): void { + $this->assertNotMatches('unknown', [1], 1); + $this->assertNotMatches('unknown', [1], 1); + } + + private function assertMatches(string $condition, $filterValue, $value): void { + $this->assertTrue($this->matchesFilter($condition, $filterValue, $value)); + } + + private function assertNotMatches(string $condition, $filterValue, $value): void { + $this->assertFalse($this->matchesFilter($condition, $filterValue, $value)); + } + + private function matchesFilter(string $condition, $filterValue, $value): bool { + $filter = new EnumFilter(); + return $filter->matches(new Filter('f1', 'enum', '', $condition, ['value' => $filterValue]), $value); + } +}