From 2adaca78b03f425a312357705c0279509d62ea08 Mon Sep 17 00:00:00 2001 From: Uladzimir Tsykun Date: Tue, 22 Aug 2023 00:04:54 +0200 Subject: [PATCH] Fix support legacy php version with Symfony 4 --- src/Clock/OkvpnLoopClock.php | 2 +- src/Command/CronCommand.php | 5 +++-- src/Cron/CronChecker.php | 3 ++- src/Logger/CronConsoleLogger.php | 10 +++++----- src/Middleware/CronMiddlewareEngine.php | 3 ++- src/Model/JitterStamp.php | 4 +++- src/Model/PeriodicalScheduleStamp.php | 12 +++++++----- src/React/ReactLoopAdapter.php | 5 +++-- src/Utils/CronUtils.php | 23 +++++++++++++++++++++++ 9 files changed, 49 insertions(+), 18 deletions(-) create mode 100644 src/Utils/CronUtils.php diff --git a/src/Clock/OkvpnLoopClock.php b/src/Clock/OkvpnLoopClock.php index d4b3122..65dff3c 100644 --- a/src/Clock/OkvpnLoopClock.php +++ b/src/Clock/OkvpnLoopClock.php @@ -45,7 +45,7 @@ public function sleep($seconds): void } } - public function withTimeZone(/*\DateTimeZone|string*/ $timezone): static + public function withTimeZone(/*\DateTimeZone|string*/ $timezone) { $clone = clone $this; $clone->timezone = \is_string($timezone) ? new \DateTimeZone($timezone) : $timezone; diff --git a/src/Command/CronCommand.php b/src/Command/CronCommand.php index 10f544e..481eaa8 100644 --- a/src/Command/CronCommand.php +++ b/src/Command/CronCommand.php @@ -12,6 +12,7 @@ use Okvpn\Bundle\CronBundle\React\ReactLoopAdapter; use Okvpn\Bundle\CronBundle\Runner\ScheduleLoopInterface; use Okvpn\Bundle\CronBundle\Runner\ScheduleRunnerInterface; +use Okvpn\Bundle\CronBundle\Utils\CronUtils; use Psr\Clock\ClockInterface as PsrClockInterface; use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Command\Command; @@ -135,7 +136,7 @@ protected function scheduler(InputInterface $input, OutputInterface $output): vo $options['demand'] = $input->getOption('demand'); $options['dry-run'] = $input->getOption('dry-run'); - $envStamp = new EnvironmentStamp($options + ['now' => new \DateTimeImmutable('@'.$roundTime, $now->getTimezone()), 'dispatch-loop' => null !== $this->dispatcher]); + $envStamp = new EnvironmentStamp($options + ['now' => CronUtils::toDate($roundTime, $now) , 'dispatch-loop' => null !== $this->dispatcher]); $loggerStamp = $this->createLoggerStamp($output); $this->dispatchLoopEvent(LoopEvent::LOOP_START); @@ -165,7 +166,7 @@ protected function getCurrentDate(): \DateTimeImmutable { $now = $this->clock ? $this->clock->now() : new \DateTimeImmutable('now'); if (null !== $this->timezone) { - $now = new \DateTimeImmutable('@'.$now->format('U.u'), new \DateTimeZone($this->timezone)); + $now = CronUtils::toDate($now, $this->timezone); } return $now; diff --git a/src/Cron/CronChecker.php b/src/Cron/CronChecker.php index 60c6ce1..824a714 100644 --- a/src/Cron/CronChecker.php +++ b/src/Cron/CronChecker.php @@ -5,6 +5,7 @@ namespace Okvpn\Bundle\CronBundle\Cron; use Cron\CronExpression; +use Okvpn\Bundle\CronBundle\Utils\CronUtils; class CronChecker { @@ -54,7 +55,7 @@ public static function isRandomNext(string $cron, $timeZone, $current): \DateTim $current = \is_string($current) ? new \DateTime($current) : $current; $next = $current->getTimestamp() + \random_int(0, $cron); - return new \DateTimeImmutable('@'.$next, \is_string($timeZone) ? new \DateTimeZone($timeZone) : $timeZone); + return CronUtils::toDate($next, $timeZone); } public static function isRandomDue(string $cron): bool diff --git a/src/Logger/CronConsoleLogger.php b/src/Logger/CronConsoleLogger.php index 18fc265..b1359b1 100644 --- a/src/Logger/CronConsoleLogger.php +++ b/src/Logger/CronConsoleLogger.php @@ -27,8 +27,8 @@ class CronConsoleLogger extends AbstractLogger public const INFO = 'info'; public const ERROR = 'error'; - private OutputInterface $output; - private array $verbosityLevelMap = [ + private $output; + private $verbosityLevelMap = [ LogLevel::EMERGENCY => OutputInterface::VERBOSITY_NORMAL, LogLevel::ALERT => OutputInterface::VERBOSITY_NORMAL, LogLevel::CRITICAL => OutputInterface::VERBOSITY_NORMAL, @@ -38,7 +38,7 @@ class CronConsoleLogger extends AbstractLogger LogLevel::INFO => OutputInterface::VERBOSITY_VERY_VERBOSE, LogLevel::DEBUG => OutputInterface::VERBOSITY_DEBUG, ]; - private array $formatLevelMap = [ + private $formatLevelMap = [ LogLevel::EMERGENCY => self::ERROR, LogLevel::ALERT => self::ERROR, LogLevel::CRITICAL => self::ERROR, @@ -48,7 +48,7 @@ class CronConsoleLogger extends AbstractLogger LogLevel::INFO => self::INFO, LogLevel::DEBUG => self::INFO, ]; - private bool $errored = false; + private $errored = false; public function __construct(OutputInterface $output, array $verbosityLevelMap = [], array $formatLevelMap = []) { @@ -106,7 +106,7 @@ private function interpolate(string $message, array $context): string } elseif ($val instanceof \DateTimeInterface) { $replacements["{{$key}}"] = $val->format(\DateTimeInterface::RFC3339); } elseif (\is_object($val)) { - $replacements["{{$key}}"] = '[object '.$val::class.']'; + $replacements["{{$key}}"] = '[object '.get_class($val).']'; } else { $replacements["{{$key}}"] = '['.\gettype($val).']'; } diff --git a/src/Middleware/CronMiddlewareEngine.php b/src/Middleware/CronMiddlewareEngine.php index 4d54d4f..c611c3f 100644 --- a/src/Middleware/CronMiddlewareEngine.php +++ b/src/Middleware/CronMiddlewareEngine.php @@ -12,6 +12,7 @@ use Okvpn\Bundle\CronBundle\Model\ScheduleStamp; use Okvpn\Bundle\CronBundle\Runner\ScheduleLoopInterface; use Okvpn\Bundle\CronBundle\Runner\TimerStorage; +use Okvpn\Bundle\CronBundle\Utils\CronUtils; use Psr\Clock\ClockInterface as PsrClockInterface; final class CronMiddlewareEngine implements MiddlewareEngineInterface @@ -133,7 +134,7 @@ private function handleNoDemand(\DateTimeInterface $now, ScheduleEnvelope $envel } } else { $currentTime = (int)(60 * \floor($now->getTimestamp()/60)); - $now = new \DateTimeImmutable('@'.($currentTime-1), $now->getTimezone()); + $now = CronUtils::toDate(($currentTime-1), $now); $nextRun = $stamp->getNextRunDate($now); $nextRun = (int)(60 * \floor($nextRun->getTimestamp()/60)); diff --git a/src/Model/JitterStamp.php b/src/Model/JitterStamp.php index c83d87a..07f1464 100644 --- a/src/Model/JitterStamp.php +++ b/src/Model/JitterStamp.php @@ -4,6 +4,8 @@ namespace Okvpn\Bundle\CronBundle\Model; +use Okvpn\Bundle\CronBundle\Utils\CronUtils; + final class JitterStamp implements CommandStamp, PeriodicalStampInterface { private $stamp; @@ -23,7 +25,7 @@ public function getNextRunDate(\DateTimeInterface $run): \DateTimeInterface $nextRun = $this->stamp->getNextRunDate($run); $nextRun = (float)$nextRun->format('U.u') + $this->maxSeconds * random_int(0, PHP_INT_MAX)/PHP_INT_MAX; - return new \DateTimeImmutable('@'. round($nextRun, 6), $run->getTimezone()); + return CronUtils::toDate($nextRun, $run); } /** diff --git a/src/Model/PeriodicalScheduleStamp.php b/src/Model/PeriodicalScheduleStamp.php index 7707fb8..b189043 100644 --- a/src/Model/PeriodicalScheduleStamp.php +++ b/src/Model/PeriodicalScheduleStamp.php @@ -4,6 +4,8 @@ namespace Okvpn\Bundle\CronBundle\Model; +use Okvpn\Bundle\CronBundle\Utils\CronUtils; + class PeriodicalScheduleStamp implements CommandStamp, PeriodicalStampInterface { private $interval; @@ -11,14 +13,14 @@ class PeriodicalScheduleStamp implements CommandStamp, PeriodicalStampInterface public function __construct( /* string|int|float|\DateInterval */ $interval, - /* string|int|float|\DateTimeImmutable */ $from = 0, + /* string|int|float|\DateTimeImmutable */ $from = 0 ) { $this->from = \is_string($from) && !\is_numeric($from) ? (new \DateTimeImmutable($from))->getTimestamp() : (int)$from; - $interval = \is_string($interval) && !\is_numeric($interval) ? (new \DateInterval($interval)) : $interval; + $interval = \is_string($interval) && !\is_numeric($interval) ? ('P' === ($interval[0] ?? '') ? new \DateInterval($interval) : \DateInterval::createFromDateString($interval)) : $interval; if ($interval instanceof \DateInterval) { - $time1 = new \DateTime('now'); - $interval = (float)(clone $time1)->add($interval)->format('U.u') - (float)$time1->format('U.u'); + $time1 = new \DateTimeImmutable('now'); + $interval = (float)$time1->add($interval)->format('U.u') - (float)$time1->format('U.u'); } $this->interval = (float)$interval; @@ -34,7 +36,7 @@ public function getNextRunDate(\DateTimeInterface $run): \DateTimeInterface $delay = $this->interval - fmod($unix, $this->interval); - return new \DateTimeImmutable('@'.round($delay + $now, 6), $run->getTimezone()); + return CronUtils::toDate($delay + $now, $run); } /** diff --git a/src/React/ReactLoopAdapter.php b/src/React/ReactLoopAdapter.php index 5e83a27..214c59e 100644 --- a/src/React/ReactLoopAdapter.php +++ b/src/React/ReactLoopAdapter.php @@ -5,6 +5,7 @@ namespace Okvpn\Bundle\CronBundle\React; use Okvpn\Bundle\CronBundle\Runner\ScheduleLoopInterface; +use Okvpn\Bundle\CronBundle\Utils\CronUtils; use React\EventLoop\ExtEvLoop; use React\EventLoop\Loop; use React\EventLoop\LoopInterface; @@ -102,7 +103,7 @@ public function now(): \DateTimeImmutable $now = ($this->nowAccessor)(); if (null !== $this->timeZone) { - $now = new \DateTimeImmutable('@'.$now->format('U.u'), new \DateTimeZone($this->timeZone)); + $now = CronUtils::toDate($now, $this->timeZone); } return $now; @@ -133,7 +134,7 @@ private function createLoopAccessor(): \Closure if ($this->loop instanceof ExtEvLoop && (new \ReflectionObject($this->loop))->hasProperty('loop')) { return \Closure::bind(function (): \DateTimeImmutable { $now = $this->loop->now(); - return new \DateTimeImmutable('@'.round($now, 6)); + return CronUtils::toDate($now); }, $this->loop, ExtEvLoop::class); } diff --git a/src/Utils/CronUtils.php b/src/Utils/CronUtils.php new file mode 100644 index 0000000..875f213 --- /dev/null +++ b/src/Utils/CronUtils.php @@ -0,0 +1,23 @@ +getTimezone() : $timezone; + $timezone = \is_string($timezone) ? new \DateTimeZone($timezone) : $timezone; + + if ($unix instanceof \DateTimeInterface) { + $unix = $unix->format('U.u'); + } + + return \DateTimeImmutable::createFromFormat("U.u", sprintf("%.6f", $unix), $timezone); + } +}