[BUGFIX] Catch __PHP_Incomplete_Class classes
[Packages/TYPO3.CMS.git] / typo3 / sysext / scheduler / Classes / Execution.php
1 <?php
2 namespace TYPO3\CMS\Scheduler;
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
17 /**
18 * This class manages the logic of a particular execution of a task
19 */
20 class Execution
21 {
22 /**
23 * Start date of a task (timestamp)
24 *
25 * @var int
26 */
27 protected $start;
28
29 /**
30 * End date of a task (timestamp)
31 *
32 * @var int
33 */
34 protected $end;
35
36 /**
37 * Interval between executions (in seconds)
38 *
39 * @var int
40 */
41 protected $interval;
42
43 /**
44 * Flag for concurrent executions: TRUE if allowed, FALSE otherwise (default)
45 *
46 * @var bool
47 */
48 protected $multiple = false;
49
50 /**
51 * The cron command string of this task,
52 *
53 * @var string
54 */
55 protected $cronCmd;
56
57 /**
58 * This flag is used to mark a new single execution
59 * See explanations in method setIsNewSingleExecution()
60 *
61 * @var bool
62 * @see \TYPO3\CMS\Scheduler\Execution::setIsNewSingleExecution()
63 */
64 protected $isNewSingleExecution = false;
65
66 /**********************************
67 * Setters and getters
68 **********************************/
69 /**
70 * This method is used to set the start date
71 *
72 * @param int $start Start date (timestamp)
73 */
74 public function setStart($start)
75 {
76 $this->start = $start;
77 }
78
79 /**
80 * This method is used to get the start date
81 *
82 * @return int Start date (timestamp)
83 */
84 public function getStart()
85 {
86 return $this->start;
87 }
88
89 /**
90 * This method is used to set the end date
91 *
92 * @param int $end End date (timestamp)
93 */
94 public function setEnd($end)
95 {
96 $this->end = $end;
97 }
98
99 /**
100 * This method is used to get the end date
101 *
102 * @return int End date (timestamp)
103 */
104 public function getEnd()
105 {
106 return $this->end;
107 }
108
109 /**
110 * This method is used to set the interval
111 *
112 * @param int $interval Interval (in seconds)
113 */
114 public function setInterval($interval)
115 {
116 $this->interval = $interval;
117 }
118
119 /**
120 * This method is used to get the interval
121 *
122 * @return int Interval (in seconds)
123 */
124 public function getInterval()
125 {
126 return $this->interval;
127 }
128
129 /**
130 * This method is used to set the multiple execution flag
131 *
132 * @param bool $multiple TRUE if concurrent executions are allowed, FALSE otherwise
133 */
134 public function setMultiple($multiple)
135 {
136 $this->multiple = $multiple;
137 }
138
139 /**
140 * This method is used to get the multiple execution flag
141 *
142 * @return bool TRUE if concurrent executions are allowed, FALSE otherwise
143 */
144 public function getMultiple()
145 {
146 return $this->multiple;
147 }
148
149 /**
150 * Set the value of the cron command
151 *
152 * @param string $cmd Cron command, using cron-like syntax
153 */
154 public function setCronCmd($cmd)
155 {
156 $this->cronCmd = $cmd;
157 }
158
159 /**
160 * Get the value of the cron command
161 *
162 * @return string Cron command, using cron-like syntax
163 */
164 public function getCronCmd()
165 {
166 return $this->cronCmd;
167 }
168
169 /**
170 * Set whether this is a newly created single execution.
171 * This is necessary for the following reason: if a new single-running task
172 * is created and its start date is in the past (even for only a few seconds),
173 * the next run time calculation (which happens upon saving) will disable
174 * that task, because it was meant to run only once and is in the past.
175 * Setting this flag to TRUE preserves this task for a single run.
176 * Upon next execution, this flag is set to FALSE.
177 *
178 * @param bool $isNewSingleExecution Is newly created single execution?
179 * @see \TYPO3\CMS\Scheduler\Execution::getNextExecution()
180 */
181 public function setIsNewSingleExecution($isNewSingleExecution)
182 {
183 $this->isNewSingleExecution = $isNewSingleExecution;
184 }
185
186 /**
187 * Get whether this is a newly created single execution
188 *
189 * @return bool Is newly created single execution?
190 */
191 public function getIsNewSingleExecution()
192 {
193 return $this->isNewSingleExecution;
194 }
195
196 /**********************************
197 * Execution calculations and logic
198 **********************************/
199 /**
200 * This method gets or calculates the next execution date
201 *
202 * @return int Timestamp of the next execution
203 * @throws \OutOfBoundsException
204 */
205 public function getNextExecution()
206 {
207 if ($this->getIsNewSingleExecution()) {
208 $this->setIsNewSingleExecution(false);
209 return $this->start;
210 }
211 if (!$this->isEnded()) {
212 // If the schedule has not yet run out, find out the next date
213 if (!$this->isStarted()) {
214 // If the schedule hasn't started yet, next date is start date
215 $date = $this->start;
216 } else {
217 // If the schedule has already started, calculate next date
218 if ($this->cronCmd) {
219 // If it uses cron-like syntax, calculate next date
220 $date = $this->getNextCronExecution();
221 } elseif ($this->interval == 0) {
222 // If not and there's no interval either, it's a singe execution: use start date
223 $date = $this->start;
224 } else {
225 // Otherwise calculate date based on interval
226 $now = time();
227 $date = $now + $this->interval - ($now - $this->start) % $this->interval;
228 }
229 // If date is in the future, throw an exception
230 if (!empty($this->end) && $date > $this->end) {
231 throw new \OutOfBoundsException('Next execution date is past end date.', 1250715528);
232 }
233 }
234 } else {
235 // The event has ended, throw an exception
236 throw new \OutOfBoundsException('Task is past end date.', 1250715544);
237 }
238 return $date;
239 }
240
241 /**
242 * Calculates the next execution from a cron command
243 *
244 * @return int Next execution (timestamp)
245 */
246 public function getNextCronExecution()
247 {
248 /** @var $cronCmd \TYPO3\CMS\Scheduler\CronCommand\CronCommand */
249 $cronCmd = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Scheduler\CronCommand\CronCommand::class, $this->getCronCmd());
250 $cronCmd->calculateNextValue();
251 return $cronCmd->getTimestamp();
252 }
253
254 /**
255 * Checks if the schedule for a task is started or not
256 *
257 * @return bool TRUE if the schedule is already active, FALSE otherwise
258 */
259 public function isStarted()
260 {
261 return $this->start < time();
262 }
263
264 /**
265 * Checks if the schedule for a task is passed or not
266 *
267 * @return bool TRUE if the schedule is not active anymore, FALSE otherwise
268 */
269 public function isEnded()
270 {
271 if (empty($this->end)) {
272 // If no end is defined, the schedule never ends
273 $result = false;
274 } else {
275 // Otherwise check if end is in the past
276 $result = $this->end < time();
277 }
278 return $result;
279 }
280 }