From 892e932f75022069db52ff2abce3108cc6056284 Mon Sep 17 00:00:00 2001 From: yoye Date: Tue, 20 Jan 2026 15:17:57 +0100 Subject: [PATCH] Add sorting option to DebugCommand for recurring messages --- CHANGELOG.md | 5 +++ Command/DebugCommand.php | 16 +++++-- Tests/Command/DebugCommandTest.php | 72 ++++++++++++++++++++++++++++++ 3 files changed, 89 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 26067e3..bb6b13c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGELOG ========= +8.1 +--- + + * Add `--sort` option to `debug:command` to order recurring messages by next run date + 7.3 --- diff --git a/Command/DebugCommand.php b/Command/DebugCommand.php index 42d7b9b..3db8dc4 100644 --- a/Command/DebugCommand.php +++ b/Command/DebugCommand.php @@ -45,6 +45,7 @@ final class DebugCommand extends Command ->addArgument('schedule', InputArgument::OPTIONAL | InputArgument::IS_ARRAY, \sprintf('The schedule name (one of "%s")', implode('", "', $this->scheduleNames)), null, $this->scheduleNames) ->addOption('date', null, InputOption::VALUE_REQUIRED, 'The date to use for the next run date', 'now') ->addOption('all', null, InputOption::VALUE_NONE, 'Display all recurring messages, including the terminated ones') + ->addOption('sort', null, InputOption::VALUE_NONE, 'Sort recurring messages by next run date') ->setHelp(<<<'EOF' The %command.name% lists schedules and their recurring messages: @@ -93,9 +94,16 @@ final class DebugCommand extends Command continue; } + + $recurringMessages = array_filter(array_map(self::renderRecurringMessage(...), $messages, array_fill(0, \count($messages), $date), array_fill(0, \count($messages), $input->getOption('all')))); + + if ($input->getOption('sort')) { + usort($recurringMessages, static fn (array $a, array $b): int => $a[2] <=> $b[2]); + } + $io->table( ['Trigger', 'Provider', 'Next Run'], - array_filter(array_map(self::renderRecurringMessage(...), $messages, array_fill(0, \count($messages), $date), array_fill(0, \count($messages), $input->getOption('all')))), + array_map(static fn (array $row): array => [$row[0], $row[1], $row[2]?->format('r') ?? '-'], $recurringMessages), ); } @@ -103,14 +111,14 @@ final class DebugCommand extends Command } /** - * @return array{0:string,1:string,2:string}|null + * @return array{0:string,1:string,2:\DateTimeImmutable|null}|null */ private static function renderRecurringMessage(RecurringMessage $recurringMessage, \DateTimeImmutable $date, bool $all): ?array { $trigger = $recurringMessage->getTrigger(); - $next = $trigger->getNextRunDate($date)?->format('r') ?? '-'; - if ('-' === $next && !$all) { + $next = $trigger->getNextRunDate($date); + if (null === $next && !$all) { return null; } diff --git a/Tests/Command/DebugCommandTest.php b/Tests/Command/DebugCommandTest.php index 50ef169..a27f2a2 100644 --- a/Tests/Command/DebugCommandTest.php +++ b/Tests/Command/DebugCommandTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Scheduler\Tests\Command; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Component\Console\Tester\CommandTester; use Symfony\Component\Scheduler\Command\DebugCommand; @@ -150,4 +151,75 @@ class DebugCommandTest extends TestCase " ------------------------------- ---------- --------------------------------- \n". "\n/", $tester->getDisplay(true)); } + + #[DataProvider('provideSorting')] + public function testExecuteWithScheduleAndSortOption(bool $sorted, string $expected) + { + $schedule = new Schedule(); + $schedule + ->add(RecurringMessage::every('3 minutes', new \stdClass())) + ->add(RecurringMessage::every('1 minute', new \stdClass())) + ->add(RecurringMessage::every('2 minutes', new \stdClass())) + ; + + $schedules = $this->createMock(ServiceProviderInterface::class); + $schedules + ->expects($this->once()) + ->method('getProvidedServices') + ->willReturn(['schedule_name' => $schedule]) + ; + $schedules + ->expects($this->once()) + ->method('get') + ->willReturn($schedule) + ; + + $command = new DebugCommand($schedules); + $tester = new CommandTester($command); + + $tester->execute(['--sort' => $sorted], ['decorated' => false]); + + $this->assertMatchesRegularExpression($expected, $tester->getDisplay(true)); + } + + public static function provideSorting(): iterable + { + yield 'Not sorted results' => [ + false, + "/\n". + "Scheduler\n". + "=========\n". + "\n". + "schedule_name\n". + "-------------\n". + "\n". + " ----------------- ---------- --------------------------------- \n". + " Trigger Provider Next Run \n". + " ----------------- ---------- --------------------------------- \n". + " every 3 minutes stdClass \w{3}, \d{1,2} \w{3} \d{4} \d{2}:\d{2}:\d{2} (\+|-)\d{4} \n". + " every 1 minute stdClass \w{3}, \d{1,2} \w{3} \d{4} \d{2}:\d{2}:\d{2} (\+|-)\d{4} \n". + " every 2 minutes stdClass \w{3}, \d{1,2} \w{3} \d{4} \d{2}:\d{2}:\d{2} (\+|-)\d{4} \n". + " ----------------- ---------- --------------------------------- \n". + "\n/", + ]; + + yield 'Sorted results' => [ + true, + "/\n". + "Scheduler\n". + "=========\n". + "\n". + "schedule_name\n". + "-------------\n". + "\n". + " ----------------- ---------- --------------------------------- \n". + " Trigger Provider Next Run \n". + " ----------------- ---------- --------------------------------- \n". + " every 1 minute stdClass \w{3}, \d{1,2} \w{3} \d{4} \d{2}:\d{2}:\d{2} (\+|-)\d{4} \n". + " every 2 minutes stdClass \w{3}, \d{1,2} \w{3} \d{4} \d{2}:\d{2}:\d{2} (\+|-)\d{4} \n". + " every 3 minutes stdClass \w{3}, \d{1,2} \w{3} \d{4} \d{2}:\d{2}:\d{2} (\+|-)\d{4} \n". + " ----------------- ---------- --------------------------------- \n". + "\n/", + ]; + } }