‪TYPO3CMS  10.4
AbstractTask.php
Go to the documentation of this file.
1 <?php
2 
3 /*
4  * This file is part of the TYPO3 CMS project.
5  *
6  * It is free software; you can redistribute it and/or modify it under
7  * the terms of the GNU General Public License, either version 2
8  * of the License, or any later version.
9  *
10  * For the full copyright and license information, please read the
11  * LICENSE.txt file that was distributed with this source code.
12  *
13  * The TYPO3 project - inspiring people to share!
14  */
15 
17 
18 use Psr\Log\LoggerAwareInterface;
19 use Psr\Log\LoggerAwareTrait;
28 
34 abstract class ‪AbstractTask implements LoggerAwareInterface
35 {
36  use LoggerAwareTrait;
37 
38  const ‪TYPE_SINGLE = 1;
39  const ‪TYPE_RECURRING = 2;
40 
46  protected ‪$scheduler;
47 
53  protected ‪$taskUid;
54 
60  protected ‪$disabled = false;
61 
67  protected ‪$runOnNextCronJob = false;
68 
74  protected ‪$execution;
75 
81  protected ‪$executionTime = 0;
82 
88  protected ‪$description = '';
89 
95  protected ‪$taskGroup = 0;
96 
100  public function ‪__construct()
101  {
102  // Using makeInstance instead of setScheduler() here as the logger is injected due to LoggerAwareTrait
103  $this->scheduler = GeneralUtility::makeInstance(Scheduler::class);
104  $this->execution = GeneralUtility::makeInstance(Execution::class);
105  }
106 
116  abstract public function ‪execute();
117 
126  public function ‪getAdditionalInformation()
127  {
128  return '';
129  }
130 
136  public function ‪setTaskUid($id)
137  {
138  $this->taskUid = (int)$id;
139  }
140 
146  public function ‪getTaskUid()
147  {
149  }
150 
156  public function ‪getTaskTitle()
157  {
158  return $this->‪getLanguageService()->‪sL(‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['scheduler']['tasks'][static::class]['title']);
159  }
160 
166  public function ‪getTaskDescription()
167  {
168  return $this->‪getLanguageService()->‪sL(‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['scheduler']['tasks'][static::class]['description']);
169  }
170 
176  public function ‪getTaskClassName()
177  {
178  return static::class;
179  }
180 
186  public function ‪isDisabled()
187  {
189  }
190 
196  public function ‪setDisabled($flag)
197  {
198  if ($flag) {
199  $this->disabled = true;
200  } else {
201  $this->disabled = false;
202  }
203  }
204 
210  public function ‪setRunOnNextCronJob($flag)
211  {
212  $this->runOnNextCronJob = $flag;
213  }
214 
220  public function ‪getRunOnNextCronJob()
221  {
223  }
224 
230  public function ‪setExecutionTime($timestamp)
231  {
232  $this->executionTime = (int)$timestamp;
233  }
234 
240  public function ‪getTaskGroup()
241  {
243  }
244 
250  public function ‪setTaskGroup(‪$taskGroup)
251  {
252  $this->taskGroup = (int)‪$taskGroup;
253  }
254 
260  public function ‪getExecutionTime()
261  {
263  }
264 
270  public function ‪setDescription(‪$description)
271  {
272  $this->description = ‪$description;
273  }
274 
280  public function ‪getDescription()
281  {
282  return ‪$this->description;
283  }
284 
289  public function ‪setScheduler()
290  {
291  $this->scheduler = GeneralUtility::makeInstance(Scheduler::class);
292  $this->logger = GeneralUtility::makeInstance(LogManager::class)->getLogger(__CLASS__);
293  }
294 
301  public function ‪unsetScheduler()
302  {
303  $this->scheduler = null;
304  $this->logger = null;
305  }
306 
312  public function ‪registerSingleExecution($timestamp)
313  {
315  ‪$execution = GeneralUtility::makeInstance(Execution::class);
316  ‪$execution->‪setStart($timestamp);
318  ‪$execution->‪setEnd($timestamp);
322  // Replace existing execution object
323  $this->execution = ‪$execution;
324  }
325 
335  public function ‪registerRecurringExecution($start, $interval, $end = 0, $multiple = false, $cron_cmd = '')
336  {
338  ‪$execution = GeneralUtility::makeInstance(Execution::class);
339  // Set general values
340  ‪$execution->‪setStart($start);
341  ‪$execution->‪setEnd($end);
342  ‪$execution->‪setMultiple($multiple);
343  if (empty($cron_cmd)) {
344  // Use interval
345  ‪$execution->‪setInterval($interval);
347  } else {
348  // Use cron syntax
350  ‪$execution->‪setCronCmd($cron_cmd);
351  }
352  // Replace existing execution object
353  $this->execution = ‪$execution;
354  }
355 
362  {
363  $this->execution = ‪$execution;
364  }
365 
371  public function ‪getExecution()
372  {
374  }
375 
381  public function ‪getNextDueExecution()
382  {
383  // NOTE: this call may throw an exception, but we let it bubble up
384  return $this->execution->getNextExecution();
385  }
386 
392  public function ‪areMultipleExecutionsAllowed()
393  {
394  return $this->execution->getMultiple();
395  }
396 
402  public function ‪isExecutionRunning()
403  {
404  $isRunning = false;
405  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
406  ->getQueryBuilderForTable('tx_scheduler_task');
407  $row = $queryBuilder
408  ->select('serialized_executions')
409  ->from('tx_scheduler_task')
410  ->where(
411  $queryBuilder->expr()->eq('uid', $queryBuilder->createNamedParameter($this->taskUid, \PDO::PARAM_INT))
412  )
413  ->execute()
414  ->fetch();
415 
416  if ($row && !empty($row['serialized_executions'])) {
417  $isRunning = true;
418  }
419  return $isRunning;
420  }
421 
428  public function ‪markExecution()
429  {
430  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
431  ->getQueryBuilderForTable('tx_scheduler_task');
432 
433  $row = $queryBuilder
434  ->select('serialized_executions')
435  ->from('tx_scheduler_task')
436  ->where(
437  $queryBuilder->expr()->eq('uid', $queryBuilder->createNamedParameter($this->taskUid, \PDO::PARAM_INT))
438  )
439  ->execute()
440  ->fetch();
441 
442  $runningExecutions = [];
443  if ($row && !empty($row['serialized_executions'])) {
444  $runningExecutions = unserialize($row['serialized_executions']);
445  }
446  // Count the number of existing executions and use that number as a key
447  // (we need to know that number, because it is returned at the end of the method)
448  $numExecutions = count($runningExecutions);
449  $runningExecutions[$numExecutions] = time();
450  GeneralUtility::makeInstance(ConnectionPool::class)
451  ->getConnectionForTable('tx_scheduler_task')
452  ->update(
453  'tx_scheduler_task',
454  [
455  'serialized_executions' => serialize($runningExecutions),
456  'lastexecution_time' => time(),
457  // Define the context in which the script is running
458  'lastexecution_context' => ‪Environment::isCli() ? 'CLI' : 'BE'
459  ],
460  [
461  'uid' => $this->taskUid
462  ],
463  [
464  'serialized_executions' => ‪Connection::PARAM_LOB,
465  ]
466  );
467  return $numExecutions;
468  }
469 
476  public function ‪unmarkExecution($executionID, \Throwable $failure = null)
477  {
478  // Get the executions for the task
479  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
480  ->getQueryBuilderForTable('tx_scheduler_task');
481 
482  $row = $queryBuilder
483  ->select('serialized_executions')
484  ->from('tx_scheduler_task')
485  ->where(
486  $queryBuilder->expr()->eq('uid', $queryBuilder->createNamedParameter($this->taskUid, \PDO::PARAM_INT))
487  )
488  ->execute()
489  ->fetch();
490 
491  if ($row && $row['serialized_executions'] !== '') {
492  $runningExecutions = unserialize($row['serialized_executions']);
493  // Remove the selected execution
494  unset($runningExecutions[$executionID]);
495  if (!empty($runningExecutions)) {
496  // Re-serialize the updated executions list (if necessary)
497  $runningExecutionsSerialized = serialize($runningExecutions);
498  } else {
499  $runningExecutionsSerialized = '';
500  }
501  if ($failure instanceof \Throwable) {
502  // Log failed execution
503  $logMessage = 'Task failed to execute successfully. Class: ' . static::class
504  . ', UID: ' . $this->taskUid . ', Code: ' . $failure->getCode() . ', ' . $failure->getMessage();
505  $this->logger->error($logMessage, ['exception' => $failure]);
506  // Do not serialize the complete exception or the trace, this can lead to huge strings > 50MB
507  $failureString = serialize([
508  'code' => $failure->getCode(),
509  'message' => $failure->getMessage(),
510  'file' => $failure->getFile(),
511  'line' => $failure->getLine(),
512  'traceString' => $failure->getTraceAsString(),
513  ]);
514  } else {
515  $failureString = '';
516  }
517  // Save the updated executions list
518  GeneralUtility::makeInstance(ConnectionPool::class)
519  ->getConnectionForTable('tx_scheduler_task')
520  ->update(
521  'tx_scheduler_task',
522  [
523  'serialized_executions' => $runningExecutionsSerialized,
524  'lastexecution_failure' => $failureString
525  ],
526  [
527  'uid' => $this->taskUid
528  ],
529  [
530  'serialized_executions' => ‪Connection::PARAM_LOB,
531  ]
532  );
533  }
534  }
535 
541  public function ‪unmarkAllExecutions()
542  {
543  // Set the serialized executions field to empty
544  $result = GeneralUtility::makeInstance(ConnectionPool::class)
545  ->getConnectionForTable('tx_scheduler_task')
546  ->update(
547  'tx_scheduler_task',
548  [
549  'serialized_executions' => ''
550  ],
551  [
552  'uid' => $this->taskUid
553  ],
554  [
555  'serialized_executions' => ‪Connection::PARAM_LOB,
556  ]
557  );
558  return (bool)$result;
559  }
560 
566  public function ‪save()
567  {
568  return $this->scheduler->saveTask($this);
569  }
570 
575  public function ‪stop()
576  {
577  $this->execution = GeneralUtility::makeInstance(Execution::class);
578  }
579 
583  public function remove()
584  {
585  $this->scheduler->removeTask($this);
586  }
587 
594  public function ‪getType()
595  {
596  if (!empty($this->‪getExecution()->getInterval()) || !empty($this->‪getExecution()->getCronCmd())) {
598  }
599  return ‪self::TYPE_SINGLE;
600  }
601 
605  protected function ‪logException(\Exception $e)
606  {
607  $this->logger->error('A Task Exception was captured: ' . $e->getMessage() . ' (' . $e->getCode() . ')', ['exception' => $e]);
608  }
609 
613  protected function ‪getLanguageService(): ?‪LanguageService
614  {
615  return ‪$GLOBALS['LANG'] ?? null;
616  }
617 }
‪TYPO3\CMS\Scheduler\Execution\setStart
‪setStart($start)
Definition: Execution.php:73
‪TYPO3\CMS\Scheduler\Task\AbstractTask\save
‪bool save()
Definition: AbstractTask.php:558
‪TYPO3\CMS\Scheduler\Task\AbstractTask\getTaskUid
‪int getTaskUid()
Definition: AbstractTask.php:138
‪TYPO3\CMS\Scheduler\Task\AbstractTask\getRunOnNextCronJob
‪bool getRunOnNextCronJob()
Definition: AbstractTask.php:212
‪TYPO3\CMS\Scheduler\Task\AbstractTask\setTaskUid
‪setTaskUid($id)
Definition: AbstractTask.php:128
‪TYPO3\CMS\Scheduler\Task\AbstractTask\unmarkExecution
‪unmarkExecution($executionID, \Throwable $failure=null)
Definition: AbstractTask.php:468
‪TYPO3\CMS\Scheduler\Execution\setCronCmd
‪setCronCmd($cmd)
Definition: Execution.php:153
‪TYPO3\CMS\Scheduler\Execution\setIsNewSingleExecution
‪setIsNewSingleExecution($isNewSingleExecution)
Definition: Execution.php:180
‪TYPO3\CMS\Scheduler\Task\AbstractTask\getExecution
‪Execution getExecution()
Definition: AbstractTask.php:363
‪TYPO3\CMS\Scheduler\Task
Definition: AbstractTask.php:16
‪TYPO3\CMS\Scheduler\Task\AbstractTask\setRunOnNextCronJob
‪setRunOnNextCronJob($flag)
Definition: AbstractTask.php:202
‪TYPO3\CMS\Scheduler\Task\AbstractTask\setDisabled
‪setDisabled($flag)
Definition: AbstractTask.php:188
‪TYPO3\CMS\Scheduler\Task\AbstractTask\getType
‪int getType()
Definition: AbstractTask.php:586
‪TYPO3\CMS\Scheduler\Task\AbstractTask\getTaskTitle
‪string getTaskTitle()
Definition: AbstractTask.php:148
‪TYPO3\CMS\Core\Localization\LanguageService\sL
‪string sL($input)
Definition: LanguageService.php:194
‪TYPO3\CMS\Scheduler\Task\AbstractTask\getNextDueExecution
‪int getNextDueExecution()
Definition: AbstractTask.php:373
‪TYPO3\CMS\Scheduler\Task\AbstractTask\$executionTime
‪int $executionTime
Definition: AbstractTask.php:75
‪TYPO3\CMS\Scheduler\Task\AbstractTask\$execution
‪Execution $execution
Definition: AbstractTask.php:69
‪TYPO3\CMS\Scheduler\Task\AbstractTask\getTaskClassName
‪string getTaskClassName()
Definition: AbstractTask.php:168
‪TYPO3\CMS\Scheduler\Task\AbstractTask\getLanguageService
‪LanguageService null getLanguageService()
Definition: AbstractTask.php:605
‪TYPO3\CMS\Scheduler\Task\AbstractTask\getAdditionalInformation
‪string getAdditionalInformation()
Definition: AbstractTask.php:118
‪TYPO3\CMS\Scheduler\Task\AbstractTask\setScheduler
‪setScheduler()
Definition: AbstractTask.php:281
‪TYPO3\CMS\Scheduler\Task\AbstractTask\$taskGroup
‪int $taskGroup
Definition: AbstractTask.php:87
‪TYPO3\CMS\Scheduler\Task\AbstractTask
Definition: AbstractTask.php:35
‪TYPO3\CMS\Scheduler\Execution
Definition: Execution.php:26
‪TYPO3\CMS\Scheduler\Task\AbstractTask\$scheduler
‪TYPO3 CMS Scheduler Scheduler $scheduler
Definition: AbstractTask.php:45
‪TYPO3\CMS\Scheduler\Task\AbstractTask\registerSingleExecution
‪registerSingleExecution($timestamp)
Definition: AbstractTask.php:304
‪TYPO3\CMS\Scheduler\Scheduler
Definition: Scheduler.php:36
‪TYPO3\CMS\Scheduler\Execution\setInterval
‪setInterval($interval)
Definition: Execution.php:113
‪TYPO3\CMS\Scheduler\Task\AbstractTask\logException
‪logException(\Exception $e)
Definition: AbstractTask.php:597
‪TYPO3\CMS\Scheduler\Task\AbstractTask\isDisabled
‪bool isDisabled()
Definition: AbstractTask.php:178
‪TYPO3\CMS\Scheduler\Task\AbstractTask\setDescription
‪setDescription($description)
Definition: AbstractTask.php:262
‪TYPO3\CMS\Scheduler\Task\AbstractTask\areMultipleExecutionsAllowed
‪bool areMultipleExecutionsAllowed()
Definition: AbstractTask.php:384
‪TYPO3\CMS\Scheduler\Task\AbstractTask\getExecutionTime
‪int getExecutionTime()
Definition: AbstractTask.php:252
‪TYPO3\CMS\Scheduler\Execution\setEnd
‪setEnd($end)
Definition: Execution.php:93
‪TYPO3\CMS\Scheduler\Task\AbstractTask\$runOnNextCronJob
‪bool $runOnNextCronJob
Definition: AbstractTask.php:63
‪TYPO3\CMS\Scheduler\Task\AbstractTask\$description
‪string $description
Definition: AbstractTask.php:81
‪TYPO3\CMS\Scheduler\Task\AbstractTask\TYPE_RECURRING
‪const TYPE_RECURRING
Definition: AbstractTask.php:39
‪TYPO3\CMS\Core\Database\Connection
Definition: Connection.php:36
‪TYPO3\CMS\Scheduler\Task\AbstractTask\stop
‪stop()
Definition: AbstractTask.php:567
‪TYPO3\CMS\Scheduler\Task\AbstractTask\execute
‪bool execute()
‪TYPO3\CMS\Scheduler\Task\AbstractTask\isExecutionRunning
‪bool isExecutionRunning()
Definition: AbstractTask.php:394
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:5
‪TYPO3\CMS\Scheduler\Task\AbstractTask\TYPE_SINGLE
‪const TYPE_SINGLE
Definition: AbstractTask.php:38
‪TYPO3\CMS\Scheduler\Task\AbstractTask\markExecution
‪int markExecution()
Definition: AbstractTask.php:420
‪TYPO3\CMS\Core\Log\LogManager
Definition: LogManager.php:30
‪TYPO3\CMS\Core\Core\Environment
Definition: Environment.php:40
‪TYPO3\CMS\Scheduler\Task\AbstractTask\__construct
‪__construct()
Definition: AbstractTask.php:92
‪TYPO3\CMS\Scheduler\Task\AbstractTask\registerRecurringExecution
‪registerRecurringExecution($start, $interval, $end=0, $multiple=false, $cron_cmd='')
Definition: AbstractTask.php:327
‪TYPO3\CMS\Scheduler\Task\AbstractTask\$disabled
‪bool $disabled
Definition: AbstractTask.php:57
‪TYPO3\CMS\Scheduler\Task\AbstractTask\unmarkAllExecutions
‪bool unmarkAllExecutions()
Definition: AbstractTask.php:533
‪TYPO3\CMS\Core\Localization\LanguageService
Definition: LanguageService.php:42
‪TYPO3\CMS\Scheduler\Task\AbstractTask\getTaskGroup
‪int getTaskGroup()
Definition: AbstractTask.php:232
‪TYPO3\CMS\Core\Database\ConnectionPool
Definition: ConnectionPool.php:46
‪TYPO3\CMS\Scheduler\Task\AbstractTask\getDescription
‪string getDescription()
Definition: AbstractTask.php:272
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:46
‪TYPO3\CMS\Scheduler\Task\AbstractTask\setExecution
‪setExecution(Execution $execution)
Definition: AbstractTask.php:353
‪TYPO3\CMS\Scheduler\Execution\setMultiple
‪setMultiple($multiple)
Definition: Execution.php:133
‪TYPO3\CMS\Core\Core\Environment\isCli
‪static bool isCli()
Definition: Environment.php:154
‪TYPO3\CMS\Scheduler\Task\AbstractTask\unsetScheduler
‪unsetScheduler()
Definition: AbstractTask.php:293
‪TYPO3\CMS\Scheduler\Task\AbstractTask\$taskUid
‪int $taskUid
Definition: AbstractTask.php:51
‪TYPO3\CMS\Scheduler\Task\AbstractTask\setTaskGroup
‪setTaskGroup($taskGroup)
Definition: AbstractTask.php:242
‪TYPO3\CMS\Scheduler\Task\AbstractTask\getTaskDescription
‪string getTaskDescription()
Definition: AbstractTask.php:158
‪TYPO3\CMS\Scheduler\Task\AbstractTask\setExecutionTime
‪setExecutionTime($timestamp)
Definition: AbstractTask.php:222
‪TYPO3\CMS\Core\Database\Connection\PARAM_LOB
‪const PARAM_LOB
Definition: Connection.php:57