TYPO3CMS  8
 All Classes Namespaces Files Functions Variables Pages
scheduler/Classes/Task/AbstractTask.php
Go to the documentation of this file.
1 <?php
2 namespace TYPO3\CMS\Scheduler\Task;
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 
19 
25 abstract class AbstractTask
26 {
27  const TYPE_SINGLE = 1;
28  const TYPE_RECURRING = 2;
29 
35  protected $scheduler;
36 
42  protected $taskUid;
43 
49  protected $disabled = false;
50 
56  protected $execution;
57 
63  protected $executionTime = 0;
64 
70  protected $description = '';
71 
77  protected $taskGroup;
78 
82  public function __construct()
83  {
84  $this->setScheduler();
85  $this->execution = GeneralUtility::makeInstance(\TYPO3\CMS\Scheduler\Execution::class);
86  }
87 
97  abstract public function execute();
98 
107  public function getAdditionalInformation()
108  {
109  return '';
110  }
111 
118  public function setTaskUid($id)
119  {
120  $this->taskUid = (int)$id;
121  }
122 
128  public function getTaskUid()
129  {
130  return $this->taskUid;
131  }
132 
138  public function getTaskTitle()
139  {
140  return $GLOBALS['LANG']->sL($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['scheduler']['tasks'][get_class($this)]['title']);
141  }
142 
148  public function getTaskDescription()
149  {
150  return $GLOBALS['LANG']->sL($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['scheduler']['tasks'][get_class($this)]['description']);
151  }
152 
158  public function getTaskClassName()
159  {
160  return get_class($this);
161  }
162 
168  public function isDisabled()
169  {
170  return $this->disabled;
171  }
172 
179  public function setDisabled($flag)
180  {
181  if ($flag) {
182  $this->disabled = true;
183  } else {
184  $this->disabled = false;
185  }
186  }
187 
194  public function setExecutionTime($timestamp)
195  {
196  $this->executionTime = (int)$timestamp;
197  }
198 
204  public function getTaskGroup()
205  {
206  return $this->taskGroup;
207  }
208 
215  public function setTaskGroup($taskGroup)
216  {
217  $this->taskGroup = (int)$taskGroup;
218  }
219 
225  public function getExecutionTime()
226  {
227  return $this->executionTime;
228  }
229 
236  public function setDescription($description)
237  {
238  $this->description = $description;
239  }
240 
246  public function getDescription()
247  {
248  return $this->description;
249  }
250 
256  public function setScheduler()
257  {
258  $this->scheduler = GeneralUtility::makeInstance(\TYPO3\CMS\Scheduler\Scheduler::class);
259  }
260 
268  public function unsetScheduler()
269  {
270  unset($this->scheduler);
271  }
272 
278  public function registerSingleExecution($timestamp)
279  {
281  $execution = GeneralUtility::makeInstance(\TYPO3\CMS\Scheduler\Execution::class);
282  $execution->setStart($timestamp);
283  $execution->setInterval(0);
284  $execution->setEnd($timestamp);
285  $execution->setCronCmd('');
286  $execution->setMultiple(0);
287  $execution->setIsNewSingleExecution(true);
288  // Replace existing execution object
289  $this->execution = $execution;
290  }
291 
302  public function registerRecurringExecution($start, $interval, $end = 0, $multiple = false, $cron_cmd = '')
303  {
305  $execution = GeneralUtility::makeInstance(\TYPO3\CMS\Scheduler\Execution::class);
306  // Set general values
307  $execution->setStart($start);
308  $execution->setEnd($end);
309  $execution->setMultiple($multiple);
310  if (empty($cron_cmd)) {
311  // Use interval
312  $execution->setInterval($interval);
313  $execution->setCronCmd('');
314  } else {
315  // Use cron syntax
316  $execution->setInterval(0);
317  $execution->setCronCmd($cron_cmd);
318  }
319  // Replace existing execution object
320  $this->execution = $execution;
321  }
322 
328  public function setExecution(\TYPO3\CMS\Scheduler\Execution $execution)
329  {
330  $this->execution = $execution;
331  }
332 
338  public function getExecution()
339  {
340  return $this->execution;
341  }
342 
348  public function getNextDueExecution()
349  {
350  // NOTE: this call may throw an exception, but we let it bubble up
351  return $this->execution->getNextExecution();
352  }
353 
360  {
361  return $this->execution->getMultiple();
362  }
363 
369  public function isExecutionRunning()
370  {
371  $isRunning = false;
372  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
373  ->getQueryBuilderForTable('tx_scheduler_task');
374  $row = $queryBuilder
375  ->select('serialized_executions')
376  ->from('tx_scheduler_task')
377  ->where(
378  $queryBuilder->expr()->eq('uid', $queryBuilder->createNamedParameter($this->taskUid, \PDO::PARAM_INT))
379  )
380  ->execute()
381  ->fetch();
382 
383  if ($row && !empty($row['serialized_executions'])) {
384  $isRunning = true;
385  }
386  return $isRunning;
387  }
388 
395  public function markExecution()
396  {
397  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
398  ->getQueryBuilderForTable('tx_scheduler_task');
399 
400  $row = $queryBuilder
401  ->select('serialized_executions')
402  ->from('tx_scheduler_task')
403  ->where(
404  $queryBuilder->expr()->eq('uid', $queryBuilder->createNamedParameter($this->taskUid, \PDO::PARAM_INT))
405  )
406  ->execute()
407  ->fetch();
408 
409  $runningExecutions = [];
410  if ($row && $row['serialized_executions'] !== '') {
411  $runningExecutions = unserialize($row['serialized_executions']);
412  }
413  // Count the number of existing executions and use that number as a key
414  // (we need to know that number, because it is returned at the end of the method)
415  $numExecutions = count($runningExecutions);
416  $runningExecutions[$numExecutions] = time();
417  // Define the context in which the script is running
418  $context = 'BE';
419  if (TYPO3_REQUESTTYPE & TYPO3_REQUESTTYPE_CLI) {
420  $context = 'CLI';
421  }
422  GeneralUtility::makeInstance(ConnectionPool::class)
423  ->getConnectionForTable('tx_scheduler_task')
424  ->update(
425  'tx_scheduler_task',
426  [
427  'serialized_executions' => serialize($runningExecutions),
428  'lastexecution_time' => time(),
429  'lastexecution_context' => $context
430  ],
431  [
432  'uid' => $this->taskUid
433  ]
434  );
435  return $numExecutions;
436  }
437 
445  public function unmarkExecution($executionID, \Exception $failure = null)
446  {
447  // Get the executions for the task
448  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
449  ->getQueryBuilderForTable('tx_scheduler_task');
450 
451  $row = $queryBuilder
452  ->select('serialized_executions')
453  ->from('tx_scheduler_task')
454  ->where(
455  $queryBuilder->expr()->eq('uid', $queryBuilder->createNamedParameter($this->taskUid, \PDO::PARAM_INT))
456  )
457  ->execute()
458  ->fetch();
459 
460  if ($row && $row['serialized_executions'] !== '') {
461  $runningExecutions = unserialize($row['serialized_executions']);
462  // Remove the selected execution
463  unset($runningExecutions[$executionID]);
464  if (!empty($runningExecutions)) {
465  // Re-serialize the updated executions list (if necessary)
466  $runningExecutionsSerialized = serialize($runningExecutions);
467  } else {
468  $runningExecutionsSerialized = '';
469  }
470  if ($failure instanceof \Exception) {
471  // Log failed execution
472  $logMessage = 'Task failed to execute successfully. Class: ' . get_class($this) . ', UID: ' . $this->taskUid . '. ' . $failure->getMessage();
473  $this->scheduler->log($logMessage, 1, $failure->getCode());
474  // Do not serialize the complete exception or the trace, this can lead to huge strings > 50MB
475  $failureString = serialize([
476  'code' => $failure->getCode(),
477  'message' => $failure->getMessage(),
478  'file' => $failure->getFile(),
479  'line' => $failure->getLine(),
480  'traceString' => $failure->getTraceAsString(),
481  ]);
482  } else {
483  $failureString = '';
484  }
485  // Save the updated executions list
486  GeneralUtility::makeInstance(ConnectionPool::class)
487  ->getConnectionForTable('tx_scheduler_task')
488  ->update(
489  'tx_scheduler_task',
490  [
491  'serialized_executions' => $runningExecutionsSerialized,
492  'lastexecution_failure' => $failureString
493  ],
494  [
495  'uid' => $this->taskUid
496  ]
497  );
498  }
499  }
500 
506  public function unmarkAllExecutions()
507  {
508  // Set the serialized executions field to empty
509  $result = GeneralUtility::makeInstance(ConnectionPool::class)
510  ->getConnectionForTable('tx_scheduler_task')
511  ->update(
512  'tx_scheduler_task',
513  [
514  'serialized_executions' => ''
515  ],
516  [
517  'uid' => $this->taskUid
518  ]
519  );
520  return (bool)$result;
521  }
522 
528  public function save()
529  {
530  return $this->scheduler->saveTask($this);
531  }
532 
539  public function stop()
540  {
541  $this->execution = GeneralUtility::makeInstance(\TYPO3\CMS\Scheduler\Execution::class);
542  }
543 
549  public function remove()
550  {
551  $this->scheduler->removeTask($this);
552  }
553 
560  public function getType()
561  {
562  if (!empty($this->getExecution()->getInterval()) || !empty($this->getExecution()->getCronCmd())) {
563  return self::TYPE_RECURRING;
564  }
565  return self::TYPE_SINGLE;
566  }
567 }
unmarkExecution($executionID,\Exception $failure=null)
setExecution(\TYPO3\CMS\Scheduler\Execution $execution)
if(TYPO3_MODE=== 'BE') $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tsfebeuserauth.php']['frontendEditingController']['default']
static makeInstance($className,...$constructorArguments)