19declare(strict_types=1);
21use PHPUnit\Framework\TestCase;
25use PHPUnit\Framework\Attributes\DataProvider;
29 private static DateTimeImmutable
$now;
33 bool $has_flexible_schedule,
35 ?
int $default_schedule_value,
39 $job_instance = new class (
40 $has_flexible_schedule,
41 $default_schedule_type,
42 $default_schedule_value,
48 private readonly bool $has_flexible_schedule,
50 private readonly ?
int $default_schedule_value,
54 $this->schedule_type = $schedule_type;
55 $this->schedule_value = $schedule_value;
58 public function getId(): string
68 public function getDescription(): string
73 public function hasAutoActivation(): bool
78 public function hasFlexibleSchedule(): bool
80 return $this->has_flexible_schedule;
85 return $this->default_schedule_type;
88 public function getDefaultScheduleValue(): ?
int
90 return $this->default_schedule_value;
99 $job_instance->setDateTimeProvider(fn(): DateTimeImmutable => self::$now);
101 return $job_instance;
110 'Manual Run is Always Due' => [
113 JobScheduleType::DAILY,
115 JobScheduleType::DAILY,
120 JobScheduleType::DAILY,
124 'Job Without Any Run is Always Due' => [
127 JobScheduleType::DAILY,
129 JobScheduleType::DAILY,
134 JobScheduleType::DAILY,
138 'Daily Schedule / Did not run Today' => [
141 JobScheduleType::DAILY,
143 JobScheduleType::DAILY,
147 function (): DateTimeImmutable {
148 self::$now =
new DateTimeImmutable(
'@' . time());
150 return self::$now->modify(
'-1 day');
152 JobScheduleType::DAILY,
156 'Daily Schedule / Did run Today' => [
159 JobScheduleType::DAILY,
161 JobScheduleType::DAILY,
165 function (): DateTimeImmutable {
166 self::$now =
new DateTimeImmutable(
'@' . time());
170 JobScheduleType::DAILY,
174 'Weekly Schedule / Did not run this Week' => [
177 JobScheduleType::WEEKLY,
179 JobScheduleType::WEEKLY,
183 function (): DateTimeImmutable {
184 self::$now =
new DateTimeImmutable(
'@' . time());
186 return self::$now->modify(
'-1 week');
188 JobScheduleType::WEEKLY,
192 'Weekly Schedule / Did run this Week' => [
195 JobScheduleType::WEEKLY,
197 JobScheduleType::WEEKLY,
201 function (): DateTimeImmutable {
202 self::$now =
new DateTimeImmutable(
'@' . time());
204 return self::$now->modify(
'monday this week');
206 JobScheduleType::WEEKLY,
210 'Monthly Schedule / Did not run this Month' => [
213 JobScheduleType::MONTHLY,
215 JobScheduleType::MONTHLY,
219 function (): DateTimeImmutable {
220 self::$now =
new DateTimeImmutable(
'@' . time());
222 return self::$now->modify(
'last day of last month');
224 JobScheduleType::MONTHLY,
228 'Monthly Schedule / Did run this Month' => [
231 JobScheduleType::MONTHLY,
233 JobScheduleType::MONTHLY,
237 function (): DateTimeImmutable {
238 self::$now =
new DateTimeImmutable(
'@' . time());
240 return self::$now->modify(
'first day of this month');
242 JobScheduleType::MONTHLY,
246 'Yearly Schedule / Did not run this Year' => [
255 function (): DateTimeImmutable {
256 self::$now =
new DateTimeImmutable(
'@' . time());
258 return self::$now->modify(
'-1 year');
264 'Yearly Schedule / Did run this Year' => [
273 function (): DateTimeImmutable {
274 self::$now =
new DateTimeImmutable(
'@' . time());
276 return self::$now->modify(
'first day of January this year');
282 'Quarterly Schedule / Did not run this Quarter' => [
285 JobScheduleType::QUARTERLY,
287 JobScheduleType::QUARTERLY,
291 function (): DateTimeImmutable {
292 self::$now =
new DateTimeImmutable(
'@' . time());
294 $offset = (((
int) self::$now->format(
'n')) - 1) % 3;
295 self::$this_quarter_start = self::$now->modify(
"first day of -$offset month midnight");
297 return self::$this_quarter_start->modify(
'-1 seconds');
299 JobScheduleType::QUARTERLY,
303 'Quarterly Schedule / Did run this Quarter' => [
306 JobScheduleType::QUARTERLY,
308 JobScheduleType::QUARTERLY,
312 function (): DateTimeImmutable {
313 self::$now =
new DateTimeImmutable(
'@' . time());
315 $offset = (((
int) self::$now->format(
'n')) - 1) % 3;
316 self::$this_quarter_start = self::$now->modify(
"first day of -$offset month midnight");
318 return self::$this_quarter_start->modify(
'+30 seconds');
320 JobScheduleType::QUARTERLY,
324 'Minutely Schedule / Did not run this Minute' => [
327 JobScheduleType::IN_MINUTES,
329 JobScheduleType::IN_MINUTES,
333 function (): DateTimeImmutable {
334 self::$now =
new DateTimeImmutable(
'@' . time());
336 return self::$now->modify(
'-1 minute');
338 JobScheduleType::IN_MINUTES,
342 'Minutely Schedule / Did run this Minute' => [
345 JobScheduleType::IN_MINUTES,
347 JobScheduleType::IN_MINUTES,
351 function (): DateTimeImmutable {
352 self::$now =
new DateTimeImmutable(
'@' . time());
354 return self::$now->modify(
'-30 seconds');
356 JobScheduleType::IN_MINUTES,
360 'Hourly Schedule / Did not run this Hour' => [
363 JobScheduleType::IN_HOURS,
365 JobScheduleType::IN_HOURS,
369 function (): DateTimeImmutable {
370 self::$now =
new DateTimeImmutable(
'@' . time());
372 return self::$now->modify(
'-7 hours');
374 JobScheduleType::IN_HOURS,
378 'Hourly Schedule / Did run this Hour' => [
381 JobScheduleType::IN_HOURS,
383 JobScheduleType::IN_HOURS,
387 function (): DateTimeImmutable {
388 self::$now =
new DateTimeImmutable(
'@' . time());
390 return self::$now->modify(
'-7 hours +30 seconds');
392 JobScheduleType::IN_HOURS,
396 'Every 5 Days Schedule / Did not run for 5 Days' => [
399 JobScheduleType::IN_DAYS,
401 JobScheduleType::IN_DAYS,
405 function (): DateTimeImmutable {
406 self::$now =
new DateTimeImmutable(
'@' . time());
408 return self::$now->modify(
'-5 days');
410 JobScheduleType::IN_DAYS,
414 'Every 5 Days Schedule / Did run withing the last 5 Days' => [
417 JobScheduleType::IN_DAYS,
419 JobScheduleType::IN_DAYS,
423 function (): DateTimeImmutable {
424 self::$now =
new DateTimeImmutable(
'@' . time());
426 return self::$now->modify(
'-4 days');
428 JobScheduleType::IN_DAYS,
438 #[DataProvider('jobProvider')]
442 ?callable $last_run_datetime_callable,
444 ?
int $schedule_value,
447 $last_run_datetime = $last_run_datetime_callable ? $last_run_datetime_callable() : null;
450 $job_instance->
isDue($last_run_datetime, $schedule_type, $schedule_value, $is_manual_run),
451 'Last run: ' . ($last_run_datetime ? $last_run_datetime->format(DATE_ATOM) :
'never')
457 yield
'Different Week' => [
460 JobScheduleType::WEEKLY,
462 JobScheduleType::WEEKLY,
465 function (): DateTimeImmutable {
466 self::$now =
new DateTimeImmutable(
470 return self::$now->modify(
'-1 week');
475 yield
'Same Week and Year, but different Month: December (now) and January (Last run)' => [
478 JobScheduleType::WEEKLY,
480 JobScheduleType::WEEKLY,
483 function (): DateTimeImmutable {
484 self::$now =
new DateTimeImmutable(
488 return new DateTimeImmutable(
495 yield
'Same Week and Year and same Month: January' => [
498 JobScheduleType::WEEKLY,
500 JobScheduleType::WEEKLY,
503 function (): DateTimeImmutable {
504 self::$now =
new DateTimeImmutable(
508 return self::$now->modify(
515 yield
'Same Week (52nd), but Year Difference > 1' => [
518 JobScheduleType::WEEKLY,
520 JobScheduleType::WEEKLY,
523 function (): DateTimeImmutable {
524 self::$now =
new DateTimeImmutable(
528 return self::$now->modify(
'tuesday this week')->modify(
535 yield
'Same Week (52nd) in different Years, but Turn of the Year' => [
538 JobScheduleType::WEEKLY,
540 JobScheduleType::WEEKLY,
543 function (): DateTimeImmutable {
544 self::$now =
new DateTimeImmutable(
548 return self::$now->modify(
555 yield
'Same Week (52nd) in different Years, but not Turn of the Year' => [
558 JobScheduleType::WEEKLY,
560 JobScheduleType::WEEKLY,
563 function (): DateTimeImmutable {
564 self::$now =
new DateTimeImmutable(
568 return new DateTimeImmutable(
579 #[DataProvider('weeklyScheduleProvider')]
582 callable $last_run_datetime_provider,
585 $last_run_datetime = $last_run_datetime_provider();
589 $job_instance->
isDue(
595 'Last run: ' . $last_run_datetime->format(DATE_ATOM)
testSchedule(CronJob $job_instance, bool $is_manual_run, ?callable $last_run_datetime_callable, JobScheduleType $schedule_type, ?int $schedule_value, bool $should_be_due)
static getJob(bool $has_flexible_schedule, JobScheduleType $default_schedule_type, ?int $default_schedule_value, JobScheduleType $schedule_type, ?int $schedule_value)
testWeeklySchedules(CronJob $job_instance, callable $last_run_datetime_provider, bool $should_be_due)
static DateTimeImmutable $this_quarter_start
static weeklyScheduleProvider()
static DateTimeImmutable $now
getScheduleType()
Get current schedule type (if flexible)
isDue(?\DateTimeImmutable $last_run, ?JobScheduleType $schedule_type, ?int $schedule_value, bool $is_manually_executed=false)
getScheduleValue()
Get current schedule value (if flexible)
__construct(Container $dic, ilPlugin $plugin)
@inheritDoc