contacts_events-8.x-1.x-dev/src/Cron/CronBase.php
src/Cron/CronBase.php
<?php
namespace Drupal\contacts_events\Cron;
use Drupal\Component\Datetime\DateTimePlus;
use Drupal\Component\Datetime\Time;
use Drupal\Core\Logger\LoggerChannelInterface;
use Drupal\Core\State\StateInterface;
use Drupal\Core\Utility\Error;
use Psr\Log\LogLevel;
/**
* A base class to help with controlling running of cron tasks.
*/
abstract class CronBase implements CronInterface {
/**
* The state service.
*
* @var \Drupal\Core\State\StateInterface
*/
protected $state;
/**
* The time service.
*
* @var \Drupal\Component\Datetime\Time
*/
protected $time;
/**
* The logger channel.
*
* @var \Drupal\Core\Logger\LoggerChannelInterface
*/
protected $logger;
/**
* The run interval.
*
* One of:
* - Y: Yearly.
* - m: Monthly.
* - d: Daily.
* - H: Hourly.
* - i: Minutely.
*
* @var string
*/
protected $runInterval = 'd';
/**
* A formatted date/time to run after.
*
* @var string
*/
protected $runAfterFormat = 'H:i:s';
/**
* The format for the run after date/time or NULL for no restriction.
*
* Should contain be in the format of self::$runAfterFormat.
*
* @var string|null
*/
protected $runAfterTime = NULL;
/**
* Constructs the cron task.
*
* @param \Drupal\Core\State\StateInterface $state
* The state service.
* @param \Drupal\Component\Datetime\Time $time
* The time service.
* @param \Drupal\Core\Logger\LoggerChannelInterface|null $logger
* Optionally, the logger channel.
*
* @throws \Exception
* Thrown if the STATE_LAST_RUN constant is not set.
*/
public function __construct(StateInterface $state, Time $time, ?LoggerChannelInterface $logger = NULL) {
if (!defined(static::class . '::STATE_LAST_RUN') || static::STATE_LAST_RUN === NULL) {
throw new \Exception('The STATE_LAST_RUN state key constant must be set.');
}
$this->state = $state;
$this->time = $time;
$this->logger = $logger;
}
/**
* Set the logger.
*
* @param \Drupal\Core\Logger\LoggerChannelInterface|null $logger
* Optionally, the logger channel.
*
* @return $this
*/
public function setLogger(LoggerChannelInterface $logger) {
$this->logger = $logger;
return $this;
}
/**
* {@inheritdoc}
*/
public function invokeOnSchedule() {
if (!$this->scheduledToRun()) {
return;
}
$this->invoke();
}
/**
* {@inheritdoc}
*/
public function invoke() {
try {
$this->doInvoke();
$this->setLastRunTime();
}
catch (\Exception $exception) {
// Catch any errors and log them, if we have a logger.
if ($this->logger) {
$message = 'Error executing cron %cron_class: %type: @message in %function (line %line of %file).';
$variables = Error::decodeException($exception);
$variables['%cron_class'] = static::class;
$this->logger->log(LogLevel::ERROR, $message, $variables);
}
}
}
/**
* Run the actual task.
*/
abstract protected function doInvoke();
/**
* {@inheritdoc}
*/
public function scheduledToRun() {
// Get our last run day.
$last_run = $this->getLastRunTime();
$now = $this->getCurrentTime();
$format = 'Y-m-d H:i:s';
$split_pos = strpos($format, $this->runInterval);
if ($split_pos === FALSE) {
throw new \Exception('Invalid run interval.');
}
$run_format = trim(substr($format, 0, $split_pos + 1), '- ');
$after_format = trim(substr($format, $split_pos + 1), '- ');
// If we have a last run, check it was before today.
if ($last_run) {
// If the last run was today (or future), we don't want to run.
if ($last_run->format($run_format) >= $now->format($run_format)) {
return FALSE;
}
}
// If we have an $after, check that we are after that time.
return !isset($this->runAfterTime) || ($now->format($after_format) >= $this->runAfterTime);
}
/**
* Get the current time.
*
* @return \Drupal\Component\Datetime\DateTimePlus
* The current time.
*/
protected function getCurrentTime() {
return DateTimePlus::createFromTimestamp($this->time->getCurrentTime());
}
/**
* Get the last run time.
*
* @return \Drupal\Component\Datetime\DateTimePlus|null
* The last run time or NULL if never.
*/
protected function getLastRunTime() {
$timestamp = $this->state->get(static::STATE_LAST_RUN);
return isset($timestamp) ? DateTimePlus::createFromTimestamp($timestamp) : NULL;
}
/**
* Set the last run time.
*/
protected function setLastRunTime() {
$this->state->set(static::STATE_LAST_RUN, $this->time->getCurrentTime());
}
}
