Add IDs for filter groups and filter definitions
[MAILPOET-5257]
This commit is contained in:
@@ -5,6 +5,7 @@ export type NextStep = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export type Filter = {
|
export type Filter = {
|
||||||
|
id: string;
|
||||||
field_type: string;
|
field_type: string;
|
||||||
field_key: string;
|
field_key: string;
|
||||||
condition: string;
|
condition: string;
|
||||||
@@ -12,6 +13,7 @@ export type Filter = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export type FilterGroup = {
|
export type FilterGroup = {
|
||||||
|
id: string;
|
||||||
operator: 'and' | 'or';
|
operator: 'and' | 'or';
|
||||||
filters: Filter[];
|
filters: Filter[];
|
||||||
};
|
};
|
||||||
|
@@ -55,7 +55,7 @@ export function FiltersList(): JSX.Element | null {
|
|||||||
{groups.map((group) =>
|
{groups.map((group) =>
|
||||||
group.filters.map((filter) => (
|
group.filters.map((filter) => (
|
||||||
<div
|
<div
|
||||||
key={filter.field_key}
|
key={filter.id}
|
||||||
className="mailpoet-automation-filters-list-item"
|
className="mailpoet-automation-filters-list-item"
|
||||||
>
|
>
|
||||||
<div className="mailpoet-automation-filters-list-item-content">
|
<div className="mailpoet-automation-filters-list-item-content">
|
||||||
|
@@ -3,6 +3,9 @@
|
|||||||
namespace MailPoet\Automation\Engine\Data;
|
namespace MailPoet\Automation\Engine\Data;
|
||||||
|
|
||||||
class Filter {
|
class Filter {
|
||||||
|
/** @var string */
|
||||||
|
private $id;
|
||||||
|
|
||||||
/** @var string */
|
/** @var string */
|
||||||
private $fieldType;
|
private $fieldType;
|
||||||
|
|
||||||
@@ -16,17 +19,23 @@ class Filter {
|
|||||||
private $args;
|
private $args;
|
||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
|
string $id,
|
||||||
string $fieldType,
|
string $fieldType,
|
||||||
string $fieldKey,
|
string $fieldKey,
|
||||||
string $condition,
|
string $condition,
|
||||||
array $args
|
array $args
|
||||||
) {
|
) {
|
||||||
|
$this->id = $id;
|
||||||
$this->fieldType = $fieldType;
|
$this->fieldType = $fieldType;
|
||||||
$this->fieldKey = $fieldKey;
|
$this->fieldKey = $fieldKey;
|
||||||
$this->condition = $condition;
|
$this->condition = $condition;
|
||||||
$this->args = $args;
|
$this->args = $args;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getId(): string {
|
||||||
|
return $this->id;
|
||||||
|
}
|
||||||
|
|
||||||
public function getFieldType(): string {
|
public function getFieldType(): string {
|
||||||
return $this->fieldType;
|
return $this->fieldType;
|
||||||
}
|
}
|
||||||
@@ -45,6 +54,7 @@ class Filter {
|
|||||||
|
|
||||||
public function toArray(): array {
|
public function toArray(): array {
|
||||||
return [
|
return [
|
||||||
|
'id' => $this->id,
|
||||||
'field_type' => $this->fieldType,
|
'field_type' => $this->fieldType,
|
||||||
'field_key' => $this->fieldKey,
|
'field_key' => $this->fieldKey,
|
||||||
'condition' => $this->condition,
|
'condition' => $this->condition,
|
||||||
@@ -54,6 +64,7 @@ class Filter {
|
|||||||
|
|
||||||
public static function fromArray(array $data): self {
|
public static function fromArray(array $data): self {
|
||||||
return new self(
|
return new self(
|
||||||
|
$data['id'],
|
||||||
$data['field_type'],
|
$data['field_type'],
|
||||||
$data['field_key'],
|
$data['field_key'],
|
||||||
$data['condition'],
|
$data['condition'],
|
||||||
|
@@ -6,6 +6,9 @@ class FilterGroup {
|
|||||||
public const OPERATOR_AND = 'and';
|
public const OPERATOR_AND = 'and';
|
||||||
public const OPERATOR_OR = 'or';
|
public const OPERATOR_OR = 'or';
|
||||||
|
|
||||||
|
/** @var string */
|
||||||
|
private $id;
|
||||||
|
|
||||||
/** @var string */
|
/** @var string */
|
||||||
private $operator;
|
private $operator;
|
||||||
|
|
||||||
@@ -13,13 +16,19 @@ class FilterGroup {
|
|||||||
private $filters;
|
private $filters;
|
||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
|
string $id,
|
||||||
string $operator,
|
string $operator,
|
||||||
array $filters
|
array $filters
|
||||||
) {
|
) {
|
||||||
|
$this->id = $id;
|
||||||
$this->operator = $operator;
|
$this->operator = $operator;
|
||||||
$this->filters = $filters;
|
$this->filters = $filters;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getId(): string {
|
||||||
|
return $this->id;
|
||||||
|
}
|
||||||
|
|
||||||
public function getOperator(): string {
|
public function getOperator(): string {
|
||||||
return $this->operator;
|
return $this->operator;
|
||||||
}
|
}
|
||||||
@@ -30,6 +39,7 @@ class FilterGroup {
|
|||||||
|
|
||||||
public function toArray(): array {
|
public function toArray(): array {
|
||||||
return [
|
return [
|
||||||
|
'id' => $this->id,
|
||||||
'operator' => $this->operator,
|
'operator' => $this->operator,
|
||||||
'filters' => array_map(function (Filter $filter): array {
|
'filters' => array_map(function (Filter $filter): array {
|
||||||
return $filter->toArray();
|
return $filter->toArray();
|
||||||
@@ -39,6 +49,7 @@ class FilterGroup {
|
|||||||
|
|
||||||
public static function fromArray(array $data): self {
|
public static function fromArray(array $data): self {
|
||||||
return new self(
|
return new self(
|
||||||
|
$data['id'],
|
||||||
$data['operator'],
|
$data['operator'],
|
||||||
array_map(function (array $filter) {
|
array_map(function (array $filter) {
|
||||||
return Filter::fromArray($filter);
|
return Filter::fromArray($filter);
|
||||||
|
@@ -55,6 +55,7 @@ class AutomationSchema {
|
|||||||
$operatorSchema = Builder::string()->pattern('^and|or$')->required();
|
$operatorSchema = Builder::string()->pattern('^and|or$')->required();
|
||||||
|
|
||||||
$filterSchema = Builder::object([
|
$filterSchema = Builder::object([
|
||||||
|
'id' => Builder::string()->required(),
|
||||||
'field_type' => Builder::string()->required(),
|
'field_type' => Builder::string()->required(),
|
||||||
'field_key' => Builder::string()->required(),
|
'field_key' => Builder::string()->required(),
|
||||||
'condition' => Builder::string()->required(),
|
'condition' => Builder::string()->required(),
|
||||||
@@ -62,6 +63,7 @@ class AutomationSchema {
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
$filterGroupSchema = Builder::object([
|
$filterGroupSchema = Builder::object([
|
||||||
|
'id' => Builder::string()->required(),
|
||||||
'operator' => $operatorSchema,
|
'operator' => $operatorSchema,
|
||||||
'filters' => Builder::array($filterSchema)->minItems(1)->required(),
|
'filters' => Builder::array($filterSchema)->minItems(1)->required(),
|
||||||
]);
|
]);
|
||||||
|
@@ -173,8 +173,8 @@ class TriggerHandlerTest extends \MailPoetTest {
|
|||||||
|
|
||||||
// automation that doesn't match segments filter
|
// automation that doesn't match segments filter
|
||||||
$unknownId = $segment->getId() + 1;
|
$unknownId = $segment->getId() + 1;
|
||||||
$filter = new Filter('enum_array', 'mailpoet:subscriber:segments', 'matches-any-of', ['value' => [$unknownId]]);
|
$filter = new Filter('f1', 'enum_array', 'mailpoet:subscriber:segments', 'matches-any-of', ['value' => [$unknownId]]);
|
||||||
$filters = new Filters('and', [new FilterGroup('and', [$filter])]);
|
$filters = new Filters('and', [new FilterGroup('g1', 'and', [$filter])]);
|
||||||
$automation = $this->tester->createAutomation(
|
$automation = $this->tester->createAutomation(
|
||||||
'Will not run',
|
'Will not run',
|
||||||
new Step('trigger', Step::TYPE_TRIGGER, $trigger->getKey(), [], [], $filters)
|
new Step('trigger', Step::TYPE_TRIGGER, $trigger->getKey(), [], [], $filters)
|
||||||
@@ -185,8 +185,8 @@ class TriggerHandlerTest extends \MailPoetTest {
|
|||||||
$this->assertCount(0, $this->automationRunStorage->getAutomationRunsForAutomation($automation));
|
$this->assertCount(0, $this->automationRunStorage->getAutomationRunsForAutomation($automation));
|
||||||
|
|
||||||
// matches segments filter
|
// matches segments filter
|
||||||
$filter = new Filter('enum_array', 'mailpoet:subscriber:segments', 'matches-any-of', ['value' => [$segment->getId()]]);
|
$filter = new Filter('f1', 'enum_array', 'mailpoet:subscriber:segments', 'matches-any-of', ['value' => [$segment->getId()]]);
|
||||||
$filters = new Filters('and', [new FilterGroup('and', [$filter])]);
|
$filters = new Filters('and', [new FilterGroup('g1', 'and', [$filter])]);
|
||||||
$automation = $this->tester->createAutomation(
|
$automation = $this->tester->createAutomation(
|
||||||
'Will run',
|
'Will run',
|
||||||
new Step('trigger', Step::TYPE_TRIGGER, $trigger->getKey(), [], [], $filters)
|
new Step('trigger', Step::TYPE_TRIGGER, $trigger->getKey(), [], [], $filters)
|
||||||
|
@@ -25,7 +25,7 @@ use MailPoetUnitTest;
|
|||||||
class FilterHandlerTest extends MailPoetUnitTest {
|
class FilterHandlerTest extends MailPoetUnitTest {
|
||||||
/** @dataProvider dataForTestItFilters */
|
/** @dataProvider dataForTestItFilters */
|
||||||
public function testItFilters(array $stepFilters, bool $expectation): void {
|
public function testItFilters(array $stepFilters, bool $expectation): void {
|
||||||
$filters = new Filters('and', [new FilterGroup('and', $stepFilters)]);
|
$filters = new Filters('and', [new FilterGroup('g1', 'and', $stepFilters)]);
|
||||||
$step = new Step('step', Step::TYPE_TRIGGER, 'test:step', [], [], $filters);
|
$step = new Step('step', Step::TYPE_TRIGGER, 'test:step', [], [], $filters);
|
||||||
$subject = $this->createSubject('subject', [
|
$subject = $this->createSubject('subject', [
|
||||||
new Field('test:field-string', Field::TYPE_STRING, 'Test field string', function () {
|
new Field('test:field-string', Field::TYPE_STRING, 'Test field string', function () {
|
||||||
@@ -70,8 +70,8 @@ class FilterHandlerTest extends MailPoetUnitTest {
|
|||||||
// matching
|
// matching
|
||||||
[
|
[
|
||||||
[
|
[
|
||||||
new FilterData(Field::TYPE_STRING, 'test:field-string', '', ['value' => 'abc']),
|
new FilterData('f1', Field::TYPE_STRING, 'test:field-string', '', ['value' => 'abc']),
|
||||||
new FilterData(Field::TYPE_INTEGER, 'test:field-integer', '', ['value' => 123]),
|
new FilterData('f2', Field::TYPE_INTEGER, 'test:field-integer', '', ['value' => 123]),
|
||||||
],
|
],
|
||||||
true,
|
true,
|
||||||
],
|
],
|
||||||
@@ -79,15 +79,15 @@ class FilterHandlerTest extends MailPoetUnitTest {
|
|||||||
// not matching
|
// not matching
|
||||||
[
|
[
|
||||||
[
|
[
|
||||||
new FilterData(Field::TYPE_INTEGER, 'test:field-integer', '', ['value' => 999]),
|
new FilterData('f1', Field::TYPE_INTEGER, 'test:field-integer', '', ['value' => 999]),
|
||||||
],
|
],
|
||||||
false,
|
false,
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
[
|
[
|
||||||
new FilterData(Field::TYPE_STRING, 'test:field-string', '', ['value' => 'abc']),
|
new FilterData('f1', Field::TYPE_STRING, 'test:field-string', '', ['value' => 'abc']),
|
||||||
new FilterData(Field::TYPE_INTEGER, 'test:field-integer', '', ['value' => 999]),
|
new FilterData('f2', Field::TYPE_INTEGER, 'test:field-integer', '', ['value' => 999]),
|
||||||
new FilterData(Field::TYPE_BOOLEAN, 'test:field-boolean', '', ['value' => true]),
|
new FilterData('f3', Field::TYPE_BOOLEAN, 'test:field-boolean', '', ['value' => true]),
|
||||||
],
|
],
|
||||||
false,
|
false,
|
||||||
],
|
],
|
||||||
|
@@ -31,7 +31,7 @@ class ValidStepFiltersRuleTest extends AutomationRuleTest {
|
|||||||
'validate' => Expected::once(),
|
'validate' => Expected::once(),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$filters = [new FilterData('string', 'test:key', 'is', ['value' => 'test'])];
|
$filters = [new FilterData('f1', 'string', 'test:key', 'is', ['value' => 'test'])];
|
||||||
$rule = new ValidStepFiltersRule($registry, $validator);
|
$rule = new ValidStepFiltersRule($registry, $validator);
|
||||||
$automation = $this->getAutomation($filters);
|
$automation = $this->getAutomation($filters);
|
||||||
(new AutomationWalker())->walk($automation, [$rule]);
|
(new AutomationWalker())->walk($automation, [$rule]);
|
||||||
@@ -43,14 +43,14 @@ class ValidStepFiltersRuleTest extends AutomationRuleTest {
|
|||||||
'validate' => Expected::never(),
|
'validate' => Expected::never(),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$filters = [new FilterData('string', 'test:key', 'is', ['value' => 'test'])];
|
$filters = [new FilterData('f1', 'string', 'test:key', 'is', ['value' => 'test'])];
|
||||||
$rule = new ValidStepFiltersRule($registry, $validator);
|
$rule = new ValidStepFiltersRule($registry, $validator);
|
||||||
$automation = $this->getAutomation($filters);
|
$automation = $this->getAutomation($filters);
|
||||||
(new AutomationWalker())->walk($automation, [$rule]);
|
(new AutomationWalker())->walk($automation, [$rule]);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getAutomation(array $filters): Automation {
|
private function getAutomation(array $filters): Automation {
|
||||||
$filters = new Filters('and', [new FilterGroup('and', $filters)]);
|
$filters = new Filters('and', [new FilterGroup('g1', 'and', $filters)]);
|
||||||
return $this->make(Automation::class, [
|
return $this->make(Automation::class, [
|
||||||
'getSteps' => [
|
'getSteps' => [
|
||||||
'root' => new Step('root', 'root', 'core:root', [], [], $filters),
|
'root' => new Step('root', 'root', 'core:root', [], [], $filters),
|
||||||
|
@@ -102,6 +102,6 @@ class EnumArrayFilterTest extends MailPoetUnitTest {
|
|||||||
|
|
||||||
private function matchesFilter(string $condition, $filterValue, $value): bool {
|
private function matchesFilter(string $condition, $filterValue, $value): bool {
|
||||||
$filter = new EnumArrayFilter();
|
$filter = new EnumArrayFilter();
|
||||||
return $filter->matches(new Filter('string', '', $condition, ['value' => $filterValue]), $value);
|
return $filter->matches(new Filter('f1', 'string', '', $condition, ['value' => $filterValue]), $value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -166,6 +166,6 @@ class StringFilterTest extends MailPoetUnitTest {
|
|||||||
|
|
||||||
private function matchesFilter(string $condition, $filterValue, $value): bool {
|
private function matchesFilter(string $condition, $filterValue, $value): bool {
|
||||||
$filter = new StringFilter();
|
$filter = new StringFilter();
|
||||||
return $filter->matches(new Filter('string', '', $condition, ['value' => $filterValue]), $value);
|
return $filter->matches(new Filter('f1', 'string', '', $condition, ['value' => $filterValue]), $value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user