diff --git a/src/Contracts/DynamicSearchRule.php b/src/Contracts/DynamicSearchRule.php index 24679891..4273f59b 100644 --- a/src/Contracts/DynamicSearchRule.php +++ b/src/Contracts/DynamicSearchRule.php @@ -25,13 +25,18 @@ * start?: non-empty-string|null, * end?: non-empty-string|null * } + * @phpstan-type FilterCondition array{ + * values: array + * } * @phpstan-type SearchRuleConditions array{ * query?: QueryCondition|null, - * time?: TimeCondition|null + * time?: TimeCondition|null, + * filter?: FilterCondition|null * } * @phpstan-type RawDynamicSearchRule array{ * uid: non-empty-string, * description?: string|null, + * lastUpdatedAt?: non-empty-string, * precedence?: non-negative-int|null, * active?: bool, * conditions?: SearchRuleConditions|null, @@ -52,6 +57,8 @@ final class DynamicSearchRule private readonly ?string $description; + private readonly ?\DateTimeImmutable $lastUpdatedAt; + /** * @var non-negative-int|null */ @@ -73,6 +80,7 @@ public function __construct( $this->uid = $raw['uid']; $this->actions = $raw['actions']; $this->description = $raw['description'] ?? null; + $this->lastUpdatedAt = isset($raw['lastUpdatedAt']) ? new \DateTimeImmutable($raw['lastUpdatedAt']) : null; $this->precedence = $raw['precedence'] ?? null; $this->active = $raw['active'] ?? null; $this->conditions = $raw['conditions'] ?? null; @@ -96,6 +104,11 @@ public function getDescription(): ?string return $this->description; } + public function getLastUpdatedAt(): ?\DateTimeImmutable + { + return $this->lastUpdatedAt; + } + public function getPrecedence(): ?int { return $this->precedence; diff --git a/tests/Contracts/DynamicSearchRuleTest.php b/tests/Contracts/DynamicSearchRuleTest.php index fded8215..034f44e9 100644 --- a/tests/Contracts/DynamicSearchRuleTest.php +++ b/tests/Contracts/DynamicSearchRuleTest.php @@ -14,6 +14,7 @@ public function testFromArray(): void $raw = [ 'uid' => 'movie-rule', 'description' => 'Movie promotion', + 'lastUpdatedAt' => '2026-07-27T06:47:12.123456789Z', 'precedence' => 1, 'active' => true, 'conditions' => [ @@ -25,6 +26,12 @@ public function testFromArray(): void 'start' => '2026-01-01T00:00:00Z', 'end' => null, ], + 'filter' => [ + 'values' => [ + 'color' => 'red', + 'category' => 'shirt', + ], + ], ], 'actions' => [ [ @@ -44,6 +51,10 @@ public function testFromArray(): void self::assertSame('movie-rule', $rule->getUid()); self::assertSame('Movie promotion', $rule->getDescription()); + self::assertSame( + '2026-07-27T06:47:12.123456+00:00', + $rule->getLastUpdatedAt()?->format('Y-m-d\TH:i:s.uP') + ); self::assertSame(1, $rule->getPrecedence()); self::assertTrue($rule->isActive()); self::assertSame($raw['conditions'], $rule->getConditions()); @@ -51,4 +62,14 @@ public function testFromArray(): void self::assertSame($raw, $rule->getRaw()); self::assertSame($raw, $rule->toArray()); } + + public function testLastUpdatedAtIsOptionalForOlderResponses(): void + { + $rule = DynamicSearchRule::fromArray([ + 'uid' => 'movie-rule', + 'actions' => [], + ]); + + self::assertNull($rule->getLastUpdatedAt()); + } } diff --git a/tests/Contracts/UpdateDynamicSearchRuleQueryTest.php b/tests/Contracts/UpdateDynamicSearchRuleQueryTest.php index 7d0ea06a..b0866762 100644 --- a/tests/Contracts/UpdateDynamicSearchRuleQueryTest.php +++ b/tests/Contracts/UpdateDynamicSearchRuleQueryTest.php @@ -81,6 +81,12 @@ public function testFullPayload(): void 'start' => '2026-01-01T00:00:00Z', 'end' => null, ], + 'filter' => [ + 'values' => [ + 'color' => 'red', + 'category' => 'shirt', + ], + ], ]) ->setActions([ [ @@ -108,6 +114,12 @@ public function testFullPayload(): void 'start' => '2026-01-01T00:00:00Z', 'end' => null, ], + 'filter' => [ + 'values' => [ + 'color' => 'red', + 'category' => 'shirt', + ], + ], ], 'actions' => [ [