8000 feature #49739 [Scheduler] Add DateIntervalTrigger and DatePeriodTrig… · symfony/symfony@8b8045b · GitHub
[go: up one dir, main page]

Skip to content

Commit 8b8045b

Browse files
committed
feature #49739 [Scheduler] Add DateIntervalTrigger and DatePeriodTrigger (fabpot)
This PR was merged into the 6.3 branch. Discussion ---------- [Scheduler] Add DateIntervalTrigger and DatePeriodTrigger | Q | A | ------------- | --- | Branch? | 6.3 | Bug fix? | no | New feature? | yes <!-- please update src/**/CHANGELOG.md files --> | Deprecations? | no <!-- please update UPGRADE-*.md and src/**/CHANGELOG.md files --> | Tickets | n/a | License | MIT | Doc PR | - The `PeriodicalTrigger` should only be used for a fixed period of time that can be converted to a number of seconds. Using it for `DatePeriod` does not make sense as the number of seconds between 2 runs can differ. This PR introduces 2 new triggers that behave correctly in such cases. Commits ------- 9a4ee58 [Scheduler] Add DateIntervalTrigger and DatePeriodTrigger
2 parents b885d0d + 9a4ee58 commit 8b8045b

File tree

8 files changed

+341
-254
lines changed

8 files changed

+341
-254
lines changed

src/Symfony/Component/Scheduler/RecurringMessage.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414
use Symfony\Component\Scheduler\Exception\InvalidArgumentException;
1515
use Symfony\Component\Scheduler\Trigger\CronExpressionTrigger;
16-
use Symfony\Component\Scheduler\Trigger\PeriodicalTrigger;
16+
use Symfony\Component\Scheduler\Trigger\DateIntervalTrigger;
1717
use Symfony\Component\Scheduler\Trigger\TriggerInterface;
1818

1919
/**
@@ -32,13 +32,13 @@ private function __construct(
3232
*
3333
* @see https://php.net/datetime.formats.relative
3434
*/
35-
public static function every(string $frequency, object $message, \DateTimeImmutable $from = new \DateTimeImmutable(), \DateTimeImmutable $until = new \DateTimeImmutable('3000-01-01')): self
35+
public static function every(string $frequency, object $message, string|\DateTimeImmutable $from = new \DateTimeImmutable(), string|\DateTimeImmutable $until = new \DateTimeImmutable('3000-01-01')): self
3636
{
3737
if (false === $interval = \DateInterval::createFromDateString($frequency)) {
3838
throw new InvalidArgumentException(sprintf('Frequency "%s" cannot be parsed.', $frequency));
3939
}
4040

41-
return new self(PeriodicalTrigger::create($interval, $from, $until), $message);
41+
return new self(new DateIntervalTrigger($interval, $from, $until), $message);
4242
}
4343

