‪TYPO3CMS  9.5
CronCommand.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 
21 {
36  protected ‪$cronCommandSections;
37 
44  protected ‪$timestamp;
45 
52  public function ‪__construct($cronCommand, ‪$timestamp = false)
53  {
54  $cronCommand = ‪NormalizeCommand::normalize($cronCommand);
55  // Explode cron command to sections
56  $this->cronCommandSections = \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(' ', $cronCommand);
57  // Initialize the values with the starting time
58  // This takes care that the calculated time is always in the future
59  if (‪$timestamp === false) {
60  ‪$timestamp = strtotime('+1 minute');
61  } else {
62  ‪$timestamp += 60;
63  }
64  $this->timestamp = $this->‪roundTimestamp(‪$timestamp);
65  }
66 
72  public function ‪calculateNextValue()
73  {
74  $newTimestamp = $this->‪getTimestamp();
75  // Calculate next minute and hour field
76  $loopCount = 0;
77  while (true) {
78  $loopCount++;
79  // If there was no match within two days, cron command is invalid.
80  // The second day is needed to catch the summertime leap in some countries.
81  if ($loopCount > 2880) {
82  throw new \RuntimeException('Unable to determine next execution timestamp: Hour and minute combination is invalid.', 1291494126);
83  }
84  if ($this->‪minuteAndHourMatchesCronCommand($newTimestamp)) {
85  break;
86  }
87  $newTimestamp += 60;
88  }
89  $loopCount = 0;
90  while (true) {
91  $loopCount++;
92  // A date must match within the next 4 years, this high number makes
93  // sure leap year cron command configuration are caught.
94  // If the loop runs longer than that, the cron command is invalid.
95  if ($loopCount > 1464) {
96  throw new \RuntimeException('Unable to determine next execution timestamp: Day of month, month and day of week combination is invalid.', 1291501280);
97  }
98  if ($this->‪dayMatchesCronCommand($newTimestamp)) {
99  break;
100  }
101  $newTimestamp += $this->‪numberOfSecondsInDay($newTimestamp);
102  }
103  $this->timestamp = $newTimestamp;
104  }
105 
111  public function ‪getTimestamp()
112  {
113  return ‪$this->timestamp;
114  }
115 
123  public function ‪getCronCommandSections()
124  {
126  }
127 
135  {
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  {
154  $dayOfMonth = date('j', ‪$timestamp);
155  $month = date('n', ‪$timestamp);
156  $dayOfWeek = date('N', ‪$timestamp);
157  $isInDayOfMonth = $this->‪isInCommandList($this->cronCommandSections[2], $dayOfMonth);
158  $isInMonth = $this->‪isInCommandList($this->cronCommandSections[3], $month);
159  $isInDayOfWeek = $this->‪isInCommandList($this->cronCommandSections[4], $dayOfWeek);
160  // Quote from vixiecron:
161  // Note: The day of a command's execution can be specified by two fields — day of month, and day of week.
162  // If both fields are restricted (i.e., aren't *), the command will be run when either field
163  // matches the current time. For example, `30 4 1,15 * 5' would cause
164  // a command to be run at 4:30 am on the 1st and 15th of each month, plus every Friday.
165  $isDayOfMonthRestricted = (string)$this->cronCommandSections[2] !== '*';
166  $isDayOfWeekRestricted = (string)$this->cronCommandSections[4] !== '*';
167  $commandMatch = false;
168  if ($isInMonth) {
169  if ($isInDayOfMonth && $isDayOfMonthRestricted || $isInDayOfWeek && $isDayOfWeekRestricted || $isInDayOfMonth && !$isDayOfMonthRestricted && $isInDayOfWeek && !$isDayOfWeekRestricted) {
170  $commandMatch = true;
171  }
172  }
173  return $commandMatch;
174  }
175 
184  protected function ‪isInCommandList($commandExpression, $numberToMatch)
185  {
186  if ((string)$commandExpression === '*') {
187  $inList = true;
188  } else {
189  $inList = \TYPO3\CMS\Core\Utility\GeneralUtility::inList($commandExpression, $numberToMatch);
190  }
191  return $inList;
192  }
193 
206  protected function ‪numberOfSecondsInDay(‪$timestamp)
207  {
208  $now = mktime(0, 0, 0, date('n', ‪$timestamp), date('j', ‪$timestamp), date('Y', ‪$timestamp));
209  // Make sure to be in next day, even if day has 25 hours
210  $nextDay = $now + 60 * 60 * 25;
211  $nextDay = mktime(0, 0, 0, date('n', $nextDay), date('j', $nextDay), date('Y', $nextDay));
212  return $nextDay - $now;
213  }
214 
221  protected function ‪roundTimestamp(‪$timestamp)
222  {
223  return mktime(date('H', ‪$timestamp), date('i', ‪$timestamp), 0, date('n', ‪$timestamp), date('j', ‪$timestamp), date('Y', ‪$timestamp));
224  }
225 }
‪TYPO3\CMS\Scheduler\CronCommand\NormalizeCommand\normalize
‪static string normalize($cronCommand)
Definition: NormalizeCommand.php:39
‪TYPO3\CMS\Scheduler\CronCommand\CronCommand\$cronCommandSections
‪array $cronCommandSections
Definition: CronCommand.php:35
‪TYPO3\CMS\Scheduler\CronCommand\CronCommand\isInCommandList
‪bool isInCommandList($commandExpression, $numberToMatch)
Definition: CronCommand.php:183
‪TYPO3\CMS\Scheduler\CronCommand\CronCommand\minuteAndHourMatchesCronCommand
‪bool minuteAndHourMatchesCronCommand($timestamp)
Definition: CronCommand.php:133
‪TYPO3\CMS\Scheduler\CronCommand\CronCommand\calculateNextValue
‪calculateNextValue()
Definition: CronCommand.php:71
‪TYPO3\CMS\Scheduler\CronCommand\CronCommand\getTimestamp
‪int getTimestamp()
Definition: CronCommand.php:110
‪TYPO3\CMS\Scheduler\CronCommand\CronCommand\dayMatchesCronCommand
‪bool dayMatchesCronCommand($timestamp)
Definition: CronCommand.php:151
‪TYPO3\CMS\Scheduler\CronCommand
Definition: CronCommand.php:2
‪TYPO3\CMS\Scheduler\CronCommand\CronCommand\numberOfSecondsInDay
‪int numberOfSecondsInDay($timestamp)
Definition: CronCommand.php:205
‪TYPO3\CMS\Scheduler\CronCommand\CronCommand
Definition: CronCommand.php:21
‪TYPO3\CMS\Scheduler\CronCommand\CronCommand\$timestamp
‪$timestamp
Definition: CronCommand.php:43
‪TYPO3\CMS\Scheduler\CronCommand\CronCommand\__construct
‪__construct($cronCommand, $timestamp=false)
Definition: CronCommand.php:51
‪TYPO3\CMS\Scheduler\CronCommand\CronCommand\roundTimestamp
‪int roundTimestamp($timestamp)
Definition: CronCommand.php:220
‪TYPO3\CMS\Scheduler\CronCommand\CronCommand\getCronCommandSections
‪array getCronCommandSections()
Definition: CronCommand.php:122