59 lines
1.8 KiB
PHP
59 lines
1.8 KiB
PHP
<?php
|
|
|
|
namespace classes;
|
|
|
|
use InvalidArgumentException;
|
|
|
|
class cron_schedule
|
|
{
|
|
public static function normalize(array $schedule): array
|
|
{
|
|
$type = strtolower(trim((string)($schedule['type'] ?? 'interval')));
|
|
if ($type !== 'interval') {
|
|
throw new InvalidArgumentException('Unsupported cron schedule type: ' . $type);
|
|
}
|
|
|
|
$seconds = (int)($schedule['seconds'] ?? $schedule['interval'] ?? 0);
|
|
if ($seconds < 30 || $seconds > 2678400) {
|
|
throw new InvalidArgumentException('Cron interval must be between 30 seconds and 31 days.');
|
|
}
|
|
|
|
return [
|
|
'type' => 'interval',
|
|
'seconds' => $seconds,
|
|
];
|
|
}
|
|
|
|
public static function nextRunAt(array $schedule, ?string $anchorDateTime, int $now): string
|
|
{
|
|
$normalized = self::normalize($schedule);
|
|
$anchor = $anchorDateTime !== null && trim($anchorDateTime) !== ''
|
|
? strtotime($anchorDateTime)
|
|
: false;
|
|
$base = $anchor !== false ? (int)$anchor : $now;
|
|
$next = $base + (int)$normalized['seconds'];
|
|
|
|
if ($next <= $now) {
|
|
$missed = (int)floor(($now - $next) / (int)$normalized['seconds']) + 1;
|
|
$next += $missed * (int)$normalized['seconds'];
|
|
}
|
|
|
|
return date('Y-m-d H:i:s', $next);
|
|
}
|
|
|
|
public static function dueAt(array $schedule, ?string $lastRunAt, int $now, ?int $legacyLastRun = null): string
|
|
{
|
|
$normalized = self::normalize($schedule);
|
|
|
|
if ($lastRunAt !== null && trim($lastRunAt) !== '') {
|
|
return self::nextRunAt($normalized, $lastRunAt, $now);
|
|
}
|
|
|
|
if ($legacyLastRun !== null && $legacyLastRun > 0) {
|
|
return date('Y-m-d H:i:s', $legacyLastRun + (int)$normalized['seconds']);
|
|
}
|
|
|
|
return date('Y-m-d H:i:s', $now);
|
|
}
|
|
}
|