SchedulerCommand.php 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. <?php
  2. /**
  3. * @package Grav\Console\Cli
  4. *
  5. * @copyright Copyright (C) 2015 - 2019 Trilby Media, LLC. All rights reserved.
  6. * @license MIT License; see LICENSE file for details.
  7. */
  8. namespace Grav\Console\Cli;
  9. use Cron\CronExpression;
  10. use Grav\Common\Grav;
  11. use Grav\Common\Utils;
  12. use Grav\Common\Scheduler\Scheduler;
  13. use Grav\Console\ConsoleCommand;
  14. use RocketTheme\Toolbox\Event\Event;
  15. use Symfony\Component\Console\Helper\Table;
  16. use Symfony\Component\Console\Input\InputOption;
  17. use Symfony\Component\Console\Style\SymfonyStyle;
  18. class SchedulerCommand extends ConsoleCommand
  19. {
  20. protected function configure()
  21. {
  22. $this
  23. ->setName('scheduler')
  24. ->addOption(
  25. 'install',
  26. 'i',
  27. InputOption::VALUE_NONE,
  28. 'Show Install Command'
  29. )
  30. ->addOption(
  31. 'jobs',
  32. 'j',
  33. InputOption::VALUE_NONE,
  34. 'Show Jobs Summary'
  35. )
  36. ->addOption(
  37. 'details',
  38. 'd',
  39. InputOption::VALUE_NONE,
  40. 'Show Job Details'
  41. )
  42. ->setDescription('Run the Grav Scheduler. Best when integrated with system cron')
  43. ->setHelp("Running without any options will force the Scheduler to run through it's jobs and process them");
  44. }
  45. protected function serve()
  46. {
  47. // error_reporting(1);
  48. $grav = Grav::instance();
  49. $grav->setup();
  50. $grav['uri']->init();
  51. $grav['config']->init();
  52. $grav['plugins']->init();
  53. $grav['themes']->init();
  54. $grav['backups']->init();
  55. // Initialize Plugins
  56. $grav->fireEvent('onPluginsInitialized');
  57. /** @var Scheduler $scheduler */
  58. $scheduler = $grav['scheduler'];
  59. $grav->fireEvent('onSchedulerInitialized', new Event(['scheduler' => $scheduler]));
  60. $this->setHelp('foo');
  61. $io = new SymfonyStyle($this->input, $this->output);
  62. if ($this->input->getOption('jobs')) {
  63. // Show jobs list
  64. $jobs = $scheduler->getAllJobs();
  65. $job_states = $scheduler->getJobStates()->content();
  66. $rows = [];
  67. $table = new Table($this->output);
  68. $table->setStyle('box');
  69. $headers = ['Job ID', 'Command', 'Run At', 'Status', 'Last Run', 'State'];
  70. $io->title('Scheduler Jobs Listing');
  71. foreach ($jobs as $job) {
  72. $job_status = ucfirst($job_states[$job->getId()]['state'] ?? 'ready');
  73. $last_run = $job_states[$job->getId()]['last-run'] ?? 0;
  74. $status = $job_status === 'Failure' ? "<red>{$job_status}</red>" : "<green>{$job_status}</green>";
  75. $state = $job->getEnabled() ? '<cyan>Enabled</cyan>' : '<red>Disabled</red>';
  76. $row = [
  77. $job->getId(),
  78. "<white>{$job->getCommand()}</white>",
  79. "<magenta>{$job->getAt()}</magenta>",
  80. $status,
  81. '<yellow>' . ($last_run === 0 ? 'Never' : date('Y-m-d H:i', $last_run)) . '</yellow>',
  82. $state,
  83. ];
  84. $rows[] = $row;
  85. }
  86. if (!empty($rows)) {
  87. $table->setHeaders($headers);
  88. $table->setRows($rows);
  89. $table->render();
  90. } else {
  91. $io->text('no jobs found...');
  92. }
  93. $io->newLine();
  94. $io->note('For error details run "bin/grav scheduler -d"');
  95. $io->newLine();
  96. } elseif ($this->input->getOption('details')) {
  97. $jobs = $scheduler->getAllJobs();
  98. $job_states = $scheduler->getJobStates()->content();
  99. $io->title('Job Details');
  100. $table = new Table($this->output);
  101. $table->setStyle('box');
  102. $table->setHeaders(['Job ID', 'Last Run', 'Next Run', 'Errors']);
  103. $rows = [];
  104. foreach ($jobs as $job) {
  105. $job_state = $job_states[$job->getId()];
  106. $error = isset($job_state['error']) ? trim($job_state['error']) : false;
  107. /** @var CronExpression $expression */
  108. $expression = $job->getCronExpression();
  109. $next_run = $expression->getNextRunDate();
  110. $row = [];
  111. $row[] = $job->getId();
  112. if (!is_null($job_state['last-run'])) {
  113. $row[] = '<yellow>' . date('Y-m-d H:i', $job_state['last-run']) . '</yellow>';
  114. } else {
  115. $row[] = '<yellow>Never</yellow>';
  116. }
  117. $row[] = '<yellow>' . $next_run->format('Y-m-d H:i') . '</yellow>';
  118. if ($error) {
  119. $row[] = "<error>{$error}</error>";
  120. } else {
  121. $row[] = '<green>None</green>';
  122. }
  123. $rows[] = $row;
  124. }
  125. $table->setRows($rows);
  126. $table->render();
  127. } elseif ($this->input->getOption('install')) {
  128. $io->title('Install Scheduler');
  129. if ($scheduler->isCrontabSetup()) {
  130. $io->success('All Ready! You have already set up Grav\'s Scheduler in your crontab');
  131. } else {
  132. $io->error('You still need to set up Grav\'s Scheduler in your crontab');
  133. }
  134. if (!Utils::isWindows()) {
  135. $io->note('To install, run the following command from your terminal:');
  136. $io->newLine();
  137. $io->text(trim($scheduler->getCronCommand()));
  138. } else {
  139. $io->note('To install, create a scheduled task in Windows.');
  140. $io->text('Learn more at https://learn.getgrav.org/advanced/scheduler');
  141. }
  142. } else {
  143. // Run scheduler
  144. $scheduler->run();
  145. if ($this->input->getOption('verbose')) {
  146. $io->title('Running Scheduled Jobs');
  147. $io->text($scheduler->getVerboseOutput());
  148. }
  149. }
  150. }
  151. }