TYPO3 CMS  TYPO3_6-2
NormalizeCommand.php
Go to the documentation of this file.
1 <?php
3 
17 
28 
41  static public function normalize($cronCommand) {
42  $cronCommand = trim($cronCommand);
43  $cronCommand = self::convertKeywordsToCronCommand($cronCommand);
44  $cronCommand = self::normalizeFields($cronCommand);
45  return $cronCommand;
46  }
47 
55  static protected function convertKeywordsToCronCommand($cronCommand) {
56  switch ($cronCommand) {
57  case '@yearly':
58 
59  case '@annually':
60  $cronCommand = '0 0 1 1 *';
61  break;
62  case '@monthly':
63  $cronCommand = '0 0 1 * *';
64  break;
65  case '@weekly':
66  $cronCommand = '0 0 * * 0';
67  break;
68  case '@daily':
69 
70  case '@midnight':
71  $cronCommand = '0 0 * * *';
72  break;
73  case '@hourly':
74  $cronCommand = '0 * * * *';
75  break;
76  }
77  return $cronCommand;
78  }
79 
86  static protected function normalizeFields($cronCommand) {
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  static protected function splitFields($cronCommand) {
105  $fields = explode(' ', $cronCommand);
106  if (count($fields) !== 5) {
107  throw new \InvalidArgumentException('Unable to split given cron command to five fields.', 1291227373);
108  }
109  return $fields;
110  }
111 
119  static protected function normalizeMonthAndWeekdayField($expression, $isMonthField = TRUE) {
120  if ((string) $expression === '*') {
121  $fieldValues = '*';
122  } else {
123  // Fragment expression by , / and - and substitute three letter code of month and weekday to numbers
124  $listOfCommaValues = explode(',', $expression);
125  $fieldArray = array();
126  foreach ($listOfCommaValues as $listElement) {
127  if (strpos($listElement, '/') !== FALSE) {
128  list($left, $right) = explode('/', $listElement);
129  if (strpos($left, '-') !== FALSE) {
130  list($leftBound, $rightBound) = explode('-', $left);
131  $leftBound = self::normalizeMonthAndWeekday($leftBound, $isMonthField);
132  $rightBound = self::normalizeMonthAndWeekday($rightBound, $isMonthField);
133  $left = $leftBound . '-' . $rightBound;
134  } else {
135  if ((string) $left !== '*') {
136  $left = self::normalizeMonthAndWeekday($left, $isMonthField);
137  }
138  }
139  $fieldArray[] = $left . '/' . $right;
140  } elseif (strpos($listElement, '-') !== FALSE) {
141  list($left, $right) = explode('-', $listElement);
142  $left = self::normalizeMonthAndWeekday($left, $isMonthField);
143  $right = self::normalizeMonthAndWeekday($right, $isMonthField);
144  $fieldArray[] = $left . '-' . $right;
145  } else {
146  $fieldArray[] = self::normalizeMonthAndWeekday($listElement, $isMonthField);
147  }
148  }
149  $fieldValues = implode(',', $fieldArray);
150  }
151  return $isMonthField ? self::normalizeIntegerField($fieldValues, 1, 12) : self::normalizeIntegerField($fieldValues, 1, 7);
152  }
153 
163  static protected function normalizeIntegerField($expression, $lowerBound = 0, $upperBound = 59) {
164  if ((string) $expression === '*') {
165  $fieldValues = '*';
166  } else {
167  $listOfCommaValues = explode(',', $expression);
168  $fieldArray = array();
169  foreach ($listOfCommaValues as $listElement) {
170  if (strpos($listElement, '/') !== FALSE) {
171  list($left, $right) = explode('/', $listElement);
172  if ((string) $left === '*') {
173  $leftList = self::convertRangeToListOfValues($lowerBound . '-' . $upperBound);
174  } else {
175  $leftList = self::convertRangeToListOfValues($left);
176  }
177  $fieldArray[] = self::reduceListOfValuesByStepValue($leftList . '/' . $right);
178  } elseif (strpos($listElement, '-') !== FALSE) {
179  $fieldArray[] = self::convertRangeToListOfValues($listElement);
180  } elseif (MathUtility::canBeInterpretedAsInteger($listElement)) {
181  $fieldArray[] = $listElement;
182  } else {
183  throw new \InvalidArgumentException('Unable to normalize integer field.', 1291429389);
184  }
185  }
186  $fieldValues = implode(',', $fieldArray);
187  }
188  if (strlen($fieldValues) === 0) {
189  throw new \InvalidArgumentException('Unable to convert integer field to list of values: Result list empty.', 1291422012);
190  }
191  if ((string) $fieldValues !== '*') {
192  $fieldList = explode(',', $fieldValues);
193  sort($fieldList);
194  $fieldList = array_unique($fieldList);
195  if (current($fieldList) < $lowerBound) {
196  throw new \InvalidArgumentException('Lowest element in list is smaller than allowed.', 1291470084);
197  }
198  if (end($fieldList) > $upperBound) {
199  throw new \InvalidArgumentException('An element in the list is higher than allowed.', 1291470170);
200  }
201  $fieldValues = implode(',', $fieldList);
202  }
203  return (string) $fieldValues;
204  }
205 
213  static protected function convertRangeToListOfValues($range) {
214  if (strlen($range) === 0) {
215  throw new \InvalidArgumentException('Unable to convert range to list of values with empty string.', 1291234985);
216  }
217  $rangeArray = explode('-', $range);
218  // Sanitize fields and cast to integer
219  foreach ($rangeArray as $fieldNumber => $fieldValue) {
220  if (!MathUtility::canBeInterpretedAsInteger($fieldValue)) {
221  throw new \InvalidArgumentException('Unable to convert value to integer.', 1291237668);
222  }
223  $rangeArray[$fieldNumber] = (int)$fieldValue;
224  }
225  $resultList = '';
226  if (count($rangeArray) === 1) {
227  $resultList = $rangeArray[0];
228  } elseif (count($rangeArray) === 2) {
229  $left = $rangeArray[0];
230  $right = $rangeArray[1];
231  if ($left > $right) {
232  throw new \InvalidArgumentException('Unable to convert range to list: Left integer must not be greater than right integer.', 1291237145);
233  }
234  $resultListArray = array();
235  for ($i = $left; $i <= $right; $i++) {
236  $resultListArray[] = $i;
237  }
238  $resultList = implode(',', $resultListArray);
239  } else {
240  throw new \InvalidArgumentException('Unable to convert range to list of values.', 1291234986);
241  }
242  return (string) $resultList;
243  }
244 
255  static protected function reduceListOfValuesByStepValue($stepExpression) {
256  if (strlen($stepExpression) === 0) {
257  throw new \InvalidArgumentException('Unable to convert step values.', 1291234987);
258  }
259  $stepValuesAndStepArray = explode('/', $stepExpression);
260  if (count($stepValuesAndStepArray) < 1 || count($stepValuesAndStepArray) > 2) {
261  throw new \InvalidArgumentException('Unable to convert step values: Multiple slashes found.', 1291242168);
262  }
263  $left = $stepValuesAndStepArray[0];
264  $right = $stepValuesAndStepArray[1];
265  if (strlen($stepValuesAndStepArray[0]) === 0) {
266  throw new \InvalidArgumentException('Unable to convert step values: Left part of / is empty.', 1291414955);
267  }
268  if (strlen($stepValuesAndStepArray[1]) === 0) {
269  throw new \InvalidArgumentException('Unable to convert step values: Right part of / is empty.', 1291414956);
270  }
272  throw new \InvalidArgumentException('Unable to convert step values: Right part must be a single integer.', 1291414957);
273  }
274  $right = (int)$right;
275  $leftArray = explode(',', $left);
276  $validValues = array();
277  $currentStep = $right;
278  foreach ($leftArray as $leftValue) {
279  if (!MathUtility::canBeInterpretedAsInteger($leftValue)) {
280  throw new \InvalidArgumentException('Unable to convert step values: Left part must be a single integer or comma separated list of integers.', 1291414958);
281  }
282  if ($currentStep === 0) {
283  $currentStep = $right;
284  }
285  if ($currentStep === $right) {
286  $validValues[] = (int)$leftValue;
287  }
288  $currentStep--;
289  }
290  if (count($validValues) === 0) {
291  throw new \InvalidArgumentException('Unable to convert step values: Result value list is empty.', 1291414959);
292  }
293  return implode(',', $validValues);
294  }
295 
303  static protected function normalizeMonthAndWeekday($expression, $isMonth = TRUE) {
304  $expression = $isMonth ? self::normalizeMonth($expression) : self::normalizeWeekday($expression);
305  return (string) $expression;
306  }
307 
316  static protected function normalizeMonth($month) {
317  $timestamp = strtotime('2010-' . $month . '-01');
318  // timestamp must be >= 2010-01-01 and <= 2010-12-01
319  if (!$timestamp || $timestamp < strtotime('2010-01-01') || $timestamp > strtotime('2010-12-01')) {
320  throw new \InvalidArgumentException('Unable to convert given month name.', 1291083486);
321  }
322  return (int)date('n', $timestamp);
323  }
324 
333  static protected function normalizeWeekday($weekday) {
334  $normalizedWeekday = FALSE;
335  // 0 (sunday) -> 7
336  if ((string) $weekday === '0') {
337  $weekday = 7;
338  }
339  if ($weekday >= 1 && $weekday <= 7) {
340  $normalizedWeekday = (int)$weekday;
341  }
342  if (!$normalizedWeekday) {
343  // Convert string representation like 'sun' to integer
344  $timestamp = strtotime('next ' . $weekday, mktime(0, 0, 0, 1, 1, 2010));
345  if (!$timestamp || $timestamp < strtotime('2010-01-01') || $timestamp > strtotime('2010-01-08')) {
346  throw new \InvalidArgumentException('Unable to convert given weekday name.', 1291163589);
347  }
348  $normalizedWeekday = (int)date('N', $timestamp);
349  }
350  return $normalizedWeekday;
351  }
352 
353 }
static normalizeIntegerField($expression, $lowerBound=0, $upperBound=59)
static normalizeMonthAndWeekdayField($expression, $isMonthField=TRUE)
static normalizeMonthAndWeekday($expression, $isMonth=TRUE)