From 5f7b5e3c626a80230daabe26f3b287eba0d9d61c Mon Sep 17 00:00:00 2001
From: Christoph Reiter <reiter.christoph@gmail.com>
Date: Tue, 14 Feb 2023 14:01:01 +0100
Subject: [PATCH] cron: add a list command which lists all cron jobs

This shows a simple list of jobs, their class, name,
interval, and when they are going to run next.
---
 src/Cron/CronListCommand.php       | 52 ++++++++++++++++++++++++++++++
 src/Cron/CronManager.php           | 13 ++++++++
 src/Resources/config/services.yaml |  4 +++
 3 files changed, 69 insertions(+)
 create mode 100644 src/Cron/CronListCommand.php

diff --git a/src/Cron/CronListCommand.php b/src/Cron/CronListCommand.php
new file mode 100644
index 0000000..5dfed2f
--- /dev/null
+++ b/src/Cron/CronListCommand.php
@@ -0,0 +1,52 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Dbp\Relay\CoreBundle\Cron;
+
+use Psr\Log\LoggerAwareInterface;
+use Psr\Log\LoggerAwareTrait;
+use Psr\Log\NullLogger;
+use Symfony\Component\Console\Command\Command;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Output\OutputInterface;
+
+final class CronListCommand extends Command implements LoggerAwareInterface
+{
+    use LoggerAwareTrait;
+
+    // dbp:cron only for backwards compat
+    protected static $defaultName = 'dbp:relay:core:cron:list';
+
+    /**
+     * @var CronManager
+     */
+    private $manager;
+
+    public function __construct(CronManager $manager)
+    {
+        parent::__construct();
+        $this->logger = new NullLogger();
+        $this->manager = $manager;
+    }
+
+    protected function configure()
+    {
+        $this->setDescription('Lists all registered cron jobs');
+    }
+
+    protected function execute(InputInterface $input, OutputInterface $output): int
+    {
+        $currentTime = new \DateTimeImmutable('now', new \DateTimeZone('UTC'));
+        $jobs = $this->manager->getAllJobs();
+        foreach ($jobs as $job) {
+            $output->writeln('<fg=green;options=bold>['.get_class($job).']</>');
+            $output->writeln('<fg=blue;options=bold>Name:</> '.$job->getName());
+            $output->writeln('<fg=blue;options=bold>Cron:</> "'.$job->getInterval().'"');
+            $output->writeln('<fg=blue;options=bold>Now:</> '.$currentTime->format(\DateTime::ATOM));
+            $output->writeln('<fg=blue;options=bold>Next:</> '.$this->manager->getNextDate($job, $currentTime)->format(\DateTime::ATOM));
+        }
+
+        return 0;
+    }
+}
diff --git a/src/Cron/CronManager.php b/src/Cron/CronManager.php
index ea221a6..7d8bf69 100644
--- a/src/Cron/CronManager.php
+++ b/src/Cron/CronManager.php
@@ -66,6 +66,19 @@ final class CronManager implements LoggerAwareInterface
         return $shouldRun;
     }
 
+    /**
+     * Returns the date and time the job is scheduled to run the next time.
+     */
+    public static function getNextDate(CronJobInterface $job, \DateTimeInterface $currentTime): \DateTimeInterface
+    {
+        $cronExpression = $job->getInterval();
+        $cron = new CronExpression($cronExpression);
+        $nextDate = $cron->getNextRunDate($currentTime, 0, true);
+        $nextDate->setTimezone(new \DateTimeZone('UTC'));
+
+        return \DateTimeImmutable::createFromMutable($nextDate);
+    }
+
     public function getPreviousRun(\DateTimeInterface $currentTime): ?\DateTimeInterface
     {
         $cachePool = $this->cachePool;
diff --git a/src/Resources/config/services.yaml b/src/Resources/config/services.yaml
index ac806d6..e8bc21d 100644
--- a/src/Resources/config/services.yaml
+++ b/src/Resources/config/services.yaml
@@ -14,6 +14,10 @@ services:
     autowire: true
     autoconfigure: true
 
+  Dbp\Relay\CoreBundle\Cron\CronListCommand:
+    autowire: true
+    autoconfigure: true
+
   Dbp\Relay\CoreBundle\Cron\CronManager:
     autowire: true
     autoconfigure: true
-- 
GitLab