TYPO3 CMS  TYPO3_6-2
CronCommand.php
Go to the documentation of this file.
1 <?php
3 
22 class CronCommand {
23 
39 
46  protected $timestamp;
47 
56  public function __construct($cronCommand, $timestamp = FALSE) {
58  // Explode cron command to sections
59  $this->cronCommandSections = \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(' ', $cronCommand);
60  // Initialize the values with the starting time
61  // This takes care that the calculated time is always in the future
62  if ($timestamp === FALSE) {
63  $timestamp = strtotime('+1 minute');
64  } else {
65  $timestamp += 60;
66  }
67  $this->timestamp = $this->roundTimestamp($timestamp);
68  }
69 
76  public function calculateNextValue() {
77  $newTimestamp = $this->getTimestamp();
78  // Calculate next minute and hour field
79  $loopCount = 0;
80  while (TRUE) {
81  $loopCount++;
82  // If there was no match within two days, cron command is invalid.
83  // The second day is needed to catch the summertime leap in some countries.
84  if ($loopCount > 2880) {
85  throw new \RuntimeException('Unable to determine next execution timestamp: Hour and minute combination is invalid.', 1291494126);
86  }
87  if ($this->minuteAndHourMatchesCronCommand($newTimestamp)) {
88  break;
89  }
90  $newTimestamp += 60;
91  }
92  $loopCount = 0;
93  while (TRUE) {
94  $loopCount++;
95  // A date must match within the next 4 years, this high number makes
96  // sure leap year cron command configuration are caught.
97  // If the loop runs longer than that, the cron command is invalid.
98  if ($loopCount > 1464) {
99  throw new \RuntimeException('Unable to determine next execution timestamp: Day of month, month and day of week combination is invalid.', 1291501280);
100  }
101  if ($this->dayMatchesCronCommand($newTimestamp)) {
102  break;
103  }
104  $newTimestamp += $this->numberOfSecondsInDay($newTimestamp);
105  }
106  $this->timestamp = $newTimestamp;
107  }
108 
109  /*
110  * Get next timestamp
111  *
112  * @api
113  * @return integer Unix timestamp
114  */
115  public function getTimestamp() {
116  return $this->timestamp;
117  }
118 
125  public function getCronCommandSections() {
127  }
128 
136  $minute = (int)date('i', $timestamp);
137  $hour = (int)date('G', $timestamp);
138  $commandMatch = FALSE;
139  if ($this->isInCommandList($this->cronCommandSections[0], $minute) && $this->isInCommandList($this->cronCommandSections[1], $hour)) {
140  $commandMatch = TRUE;
141  }
142  return $commandMatch;
143  }
144 
152  protected function dayMatchesCronCommand($timestamp) {
153  $dayOfMonth = date('j', $timestamp);
154  $month = date('n', $timestamp);
155  $dayOfWeek = date('N', $timestamp);
156  $isInDayOfMonth = $this->isInCommandList($this->cronCommandSections[2], $dayOfMonth);
157  $isInMonth = $this->isInCommandList($this->cronCommandSections[3], $month);
158  $isInDayOfWeek = $this->isInCommandList($this->cronCommandSections[4], $dayOfWeek);
159  // Quote from vixiecron:
160  // Note: The day of a command's execution can be specified by two fields — day of month, and day of week.
161  // If both fields are restricted (i.e., aren't *), the command will be run when either field
162  // matches the current time. For example, `30 4 1,15 * 5' would cause
163  // a command to be run at 4:30 am on the 1st and 15th of each month, plus every Friday.
164  $isDayOfMonthRestricted = (string)$this->cronCommandSections[2] !== '*';
165  $isDayOfWeekRestricted = (string)$this->cronCommandSections[4] !== '*';
166  $commandMatch = FALSE;
167  if ($isInMonth) {
168  if ($isInDayOfMonth && $isDayOfMonthRestricted || $isInDayOfWeek && $isDayOfWeekRestricted || $isInDayOfMonth && !$isDayOfMonthRestricted && $isInDayOfWeek && !$isDayOfWeekRestricted) {
169  $commandMatch = TRUE;
170  }
171  }
172  return $commandMatch;
173  }
174 
183  protected function isInCommandList($commandExpression, $numberToMatch) {
184  $inList = FALSE;
185  if ((string) $commandExpression === '*') {
186  $inList = TRUE;
187  } else {
188  $inList = \TYPO3\CMS\Core\Utility\GeneralUtility::inList($commandExpression, $numberToMatch);
189  }
190  return $inList;
191  }
192 
205  protected function numberOfSecondsInDay($timestamp) {
206  $now = mktime(0, 0, 0, date('n', $timestamp), date('j', $timestamp), date('Y', $timestamp));
207  // Make sure to be in next day, even if day has 25 hours
208  $nextDay = $now + 60 * 60 * 25;
209  $nextDay = mktime(0, 0, 0, date('n', $nextDay), date('j', $nextDay), date('Y', $nextDay));
210  return $nextDay - $now;
211  }
212 
219  protected function roundTimestamp($timestamp) {
220  return mktime(date('H', $timestamp), date('i', $timestamp), 0, date('n', $timestamp), date('j', $timestamp), date('Y', $timestamp));
221  }
222 
223 }
isInCommandList($commandExpression, $numberToMatch)
static trimExplode($delim, $string, $removeEmptyValues=FALSE, $limit=0)
__construct($cronCommand, $timestamp=FALSE)
Definition: CronCommand.php:56