ILIAS  release_9 Revision v9.13-25-g2c18ec4c24f
class.ilCronJob.php
Go to the documentation of this file.
1 <?php
2 
19 declare(strict_types=1);
20 
22 
23 abstract class ilCronJob
24 {
26  protected ?int $schedule_value = null;
27  protected ?Closure $date_time_provider = null;
28 
29  private function checkWeeklySchedule(DateTimeImmutable $last_run, DateTimeImmutable $now): bool
30  {
31  $last_year = (int) $last_run->format('Y');
32  $now_year = (int) $now->format('Y');
33 
34  if ($last_year > $now_year) {
35  // Should never happen, don't execute otherwise
36  return false;
37  }
38 
39  $last_week = $last_run->format('W');
40  $now_week = $now->format('W');
41 
42  if ($last_week !== $now_week) {
43  // Week differs, always execute the job
44  return true;
45  }
46 
47  // For all following cases, the week number is always identical
48 
49  $last_month = (int) $last_run->format('m');
50  $now_month = (int) $now->format('m');
51 
52  $is_within_same_week_in_same_year = ($last_year . '-' . $last_week) === ($now_year . '-' . $now_week);
53  if ($is_within_same_week_in_same_year) {
54  // Same week in same year, only execute if the month differs (2022-52 is valid for January and December)
55  return $last_month !== $now_month && $now->diff($last_run)->d > 7;
56  }
57 
58  if ($now_year - $last_year > 1) {
59  // Always execute if the difference of years is greater than 1
60  return true;
61  }
62 
63  // Execute for week number 52 in 2022 (last run) and week number 52 in December of 2022 (now), but not for week number 52 in January of 2022 (now)
64  return $last_month === $now_month;
65  }
66 
67  private function checkSchedule(?DateTimeImmutable $last_run, ?CronJobScheduleType $schedule_type, ?int $schedule_value): bool
68  {
69  if (null === $schedule_type) {
70  return false;
71  }
72 
73  if (null === $last_run) {
74  return true;
75  }
76 
77  if ($this->date_time_provider === null) {
78  $now = new DateTimeImmutable('@' . time(), new DateTimeZone(date_default_timezone_get()));
79  } else {
80  $now = ($this->date_time_provider)();
81  }
82 
83  switch ($schedule_type) {
84  case CronJobScheduleType::SCHEDULE_TYPE_DAILY:
85  $last = $last_run->format('Y-m-d');
86  $ref = $now->format('Y-m-d');
87  return ($last !== $ref);
88 
89  case CronJobScheduleType::SCHEDULE_TYPE_WEEKLY:
90  return $this->checkWeeklySchedule($last_run, $now);
91 
92  case CronJobScheduleType::SCHEDULE_TYPE_MONTHLY:
93  $last = $last_run->format('Y-n');
94  $ref = $now->format('Y-n');
95  return ($last !== $ref);
96 
97  case CronJobScheduleType::SCHEDULE_TYPE_QUARTERLY:
98  $last = $last_run->format('Y') . '-' . ceil(((int) $last_run->format('n')) / 3);
99  $ref = $now->format('Y') . '-' . ceil(((int) $now->format('n')) / 3);
100  return ($last !== $ref);
101 
103  $last = $last_run->format('Y');
104  $ref = $now->format('Y');
105  return ($last !== $ref);
106 
107  case CronJobScheduleType::SCHEDULE_TYPE_IN_MINUTES:
108  $diff = floor(($now->getTimestamp() - $last_run->getTimestamp()) / 60);
109  return ($diff >= $schedule_value);
110 
111  case CronJobScheduleType::SCHEDULE_TYPE_IN_HOURS:
112  $diff = floor(($now->getTimestamp() - $last_run->getTimestamp()) / (60 * 60));
113  return ($diff >= $schedule_value);
114 
115  case CronJobScheduleType::SCHEDULE_TYPE_IN_DAYS:
116  $diff = floor(($now->getTimestamp() - $last_run->getTimestamp()) / (60 * 60 * 24));
117  return ($diff >= $schedule_value);
118  }
119 
120  return false;
121  }
122 
126  public function setDateTimeProvider(?Closure $date_time_provider): void
127  {
128  if ($date_time_provider !== null) {
129  $r = new ReflectionFunction($date_time_provider);
130  $return_type = $r->getReturnType();
131  if ($return_type !== null) {
132  $return_type = $return_type->getName();
133  }
134  $expected_type = DateTimeInterface::class;
135  if (!is_subclass_of($return_type, $expected_type)) {
136  throw new InvalidArgumentException(sprintf(
137  'The return type of the datetime provider must be of type %s',
138  $expected_type
139  ));
140  }
141 
142  $r = new ReflectionFunction($date_time_provider);
143  $parameters = $r->getParameters();
144  if ($parameters !== []) {
145  throw new InvalidArgumentException(
146  'The datetime provider must not define any parameters',
147  );
148  }
149  }
150 
151  $this->date_time_provider = $date_time_provider;
152  }
153 
154  public function isDue(
155  ?DateTimeImmutable $last_run,
156  ?CronJobScheduleType $schedule_type,
157  ?int $schedule_value,
158  bool $is_manually_executed = false
159  ): bool {
160  if ($is_manually_executed) {
161  return true;
162  }
163 
164  if (!$this->hasFlexibleSchedule()) {
165  $schedule_type = $this->getDefaultScheduleType();
166  $schedule_value = $this->getDefaultScheduleValue();
167  }
168 
169  return $this->checkSchedule($last_run, $schedule_type, $schedule_value);
170  }
171 
176  {
177  if ($this->schedule_type && $this->hasFlexibleSchedule()) {
178  return $this->schedule_type;
179  }
180 
181  return null;
182  }
183 
187  public function getScheduleValue(): ?int
188  {
189  if ($this->schedule_value && $this->hasFlexibleSchedule()) {
190  return $this->schedule_value;
191  }
192 
193  return null;
194  }
195 
199  public function setSchedule(?CronJobScheduleType $a_type, ?int $a_value): void
200  {
201  if (
202  $a_value &&
203  $this->hasFlexibleSchedule() &&
204  in_array($a_type, $this->getValidScheduleTypes(), true)
205  ) {
206  $this->schedule_type = $a_type;
207  $this->schedule_value = $a_value;
208  }
209  }
210 
215  public function getAllScheduleTypes(): array
216  {
217  return CronJobScheduleType::cases();
218  }
219 
223  public function getScheduleTypesWithValues(): array
224  {
225  return [
226  CronJobScheduleType::SCHEDULE_TYPE_IN_MINUTES,
227  CronJobScheduleType::SCHEDULE_TYPE_IN_HOURS,
228  CronJobScheduleType::SCHEDULE_TYPE_IN_DAYS,
229  ];
230  }
231 
236  public function getValidScheduleTypes(): array
237  {
238  return $this->getAllScheduleTypes();
239  }
240 
241  public function isManuallyExecutable(): bool
242  {
243  return true;
244  }
245 
246  public function hasCustomSettings(): bool
247  {
248  return false;
249  }
250 
251  public function addCustomSettingsToForm(ilPropertyFormGUI $a_form): void
252  {
253  }
254 
255  public function saveCustomSettings(ilPropertyFormGUI $a_form): bool
256  {
257  return true;
258  }
259 
260  public function addToExternalSettingsForm(int $a_form_id, array &$a_fields, bool $a_is_active): void
261  {
262  }
263 
268  public function activationWasToggled(ilDBInterface $db, ilSetting $setting, bool $a_currently_active): void
269  {
270  }
271 
272  abstract public function getId(): string;
273 
274  abstract public function getTitle(): string;
275 
276  abstract public function getDescription(): string;
277 
281  abstract public function hasAutoActivation(): bool;
282 
283  abstract public function hasFlexibleSchedule(): bool;
284 
285  abstract public function getDefaultScheduleType(): CronJobScheduleType;
286 
287  abstract public function getDefaultScheduleValue(): ?int;
288 
289  abstract public function run(): ilCronJobResult;
290 }
activationWasToggled(ilDBInterface $db, ilSetting $setting, bool $a_currently_active)
Important: This method is (also) called from the setup process, where the constructor of an ilCronJob...
checkSchedule(?DateTimeImmutable $last_run, ?CronJobScheduleType $schedule_type, ?int $schedule_value)
getValidScheduleTypes()
Returns a collection of all valid schedule types for a specific job.
setDateTimeProvider(?Closure $date_time_provider)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
getAllScheduleTypes()
Get all available schedule types.
isDue(?DateTimeImmutable $last_run, ?CronJobScheduleType $schedule_type, ?int $schedule_value, bool $is_manually_executed=false)
getDescription()
addCustomSettingsToForm(ilPropertyFormGUI $a_form)
hasFlexibleSchedule()
CronJobScheduleType $schedule_type
addToExternalSettingsForm(int $a_form_id, array &$a_fields, bool $a_is_active)
getScheduleTypesWithValues()
getDefaultScheduleType()
Closure $date_time_provider
setSchedule(?CronJobScheduleType $a_type, ?int $a_value)
Update current schedule (if flexible)
getDefaultScheduleValue()
saveCustomSettings(ilPropertyFormGUI $a_form)
getScheduleValue()
Get current schedule value (if flexible)
hasAutoActivation()
Is to be activated on "installation", does only work for ILIAS core cron jobs.
getScheduleType()
Get current schedule type (if flexible)
checkWeeklySchedule(DateTimeImmutable $last_run, DateTimeImmutable $now)
$r