From 125ac29ef257ca24b28121d9dfe4888e0bc8dcb8 Mon Sep 17 00:00:00 2001 From: Moshe Brodsky <44633930+moshe-autoleadstar@users.noreply.github.com> Date: Tue, 6 Dec 2022 13:06:38 +0200 Subject: [PATCH 1/5] Add sort option for schedule:list Currently, in order to see what's schedule will be run, I need to run schedule:list and eyeball the list to find the relevant ones. This PR adds an option to sort the list by the next due date. Before: ``` php artisan schedule:list 0 * * * * php artisan command-one .......... Next Due: 55 minutes from now 15 * * * * php artisan command-three ........ Next Due: 10 minutes from now 17 * * * * php artisan command-two .......... Next Due: 12 minutes from now ``` After: ``` php artisan schedule:list 15 * * * * php artisan command-three ........ Next Due: 10 minutes from now 17 * * * * php artisan command-two .......... Next Due: 12 minutes from now 0 * * * * php artisan command-one .......... Next Due: 55 minutes from now ``` --- .../Scheduling/ScheduleListCommand.php | 41 ++++++++++++++++--- 1 file changed, 36 insertions(+), 5 deletions(-) diff --git a/src/Illuminate/Console/Scheduling/ScheduleListCommand.php b/src/Illuminate/Console/Scheduling/ScheduleListCommand.php index 04ca6a09bbec..ac0fbbe211a6 100644 --- a/src/Illuminate/Console/Scheduling/ScheduleListCommand.php +++ b/src/Illuminate/Console/Scheduling/ScheduleListCommand.php @@ -21,7 +21,10 @@ class ScheduleListCommand extends Command * * @var string */ - protected $signature = 'schedule:list {--timezone= : The timezone that times should be displayed in}'; + protected $signature = 'schedule:list + {--timezone= : The timezone that times should be displayed in} + {--s|sort : Sort by next due date} + '; /** * The name of the console command. @@ -72,6 +75,8 @@ public function handle(Schedule $schedule) $timezone = new DateTimeZone($this->option('timezone') ?? config('app.timezone')); + $events = $this->sortEvents($events, $timezone); + $events = $events->map(function ($event) use ($terminalWidth, $expressionSpacing, $timezone) { $expression = $this->formatCronExpression($event->expression, $expressionSpacing); @@ -98,10 +103,7 @@ public function handle(Schedule $schedule) $nextDueDateLabel = 'Next Due:'; - $nextDueDate = Carbon::create((new CronExpression($event->expression)) - ->getNextRunDate(Carbon::now()->setTimezone($event->timezone)) - ->setTimezone($timezone) - ); + $nextDueDate = $this->getNextDueDate($event, $timezone); $nextDueDate = $this->output->isVerbose() ? $nextDueDate->format('Y-m-d H:i:s P') @@ -150,6 +152,35 @@ private function getCronExpressionSpacing($events) return collect($rows[0] ?? [])->keys()->map(fn ($key) => $rows->max($key)); } + /** + * Sorts the events by due date if option set. + * + * @param \Illuminate\Support\Collection $events + * @return \Illuminate\Support\Collection + */ + private function sortEvents(\Illuminate\Support\Collection $events, DateTimeZone $timezone): \Illuminate\Support\Collection + { + if (!$this->option('sort')) { + return $events; + } + return $events->sortBy(fn ($event) => $this->getNextDueDate($event, $timezone)); + } + + /** + * Get the next due date for an event + * + * @param Event $event + * @param DateTimeZone $timezone + * @return Carbon + */ + private function getNextDueDate(\Illuminate\Console\Scheduling\Event $event, DateTimeZone $timezone): Carbon + { + return Carbon::create((new CronExpression($event->expression)) + ->getNextRunDate(Carbon::now()->setTimezone($event->timezone)) + ->setTimezone($timezone) + ); + } + /** * Formats the cron expression based on the spacing provided. * From c606174bfe51878bd167309ae8358568de773474 Mon Sep 17 00:00:00 2001 From: Moshe Brodsky <44633930+moshe-autoleadstar@users.noreply.github.com> Date: Tue, 6 Dec 2022 13:08:37 +0200 Subject: [PATCH 2/5] Add a test --- .../Scheduling/ScheduleListCommandTest.php | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/tests/Integration/Console/Scheduling/ScheduleListCommandTest.php b/tests/Integration/Console/Scheduling/ScheduleListCommandTest.php index 64d024a37fdd..ca170061155c 100644 --- a/tests/Integration/Console/Scheduling/ScheduleListCommandTest.php +++ b/tests/Integration/Console/Scheduling/ScheduleListCommandTest.php @@ -52,6 +52,30 @@ public function testDisplaySchedule() ->expectsOutput(' * * * * * Closure at: '.$closureFilePath.':'.$closureLineNumber.' Next Due: 1 minute from now'); } + public function testDisplayScheduleWithSort() + { + $this->schedule->command(FooCommand::class)->quarterly(); + $this->schedule->command('inspire')->twiceDaily(14, 18); + $this->schedule->command('foobar', ['a' => 'b'])->everyMinute(); + $this->schedule->job(FooJob::class)->everyMinute(); + $this->schedule->command('inspire')->cron('0 9,17 * * *'); + $this->schedule->command('inspire')->cron("0 10\t* * *"); + + $this->schedule->call(fn () => '')->everyMinute(); + $closureLineNumber = __LINE__ - 1; + $closureFilePath = __FILE__; + + $this->artisan(ScheduleListCommand::class) + ->assertSuccessful() + ->expectsOutput(' * * * * * php artisan foobar a='.ProcessUtils::escapeArgument('b').' ... Next Due: 1 minute from now') + ->expectsOutput(' * * * * * Illuminate\Tests\Integration\Console\Scheduling\FooJob Next Due: 1 minute from now') + ->expectsOutput(' * * * * * Closure at: '.$closureFilePath.':'.$closureLineNumber.' Next Due: 1 minute from now') + ->expectsOutput(' 0 9,17 * * * php artisan inspire ......... Next Due: 9 hours from now') + ->expectsOutput(' 0 10 * * * php artisan inspire ........ Next Due: 10 hours from now') + ->expectsOutput(' 0 14,18 * * * php artisan inspire ........ Next Due: 14 hours from now') + ->expectsOutput(' 0 0 1 1-12/3 * php artisan foo:command .... Next Due: 3 months from now'); + } + public function testDisplayScheduleInVerboseMode() { $this->schedule->command(FooCommand::class)->everyMinute(); From e7279639bc0aee128619558faf596213493419be Mon Sep 17 00:00:00 2001 From: Moshe Brodsky <44633930+moshe-autoleadstar@users.noreply.github.com> Date: Tue, 6 Dec 2022 13:11:00 +0200 Subject: [PATCH 3/5] fix styling --- .../Console/Scheduling/ScheduleListCommand.php | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/Illuminate/Console/Scheduling/ScheduleListCommand.php b/src/Illuminate/Console/Scheduling/ScheduleListCommand.php index ac0fbbe211a6..b38f4e06e220 100644 --- a/src/Illuminate/Console/Scheduling/ScheduleListCommand.php +++ b/src/Illuminate/Console/Scheduling/ScheduleListCommand.php @@ -155,22 +155,23 @@ private function getCronExpressionSpacing($events) /** * Sorts the events by due date if option set. * - * @param \Illuminate\Support\Collection $events + * @param \Illuminate\Support\Collection $events * @return \Illuminate\Support\Collection */ private function sortEvents(\Illuminate\Support\Collection $events, DateTimeZone $timezone): \Illuminate\Support\Collection { - if (!$this->option('sort')) { + if (! $this->option('sort')) { return $events; } + return $events->sortBy(fn ($event) => $this->getNextDueDate($event, $timezone)); } /** - * Get the next due date for an event + * Get the next due date for an event. * - * @param Event $event - * @param DateTimeZone $timezone + * @param Event $event + * @param DateTimeZone $timezone * @return Carbon */ private function getNextDueDate(\Illuminate\Console\Scheduling\Event $event, DateTimeZone $timezone): Carbon From 0f79978aefc6ddff88a00710f3cf27b5ce782adc Mon Sep 17 00:00:00 2001 From: Moshe Brodsky <44633930+moshe-autoleadstar@users.noreply.github.com> Date: Tue, 6 Dec 2022 13:17:03 +0200 Subject: [PATCH 4/5] need to actually use the flag in the test --- .../Integration/Console/Scheduling/ScheduleListCommandTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Integration/Console/Scheduling/ScheduleListCommandTest.php b/tests/Integration/Console/Scheduling/ScheduleListCommandTest.php index ca170061155c..c034458d67b1 100644 --- a/tests/Integration/Console/Scheduling/ScheduleListCommandTest.php +++ b/tests/Integration/Console/Scheduling/ScheduleListCommandTest.php @@ -65,7 +65,7 @@ public function testDisplayScheduleWithSort() $closureLineNumber = __LINE__ - 1; $closureFilePath = __FILE__; - $this->artisan(ScheduleListCommand::class) + $this->artisan(ScheduleListCommand::class, ['-s' => true]) ->assertSuccessful() ->expectsOutput(' * * * * * php artisan foobar a='.ProcessUtils::escapeArgument('b').' ... Next Due: 1 minute from now') ->expectsOutput(' * * * * * Illuminate\Tests\Integration\Console\Scheduling\FooJob Next Due: 1 minute from now') From 52c5e5258b6586055d44b53014e216b91d4a64f2 Mon Sep 17 00:00:00 2001 From: Taylor Otwell Date: Wed, 7 Dec 2022 09:18:17 -0600 Subject: [PATCH 5/5] formatting --- .../Scheduling/ScheduleListCommand.php | 32 +++++++++---------- .../Scheduling/ScheduleListCommandTest.php | 2 +- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/Illuminate/Console/Scheduling/ScheduleListCommand.php b/src/Illuminate/Console/Scheduling/ScheduleListCommand.php index b38f4e06e220..03a2b23f6e30 100644 --- a/src/Illuminate/Console/Scheduling/ScheduleListCommand.php +++ b/src/Illuminate/Console/Scheduling/ScheduleListCommand.php @@ -23,7 +23,7 @@ class ScheduleListCommand extends Command */ protected $signature = 'schedule:list {--timezone= : The timezone that times should be displayed in} - {--s|sort : Sort by next due date} + {--next : Sort the listed tasks by their next due date} '; /** @@ -42,7 +42,7 @@ class ScheduleListCommand extends Command * * @var string */ - protected $description = 'List the scheduled commands'; + protected $description = 'List all scheduled tasks'; /** * The terminal width resolver callback. @@ -103,7 +103,7 @@ public function handle(Schedule $schedule) $nextDueDateLabel = 'Next Due:'; - $nextDueDate = $this->getNextDueDate($event, $timezone); + $nextDueDate = $this->getNextDueDateForEvent($event, $timezone); $nextDueDate = $this->output->isVerbose() ? $nextDueDate->format('Y-m-d H:i:s P') @@ -156,29 +156,29 @@ private function getCronExpressionSpacing($events) * Sorts the events by due date if option set. * * @param \Illuminate\Support\Collection $events + * @param \DateTimeZone $timezone * @return \Illuminate\Support\Collection */ - private function sortEvents(\Illuminate\Support\Collection $events, DateTimeZone $timezone): \Illuminate\Support\Collection + private function sortEvents(\Illuminate\Support\Collection $events, DateTimeZone $timezone) { - if (! $this->option('sort')) { - return $events; - } - - return $events->sortBy(fn ($event) => $this->getNextDueDate($event, $timezone)); + return $this->option('next') + ? $events->sortBy(fn ($event) => $this->getNextDueDateForEvent($event, $timezone)) + : $events; } /** * Get the next due date for an event. * - * @param Event $event - * @param DateTimeZone $timezone - * @return Carbon + * @param \Illuminate\Console\Scheduling\Event $event + * @param \DateTimeZone $timezone + * @return \Illuminate\Support\Carbon */ - private function getNextDueDate(\Illuminate\Console\Scheduling\Event $event, DateTimeZone $timezone): Carbon + private function getNextDueDateForEvent($event, DateTimeZone $timezone) { - return Carbon::create((new CronExpression($event->expression)) - ->getNextRunDate(Carbon::now()->setTimezone($event->timezone)) - ->setTimezone($timezone) + return Carbon::create( + (new CronExpression($event->expression)) + ->getNextRunDate(Carbon::now()->setTimezone($event->timezone)) + ->setTimezone($timezone) ); } diff --git a/tests/Integration/Console/Scheduling/ScheduleListCommandTest.php b/tests/Integration/Console/Scheduling/ScheduleListCommandTest.php index c034458d67b1..efa6f60d8b20 100644 --- a/tests/Integration/Console/Scheduling/ScheduleListCommandTest.php +++ b/tests/Integration/Console/Scheduling/ScheduleListCommandTest.php @@ -65,7 +65,7 @@ public function testDisplayScheduleWithSort() $closureLineNumber = __LINE__ - 1; $closureFilePath = __FILE__; - $this->artisan(ScheduleListCommand::class, ['-s' => true]) + $this->artisan(ScheduleListCommand::class, ['--next' => true]) ->assertSuccessful() ->expectsOutput(' * * * * * php artisan foobar a='.ProcessUtils::escapeArgument('b').' ... Next Due: 1 minute from now') ->expectsOutput(' * * * * * Illuminate\Tests\Integration\Console\Scheduling\FooJob Next Due: 1 minute from now')