View source
<?php
namespace Drupal\ultimate_cron\Plugin\ultimate_cron\Scheduler;
use Drupal\Core\Form\FormStateInterface;
use Drupal\ultimate_cron\CronJobInterface;
use Drupal\ultimate_cron\CronRule;
use Drupal\ultimate_cron\Entity\CronJob;
class Crontab extends SchedulerBase {
public function defaultConfiguration() {
return array(
'rules' => array(
'0+@ */3 * * *',
),
'catch_up' => '0',
);
}
public function formatLabel(CronJob $job) {
return implode("\n", $this->configuration['rules']);
}
public function formatLabelVerbose(CronJob $job) {
$parsed = '';
$next_schedule = NULL;
$time = REQUEST_TIME;
$skew = $this
->getSkew($job);
foreach ($this->configuration['rules'] as $rule) {
$cron = CronRule::factory($rule, $time, $skew);
$parsed .= $cron
->parseRule() . "\n";
$result = $cron
->getNextSchedule();
$next_schedule = is_null($next_schedule) || $next_schedule > $result ? $result : $next_schedule;
$result = $cron
->getLastSchedule();
if ($time < $result + $this->configuration['catch_up']) {
$result = floor($time / 60) * 60 + 60;
$next_schedule = $next_schedule > $result ? $result : $next_schedule;
}
}
$parsed .= t('Next scheduled run at @datetime', array(
'@datetime' => \Drupal::service('date.formatter')
->format($next_schedule, 'custom', 'Y-m-d H:i:s'),
));
return $parsed;
}
public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
$form['rules'][0] = array(
'#title' => t("Rules"),
'#type' => 'textfield',
'#default_value' => $this->configuration['rules'],
'#description' => t('Comma separated list of crontab rules.'),
'#fallback' => TRUE,
'#required' => TRUE,
);
$form['rules_help'] = array(
'#type' => 'fieldset',
'#title' => t('Rules help'),
'#collapsible' => TRUE,
'#collapsed' => TRUE,
);
$form['rules_help']['info'] = array(
'#markup' => file_get_contents(drupal_get_path('module', 'ultimate_cron') . '/help/rules.html'),
);
$form['catch_up'] = array(
'#title' => t("Catch up"),
'#type' => 'textfield',
'#default_value' => $this->configuration['catch_up'],
'#description' => t("Don't run job after X seconds of rule."),
'#fallback' => TRUE,
'#required' => TRUE,
);
return $form;
}
public function validateConfigurationForm(array &$form, FormStateInterface $form_state) {
parent::validateConfigurationForm($form, $form_state);
$rule = $form_state
->getValues()['scheduler']['configuration']['rules'][0];
$cron = CronRule::factory($rule);
if (!$cron
->isValid()) {
$form_state
->setErrorByName('scheduler][configuration][rules][0', t('Rule is invalid'));
}
}
public function settingsFormSubmit(&$form, &$form_state, CronJob $job = NULL) {
$values =& $form_state['values']['settings'][$this->type][$this->name];
if (!empty($values['rules'])) {
$rules = explode(',', $values['rules']);
$values['rules'] = array_map('trim', $rules);
}
}
public function isScheduled(CronJob $job) {
$log_entry = isset($job->log_entry) ? $job->log_entry : $job
->loadLatestLogEntry();
$skew = $this
->getSkew($job);
$class = get_class($this);
return $class::shouldRun($this->configuration['rules'], $log_entry->start_time, NULL, $this->configuration['catch_up'], $skew) ? TRUE : FALSE;
}
public static function shouldRun($rules, $job_last_ran, $time = NULL, $catch_up = 0, $skew = 0) {
$time = is_null($time) ? time() : $time;
foreach ($rules as $rule) {
$cron = CronRule::factory($rule, $time, $skew);
$cron_last_ran = $cron
->getLastSchedule();
if ($job_last_ran < $cron_last_ran && $cron_last_ran <= $time) {
if ($time <= $cron_last_ran + $catch_up || $catch_up == 0) {
return $time - $job_last_ran;
}
}
}
return FALSE;
}
public function isBehind(CronJob $job) {
if (!$job
->status()) {
return FALSE;
}
$log_entry = isset($job->log_entry) ? $job->log_entry : $job
->loadLatestLogEntry();
$job_last_ran = $log_entry->start_time;
if (!$job_last_ran) {
$registered = \Drupal::config('ultimate_cron')
->get('ultimate_cron_hooks_registered');
if (empty($registered[$job
->id()])) {
return FALSE;
}
$job_last_ran = $registered[$job
->id()];
}
$skew = $this
->getSkew($job);
$next_schedule = NULL;
foreach ($this->configuration['rules'] as $rule) {
$cron = CronRule::factory($rule, $job_last_ran, $skew);
$time = $cron
->getNextSchedule();
$next_schedule = is_null($next_schedule) || $time < $next_schedule ? $time : $next_schedule;
}
$behind = REQUEST_TIME - $next_schedule;
return $behind > $this->configuration['catch_up'] ? $behind : FALSE;
}
protected function getSkew(CronJob $job) {
return $job
->getUniqueID() & 0xff;
}
}