‪TYPO3CMS  ‪main
SchedulerTaskRepository.php
Go to the documentation of this file.
1 <?php
2 
3 declare(strict_types=1);
4 
5 /*
6  * This file is part of the TYPO3 CMS project.
7  *
8  * It is free software; you can redistribute it and/or modify it under
9  * the terms of the GNU General Public License, either version 2
10  * of the License, or any later version.
11  *
12  * For the full copyright and license information, please read the
13  * LICENSE.txt file that was distributed with this source code.
14  *
15  * The TYPO3 project - inspiring people to share!
16  */
17 
19 
20 use Doctrine\DBAL\Exception as DBALException;
31 
36 {
37  protected const ‪TABLE_NAME = 'tx_scheduler_task';
38 
39  public function ‪__construct(
40  protected readonly ‪TaskSerializer $taskSerializer,
41  ) {}
42 
49  public function ‪add(‪AbstractTask $task): bool
50  {
51  $taskUid = $task->‪getTaskUid();
52  if (!empty($taskUid)) {
53  return false;
54  }
55  ‪$fields = [
56  'crdate' => ‪$GLOBALS['EXEC_TIME'],
57  'disable' => (int)$task->‪isDisabled(),
58  'description' => $task->‪getDescription(),
59  'task_group' => $task->‪getTaskGroup(),
60  'serialized_task_object' => 'RESERVED',
61  ];
62  $connection = GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable(self::TABLE_NAME);
63  $result = $connection->insert(
64  self::TABLE_NAME,
65  ‪$fields,
66  ['serialized_task_object' => ‪Connection::PARAM_LOB]
67  );
68  if ($result) {
69  $task->‪setTaskUid((int)$connection->lastInsertId());
70  $this->‪update($task);
71  $result = true;
72  } else {
73  $result = false;
74  }
75  return $result;
76  }
77 
84  public function remove(int|‪AbstractTask $task): bool
85  {
86  $taskUid = is_int($task) ? $task : $task->getTaskUid();
87  if (empty($taskUid)) {
88  return false;
89  }
90  $affectedRows = GeneralUtility::makeInstance(ConnectionPool::class)
91  ->getConnectionForTable(self::TABLE_NAME)
92  ->update(self::TABLE_NAME, ['deleted' => 1], ['uid' => $taskUid]);
93  return $affectedRows === 1;
94  }
95 
99  public function ‪update(‪AbstractTask $task): bool
100  {
101  $result = true;
102  $taskUid = $task->‪getTaskUid();
103  if (empty($taskUid)) {
104  return false;
105  }
106  try {
107  if ($task->‪getRunOnNextCronJob()) {
108  $executionTime = time();
109  } else {
110  $executionTime = $task->‪getNextDueExecution();
111  }
112  $task->‪setExecutionTime($executionTime);
113  } catch (\‪Exception $e) {
114  $task->‪setDisabled(true);
115  $executionTime = 0;
116  }
117  $task->‪unsetScheduler();
118  ‪$fields = [
119  'nextexecution' => $executionTime,
120  'disable' => (int)$task->‪isDisabled(),
121  'description' => $task->‪getDescription(),
122  'task_group' => $task->‪getTaskGroup(),
123  'serialized_task_object' => serialize($task),
124  ];
125  try {
126  GeneralUtility::makeInstance(ConnectionPool::class)
127  ->getConnectionForTable(self::TABLE_NAME)
128  ->update(
129  self::TABLE_NAME,
130  ‪$fields,
131  ['uid' => $taskUid],
132  ['serialized_task_object' => ‪Connection::PARAM_LOB]
133  );
134  } catch (DBALException $e) {
135  $result = false;
136  }
137  return $result;
138  }
139 
148  public function ‪findRecordByUid(int ‪$uid): ?array
149  {
150  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
151  ->getQueryBuilderForTable(self::TABLE_NAME);
152  $row = $queryBuilder->select('*')
153  ->from(self::TABLE_NAME)
154  ->where(
155  $queryBuilder->expr()->eq('uid', $queryBuilder->createNamedParameter(‪$uid, ‪Connection::PARAM_INT)),
156  $queryBuilder->expr()->eq('deleted', $queryBuilder->createNamedParameter(0, ‪Connection::PARAM_INT))
157  )
158  ->executeQuery()
159  ->fetchAssociative();
160 
161  if (empty($row)) {
162  return null;
163  }
164  return $row;
165  }
166 
176  public function ‪findByUid(int ‪$uid): ‪AbstractTask
177  {
178  $connectionPool = GeneralUtility::makeInstance(ConnectionPool::class);
179  $queryBuilder = $connectionPool->getQueryBuilderForTable(self::TABLE_NAME);
180 
181  $queryBuilder->select('uid', 'serialized_task_object')
182  ->from(self::TABLE_NAME)
183  ->setMaxResults(1)
184  ->where(
185  $queryBuilder->expr()->eq('uid', $queryBuilder->createNamedParameter(‪$uid, ‪Connection::PARAM_INT)),
186  $queryBuilder->expr()->eq('deleted', $queryBuilder->createNamedParameter(0, ‪Connection::PARAM_INT))
187  );
188 
189  $row = $queryBuilder->executeQuery()->fetchAssociative();
190  if (empty($row)) {
191  // Although an uid was passed, no task with given was found
192  throw new \OutOfBoundsException('No task with id ' . ‪$uid . ' found', 1422044826);
193  }
194 
195  return $this->‪createValidTaskObjectOrDisableTask($row);
196  }
197 
206  {
207  // If no uid is given, take any non-disabled task which has a next execution time in the past
208  $connectionPool = GeneralUtility::makeInstance(ConnectionPool::class);
209  $queryBuilder = $connectionPool->getQueryBuilderForTable(self::TABLE_NAME);
210 
211  $queryBuilder->select('t.uid', 't.serialized_task_object')
212  ->from(self::TABLE_NAME, 't')
213  ->setMaxResults(1);
214  // Define where clause
215  $queryBuilder->getRestrictions()->removeAll();
216  $queryBuilder->leftJoin(
217  't',
218  'tx_scheduler_task_group',
219  'g',
220  $queryBuilder->expr()->eq('t.task_group', $queryBuilder->quoteIdentifier('g.uid'))
221  );
222  $queryBuilder->where(
223  $queryBuilder->expr()->eq('t.disable', $queryBuilder->createNamedParameter(0, ‪Connection::PARAM_INT)),
224  $queryBuilder->expr()->neq(
225  't.nextexecution',
226  $queryBuilder->createNamedParameter(0, ‪Connection::PARAM_INT)
227  ),
228  $queryBuilder->expr()->lte(
229  't.nextexecution',
230  $queryBuilder->createNamedParameter(‪$GLOBALS['EXEC_TIME'], ‪Connection::PARAM_INT)
231  ),
232  $queryBuilder->expr()->or(
233  $queryBuilder->expr()->eq('g.hidden', $queryBuilder->createNamedParameter(0, ‪Connection::PARAM_INT)),
234  $queryBuilder->expr()->isNull('g.hidden')
235  ),
236  $queryBuilder->expr()->eq('t.deleted', $queryBuilder->createNamedParameter(0, ‪Connection::PARAM_INT))
237  );
238  $queryBuilder->orderBy('t.nextexecution', 'ASC');
239 
240  $row = $queryBuilder->executeQuery()->fetchAssociative();
241  if (empty($row)) {
242  return null;
243  }
244 
245  return $this->‪createValidTaskObjectOrDisableTask($row);
246  }
247 
251  public function ‪getGroupedTasks(): array
252  {
253  $registeredClasses = GeneralUtility::makeInstance(TaskService::class)->getAvailableTaskTypes();
254 
255  // Get all registered tasks
256  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable(self::TABLE_NAME);
257  $queryBuilder->getRestrictions()->removeAll();
258  $result = $queryBuilder->select('t.*')
259  ->addSelect(
260  'g.groupName AS taskGroupName',
261  'g.description AS taskGroupDescription',
262  'g.uid AS taskGroupId',
263  'g.deleted AS isTaskGroupDeleted',
264  'g.hidden AS isTaskGroupHidden',
265  )
266  ->from(self::TABLE_NAME, 't')
267  ->leftJoin(
268  't',
269  'tx_scheduler_task_group',
270  'g',
271  $queryBuilder->expr()->eq('t.task_group', $queryBuilder->quoteIdentifier('g.uid'))
272  )
273  ->where(
274  $queryBuilder->expr()->eq('t.deleted', 0)
275  )
276  ->orderBy('g.sorting')
277  ->executeQuery();
278 
279  $taskGroupsWithTasks = [];
280  $errorClasses = [];
281  while ($row = $result->fetchAssociative()) {
282  $taskData = [
283  'uid' => (int)$row['uid'],
284  'lastExecutionTime' => (int)$row['lastexecution_time'],
285  'lastExecutionContext' => $row['lastexecution_context'],
286  'errorMessage' => '',
287  'description' => $row['description'],
288  ];
289 
290  try {
291  $taskObject = $this->taskSerializer->deserialize($row['serialized_task_object']);
292  } catch (‪InvalidTaskException $e) {
293  $taskData['errorMessage'] = $e->getMessage();
294  $taskData['class'] = $this->taskSerializer->extractClassName($row['serialized_task_object']);
295  $errorClasses[] = $taskData;
296  continue;
297  }
298 
299  $taskClass = $this->taskSerializer->resolveClassName($taskObject);
300  $taskData['class'] = $taskClass;
301 
302  if (!$this->‪isValidTaskObject($taskObject)) {
303  $taskData['errorMessage'] = 'The class ' . $taskClass . ' is not a valid task';
304  $errorClasses[] = $taskData;
305  continue;
306  }
307 
308  if (!isset($registeredClasses[$taskClass])) {
309  $taskData['errorMessage'] = 'The class ' . $taskClass . ' is not a registered task';
310  $errorClasses[] = $taskData;
311  continue;
312  }
313 
314  if ($taskObject instanceof ‪ProgressProviderInterface) {
315  $taskData['progress'] = round((float)$taskObject->getProgress(), 2);
316  }
317  $taskData['classTitle'] = $registeredClasses[$taskClass]['title'];
318  $taskData['classExtension'] = $registeredClasses[$taskClass]['extension'];
319  $taskData['additionalInformation'] = $taskObject->getAdditionalInformation();
320  $taskData['disabled'] = (bool)$row['disable'];
321  $taskData['isRunning'] = !empty($row['serialized_executions']);
322  $taskData['nextExecution'] = (int)$row['nextexecution'];
323  $taskData['type'] = 'single';
324  $taskData['frequency'] = '';
325  if ($taskObject->getType() === ‪AbstractTask::TYPE_RECURRING) {
326  $taskData['type'] = 'recurring';
327  $taskData['frequency'] = $taskObject->getExecution()->getCronCmd() ?: $taskObject->getExecution()->getInterval();
328  }
329  $taskData['multiple'] = (bool)$taskObject->getExecution()->getMultiple();
330  $taskData['lastExecutionFailure'] = false;
331  if (!empty($row['lastexecution_failure'])) {
332  $taskData['lastExecutionFailure'] = true;
333  $exceptionArray = @unserialize($row['lastexecution_failure']);
334  $taskData['lastExecutionFailureCode'] = '';
335  $taskData['lastExecutionFailureMessage'] = '';
336  if (is_array($exceptionArray)) {
337  $taskData['lastExecutionFailureCode'] = $exceptionArray['code'];
338  $taskData['lastExecutionFailureMessage'] = $exceptionArray['message'];
339  }
340  }
341 
342  // If a group is deleted or no group is set it needs to go into "not assigned groups"
343  $groupIndex = $row['isTaskGroupDeleted'] === 1 || $row['isTaskGroupDeleted'] === null ? 0 : (int)$row['task_group'];
344  if (!isset($taskGroupsWithTasks[$groupIndex])) {
345  $taskGroupsWithTasks[$groupIndex] = [
346  'uid' => $row['taskGroupId'],
347  'groupName' => $row['taskGroupName'],
348  'description' => $row['taskGroupDescription'],
349  'hidden' => $row['isTaskGroupHidden'],
350  'tasks' => [],
351  ];
352  }
353  $taskGroupsWithTasks[$groupIndex]['tasks'][] = $taskData;
354  }
355 
356  return [
357  'taskGroupsWithTasks' => $taskGroupsWithTasks,
358  'errorClasses' => $errorClasses,
359  ];
360  }
361 
363  {
364  $isInvalidTask = false;
365  $task = null;
366  try {
367  $task = $this->taskSerializer->deserialize($row['serialized_task_object']);
368  } catch (‪InvalidTaskException) {
369  $isInvalidTask = true;
370  }
371  if ($isInvalidTask || !$this->‪isValidTaskObject($task)) {
372  // Forcibly set the disabled flag to 1 in the database,
373  // so that the task does not come up again and again for execution
374  $connectionPool = GeneralUtility::makeInstance(ConnectionPool::class);
375  $connectionPool->getConnectionForTable(self::TABLE_NAME)->update(
376  self::TABLE_NAME,
377  ['disable' => 1],
378  ['uid' => (int)$row['uid']]
379  );
380  // Throw an exception to raise the problem
381  // @todo: This should most likely be changed to a specific exception.
382  throw new \UnexpectedValueException('Could not unserialize task', 1255083671);
383  }
384 
385  // The task is valid, return it
386  $task->setScheduler();
387  if ($task->getTaskGroup() === null) {
388  // Fix invalid task_group=NULL settings in order to avoid exceptions when saving on PostgreSQL
389  $task->setTaskGroup(0);
390  }
391  return $task;
392  }
393 
398  {
399  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
400  ->getQueryBuilderForTable(self::TABLE_NAME);
401 
402  $queryBuilder
403  ->select('serialized_task_object')
404  ->from(self::TABLE_NAME)
405  ->where(
406  $queryBuilder->expr()->eq('uid', $queryBuilder->createNamedParameter(‪$uid, ‪Connection::PARAM_INT)),
407  $queryBuilder->expr()->eq('deleted', $queryBuilder->createNamedParameter(0, ‪Connection::PARAM_INT)),
408  $queryBuilder->expr()->eq('disable', $queryBuilder->createNamedParameter(0, ‪Connection::PARAM_INT)),
409  $queryBuilder->expr()->neq('nextexecution', $queryBuilder->createNamedParameter(0, ‪Connection::PARAM_INT)),
410  $queryBuilder->expr()->lte('nextexecution', $queryBuilder->createNamedParameter(‪$GLOBALS['EXEC_TIME'], ‪Connection::PARAM_INT)),
411  );
412 
413  $result = $queryBuilder->executeQuery();
414  while ($row = $result->fetchAssociative()) {
415  try {
416  $task = $this->taskSerializer->deserialize($row['serialized_task_object']);
417  } catch (‪InvalidTaskException) {
418  continue;
419  }
420 
421  // Add the task to the list only if it is valid
422  if ($this->‪isValidTaskObject($task)) {
423  $task->‪setScheduler();
424  return $task;
425  }
426  }
427  return null;
428  }
429 
430  public function ‪isTaskMarkedAsRunning(‪AbstractTask $task): bool
431  {
432  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
433  ->getQueryBuilderForTable(self::TABLE_NAME);
434  $row = $queryBuilder
435  ->select('serialized_executions')
436  ->from(self::TABLE_NAME)
437  ->where(
438  $queryBuilder->expr()->eq('uid', $queryBuilder->createNamedParameter($task->‪getTaskUid(), ‪Connection::PARAM_INT))
439  )
440  ->executeQuery()
441  ->fetchAssociative();
442 
443  if ($row && !empty($row['serialized_executions'])) {
444  return true;
445  }
446  return false;
447  }
448 
455  public function ‪addExecutionToTask(‪AbstractTask $task): int
456  {
457  $row = $this->‪findRecordByUid($task->‪getTaskUid());
458 
459  $runningExecutions = [];
460  if ($row && !empty($row['serialized_executions'])) {
461  $runningExecutions = unserialize($row['serialized_executions']);
462  }
463  // Count the number of existing executions and use that number as a key
464  // (we need to know that number, because it is returned at the end of the method)
465  $numExecutions = count($runningExecutions);
466  $runningExecutions[$numExecutions] = time();
467  GeneralUtility::makeInstance(ConnectionPool::class)
468  ->getConnectionForTable(self::TABLE_NAME)
469  ->update(
470  self::TABLE_NAME,
471  [
472  'serialized_executions' => serialize($runningExecutions),
473  'lastexecution_time' => time(),
474  // Define the context in which the script is running
475  'lastexecution_context' => ‪Environment::isCli() ? 'CLI' : 'BE',
476  ],
477  [
478  'uid' => $task->‪getTaskUid(),
479  ],
480  [
481  'serialized_executions' => ‪Connection::PARAM_LOB,
482  ]
483  );
484  return $numExecutions;
485  }
486 
493  public function ‪removeExecutionOfTask(‪AbstractTask $task, int $executionID, array|string $failureReason = null): void
494  {
495  $row = $this->‪findRecordByUid($task->‪getTaskUid());
496  if ($row && $row['serialized_executions'] !== '') {
497  $runningExecutions = unserialize($row['serialized_executions']);
498  // Remove the selected execution
499  unset($runningExecutions[$executionID]);
500  if (!empty($runningExecutions)) {
501  // Re-serialize the updated executions list (if necessary)
502  $runningExecutionsSerialized = serialize($runningExecutions);
503  } else {
504  $runningExecutionsSerialized = '';
505  }
506  if (is_array($failureReason)) {
507  $failureReason = json_encode($failureReason);
508  }
509  // Save the updated executions list
510  GeneralUtility::makeInstance(ConnectionPool::class)
511  ->getConnectionForTable(self::TABLE_NAME)
512  ->update(
513  self::TABLE_NAME,
514  [
515  'serialized_executions' => $runningExecutionsSerialized,
516  'lastexecution_failure' => (string)$failureReason,
517  ],
518  [
519  'uid' => $task->‪getTaskUid(),
520  ],
521  [
522  'serialized_executions' => ‪Connection::PARAM_LOB,
523  ]
524  );
525  }
526  }
527 
534  {
535  // Set the serialized executions field to empty
536  $result = GeneralUtility::makeInstance(ConnectionPool::class)
537  ->getConnectionForTable(self::TABLE_NAME)
538  ->update(
539  self::TABLE_NAME,
540  ['serialized_executions' => ''],
541  ['uid' => $task->‪getTaskUid()],
542  ['serialized_executions' => ‪Connection::PARAM_LOB]
543  );
544  return (bool)$result;
545  }
546 
550  public function ‪hasTasks(): bool
551  {
552  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable(self::TABLE_NAME);
553  $queryBuilder->getRestrictions()->removeAll();
554  $queryBuilder
555  ->count('*')
556  ->from(self::TABLE_NAME)
557  ->where(
558  $queryBuilder->expr()->eq('deleted', 0)
559  );
560  return $queryBuilder->executeQuery()->fetchOne() > 0;
561  }
562 
563  protected function ‪isValidTaskObject($task): bool
564  {
565  return (new ‪TaskValidator())->isValid($task);
566  }
567 }
‪TYPO3\CMS\Scheduler\Domain\Repository\SchedulerTaskRepository\removeAllRegisteredExecutionsForTask
‪bool removeAllRegisteredExecutionsForTask(AbstractTask $task)
Definition: SchedulerTaskRepository.php:533
‪TYPO3\CMS\Scheduler\Domain\Repository\SchedulerTaskRepository\findNextExecutableTaskForUid
‪findNextExecutableTaskForUid(int $uid)
Definition: SchedulerTaskRepository.php:397
‪TYPO3\CMS\Core\Database\Connection\PARAM_INT
‪const PARAM_INT
Definition: Connection.php:52
‪TYPO3\CMS\Scheduler\Task\AbstractTask\getTaskUid
‪int getTaskUid()
Definition: AbstractTask.php:134
‪TYPO3\CMS\Scheduler\Task\AbstractTask\getRunOnNextCronJob
‪bool getRunOnNextCronJob()
Definition: AbstractTask.php:208
‪TYPO3\CMS\Scheduler\Task\AbstractTask\setTaskUid
‪setTaskUid($id)
Definition: AbstractTask.php:124
‪TYPO3\CMS\Scheduler\Domain\Repository\SchedulerTaskRepository\createValidTaskObjectOrDisableTask
‪createValidTaskObjectOrDisableTask(array $row)
Definition: SchedulerTaskRepository.php:362
‪TYPO3\CMS\Scheduler\Domain\Repository\SchedulerTaskRepository\findByUid
‪findByUid(int $uid)
Definition: SchedulerTaskRepository.php:176
‪TYPO3\CMS\Scheduler\Domain\Repository\SchedulerTaskRepository
Definition: SchedulerTaskRepository.php:36
‪TYPO3\CMS\Scheduler\Task\TaskSerializer
Definition: TaskSerializer.php:28
‪TYPO3\CMS\Scheduler\Domain\Repository
Definition: SchedulerTaskRepository.php:18
‪TYPO3\CMS\Scheduler\Task\AbstractTask\setDisabled
‪setDisabled($flag)
Definition: AbstractTask.php:184
‪TYPO3\CMS\Scheduler\Domain\Repository\SchedulerTaskRepository\TABLE_NAME
‪const TABLE_NAME
Definition: SchedulerTaskRepository.php:37
‪$fields
‪$fields
Definition: pages.php:5
‪TYPO3\CMS\Scheduler\Task\AbstractTask\getNextDueExecution
‪int getNextDueExecution()
Definition: AbstractTask.php:374
‪TYPO3\CMS\Scheduler\Domain\Repository\SchedulerTaskRepository\hasTasks
‪hasTasks()
Definition: SchedulerTaskRepository.php:550
‪TYPO3\CMS\Scheduler\Domain\Repository\SchedulerTaskRepository\isValidTaskObject
‪isValidTaskObject($task)
Definition: SchedulerTaskRepository.php:563
‪TYPO3\CMS\Scheduler\Domain\Repository\SchedulerTaskRepository\add
‪bool add(AbstractTask $task)
Definition: SchedulerTaskRepository.php:49
‪TYPO3\CMS\Scheduler\Domain\Repository\SchedulerTaskRepository\update
‪update(AbstractTask $task)
Definition: SchedulerTaskRepository.php:99
‪TYPO3\CMS\Scheduler\Domain\Repository\SchedulerTaskRepository\__construct
‪__construct(protected readonly TaskSerializer $taskSerializer,)
Definition: SchedulerTaskRepository.php:39
‪TYPO3\CMS\Scheduler\Task\AbstractTask\setScheduler
‪setScheduler()
Definition: AbstractTask.php:278
‪TYPO3\CMS\Scheduler\Domain\Repository\SchedulerTaskRepository\addExecutionToTask
‪int addExecutionToTask(AbstractTask $task)
Definition: SchedulerTaskRepository.php:455
‪TYPO3\CMS\Scheduler\Task\AbstractTask
Definition: AbstractTask.php:33
‪TYPO3\CMS\Scheduler\ProgressProviderInterface
Definition: ProgressProviderInterface.php:22
‪TYPO3\CMS\Scheduler\Task\AbstractTask\isDisabled
‪bool isDisabled()
Definition: AbstractTask.php:174
‪TYPO3\CMS\Core\Core\Environment\isCli
‪static isCli()
Definition: Environment.php:145
‪TYPO3\CMS\Scheduler\Exception
Definition: Exception.php:25
‪TYPO3\CMS\Scheduler\Task\AbstractTask\TYPE_RECURRING
‪const TYPE_RECURRING
Definition: AbstractTask.php:37
‪TYPO3\CMS\Scheduler\Domain\Repository\SchedulerTaskRepository\findNextExecutableTask
‪AbstractTask findNextExecutableTask()
Definition: SchedulerTaskRepository.php:205
‪TYPO3\CMS\Core\Database\Connection
Definition: Connection.php:41
‪TYPO3\CMS\Scheduler\Validation\Validator\TaskValidator
Definition: TaskValidator.php:23
‪TYPO3\CMS\Webhooks\Message\$uid
‪identifier readonly int $uid
Definition: PageModificationMessage.php:35
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:25
‪TYPO3\CMS\Scheduler\Task\AbstractTask\getTaskGroup
‪int null getTaskGroup()
Definition: AbstractTask.php:228
‪TYPO3\CMS\Core\Core\Environment
Definition: Environment.php:41
‪TYPO3\CMS\Scheduler\Domain\Repository\SchedulerTaskRepository\getGroupedTasks
‪getGroupedTasks()
Definition: SchedulerTaskRepository.php:251
‪TYPO3\CMS\Scheduler\Domain\Repository\SchedulerTaskRepository\removeExecutionOfTask
‪removeExecutionOfTask(AbstractTask $task, int $executionID, array|string $failureReason=null)
Definition: SchedulerTaskRepository.php:493
‪TYPO3\CMS\Core\Database\ConnectionPool
Definition: ConnectionPool.php:46
‪TYPO3\CMS\Scheduler\Task\AbstractTask\getDescription
‪string getDescription()
Definition: AbstractTask.php:268
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:52
‪TYPO3\CMS\Scheduler\Domain\Repository\SchedulerTaskRepository\isTaskMarkedAsRunning
‪isTaskMarkedAsRunning(AbstractTask $task)
Definition: SchedulerTaskRepository.php:430
‪TYPO3\CMS\Scheduler\Task\AbstractTask\unsetScheduler
‪unsetScheduler()
Definition: AbstractTask.php:291
‪TYPO3\CMS\Scheduler\Service\TaskService
Definition: TaskService.php:27
‪TYPO3\CMS\Scheduler\Task\AbstractTask\setExecutionTime
‪setExecutionTime($timestamp)
Definition: AbstractTask.php:218
‪TYPO3\CMS\Scheduler\Exception\InvalidTaskException
Definition: InvalidTaskException.php:26
‪TYPO3\CMS\Core\Database\Connection\PARAM_LOB
‪const PARAM_LOB
Definition: Connection.php:62
‪TYPO3\CMS\Scheduler\Domain\Repository\SchedulerTaskRepository\findRecordByUid
‪array null findRecordByUid(int $uid)
Definition: SchedulerTaskRepository.php:148