Implement datetime filter
[MAILPOET-5000]
This commit is contained in:
@ -2,6 +2,7 @@
|
||||
|
||||
namespace MailPoet\Automation\Engine;
|
||||
|
||||
use DateTimeZone;
|
||||
use WP_User;
|
||||
|
||||
class WordPress {
|
||||
@ -23,6 +24,10 @@ class WordPress {
|
||||
return apply_filters($hookName, $value, ...$args);
|
||||
}
|
||||
|
||||
public function wpTimezone(): DateTimeZone {
|
||||
return wp_timezone();
|
||||
}
|
||||
|
||||
public function wpGetCurrentUser(): WP_User {
|
||||
return wp_get_current_user();
|
||||
}
|
||||
|
@ -4,16 +4,22 @@ namespace MailPoet\Automation\Integrations\Core;
|
||||
|
||||
use MailPoet\Automation\Engine\Integration;
|
||||
use MailPoet\Automation\Engine\Registry;
|
||||
use MailPoet\Automation\Engine\WordPress;
|
||||
use MailPoet\Automation\Integrations\Core\Actions\DelayAction;
|
||||
|
||||
class CoreIntegration implements Integration {
|
||||
/** @var DelayAction */
|
||||
private $delayAction;
|
||||
|
||||
/** @var WordPress */
|
||||
private $wordPress;
|
||||
|
||||
public function __construct(
|
||||
DelayAction $delayAction
|
||||
DelayAction $delayAction,
|
||||
WordPress $wordPress
|
||||
) {
|
||||
$this->delayAction = $delayAction;
|
||||
$this->wordPress = $wordPress;
|
||||
}
|
||||
|
||||
public function register(Registry $registry): void {
|
||||
@ -23,6 +29,7 @@ class CoreIntegration implements Integration {
|
||||
$registry->addFilter(new Filters\NumberFilter());
|
||||
$registry->addFilter(new Filters\IntegerFilter());
|
||||
$registry->addFilter(new Filters\StringFilter());
|
||||
$registry->addFilter(new Filters\DateTimeFilter($this->wordPress->wpTimezone()));
|
||||
$registry->addFilter(new Filters\EnumFilter());
|
||||
$registry->addFilter(new Filters\EnumArrayFilter());
|
||||
}
|
||||
|
@ -0,0 +1,173 @@
|
||||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace MailPoet\Automation\Integrations\Core\Filters;
|
||||
|
||||
use DateTimeImmutable;
|
||||
use DateTimeInterface;
|
||||
use DateTimeZone;
|
||||
use MailPoet\Automation\Engine\Data\Field;
|
||||
use MailPoet\Automation\Engine\Data\Filter as FilterData;
|
||||
use MailPoet\Automation\Engine\Exceptions\InvalidStateException;
|
||||
use MailPoet\Automation\Engine\Integration\Filter;
|
||||
use MailPoet\Validator\Builder;
|
||||
use MailPoet\Validator\Schema\ObjectSchema;
|
||||
|
||||
class DateTimeFilter implements Filter {
|
||||
public const CONDITION_BEFORE = 'before';
|
||||
public const CONDITION_AFTER = 'after';
|
||||
public const CONDITION_ON = 'on';
|
||||
public const CONDITION_NOT_ON = 'not-on';
|
||||
public const CONDITION_IN_THE_LAST = 'in-the-last';
|
||||
public const CONDITION_NOT_IN_THE_LAST = 'not-in-the-last';
|
||||
public const CONDITION_IS_SET = 'is-set';
|
||||
public const CONDITION_IS_NOT_SET = 'is-not-set';
|
||||
public const CONDITION_ON_THE_DAYS_OF_THE_WEEK = 'on-the-days-of-the-week';
|
||||
|
||||
public const FORMAT_DATETIME = 'Y-m-d\TH:i:s';
|
||||
public const FORMAT_DATE = 'Y-m-d';
|
||||
|
||||
public const REGEX_DATETIME = '^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}$';
|
||||
public const REGEX_DATE = '^\d{4}-\d{2}-\d{2}$';
|
||||
|
||||
/** @var DateTimeZone */
|
||||
private $timezone;
|
||||
|
||||
public function __construct(
|
||||
DateTimeZone $timeZone
|
||||
) {
|
||||
$this->timezone = $timeZone;
|
||||
}
|
||||
|
||||
public function getFieldType(): string {
|
||||
return Field::TYPE_DATETIME;
|
||||
}
|
||||
|
||||
public function getConditions(): array {
|
||||
return [
|
||||
self::CONDITION_BEFORE => __('before', 'mailpoet'),
|
||||
self::CONDITION_AFTER => __('after', 'mailpoet'),
|
||||
self::CONDITION_ON => __('on', 'mailpoet'),
|
||||
self::CONDITION_NOT_ON => __('not on', 'mailpoet'),
|
||||
self::CONDITION_IN_THE_LAST => __('in the last', 'mailpoet'),
|
||||
self::CONDITION_NOT_IN_THE_LAST => __('not in the last', 'mailpoet'),
|
||||
self::CONDITION_IS_SET => __('is set', 'mailpoet'),
|
||||
self::CONDITION_IS_NOT_SET => __('is not set', 'mailpoet'),
|
||||
self::CONDITION_ON_THE_DAYS_OF_THE_WEEK => __('on the day(s) of the week', 'mailpoet'),
|
||||
];
|
||||
}
|
||||
|
||||
public function getArgsSchema(): ObjectSchema {
|
||||
return Builder::object([
|
||||
'value' => Builder::oneOf([
|
||||
Builder::string()->pattern(self::REGEX_DATETIME),
|
||||
Builder::string()->pattern(self::REGEX_DATE),
|
||||
Builder::array(Builder::integer()->minimum(0)->maximum(6))->minItems(1),
|
||||
Builder::object([
|
||||
'number' => Builder::integer()->minimum(1)->required(),
|
||||
'unit' => Builder::string()->pattern('^days|weeks|months$')->required(),
|
||||
]),
|
||||
]),
|
||||
]);
|
||||
}
|
||||
|
||||
public function matches(FilterData $data, $value): bool {
|
||||
$filterValue = $data->getArgs()['value'] ?? null;
|
||||
$condition = $data->getCondition();
|
||||
|
||||
// is set/is not set
|
||||
if (in_array($condition, [self::CONDITION_IS_SET, self::CONDITION_IS_NOT_SET], true)) {
|
||||
return $this->matchesSet($condition, $value);
|
||||
}
|
||||
|
||||
// in the last/not in the last
|
||||
if (in_array($condition, [self::CONDITION_IN_THE_LAST, self::CONDITION_NOT_IN_THE_LAST], true)) {
|
||||
return $this->matchesInTheLast($condition, $filterValue, $value);
|
||||
}
|
||||
|
||||
// on the day(s) of the week
|
||||
if ($condition === self::CONDITION_ON_THE_DAYS_OF_THE_WEEK) {
|
||||
return $this->matchesOnTheDaysOfTheWeek($filterValue, $value);
|
||||
}
|
||||
|
||||
// other conditions
|
||||
if (!is_string($filterValue) || !$value instanceof DateTimeInterface) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$datetime = $this->convertToWpTimezone($value);
|
||||
switch ($condition) {
|
||||
case 'before':
|
||||
$ref = DateTimeImmutable::createFromFormat(self::FORMAT_DATETIME, $filterValue, $this->timezone);
|
||||
return $ref && $datetime < $ref;
|
||||
case 'after':
|
||||
$ref = DateTimeImmutable::createFromFormat(self::FORMAT_DATETIME, $filterValue, $this->timezone);
|
||||
return $ref && $datetime > $ref;
|
||||
case 'on':
|
||||
return $datetime->format(self::FORMAT_DATE) === $filterValue;
|
||||
case 'not-on':
|
||||
return $datetime->format(self::FORMAT_DATE) !== $filterValue;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/** @param mixed $value */
|
||||
private function matchesSet(string $condition, $value): bool {
|
||||
switch ($condition) {
|
||||
case self::CONDITION_IS_SET:
|
||||
return $value !== null;
|
||||
case self::CONDITION_IS_NOT_SET:
|
||||
return $value === null;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $filterValue
|
||||
* @param mixed $value
|
||||
*/
|
||||
private function matchesInTheLast(string $condition, $filterValue, $value): bool {
|
||||
if (!is_array($filterValue) || !isset($filterValue['number']) || !isset($filterValue['unit']) || !$value instanceof DateTimeInterface) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$number = $filterValue['number'];
|
||||
$unit = $filterValue['unit'];
|
||||
if (!is_integer($number) || !in_array($unit, ['days', 'weeks', 'months'], true)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$now = new DateTimeImmutable('now', $this->timezone);
|
||||
$ref = $now->modify("-$number $unit");
|
||||
$matches = $ref <= $value && $value <= $now;
|
||||
return $condition === self::CONDITION_IN_THE_LAST ? $matches : !$matches;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $filterValue
|
||||
* @param mixed $value
|
||||
*/
|
||||
private function matchesOnTheDaysOfTheWeek($filterValue, $value): bool {
|
||||
if (!is_array($filterValue) || !$value instanceof DateTimeInterface) {
|
||||
return false;
|
||||
}
|
||||
foreach ($filterValue as $day) {
|
||||
if (!is_integer($day) || $day < 0 || $day > 6) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
$date = $this->convertToWpTimezone($value);
|
||||
$day = (int)$date->format('w');
|
||||
return in_array($day, $filterValue, true);
|
||||
}
|
||||
|
||||
private function convertToWpTimezone(DateTimeInterface $datetime): DateTimeImmutable {
|
||||
$value = DateTimeImmutable::createFromFormat('U', (string)$datetime->getTimestamp(), $this->timezone);
|
||||
if (!$value) {
|
||||
throw new InvalidStateException('Failed to convert datetime to WP timezone');
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
}
|
@ -0,0 +1,264 @@
|
||||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace MailPoet\Test\Automation\Integrations\Core\Filters;
|
||||
|
||||
use DateTimeImmutable;
|
||||
use DateTimeZone;
|
||||
use MailPoet\Automation\Engine\Data\Filter;
|
||||
use MailPoet\Automation\Integrations\Core\Filters\DateTimeFilter;
|
||||
use MailPoet\InvalidStateException;
|
||||
use MailPoetUnitTest;
|
||||
use stdClass;
|
||||
|
||||
class DateTimeFilterTest extends MailPoetUnitTest {
|
||||
/** @var DateTimeZone */
|
||||
private $timezone;
|
||||
|
||||
public function _before() {
|
||||
// let's test with a timezone far from UTC
|
||||
$this->timezone = new DateTimeZone('America/Los_Angeles');
|
||||
}
|
||||
|
||||
public function testItReturnsCorrectConfiguration(): void {
|
||||
$filter = new DateTimeFilter($this->timezone);
|
||||
$this->assertSame('datetime', $filter->getFieldType());
|
||||
$this->assertSame([
|
||||
'before' => 'before',
|
||||
'after' => 'after',
|
||||
'on' => 'on',
|
||||
'not-on' => 'not on',
|
||||
'in-the-last' => 'in the last',
|
||||
'not-in-the-last' => 'not in the last',
|
||||
'is-set' => 'is set',
|
||||
'is-not-set' => 'is not set',
|
||||
'on-the-days-of-the-week' => 'on the day(s) of the week',
|
||||
], $filter->getConditions());
|
||||
|
||||
$this->assertSame([
|
||||
'type' => 'object',
|
||||
'properties' => [
|
||||
'value' => [
|
||||
'oneOf' => [
|
||||
[
|
||||
'type' => 'string',
|
||||
'pattern' => '^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}$',
|
||||
],
|
||||
[
|
||||
'type' => 'string',
|
||||
'pattern' => '^\d{4}-\d{2}-\d{2}$',
|
||||
],
|
||||
[
|
||||
'type' => 'array',
|
||||
'items' => [
|
||||
'type' => 'integer',
|
||||
'minimum' => 0,
|
||||
'maximum' => 6,
|
||||
],
|
||||
'minItems' => 1,
|
||||
],
|
||||
[
|
||||
'type' => 'object',
|
||||
'properties' => [
|
||||
'number' => [
|
||||
'type' => 'integer',
|
||||
'minimum' => 1,
|
||||
'required' => true,
|
||||
],
|
||||
'unit' => [
|
||||
'type' => 'string',
|
||||
'pattern' => '^days|weeks|months$',
|
||||
'required' => true,
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
], $filter->getArgsSchema()->toArray());
|
||||
}
|
||||
|
||||
public function testInvalidValues(): void {
|
||||
$this->assertNotMatches('before', '2023-04-26T16:42', null);
|
||||
$this->assertNotMatches('before', '2023-04-26T16:42', true);
|
||||
$this->assertNotMatches('before', '2023-04-26T16:42', 123);
|
||||
$this->assertNotMatches('before', '2023-04-26T16:42', 'abc');
|
||||
$this->assertNotMatches('before', '2023-04-26T16:42', []);
|
||||
$this->assertNotMatches('before', '2023-04-26T16:42', [1, 2, 3, 'a', 'b', 'c']);
|
||||
$this->assertNotMatches('before', '2023-04-26T16:42', new stdClass());
|
||||
|
||||
$this->assertNotMatches('before', null, '2023-04-26T16:42+02:00');
|
||||
$this->assertNotMatches('before', true, '2023-04-26T16:42+02:00');
|
||||
$this->assertNotMatches('before', 123, '2023-04-26T16:42+02:00');
|
||||
$this->assertNotMatches('before', 'abc', '2023-04-26T16:42+02:00');
|
||||
$this->assertNotMatches('before', [], '2023-04-26T16:42+02:00');
|
||||
$this->assertNotMatches('before', [1, 2, 3, 'a', 'b', 'c'], '2023-04-26T16:42+02:00');
|
||||
$this->assertNotMatches('before', new stdClass(), '2023-04-26T16:42+02:00');
|
||||
}
|
||||
|
||||
public function testBeforeCondition(): void {
|
||||
$filterValue = '2023-04-26T16:42:01';
|
||||
|
||||
$this->assertMatches('before', $filterValue, $this->getDateTime('1900-01-01'));
|
||||
$this->assertMatches('before', $filterValue, $this->getDateTime('2023-04-25'));
|
||||
$this->assertMatches('before', $filterValue, $this->getDateTime('2023-04-26', '16:42:00', '+02:00'));
|
||||
|
||||
$this->assertNotMatches('before', $filterValue, $this->getDateTime('2100-01-01'));
|
||||
$this->assertNotMatches('before', $filterValue, $this->getDateTime('2023-04-27'));
|
||||
$this->assertNotMatches('before', $filterValue, $this->getDateTime('2023-04-27', '16:42:00', '+01:00'));
|
||||
}
|
||||
|
||||
public function testAfterCondition(): void {
|
||||
$filterValue = '2023-04-26T16:42:01';
|
||||
|
||||
$this->assertMatches('after', $filterValue, $this->getDateTime('2100-01-01'));
|
||||
$this->assertMatches('after', $filterValue, $this->getDateTime('2023-04-27'));
|
||||
$this->assertMatches('after', $filterValue, $this->getDateTime('2023-04-27', '16:42:00', '+01:00'));
|
||||
|
||||
$this->assertNotMatches('after', $filterValue, $this->getDateTime('1900-01-01'));
|
||||
$this->assertNotMatches('after', $filterValue, $this->getDateTime('2023-04-25'));
|
||||
$this->assertNotMatches('after', $filterValue, $this->getDateTime('2023-04-26', '16:42:00', '+02:00'));
|
||||
}
|
||||
|
||||
public function testOnCondition(): void {
|
||||
$filterValue = '2023-04-26';
|
||||
|
||||
$this->assertMatches('on', $filterValue, $this->getDateTime('2023-04-26'));
|
||||
$this->assertMatches('on', $filterValue, $this->getDateTime('2023-04-26', '00:00:00'));
|
||||
$this->assertMatches('on', $filterValue, $this->getDateTime('2023-04-26', '23:59:59'));
|
||||
$this->assertMatches('on', $filterValue, $this->getDateTime('2023-04-26', '16:42:01', '+02:00'));
|
||||
$this->assertMatches('on', $filterValue, $this->getDateTime('2023-04-26', '00:00:00', '-05:00'));
|
||||
$this->assertMatches('on', $filterValue, $this->getDateTime('2023-04-26', '23:59:59', '+05:00'));
|
||||
|
||||
$this->assertNotMatches('on', $filterValue, $this->getDateTime('1900-01-01'));
|
||||
$this->assertNotMatches('on', $filterValue, $this->getDateTime('2023-04-25'));
|
||||
$this->assertNotMatches('on', $filterValue, $this->getDateTime('2023-04-27'));
|
||||
$this->assertNotMatches('on', $filterValue, $this->getDateTime('2100-01-01'));
|
||||
$this->assertNotMatches('on', $filterValue, $this->getDateTime('2023-04-26', '00:00:00', '+05:00'));
|
||||
$this->assertNotMatches('on', $filterValue, $this->getDateTime('2023-04-26', '23:59:59', '-05:00'));
|
||||
}
|
||||
|
||||
public function testNotOnCondition(): void {
|
||||
$filterValue = '2023-04-26';
|
||||
|
||||
$this->assertMatches('not-on', $filterValue, $this->getDateTime('1900-01-01'));
|
||||
$this->assertMatches('not-on', $filterValue, $this->getDateTime('2023-04-25'));
|
||||
$this->assertMatches('not-on', $filterValue, $this->getDateTime('2023-04-27'));
|
||||
$this->assertMatches('not-on', $filterValue, $this->getDateTime('2100-01-01'));
|
||||
$this->assertMatches('not-on', $filterValue, $this->getDateTime('2023-04-26', '00:00:00', '+05:00'));
|
||||
$this->assertMatches('not-on', $filterValue, $this->getDateTime('2023-04-26', '23:59:59', '-05:00'));
|
||||
|
||||
$this->assertNotMatches('not-on', $filterValue, $this->getDateTime('2023-04-26'));
|
||||
$this->assertNotMatches('not-on', $filterValue, $this->getDateTime('2023-04-26', '00:00:00'));
|
||||
$this->assertNotMatches('not-on', $filterValue, $this->getDateTime('2023-04-26', '23:59:59'));
|
||||
$this->assertNotMatches('not-on', $filterValue, $this->getDateTime('2023-04-26', '16:42:01', '+02:00'));
|
||||
$this->assertNotMatches('not-on', $filterValue, $this->getDateTime('2023-04-26', '00:00:00', '-05:00'));
|
||||
$this->assertNotMatches('not-on', $filterValue, $this->getDateTime('2023-04-26', '23:59:59', '+05:00'));
|
||||
}
|
||||
|
||||
public function testInTheLast(): void {
|
||||
$filterDays = ['unit' => 'days', 'number' => 3];
|
||||
$filterWeeks = ['unit' => 'weeks', 'number' => 3];
|
||||
$filterMonths = ['unit' => 'months', 'number' => 3];
|
||||
|
||||
$now = new DateTimeImmutable('now', $this->timezone);
|
||||
|
||||
$this->assertMatches('in-the-last', $filterDays, $now);
|
||||
$this->assertMatches('in-the-last', $filterDays, $now->modify('-1 day'));
|
||||
$this->assertMatches('in-the-last', $filterWeeks, $now->modify('-1 day'));
|
||||
$this->assertMatches('in-the-last', $filterMonths, $now->modify('-1 day'));
|
||||
$this->assertMatches('in-the-last', $filterWeeks, $now->modify('-1 week'));
|
||||
$this->assertMatches('in-the-last', $filterMonths, $now->modify('-1 week'));
|
||||
$this->assertMatches('in-the-last', $filterMonths, $now->modify('-1 month'));
|
||||
|
||||
$this->assertNotMatches('in-the-last', $filterDays, $now->modify('+1 day'));
|
||||
$this->assertNotMatches('in-the-last', $filterWeeks, $now->modify('+1 day'));
|
||||
$this->assertNotMatches('in-the-last', $filterMonths, $now->modify('+1 day'));
|
||||
$this->assertNotMatches('in-the-last', $filterDays, $now->modify('-4 days'));
|
||||
$this->assertNotMatches('in-the-last', $filterDays, $now->modify('-1 week'));
|
||||
$this->assertNotMatches('in-the-last', $filterWeeks, $now->modify('-1 month'));
|
||||
$this->assertNotMatches('in-the-last', $filterMonths, $now->modify('-4 months'));
|
||||
}
|
||||
|
||||
public function testNotInTheLast(): void {
|
||||
$filterDays = ['unit' => 'days', 'number' => 3];
|
||||
$filterWeeks = ['unit' => 'weeks', 'number' => 3];
|
||||
$filterMonths = ['unit' => 'months', 'number' => 3];
|
||||
|
||||
$now = new DateTimeImmutable('now', $this->timezone);
|
||||
|
||||
$this->assertMatches('not-in-the-last', $filterDays, $now->modify('+1 day'));
|
||||
$this->assertMatches('not-in-the-last', $filterWeeks, $now->modify('+1 day'));
|
||||
$this->assertMatches('not-in-the-last', $filterMonths, $now->modify('+1 day'));
|
||||
$this->assertMatches('not-in-the-last', $filterDays, $now->modify('-4 days'));
|
||||
$this->assertMatches('not-in-the-last', $filterDays, $now->modify('-1 week'));
|
||||
$this->assertMatches('not-in-the-last', $filterWeeks, $now->modify('-1 month'));
|
||||
$this->assertMatches('not-in-the-last', $filterMonths, $now->modify('-4 months'));
|
||||
|
||||
$this->assertNotMatches('not-in-the-last', $filterDays, $now);
|
||||
$this->assertNotMatches('not-in-the-last', $filterDays, $now->modify('-1 day'));
|
||||
$this->assertNotMatches('not-in-the-last', $filterWeeks, $now->modify('-1 day'));
|
||||
$this->assertNotMatches('not-in-the-last', $filterMonths, $now->modify('-1 day'));
|
||||
$this->assertNotMatches('not-in-the-last', $filterWeeks, $now->modify('-1 week'));
|
||||
$this->assertNotMatches('not-in-the-last', $filterMonths, $now->modify('-1 week'));
|
||||
$this->assertNotMatches('not-in-the-last', $filterMonths, $now->modify('-1 month'));
|
||||
}
|
||||
|
||||
public function testIsSet(): void {
|
||||
$now = new DateTimeImmutable('now', $this->timezone);
|
||||
|
||||
$this->assertMatches('is-set', null, $now);
|
||||
$this->assertNotMatches('is-set', null, null);
|
||||
}
|
||||
|
||||
public function testIsNotSet(): void {
|
||||
$now = new DateTimeImmutable('now', $this->timezone);
|
||||
|
||||
$this->assertMatches('is-not-set', null, null);
|
||||
$this->assertNotMatches('is-not-set', null, $now);
|
||||
}
|
||||
|
||||
public function testOnTheDaysOfTheWeek(): void {
|
||||
$filterValue = [1, 3, 5]; // Monday, Wednesday, Friday
|
||||
|
||||
$this->assertMatches('on-the-days-of-the-week', $filterValue, $this->getDateTime('2023-04-24')); // Monday
|
||||
$this->assertMatches('on-the-days-of-the-week', $filterValue, $this->getDateTime('2023-04-26')); // Wednesday
|
||||
$this->assertMatches('on-the-days-of-the-week', $filterValue, $this->getDateTime('2023-04-28')); // Friday
|
||||
$this->assertMatches('on-the-days-of-the-week', $filterValue, $this->getDateTime('2023-04-24', '00:00:00', '-05:00'));
|
||||
$this->assertMatches('on-the-days-of-the-week', $filterValue, $this->getDateTime('2023-04-24', '23:59:59', '+05:00'));
|
||||
|
||||
$this->assertNotMatches('on-the-days-of-the-week', $filterValue, $this->getDateTime('2023-04-23')); // Sunday
|
||||
$this->assertNotMatches('on-the-days-of-the-week', $filterValue, $this->getDateTime('2023-04-25')); // Tuesday
|
||||
$this->assertNotMatches('on-the-days-of-the-week', $filterValue, $this->getDateTime('2023-04-27')); // Thursday
|
||||
$this->assertNotMatches('on-the-days-of-the-week', $filterValue, $this->getDateTime('2023-04-29')); // Saturday
|
||||
$this->assertNotMatches('on-the-days-of-the-week', $filterValue, $this->getDateTime('2023-04-30')); // Sunday
|
||||
$this->assertNotMatches('on-the-days-of-the-week', $filterValue, $this->getDateTime('2023-04-24', '00:00:00', '+05:00'));
|
||||
$this->assertNotMatches('on-the-days-of-the-week', $filterValue, $this->getDateTime('2023-04-24', '23:59:59', '-05:00'));
|
||||
}
|
||||
|
||||
public function testUnknownCondition(): void {
|
||||
$value = DateTimeImmutable::createFromFormat(DateTimeImmutable::W3C, '2023-04-26T16:42+02:00');
|
||||
$this->assertNotMatches('unknown', '2023-04-26T16:42', $value);
|
||||
$this->assertNotMatches('unknown', ['2023-04-26T16:42', '2023-04-26T17:42'], $value);
|
||||
}
|
||||
|
||||
private function getDateTime(string $date, string $time = '12:00:00', string $tzOffset = '+00:00'): DateTimeImmutable {
|
||||
$datetime = DateTimeImmutable::createFromFormat(DateTimeImmutable::W3C, "{$date}T{$time}{$tzOffset}");
|
||||
if ($datetime === false) {
|
||||
throw new InvalidStateException('Invalid date format');
|
||||
}
|
||||
return $datetime;
|
||||
}
|
||||
|
||||
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 DateTimeFilter($this->timezone);
|
||||
return $filter->matches(new Filter('f1', 'datetime', '', $condition, ['value' => $filterValue]), $value);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user