diff --git a/Makefile b/Makefile index 5b149283..8ea88809 100644 --- a/Makefile +++ b/Makefile @@ -44,17 +44,14 @@ else endif ${COMPOSER} config allow-plugins true ifeq ($(shell [[ $(SYLIUS_VERSION) == *dev ]] && echo true ),true) - ${COMPOSER} require sylius/sylius:"${SYLIUS_VERSION}" + ${COMPOSER} require --no-update sylius/sylius:"${SYLIUS_VERSION}" else - ${COMPOSER} require sylius/sylius:"~${SYLIUS_VERSION}" + ${COMPOSER} require --no-update sylius/sylius:"~${SYLIUS_VERSION}" endif update-dependencies: ${COMPOSER} config extra.symfony.require "~${SYMFONY_VERSION}" ${COMPOSER} require symfony/asset:~${SYMFONY_VERSION} --no-scripts --no-update -ifeq ($(shell [[ $(SYLIUS_VERSION) == 1.10.0 ]] && echo true ),true) - ${COMPOSER} require php-http/message-factory --no-scripts --no-update -endif ${COMPOSER} update --no-progress -n install-plugin: @@ -72,6 +69,7 @@ install-sylius: ${CONSOLE} sylius:fixtures:load default -n ${YARN} install ${YARN} build + ${CONSOLE} assets:install -n ${CONSOLE} cache:clear phpunit-configure: diff --git a/README.md b/README.md index 878c5e9b..b2c4d96b 100644 --- a/README.md +++ b/README.md @@ -68,6 +68,10 @@ cp -R vendor/synolia/sylius-scheduler-command-plugin/install/Application/config/packages/* config/packages/ cp -R vendor/synolia/sylius-scheduler-command-plugin/install/Application/config/routes/* config/routes/ +6. Installing assets (JS and CSS) fot the plugin + + bin/console assets:install + ## Usage * Log into admin panel @@ -113,6 +117,12 @@ Execute scheduled commands. **Run a specific scheduled command :** php bin/console synolia:scheduler-run --id=5 +Is it possible to choose the timezone of the command execution by setting the `SYNOLIA_SCHEDULER_PLUGIN_TIMEZONE` environment variable, example: + +``` +SYNOLIA_SCHEDULER_PLUGIN_TIMEZONE=Europe/Paris +``` + ### synolia:scheduler:purge-history Purge scheduled command history greater than {X} days old. diff --git a/UPGRADE.md b/UPGRADE.md index 3b16b9f2..f75b8d78 100644 --- a/UPGRADE.md +++ b/UPGRADE.md @@ -6,3 +6,14 @@ * `logFile` field must be renamed to `logFilePrefix` and must not end with the file extension Also, for old existing schedules in your database, please remove the log file extension in column `logFilePrefix`. + +## from 3.8 to 3.9 + +* The constructors of `Synolia\SyliusSchedulerCommandPlugin\Checker\EveryMinuteIsDueChecker` and `Synolia\SyliusSchedulerCommandPlugin\Checker\SoftLimitThresholdIsDueChecker` has been modified, a new argument has been added : + + ```php + public function __construct( + // ... + private ?DateTimeProviderInterface $dateTimeProvider = null, + ) + ``` diff --git a/src/Checker/EveryMinuteIsDueChecker.php b/src/Checker/EveryMinuteIsDueChecker.php index 057ee125..7c329c8c 100644 --- a/src/Checker/EveryMinuteIsDueChecker.php +++ b/src/Checker/EveryMinuteIsDueChecker.php @@ -5,6 +5,7 @@ namespace Synolia\SyliusSchedulerCommandPlugin\Checker; use Cron\CronExpression; +use Sylius\Calendar\Provider\DateTimeProviderInterface; use Symfony\Component\DependencyInjection\Attribute\AutoconfigureTag; use Synolia\SyliusSchedulerCommandPlugin\Components\Exceptions\Checker\IsNotDueException; use Synolia\SyliusSchedulerCommandPlugin\Entity\CommandInterface; @@ -17,6 +18,20 @@ class EveryMinuteIsDueChecker implements IsDueCheckerInterface { private const PRIORITY = 0; + public function __construct( + private readonly ?DateTimeProviderInterface $dateTimeProvider = null, + ) { + if (!$dateTimeProvider instanceof DateTimeProviderInterface) { + trigger_deprecation( + 'synolia/sylius-scheduler-command-plugin', + '3.9', + 'Not passing a service that implements "%s" as a 1st argument of "%s" constructor is deprecated and will be prohibited in 4.0.', + DateTimeProviderInterface::class, + self::class, + ); + } + } + public static function getDefaultPriority(): int { return self::PRIORITY; @@ -28,7 +43,7 @@ public static function getDefaultPriority(): int public function isDue(CommandInterface $command, ?\DateTimeInterface $dateTime = null): bool { if (!$dateTime instanceof \DateTimeInterface) { - $dateTime = new \DateTime(); + $dateTime = $this->dateTimeProvider?->now() ?? new \DateTime(); } $cron = new CronExpression($command->getCronExpression()); diff --git a/src/Checker/SoftLimitThresholdIsDueChecker.php b/src/Checker/SoftLimitThresholdIsDueChecker.php index ee9d7f75..1c1067bd 100644 --- a/src/Checker/SoftLimitThresholdIsDueChecker.php +++ b/src/Checker/SoftLimitThresholdIsDueChecker.php @@ -5,6 +5,7 @@ namespace Synolia\SyliusSchedulerCommandPlugin\Checker; use Cron\CronExpression; +use Sylius\Calendar\Provider\DateTimeProviderInterface; use Symfony\Component\DependencyInjection\Attribute\AutoconfigureTag; use Synolia\SyliusSchedulerCommandPlugin\Components\Exceptions\Checker\IsNotDueException; use Synolia\SyliusSchedulerCommandPlugin\Entity\CommandInterface; @@ -22,11 +23,21 @@ public static function getDefaultPriority(): int public function __construct( private readonly ScheduledCommandRepositoryInterface $scheduledCommandRepository, + private readonly ?DateTimeProviderInterface $dateTimeProvider = null, /** * Threshold in minutes */ private readonly int $threshold = 5, ) { + if (!$dateTimeProvider instanceof DateTimeProviderInterface) { + trigger_deprecation( + 'synolia/sylius-scheduler-command-plugin', + '3.9', + 'Not passing a service that implements "%s" as a 1st argument of "%s" constructor is deprecated and will be prohibited in 4.0.', + DateTimeProviderInterface::class, + self::class, + ); + } } /** @@ -35,7 +46,7 @@ public function __construct( public function isDue(CommandInterface $command, ?\DateTimeInterface $dateTime = null): bool { if (!$dateTime instanceof \DateTimeInterface) { - $dateTime = new \DateTime(); + $dateTime = $this->dateTimeProvider?->now() ?? new \DateTime(); } $cron = new CronExpression($command->getCronExpression()); diff --git a/src/EventSubscriber/ConsoleSubscriber.php b/src/EventSubscriber/ConsoleSubscriber.php new file mode 100644 index 00000000..efa0ac10 --- /dev/null +++ b/src/EventSubscriber/ConsoleSubscriber.php @@ -0,0 +1,69 @@ + 'onConsoleTerminate', + ConsoleEvents::SIGNAL => 'onConsoleSignal', + ]; + } + + public function onConsoleTerminate(ConsoleTerminateEvent $event): void + { + $this->updateCommand($event); + } + + public function onConsoleSignal(ConsoleSignalEvent $event): void + { + $this->updateCommand($event); + } + + private function updateCommand(ConsoleSignalEvent|ConsoleTerminateEvent $event): void + { + try { + $commandCode = $event->getCommand()?->getName() ?? 'no_command'; + /** @var ScheduledCommand|null $schedulerCommand */ + $schedulerCommand = $this->scheduledCommandRepository->findOneBy(['command' => $commandCode], ['id' => 'DESC']); + } catch (Exception) { + return; + } + + if (null === $schedulerCommand) { + return; + } + + if ($schedulerCommand->getState() !== ScheduledCommandStateEnum::IN_PROGRESS) { + return; + } + + $exitCode = $event->getExitCode(); + if (false === $exitCode) { + $exitCode = -1; + } + + $schedulerCommand->setCommandEndTime(new \DateTime()); + $schedulerCommand->setState(ScheduledCommandStateEnum::TERMINATION); + $schedulerCommand->setLastReturnCode($exitCode); + $this->scheduledCommandRepository->add($schedulerCommand); + } +} diff --git a/src/Humanizer/CronExpressionHumanizer.php b/src/Humanizer/CronExpressionHumanizer.php index 9f1040c7..c8b589c9 100644 --- a/src/Humanizer/CronExpressionHumanizer.php +++ b/src/Humanizer/CronExpressionHumanizer.php @@ -7,11 +7,15 @@ use Lorisleiva\CronTranslator\CronTranslator; use Sylius\Component\Locale\Context\LocaleContextInterface; use Sylius\Component\Locale\Context\LocaleNotFoundException; +use Symfony\Component\DependencyInjection\Attribute\Autowire; class CronExpressionHumanizer implements HumanizerInterface { - public function __construct(private readonly LocaleContextInterface $localeContext) - { + public function __construct( + private readonly LocaleContextInterface $localeContext, + #[Autowire(param: 'env(bool:SYNOLIA_SCHEDULER_PLUGIN_TIMEFORMAT_24H)')] + private readonly bool $timeFormat24Hours = false, + ) { } public function humanize(string $expression): string @@ -23,7 +27,7 @@ public function humanize(string $expression): string $locale = $this->getLocale(); try { - return CronTranslator::translate($expression, $locale); + return CronTranslator::translate($expression, $locale, $this->timeFormat24Hours); } catch (\Throwable) { return $expression; } diff --git a/src/Provider/CalendarWithTimezone.php b/src/Provider/CalendarWithTimezone.php new file mode 100644 index 00000000..30436154 --- /dev/null +++ b/src/Provider/CalendarWithTimezone.php @@ -0,0 +1,32 @@ +timezone ?? date_default_timezone_get(); + + return new DateTimeImmutable(timezone: new DateTimeZone($timezone)); + } +} diff --git a/src/Resources/config/services.yaml b/src/Resources/config/services.yaml index 2678fd29..19d67851 100644 --- a/src/Resources/config/services.yaml +++ b/src/Resources/config/services.yaml @@ -2,6 +2,8 @@ parameters: env(SYNOLIA_SCHEDULER_PLUGIN_PING_INTERVAL): 300 env(SYNOLIA_SCHEDULER_PLUGIN_KEEP_ALIVE): true env(SYNOLIA_SCHEDULER_PLUGIN_LOGS_DIR): '%kernel.logs_dir%' + env(SYNOLIA_SCHEDULER_PLUGIN_TIMEFORMAT_24H): false + env(SYNOLIA_SCHEDULER_PLUGIN_TIMEZONE): ~ services: _defaults: @@ -10,4 +12,4 @@ services: Synolia\SyliusSchedulerCommandPlugin\: resource: '../../*' - exclude: '../../{Entity,Migrations,SynoliaSyliusSchedulerCommandPlugin.php}' \ No newline at end of file + exclude: '../../{Entity,Migrations,SynoliaSyliusSchedulerCommandPlugin.php}' diff --git a/src/Resources/public/column/index.js b/src/Resources/public/column/index.js index cb4e4f4a..b452bdd0 100644 --- a/src/Resources/public/column/index.js +++ b/src/Resources/public/column/index.js @@ -2,7 +2,7 @@ function fireLog(e) { e.preventDefault(); var url = $(e.currentTarget).data('href'); $.get(url, function (data) { - $('#log-modal .description').html($(data).find('#content')); + $('#log-content').html($(data)); }).done(function () { $('#log-modal').modal('show'); }) diff --git a/src/Resources/public/controller/index.css b/src/Resources/public/controller/index.css index 5e8c539e..ae646216 100644 --- a/src/Resources/public/controller/index.css +++ b/src/Resources/public/controller/index.css @@ -8,20 +8,15 @@ pre { #results { border: solid 1px; - padding: 5px; + padding: 10px; overflow-y: scroll; - height: calc(100% - 150px); + height: calc(100% - 80px); } #log-modal { - width: calc(100% - 100px); - height: calc(100% - 100px); -} - -#log-modal .description, -#log-modal > .content, -#log-modal #content { - height: 100%; + width: calc(100% - 120px); + height: calc(100% - 120px); + overflow-y: hidden; } #results .loader:before { @@ -31,3 +26,12 @@ pre { #results .loader:after { border-color: #767676 transparent transparent; } + +#log-content { + padding: 10px; + height: calc(100% - 20px); +} + +#log-results { + height: calc(100% - 20px); +} diff --git a/src/Resources/views/Controller/modal.html.twig b/src/Resources/views/Controller/modal.html.twig index f8fd33a1..9bf01fad 100644 --- a/src/Resources/views/Controller/modal.html.twig +++ b/src/Resources/views/Controller/modal.html.twig @@ -4,7 +4,6 @@ -
+