‪TYPO3CMS  9.5
AbstractTask.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 
17 use Psr\Log\LoggerAwareInterface;
18 use Psr\Log\LoggerAwareTrait;
25 
31 abstract class ‪AbstractTask implements LoggerAwareInterface
32 {
33  use LoggerAwareTrait;
34 
35  const ‪TYPE_SINGLE = 1;
36  const ‪TYPE_RECURRING = 2;
37 
43  protected ‪$scheduler;
44 
50  protected ‪$taskUid;
51 
57  protected ‪$disabled = false;
58 
64  protected ‪$runOnNextCronJob = false;
65 
71  protected ‪$execution;
72 
78  protected ‪$executionTime = 0;
79 
85  protected ‪$description = '';
86 
92  protected ‪$taskGroup;
93 
97  public function ‪__construct()
98  {
99  // Using makeInstance instead of setScheduler() here as the logger is injected due to LoggerAwareTrait
100  $this->scheduler = GeneralUtility::makeInstance(\‪TYPO3\CMS\‪Scheduler\Scheduler::class);
101  $this->execution = GeneralUtility::makeInstance(Execution::class);
102  }
103 
113  abstract public function ‪execute();
114 
123  public function ‪getAdditionalInformation()
124  {
125  return '';
126  }
127 
133  public function ‪setTaskUid($id)
134  {
135  $this->taskUid = (int)$id;
136  }
137 
143  public function ‪getTaskUid()
144  {
146  }
147 
153  public function ‪getTaskTitle()
154  {
155  return ‪$GLOBALS['LANG']->sL(‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['scheduler']['tasks'][static::class]['title']);
156  }
157 
163  public function ‪getTaskDescription()
164  {
165  return ‪$GLOBALS['LANG']->sL(‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['scheduler']['tasks'][static::class]['description']);
166  }
167 
173  public function ‪getTaskClassName()
174  {
175  return static::class;
176  }
177 
183  public function ‪isDisabled()
184  {
186  }
187 
193  public function ‪setDisabled($flag)
194  {
195  if ($flag) {
196  $this->disabled = true;
197  } else {
198  $this->disabled = false;
199  }
200  }
201 
207  public function ‪setRunOnNextCronJob($flag)
208  {
209  $this->runOnNextCronJob = $flag;
210  }
211 
217  public function ‪getRunOnNextCronJob()
218  {
220  }
221 
227  public function ‪setExecutionTime($timestamp)
228  {
229  $this->executionTime = (int)$timestamp;
230  }
231 
237  public function ‪getTaskGroup()
238  {
240  }
241 
247  public function ‪setTaskGroup(‪$taskGroup)
248  {
249  $this->taskGroup = (int)‪$taskGroup;
250  }
251 
257  public function ‪getExecutionTime()
258  {
260  }
261 
267  public function ‪setDescription(‪$description)
268  {
269  $this->description = ‪$description;
270  }
271 
277  public function ‪getDescription()
278  {
279  return ‪$this->description;
280  }
281 
286  public function ‪setScheduler()
287  {
288  $this->scheduler = GeneralUtility::makeInstance(\‪TYPO3\CMS\‪Scheduler\Scheduler::class);
289  $this->logger = GeneralUtility::makeInstance(LogManager::class)->getLogger(__CLASS__);
290  }
291 
298  public function ‪unsetScheduler()
299  {
300  $this->scheduler = null;
301  $this->logger = null;
302  }
303 
309  public function ‪registerSingleExecution($timestamp)
310  {
312  ‪$execution = GeneralUtility::makeInstance(Execution::class);
313  ‪$execution->‪setStart($timestamp);
315  ‪$execution->‪setEnd($timestamp);
319  // Replace existing execution object
320  $this->execution = ‪$execution;
321  }
322 
332  public function ‪registerRecurringExecution($start, $interval, $end = 0, $multiple = false, $cron_cmd = '')
333  {
335  ‪$execution = GeneralUtility::makeInstance(Execution::class);
336  // Set general values
337  ‪$execution->‪setStart($start);
338  ‪$execution->‪setEnd($end);
339  ‪$execution->‪setMultiple($multiple);
340  if (empty($cron_cmd)) {
341  // Use interval
342  ‪$execution->‪setInterval($interval);
344  } else {
345  // Use cron syntax
347  ‪$execution->‪setCronCmd($cron_cmd);
348  }
349  // Replace existing execution object
350  $this->execution = ‪$execution;
351  }
352 
359  {
360  $this->execution = ‪$execution;
361  }
362 
368  public function ‪getExecution()
369  {
371  }
372 
378  public function ‪getNextDueExecution()
379  {
380  // NOTE: this call may throw an exception, but we let it bubble up
381  return $this->execution->getNextExecution();
382  }
383 
389  public function ‪areMultipleExecutionsAllowed()
390  {
391  return $this->execution->getMultiple();
392  }
393 
399  public function ‪isExecutionRunning()
400  {
401  $isRunning = false;
402  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
403  ->getQueryBuilderForTable('tx_scheduler_task');
404  $row = $queryBuilder
405  ->select('serialized_executions')
406  ->from('tx_scheduler_task')
407  ->where(
408  $queryBuilder->expr()->eq('uid', $queryBuilder->createNamedParameter($this->taskUid, \PDO::PARAM_INT))
409  )
410  ->execute()
411  ->fetch();
412 
413  if ($row && !empty($row['serialized_executions'])) {
414  $isRunning = true;
415  }
416  return $isRunning;
417  }
418 
425  public function ‪markExecution()
426  {
427  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
428  ->getQueryBuilderForTable('tx_scheduler_task');
429 
430  $row = $queryBuilder
431  ->select('serialized_executions')
432  ->from('tx_scheduler_task')
433  ->where(
434  $queryBuilder->expr()->eq('uid', $queryBuilder->createNamedParameter($this->taskUid, \PDO::PARAM_INT))
435  )
436  ->execute()
437  ->fetch();
438 
439  $runningExecutions = [];
440  if ($row && !empty($row['serialized_executions'])) {
441  $runningExecutions = unserialize($row['serialized_executions']);
442  }
443  // Count the number of existing executions and use that number as a key
444  // (we need to know that number, because it is returned at the end of the method)
445  $numExecutions = count($runningExecutions);
446  $runningExecutions[$numExecutions] = time();
447  GeneralUtility::makeInstance(ConnectionPool::class)
448  ->getConnectionForTable('tx_scheduler_task')
449  ->update(
450  'tx_scheduler_task',
451  [
452  'serialized_executions' => serialize($runningExecutions),
453  'lastexecution_time' => time(),
454  // Define the context in which the script is running
455  'lastexecution_context' => ‪Environment::isCli() ? 'CLI' : 'BE'
456  ],
457  [
458  'uid' => $this->taskUid
459  ],
460  [
461  'serialized_executions' => ‪Connection::PARAM_LOB,
462  ]
463  );
464  return $numExecutions;
465  }
466 
473  public function ‪unmarkExecution($executionID, \Throwable $failure = null)
474  {
475  // Get the executions for the task
476  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
477  ->getQueryBuilderForTable('tx_scheduler_task');
478 
479  $row = $queryBuilder
480  ->select('serialized_executions')
481  ->from('tx_scheduler_task')
482  ->where(
483  $queryBuilder->expr()->eq('uid', $queryBuilder->createNamedParameter($this->taskUid, \PDO::PARAM_INT))
484  )
485  ->execute()
486  ->fetch();
487 
488  if ($row && $row['serialized_executions'] !== '') {
489  $runningExecutions = unserialize($row['serialized_executions']);
490  // Remove the selected execution
491  unset($runningExecutions[$executionID]);
492  if (!empty($runningExecutions)) {
493  // Re-serialize the updated executions list (if necessary)
494  $runningExecutionsSerialized = serialize($runningExecutions);
495  } else {
496  $runningExecutionsSerialized = '';
497  }
498  if ($failure instanceof \Throwable) {
499  // Log failed execution
500  $logMessage = 'Task failed to execute successfully. Class: ' . static::class
501  . ', UID: ' . $this->taskUid . ', Code: ' . $failure->getCode() . ', ' . $failure->getMessage();
502  $this->logger->error($logMessage, ['exception' => $failure]);
503  // Do not serialize the complete exception or the trace, this can lead to huge strings > 50MB
504  $failureString = serialize([
505  'code' => $failure->getCode(),
506  'message' => $failure->getMessage(),
507  'file' => $failure->getFile(),
508  'line' => $failure->getLine(),
509  'traceString' => $failure->getTraceAsString(),
510  ]);
511  } else {
512  $failureString = '';
513  }
514  // Save the updated executions list
515  GeneralUtility::makeInstance(ConnectionPool::class)
516  ->getConnectionForTable('tx_scheduler_task')
517  ->update(
518  'tx_scheduler_task',
519  [
520  'serialized_executions' => $runningExecutionsSerialized,
521  'lastexecution_failure' => $failureString
522  ],
523  [
524  'uid' => $this->taskUid
525  ],
526  [
527  'serialized_executions' => ‪Connection::PARAM_LOB,
528  ]
529  );
530  }
531  }
532 
538  public function ‪unmarkAllExecutions()
539  {
540  // Set the serialized executions field to empty
541  $result = GeneralUtility::makeInstance(ConnectionPool::class)
542  ->getConnectionForTable('tx_scheduler_task')
543  ->update(
544  'tx_scheduler_task',
545  [
546  'serialized_executions' => ''
547  ],
548  [
549  'uid' => $this->taskUid
550  ],
551  [
552  'serialized_executions' => ‪Connection::PARAM_LOB,
553  ]
554  );
555  return (bool)$result;
556  }
557 
563  public function ‪save()
564  {
565  return $this->scheduler->saveTask($this);
566  }
567 
572  public function ‪stop()
573  {
574  $this->execution = GeneralUtility::makeInstance(Execution::class);
575  }
576 
580  public function remove()
581  {
582  $this->scheduler->removeTask($this);
583  }
584 
591  public function ‪getType()
592  {
593  if (!empty($this->‪getExecution()->getInterval()) || !empty($this->‪getExecution()->getCronCmd())) {
595  }
596  return ‪self::TYPE_SINGLE;
597  }
598 
602  protected function ‪logException(\Exception $e)
603  {
604  $this->logger->error('A Task Exception was captured: ' . $e->getMessage() . ' (' . $e->getCode() . ')', ['exception' => $e]);
605  }
606 }
‪TYPO3\CMS\Scheduler\Execution\setStart
‪setStart($start)
Definition: Execution.php:69
‪TYPO3\CMS\Scheduler\Task\AbstractTask\save
‪bool save()
Definition: AbstractTask.php:555
‪TYPO3\CMS\Scheduler\Task\AbstractTask\getTaskUid
‪int getTaskUid()
Definition: AbstractTask.php:135
‪TYPO3\CMS\Scheduler\Task\AbstractTask\getRunOnNextCronJob
‪bool getRunOnNextCronJob()
Definition: AbstractTask.php:209
‪TYPO3\CMS\Scheduler\Task\AbstractTask\setTaskUid
‪setTaskUid($id)
Definition: AbstractTask.php:125
‪TYPO3\CMS\Scheduler\Task\AbstractTask\unmarkExecution
‪unmarkExecution($executionID, \Throwable $failure=null)
Definition: AbstractTask.php:465
‪TYPO3\CMS\Scheduler\Execution\setCronCmd
‪setCronCmd($cmd)
Definition: Execution.php:149
‪TYPO3
‪TYPO3\CMS\Scheduler\Execution\setIsNewSingleExecution
‪setIsNewSingleExecution($isNewSingleExecution)
Definition: Execution.php:176
‪TYPO3\CMS\Scheduler\Task\AbstractTask\getExecution
‪Execution getExecution()
Definition: AbstractTask.php:360
‪TYPO3\CMS\Scheduler\Task
Definition: AbstractTask.php:2
‪TYPO3\CMS\Scheduler\Task\AbstractTask\setRunOnNextCronJob
‪setRunOnNextCronJob($flag)
Definition: AbstractTask.php:199
‪TYPO3\CMS\Scheduler\Task\AbstractTask\setDisabled
‪setDisabled($flag)
Definition: AbstractTask.php:185
‪TYPO3\CMS\Scheduler\Task\AbstractTask\getType
‪int getType()
Definition: AbstractTask.php:583
‪TYPO3\CMS\Scheduler\Task\AbstractTask\getTaskTitle
‪string getTaskTitle()
Definition: AbstractTask.php:145
‪TYPO3\CMS\Scheduler\Task\AbstractTask\getNextDueExecution
‪int getNextDueExecution()
Definition: AbstractTask.php:370
‪TYPO3\CMS\Scheduler\Task\AbstractTask\$executionTime
‪int $executionTime
Definition: AbstractTask.php:72
‪TYPO3\CMS\Scheduler\Task\AbstractTask\$execution
‪Execution $execution
Definition: AbstractTask.php:66
‪TYPO3\CMS\Scheduler\Task\AbstractTask\getTaskClassName
‪string getTaskClassName()
Definition: AbstractTask.php:165
‪TYPO3\CMS\Scheduler\Task\AbstractTask\getAdditionalInformation
‪string getAdditionalInformation()
Definition: AbstractTask.php:115
‪TYPO3\CMS\Scheduler\Task\AbstractTask\setScheduler
‪setScheduler()
Definition: AbstractTask.php:278
‪TYPO3\CMS\Scheduler\Task\AbstractTask\$taskGroup
‪int $taskGroup
Definition: AbstractTask.php:84
‪TYPO3\CMS\Scheduler\Task\AbstractTask
Definition: AbstractTask.php:32
‪TYPO3\CMS\Scheduler\Execution
Definition: Execution.php:22
‪TYPO3\CMS\Scheduler\Task\AbstractTask\$scheduler
‪TYPO3 CMS Scheduler Scheduler $scheduler
Definition: AbstractTask.php:42
‪TYPO3\CMS\Scheduler\Task\AbstractTask\registerSingleExecution
‪registerSingleExecution($timestamp)
Definition: AbstractTask.php:301
‪TYPO3\CMS\Scheduler\Scheduler
Definition: Scheduler.php:33
‪TYPO3\CMS\Scheduler\Execution\setInterval
‪setInterval($interval)
Definition: Execution.php:109
‪TYPO3\CMS\Scheduler\Task\AbstractTask\logException
‪logException(\Exception $e)
Definition: AbstractTask.php:594
‪TYPO3\CMS\Scheduler\Task\AbstractTask\isDisabled
‪bool isDisabled()
Definition: AbstractTask.php:175
‪TYPO3\CMS\Scheduler\Task\AbstractTask\setDescription
‪setDescription($description)
Definition: AbstractTask.php:259
‪TYPO3\CMS\Scheduler\Task\AbstractTask\areMultipleExecutionsAllowed
‪bool areMultipleExecutionsAllowed()
Definition: AbstractTask.php:381
‪TYPO3\CMS\Scheduler\Task\AbstractTask\getExecutionTime
‪int getExecutionTime()
Definition: AbstractTask.php:249
‪TYPO3\CMS\Scheduler\Execution\setEnd
‪setEnd($end)
Definition: Execution.php:89
‪TYPO3\CMS\Scheduler\Task\AbstractTask\$runOnNextCronJob
‪bool $runOnNextCronJob
Definition: AbstractTask.php:60
‪TYPO3\CMS\Scheduler\Task\AbstractTask\$description
‪string $description
Definition: AbstractTask.php:78
‪TYPO3\CMS\Scheduler\Task\AbstractTask\TYPE_RECURRING
‪const TYPE_RECURRING
Definition: AbstractTask.php:36
‪TYPO3\CMS\Core\Database\Connection
Definition: Connection.php:31
‪TYPO3\CMS\Scheduler\Task\AbstractTask\stop
‪stop()
Definition: AbstractTask.php:564
‪TYPO3\CMS\Scheduler\Task\AbstractTask\execute
‪bool execute()
‪TYPO3\CMS\Scheduler\Task\AbstractTask\isExecutionRunning
‪bool isExecutionRunning()
Definition: AbstractTask.php:391
‪$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:35
‪TYPO3\CMS\Scheduler\Task\AbstractTask\markExecution
‪int markExecution()
Definition: AbstractTask.php:417
‪TYPO3\CMS\Core\Log\LogManager
Definition: LogManager.php:25
‪TYPO3\CMS\Core\Core\Environment
Definition: Environment.php:39
‪TYPO3\CMS\Scheduler\Task\AbstractTask\__construct
‪__construct()
Definition: AbstractTask.php:89
‪TYPO3\CMS\Scheduler\Task\AbstractTask\registerRecurringExecution
‪registerRecurringExecution($start, $interval, $end=0, $multiple=false, $cron_cmd='')
Definition: AbstractTask.php:324
‪TYPO3\CMS\Scheduler\Task\AbstractTask\$disabled
‪bool $disabled
Definition: AbstractTask.php:54
‪TYPO3\CMS\Scheduler\Task\AbstractTask\unmarkAllExecutions
‪bool unmarkAllExecutions()
Definition: AbstractTask.php:530
‪TYPO3\CMS\Scheduler\Task\AbstractTask\getTaskGroup
‪int getTaskGroup()
Definition: AbstractTask.php:229
‪TYPO3\CMS\Core\Database\ConnectionPool
Definition: ConnectionPool.php:44
‪TYPO3\CMS\Scheduler\Task\AbstractTask\getDescription
‪string getDescription()
Definition: AbstractTask.php:269
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:45
‪TYPO3\CMS\Scheduler\Task\AbstractTask\setExecution
‪setExecution(Execution $execution)
Definition: AbstractTask.php:350
‪TYPO3\CMS\Scheduler\Execution\setMultiple
‪setMultiple($multiple)
Definition: Execution.php:129
‪TYPO3\CMS\Core\Core\Environment\isCli
‪static bool isCli()
Definition: Environment.php:127
‪TYPO3\CMS\Scheduler\Task\AbstractTask\unsetScheduler
‪unsetScheduler()
Definition: AbstractTask.php:290
‪TYPO3\CMS\Scheduler\Task\AbstractTask\$taskUid
‪int $taskUid
Definition: AbstractTask.php:48
‪TYPO3\CMS\Scheduler\Task\AbstractTask\setTaskGroup
‪setTaskGroup($taskGroup)
Definition: AbstractTask.php:239
‪TYPO3\CMS\Scheduler\Task\AbstractTask\getTaskDescription
‪string getTaskDescription()
Definition: AbstractTask.php:155
‪TYPO3\CMS\Scheduler\Task\AbstractTask\setExecutionTime
‪setExecutionTime($timestamp)
Definition: AbstractTask.php:219
‪TYPO3\CMS\Core\Database\Connection\PARAM_LOB
‪const PARAM_LOB
Definition: Connection.php:52