4444
public static function cron(string $expression, object $message): self
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Scheduler\Tests\Trigger;
13+
14+
use PHPUnit\Framework\TestCase;
15+
use Symfony\Component\Scheduler\Trigger\DatePeriodTrigger;
16+
use Symfony\Component\Scheduler\Trigger\TriggerInterface;
17+
18+
abstract class AbstractTriggerTest extends TestCase
19+
{
20+
/**
21+
* @dataProvider providerGetNextRunDate
22+
*/
23+
public function testGetNextRunDate(TriggerInterface $trigger, array $expected)
24+
{
25+
$this->assertEquals($expected, $this->getNextRunDates($trigger));
26+
}
27+
28+
abstract public static function providerGetNextRunDate(): iterable;
29+
30+
protected static function createTrigger(string $interval): DatePeriodTrigger
31+
{
32+
return new DatePeriodTrigger(
33+
new \DatePeriod(new \DateTimeImmutable('13:45'), \DateInterval::createFromDateString($interval), new \DateTimeImmutable('2023-06-19'))
34+
);
35+
}
36+
37+
private function getNextRunDates(TriggerInterface $trigger): array
38+
{
39+
$dates = [];
40+
$i = 0;
41+
$next = new \DateTimeImmutable();
42+
while ($i++ < 20) {
43+
$next = $trigger->getNextRunDate($next);
44+
if (!$next) {
45+
break;
46+
}
47+
48+
$dates[] = $next;
49+
}
50+
51+
return $dates;
52+
}
53+
}
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Scheduler\Tests\Trigger;
13+
14+
use Symfony\Component\Scheduler\Exception\InvalidArgumentException;
15+
use Symfony\Component\Scheduler\Trigger\DateIntervalTrigger;
16+
use Symfony\Component\Scheduler\Trigger\DatePeriodTrigger;
17+
18+
class DateIntervalTriggerTest extends DatePeriodTriggerTest
19+
{
20+
/**
21+
* @dataProvider provideForConstructor
22+
*/
23+
public function testConstructor(DateIntervalTrigger $trigger)
24+
{
25+
$run = new \DateTimeImmutable('2222-02-22 13:34:00');
26+
27+
$this->assertSame('2222-02-23 13:34:00', $trigger->getNextRunDate($run)->format('Y-m-d H:i:s'));
28+
}
29+
30+
public static function provideForConstructor(): iterable
31+
{
32+
$from = new \DateTimeImmutable($now = '2222-02-22 13:34:00');
33+
$until = new \DateTimeImmutable($farFuture = '3000-01-01');
34+
$day = new \DateInterval('P1D');
35+
36+
return [
37+
[new DateIntervalTrigger(86400, $from, $until)],
38+
[new DateIntervalTrigger('86400', $from, $until)],
39+
[new DateIntervalTrigger('P1D', $from, $until)],
40+
[new DateIntervalTrigger($day, $now, $farFuture)],
41+
[new DateIntervalTrigger($day, $now)],
42+
];
43+
}
44+
45+
/**
46+
* @dataProvider getInvalidIntervals
47+
*/
48+
public function testInvalidInterval($interval)
49+
{
50+
$this->expectException(InvalidArgumentException::class);
51+
52+
new DateIntervalTrigger($interval, $now = new \DateTimeImmutable(), $now->modify('1 day'));
53+
}
54+
55+
public static function getInvalidIntervals(): iterable
56+
{
57+
yield ['wrong'];
58+
yield ['3600.5'];
59+
yield [-3600];
60+
}
61+
62+
/**
63+
* @dataProvider providerGetNextRunDateAgain
64+
*/
65+
public function testGetNextRunDateAgain(DateIntervalTrigger $trigger, \DateTimeImmutable $lastRun, ?\DateTimeImmutable $expected)
66+
{
67+
$this->assertEquals($expected, $trigger->getNextRunDate($lastRun));
68+
}
69+
70+
public static function providerGetNextRunDateAgain(): iterable
71+
{
72+
$trigger = new DateIntervalTrigger(
73+
600,
74+
new \DateTimeImmutable('2020-02-20T02:00:00+02'),
75+
new \DateTimeImmutable('2020-02-20T03:00:00+02')
76+
);
77+
78+
yield [
79+
$trigger,
80+
new \DateTimeImmutable('@0'),
81+
new \DateTimeImmutable('2020-02-20T02:00:00+02'),
82+
];
83+
yield [
84+
$trigger,
85+
new \DateTimeImmutable('2020-02-20T01:59:59.999999+02'),
86+
new \DateTimeImmutable('2020-02-20T02:00:00+02'),
87+
];
88+
yield [
89+
$trigger,
90+
new \DateTimeImmutable('2020-02-20T02:00:00+02'),
91+
new \DateTimeImmutable('2020-02-20T02:10:00+02'),
92+
];
93+
yield [
94+
$trigger,
95+
new \DateTimeImmutable('2020-02-20T02:05:00+02'),
96+
new \DateTimeImmutable('2020-02-20T02:10:00+02'),
97+
];
98+
yield [
99+
$trigger,
100+
new \DateTimeImmutable('2020-02-20T02:49:59.999999+02'),
101+
new \DateTimeImmutable('2020-02-20T02:50:00+02'),
102+
];
103+
yield [
104+
$trigger,
105+
new \DateTimeImmutable('2020-02-20T02:50:00+02'),
106+
null,
107+
];
108+
yield [
109+
$trigger,
110+
new \DateTimeImmutable('2020-02-20T03:00:00+02'),
111+
null,
112+
];
113+
114+
$trigger = new DateIntervalTrigger(
115+
600,
116+
new \DateTimeImmutable('2020-02-20T02:00:00Z'),
117+
new \DateTimeImmutable('2020-02-20T03:01:00Z')
118+
);
119+
120+
yield [
121+
$trigger,
122+
new \DateTimeImmutable('2020-02-20T02:59:59.999999Z'),
123+
new \DateTimeImmutable('2020-02-20T03:00:00Z'),
124+
];
125+
yield [
126+
$trigger,
127+
new \DateTimeImmutable('2020-02-20T03:00:00Z'),
128+
null,
129+
];
130+
}
131+
132+
protected static function createTrigger(string $interval): DatePeriodTrigger
133+
{
134+
return new DateIntervalTrigger($interval, '2023-03-19 13:45', '2023-06-19');
135+
}
136+
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Scheduler\Tests\Trigger;
13+
14+
use Symfony\Component\Scheduler\Trigger\DatePeriodTrigger;
15+
16+
class DatePeriodTriggerTest extends AbstractTriggerTest
17+
{
18+
public static function providerGetNextRunDate(): iterable
19+
{
20+
yield [
21+
self::createTrigger('next tuesday'),
22+
[
23+
new \DateTimeImmutable('2023-03-21 13:45:00'),
24+
new \DateTimeImmutable('2023-03-28 13:45:00'),
25+
new \DateTimeImmutable('2023-04-04 13:45:00'),
26+
new \DateTimeImmutable('2023-04-11 13:45:00'),
27+
new \DateTimeImmutable('2023-04-18 13:45:00'),
28+
new \DateTimeImmutable('2023-04-25 13:45:00'),
29+
new \DateTimeImmutable('2023-05-02 13:45:00'),
30+
new \DateTimeImmutable('2023-05-09 13:45:00'),
31+
new \DateTimeImmutable('2023-05-16 13:45:00'),
32+
new \DateTimeImmutable('2023-05-23 13:45:00'),
33+
new \DateTimeImmutable('2023-05-30 13:45:00'),
34+
new \DateTimeImmutable('2023-06-06 13:45:00'),
35+
new \DateTimeImmutable('2023-06-13 13:45:00'),
36+
],
37+
];
38+
39+
yield [
40+
self::createTrigger('last day of next month'),
41+
[
42+
new \DateTimeImmutable('2023-04-30 13:45:00'),
43+
new \DateTimeImmutable('2023-05-31 13:45:00'),
44+
],
45+
];
46+
47+
yield [
48+
self::createTrigger('first monday of next month'),
49+
[
50+
new \DateTimeImmutable('2023-04-03 13:45:00'),
51+
new \DateTimeImmutable('2023-05-01 13:45:00'),
52+
new \DateTimeImmutable('2023-06-05 13:45:00'),
53+
],
54+
];
55+
}
56+
57+
protected static function createTrigger(string $interval): DatePeriodTrigger
58+
{
59+
return new DatePeriodTrigger(
60+
new \DatePeriod(new \DateTimeImmutable('2023-03-19 13:45'), \DateInterval::createFromDateString($interval), new \DateTimeImmutable('2023-06-19')),
61+
);
62+
}
63+
}

0 commit comments

Comments
 (0)
0