vendor/contao/core-bundle/src/Cron/Cron.php line 62

Open in your IDE?
  1. <?php
  2. declare(strict_types=1);
  3. /*
  4.  * This file is part of Contao.
  5.  *
  6.  * (c) Leo Feyer
  7.  *
  8.  * @license LGPL-3.0-or-later
  9.  */
  10. namespace Contao\CoreBundle\Cron;
  11. use Contao\CoreBundle\Entity\CronJob as CronJobEntity;
  12. use Contao\CoreBundle\Repository\CronJobRepository;
  13. use Cron\CronExpression;
  14. use Doctrine\ORM\EntityManagerInterface;
  15. use Psr\Log\LoggerInterface;
  16. class Cron
  17. {
  18.     public const SCOPE_WEB 'web';
  19.     public const SCOPE_CLI 'cli';
  20.     /**
  21.      * @var \Closure():CronJobRepository
  22.      */
  23.     private \Closure $repository;
  24.     /**
  25.      * @var \Closure():EntityManagerInterface
  26.      */
  27.     private \Closure $entityManager;
  28.     private ?LoggerInterface $logger;
  29.     /**
  30.      * @var array<CronJob>
  31.      */
  32.     private array $cronJobs = [];
  33.     /**
  34.      * @param \Closure():CronJobRepository      $repository
  35.      * @param \Closure():EntityManagerInterface $entityManager
  36.      */
  37.     public function __construct(\Closure $repository, \Closure $entityManagerLoggerInterface $logger null)
  38.     {
  39.         $this->repository $repository;
  40.         $this->entityManager $entityManager;
  41.         $this->logger $logger;
  42.     }
  43.     public function addCronJob(CronJob $cronjob): void
  44.     {
  45.         $this->cronJobs[] = $cronjob;
  46.     }
  47.     /**
  48.      * Run all the registered Contao cron jobs.
  49.      */
  50.     public function run(string $scope): void
  51.     {
  52.         // Validate scope
  53.         if (self::SCOPE_WEB !== $scope && self::SCOPE_CLI !== $scope) {
  54.             throw new \InvalidArgumentException('Invalid scope "'.$scope.'"');
  55.         }
  56.         /** @var CronJobRepository $repository */
  57.         $repository = ($this->repository)();
  58.         /** @var EntityManagerInterface $entityManager */
  59.         $entityManager = ($this->entityManager)();
  60.         /** @var array<CronJob> */
  61.         $cronJobsToBeRun = [];
  62.         $now = new \DateTimeImmutable();
  63.         try {
  64.             // Lock cron table
  65.             $repository->lockTable();
  66.             // Go through each cron job
  67.             foreach ($this->cronJobs as $cron) {
  68.                 $interval $cron->getInterval();
  69.                 $name $cron->getName();
  70.                 // Determine the last run date
  71.                 $lastRunDate null;
  72.                 /** @var CronJobEntity|null $lastRunEntity */
  73.                 $lastRunEntity $repository->findOneByName($name);
  74.                 if (null !== $lastRunEntity) {
  75.                     $lastRunDate $lastRunEntity->getLastRun();
  76.                 } else {
  77.                     $lastRunEntity = new CronJobEntity($name);
  78.                     $entityManager->persist($lastRunEntity);
  79.                 }
  80.                 // Check if the cron should be run
  81.                 $expression CronExpression::factory($interval);
  82.                 if (null !== $lastRunDate && $now $expression->getNextRunDate($lastRunDate)) {
  83.                     continue;
  84.                 }
  85.                 // Update the cron entry
  86.                 $lastRunEntity->setLastRun($now);
  87.                 // Add job to the crons to be run
  88.                 $cronJobsToBeRun[] = $cron;
  89.             }
  90.             $entityManager->flush();
  91.         } finally {
  92.             $repository->unlockTable();
  93.         }
  94.         // Execute all crons to be run
  95.         foreach ($cronJobsToBeRun as $cron) {
  96.             if (null !== $this->logger) {
  97.                 $this->logger->debug(sprintf('Executing cron job "%s"'$cron->getName()));
  98.             }
  99.             $cron($scope);
  100.         }
  101.     }
  102. }