‪TYPO3CMS  9.5
NormalizeCommand.php
Go to the documentation of this file.
1 <?php
3 
4 /*
5  * This file is part of the TYPO3 CMS project.
6  *
7  * It is free software; you can redistribute it and/or modify it under
8  * the terms of the GNU General Public License, either version 2
9  * of the License, or any later version.
10  *
11  * For the full copyright and license information, please read the
12  * LICENSE.txt file that was distributed with this source code.
13  *
14  * The TYPO3 project - inspiring people to share!
15  */
16 
18 
27 {
39  public static function ‪normalize($cronCommand)
40  {
41  $cronCommand = trim($cronCommand);
42  $cronCommand = ‪self::convertKeywordsToCronCommand($cronCommand);
43  $cronCommand = ‪self::normalizeFields($cronCommand);
44  return $cronCommand;
45  }
46 
54  protected static function ‪convertKeywordsToCronCommand($cronCommand)
55  {
56  switch ($cronCommand) {
57  case '@yearly':
58  case '@annually':
59  $cronCommand = '0 0 1 1 *';
60  break;
61  case '@monthly':
62  $cronCommand = '0 0 1 * *';
63  break;
64  case '@weekly':
65  $cronCommand = '0 0 * * 0';
66  break;
67  case '@daily':
68 
69  case '@midnight':
70  $cronCommand = '0 0 * * *';
71  break;
72  case '@hourly':
73  $cronCommand = '0 * * * *';
74  break;
75  }
76  return $cronCommand;
77  }
78 
85  protected static function ‪normalizeFields($cronCommand)
86  {
87  $fieldArray = ‪self::splitFields($cronCommand);
88  $fieldArray[0] = ‪self::normalizeIntegerField($fieldArray[0], 0, 59);
89  $fieldArray[1] = ‪self::normalizeIntegerField($fieldArray[1], 0, 23);
90  $fieldArray[2] = ‪self::normalizeIntegerField($fieldArray[2], 1, 31);
91  $fieldArray[3] = ‪self::normalizeMonthAndWeekdayField($fieldArray[3], true);
92  $fieldArray[4] = ‪self::normalizeMonthAndWeekdayField($fieldArray[4], false);
93  $normalizedCronCommand = implode(' ', $fieldArray);
94  return $normalizedCronCommand;
95  }
96 
104  protected static function ‪splitFields($cronCommand)
105  {
106  ‪$fields = explode(' ', $cronCommand);
107  if (count(‪$fields) !== 5) {
108  throw new \InvalidArgumentException('Unable to split given cron command to five fields.', 1291227373);
109  }
110  return ‪$fields;
111  }
112 
120  protected static function ‪normalizeMonthAndWeekdayField($expression, $isMonthField = true)
121  {
122  if ((string)$expression === '*') {
123  $fieldValues = '*';
124  } else {
125  // Fragment expression by , / and - and substitute three letter code of month and weekday to numbers
126  $listOfCommaValues = explode(',', $expression);
127  $fieldArray = [];
128  foreach ($listOfCommaValues as $listElement) {
129  if (strpos($listElement, '/') !== false) {
130  list($left, $right) = explode('/', $listElement);
131  if (strpos($left, '-') !== false) {
132  list($leftBound, $rightBound) = explode('-', $left);
133  $leftBound = ‪self::normalizeMonthAndWeekday($leftBound, $isMonthField);
134  $rightBound = ‪self::normalizeMonthAndWeekday($rightBound, $isMonthField);
135  $left = $leftBound . '-' . $rightBound;
136  } else {
137  if ((string)$left !== '*') {
138  $left = ‪self::normalizeMonthAndWeekday($left, $isMonthField);
139  }
140  }
141  $fieldArray[] = $left . '/' . $right;
142  } elseif (strpos($listElement, '-') !== false) {
143  list($left, $right) = explode('-', $listElement);
144  $left = ‪self::normalizeMonthAndWeekday($left, $isMonthField);
145  $right = ‪self::normalizeMonthAndWeekday($right, $isMonthField);
146  $fieldArray[] = $left . '-' . $right;
147  } else {
148  $fieldArray[] = ‪self::normalizeMonthAndWeekday($listElement, $isMonthField);
149  }
150  }
151  $fieldValues = implode(',', $fieldArray);
152  }
153  return $isMonthField ? ‪self::normalizeIntegerField($fieldValues, 1, 12) : ‪self::normalizeIntegerField($fieldValues, 1, 7);
154  }
155 
165  protected static function ‪normalizeIntegerField($expression, $lowerBound = 0, $upperBound = 59)
166  {
167  if ((string)$expression === '*') {
168  $fieldValues = '*';
169  } else {
170  $listOfCommaValues = explode(',', $expression);
171  $fieldArray = [];
172  foreach ($listOfCommaValues as $listElement) {
173  if (strpos($listElement, '/') !== false) {
174  list($left, $right) = explode('/', $listElement);
175  if ((string)$left === '*') {
176  $leftList = ‪self::convertRangeToListOfValues($lowerBound . '-' . $upperBound);
177  } else {
178  $leftList = ‪self::convertRangeToListOfValues($left);
179  }
180  $fieldArray[] = ‪self::reduceListOfValuesByStepValue($leftList . '/' . $right);
181  } elseif (strpos($listElement, '-') !== false) {
182  $fieldArray[] = ‪self::convertRangeToListOfValues($listElement);
183  } elseif (‪MathUtility::canBeInterpretedAsInteger($listElement)) {
184  $fieldArray[] = $listElement;
185  } elseif (strlen($listElement) === 2 && $listElement[0] === '0') {
186  $fieldArray[] = (int)$listElement;
187  } else {
188  throw new \InvalidArgumentException('Unable to normalize integer field.', 1291429389);
189  }
190  }
191  $fieldValues = implode(',', $fieldArray);
192  }
193  if ((string)$fieldValues === '') {
194  throw new \InvalidArgumentException('Unable to convert integer field to list of values: Result list empty.', 1291422012);
195  }
196  if ((string)$fieldValues !== '*') {
197  $fieldList = explode(',', $fieldValues);
198  sort($fieldList);
199  $fieldList = array_unique($fieldList);
200  if (current($fieldList) < $lowerBound) {
201  throw new \InvalidArgumentException('Lowest element in list is smaller than allowed.', 1291470084);
202  }
203  if (end($fieldList) > $upperBound) {
204  throw new \InvalidArgumentException('An element in the list is higher than allowed.', 1291470170);
205  }
206  $fieldValues = implode(',', $fieldList);
207  }
208  return (string)$fieldValues;
209  }
210 
218  protected static function ‪convertRangeToListOfValues($range)
219  {
220  if ((string)$range === '') {
221  throw new \InvalidArgumentException('Unable to convert range to list of values with empty string.', 1291234985);
222  }
223  $rangeArray = explode('-', $range);
224  // Sanitize fields and cast to integer
225  foreach ($rangeArray as $fieldNumber => $fieldValue) {
226  if (!‪MathUtility::canBeInterpretedAsInteger($fieldValue)) {
227  throw new \InvalidArgumentException('Unable to convert value to integer.', 1291237668);
228  }
229  $rangeArray[$fieldNumber] = (int)$fieldValue;
230  }
231 
232  $rangeArrayCount = count($rangeArray);
233  if ($rangeArrayCount === 1) {
234  $resultList = $rangeArray[0];
235  } elseif ($rangeArrayCount === 2) {
236  $left = $rangeArray[0];
237  $right = $rangeArray[1];
238  if ($left > $right) {
239  throw new \InvalidArgumentException('Unable to convert range to list: Left integer must not be greater than right integer.', 1291237145);
240  }
241  $resultListArray = [];
242  for ($i = $left; $i <= $right; $i++) {
243  $resultListArray[] = $i;
244  }
245  $resultList = implode(',', $resultListArray);
246  } else {
247  throw new \InvalidArgumentException('Unable to convert range to list of values.', 1291234986);
248  }
249  return (string)$resultList;
250  }
251 
262  protected static function ‪reduceListOfValuesByStepValue($stepExpression)
263  {
264  if ($stepExpression === '') {
265  throw new \InvalidArgumentException('Unable to convert step values.', 1291234987);
266  }
267  $stepValuesAndStepArray = explode('/', $stepExpression);
268  $stepValuesAndStepArrayCount = count($stepValuesAndStepArray);
269  if ($stepValuesAndStepArrayCount < 1 || $stepValuesAndStepArrayCount > 2) {
270  throw new \InvalidArgumentException('Unable to convert step values: Multiple slashes found.', 1291242168);
271  }
272  $left = $stepValuesAndStepArray[0] ?? '';
273  $right = $stepValuesAndStepArray[1] ?? '';
274  if ($left === '') {
275  throw new \InvalidArgumentException('Unable to convert step values: Left part of / is empty.', 1291414955);
276  }
277  if ($right === '') {
278  throw new \InvalidArgumentException('Unable to convert step values: Right part of / is empty.', 1291414956);
279  }
281  throw new \InvalidArgumentException('Unable to convert step values: Right part must be a single integer.', 1291414957);
282  }
283  $right = (int)$right;
284  $leftArray = explode(',', $left);
285  $validValues = [];
286  $currentStep = $right;
287  foreach ($leftArray as $leftValue) {
289  throw new \InvalidArgumentException('Unable to convert step values: Left part must be a single integer or comma separated list of integers.', 1291414958);
290  }
291  if ($currentStep === 0) {
292  $currentStep = $right;
293  }
294  if ($currentStep === $right) {
295  $validValues[] = (int)$leftValue;
296  }
297  $currentStep--;
298  }
299  if (empty($validValues)) {
300  throw new \InvalidArgumentException('Unable to convert step values: Result value list is empty.', 1291414959);
301  }
302  return implode(',', $validValues);
303  }
304 
312  protected static function ‪normalizeMonthAndWeekday($expression, $isMonth = true)
313  {
314  $expression = $isMonth ? ‪self::normalizeMonth($expression) : ‪self::normalizeWeekday($expression);
315  return (string)$expression;
316  }
317 
326  protected static function ‪normalizeMonth($month)
327  {
328  $timestamp = strtotime('2010-' . $month . '-01');
329  // timestamp must be >= 2010-01-01 and <= 2010-12-01
330  if (!$timestamp || $timestamp < strtotime('2010-01-01') || $timestamp > strtotime('2010-12-01')) {
331  throw new \InvalidArgumentException('Unable to convert given month name.', 1291083486);
332  }
333  return (int)date('n', $timestamp);
334  }
335 
344  protected static function ‪normalizeWeekday($weekday)
345  {
346  $normalizedWeekday = false;
347  // 0 (sunday) -> 7
348  if ((string)$weekday === '0') {
349  $weekday = 7;
350  }
351  if ($weekday >= 1 && $weekday <= 7) {
352  $normalizedWeekday = (int)$weekday;
353  }
354  if (!$normalizedWeekday) {
355  // Convert string representation like 'sun' to integer
356  $timestamp = strtotime('next ' . $weekday, mktime(0, 0, 0, 1, 1, 2010));
357  if (!$timestamp || $timestamp < strtotime('2010-01-01') || $timestamp > strtotime('2010-01-08')) {
358  throw new \InvalidArgumentException('Unable to convert given weekday name.', 1291163589);
359  }
360  $normalizedWeekday = (int)date('N', $timestamp);
361  }
362  return $normalizedWeekday;
363  }
364 }
‪TYPO3\CMS\Scheduler\CronCommand\NormalizeCommand\normalizeMonth
‪static int normalizeMonth($month)
Definition: NormalizeCommand.php:326
‪TYPO3\CMS\Scheduler\CronCommand\NormalizeCommand\normalize
‪static string normalize($cronCommand)
Definition: NormalizeCommand.php:39
‪TYPO3\CMS\Scheduler\CronCommand\NormalizeCommand\reduceListOfValuesByStepValue
‪static string reduceListOfValuesByStepValue($stepExpression)
Definition: NormalizeCommand.php:262
‪TYPO3\CMS\Core\Utility\MathUtility\canBeInterpretedAsInteger
‪static bool canBeInterpretedAsInteger($var)
Definition: MathUtility.php:73
‪TYPO3\CMS\Scheduler\CronCommand\NormalizeCommand
Definition: NormalizeCommand.php:27
‪TYPO3\CMS\Scheduler\CronCommand\NormalizeCommand\normalizeMonthAndWeekdayField
‪static string normalizeMonthAndWeekdayField($expression, $isMonthField=true)
Definition: NormalizeCommand.php:120
‪TYPO3\CMS\Scheduler\CronCommand\NormalizeCommand\convertRangeToListOfValues
‪static string convertRangeToListOfValues($range)
Definition: NormalizeCommand.php:218
‪TYPO3\CMS\Scheduler\CronCommand\NormalizeCommand\normalizeIntegerField
‪static string normalizeIntegerField($expression, $lowerBound=0, $upperBound=59)
Definition: NormalizeCommand.php:165
‪TYPO3\CMS\Scheduler\CronCommand\NormalizeCommand\normalizeFields
‪static string normalizeFields($cronCommand)
Definition: NormalizeCommand.php:85
‪$fields
‪$fields
Definition: pages.php:4
‪TYPO3\CMS\Scheduler\CronCommand\NormalizeCommand\normalizeMonthAndWeekday
‪static string normalizeMonthAndWeekday($expression, $isMonth=true)
Definition: NormalizeCommand.php:312
‪TYPO3\CMS\Scheduler\CronCommand
Definition: CronCommand.php:2
‪TYPO3\CMS\Scheduler\CronCommand\NormalizeCommand\splitFields
‪static array splitFields($cronCommand)
Definition: NormalizeCommand.php:104
‪TYPO3\CMS\Scheduler\CronCommand\NormalizeCommand\normalizeWeekday
‪static int normalizeWeekday($weekday)
Definition: NormalizeCommand.php:344
‪TYPO3\CMS\Core\Utility\MathUtility
Definition: MathUtility.php:21
‪TYPO3\CMS\Scheduler\CronCommand\NormalizeCommand\convertKeywordsToCronCommand
‪static string convertKeywordsToCronCommand($cronCommand)
Definition: NormalizeCommand.php:54