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