Scheduler Tasks

Kommandos ausführen

Kommandos können via Scheduler ausgeführt werden und so Tasks im Hintergrund erledigen.

commandControllers

Die commandControllers wurden wieder abgelöst von Symfony\Component\Console\Command\Command. Leider ist es dadurch alles wieder komplizierter geworden, vor allem der Zugriff auf die TYPO3 Unmgebung ist nihct mehr so einfach. ich versuche hier einen kurzen Überblick zu geben über die wesentliche Verwendung der Symfony Command basierten Routinen für den Scheduler. Die Doku der commandControllers ist hier im Archiv.

Erstellt: 03/2023| Geändert: 03/2023

Konfiguration

Zunächst in der Datei Configuration/Services.yaml das Command registrieren:

services:
  RSYS\RsystemplateBootstrap\Command\CleanAdressesCommand:
    tags:
      - name: console.command
        command: rsystemplate_bootstrap:cleanadresses
        identifier: 'rsystemplate_bootstrap:cleanadresses'
        schedulable: true

Dann die Klasse anlegen in Classes/Commend/CleanAdressesCommand.php - hier erst mal das Gerüst, ohne Methoden:

<?php
namespace RSYS\RsystemplateBootstrap\Command;

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
use TYPO3\CMS\Backend\Utility\BackendUtility;
use TYPO3\CMS\Core\Core\Bootstrap;
use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\DataHandling\DataHandler;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use RSYS\RsystemplateBootstrap\Utility\ArrayUtility;

class CleanAdressesCommand extends Command {
  /**
  * @var \TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface
  */
  protected $configurationManager;

  /**
  * TS settings
  * @var Array
  */
  protected $settings=Array();
}

Methoden

Konfiguration

/**
* Configure the command by defining the name, options and arguments
*/
protected function configure()
{
  $this->setDescription('Clean address records for non-confirmed addresses to be deleted.');
  $this->setHelp('Clean address records.' . LF . 'If you want to get more detailed information, use the --verbose option.');
  $this->addOption(
    'dry-run',
    null,
    InputOption::VALUE_NONE,
    'If this option is set, the records will not actually be deleted, but just the output which records would be deleted are shown'
  );
}

Hauptfunktion

Hier der Rahmen der Einstiegs Funktion:

/**
 * Executes the command for showing sys_log entries
 *
 * @param InputInterface $input
 * @param OutputInterface $output
 */
protected function execute(InputInterface $input, OutputInterface $output)
{
 ...

  # this must be 0
  return 0;
}

Innerhalb dieser Funktion hier einige wichtige Code Schnipsel:

Konfiguration

$this->configurationManager = GeneralUtility::makeInstance(\TYPO3\CMS\Extbase\Configuration\ConfigurationManager::class);

// settings
$typoscriptFull = $this->configurationManager->getConfiguration(\TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface::CONFIGURATION_TYPE_FULL_TYPOSCRIPT);
$this->settings = ArrayUtility::replaceKeys($typoscriptFull['plugin.']['tx_rsystemplatebootstrap.']['settings.']);

Optionen

Am Beispiel der DryRun Option:

// type unsafe comparison and explicit boolean setting on purpose
$dryRun = $input->hasOption('dry-run') && $input->getOption('dry-run') != false ? true : false;

Aktion

Hier eine Beispiel Aktion zum löschen von Adressen:

$addressesDeleted = $this->removeDeleted($dryRun);
if(count($addressesDeleted) > 0) {
  $io->text('Deleted ' . count($addressesDeleted)  . ' records.');
}

Der Code $io->text gibt Text aus wenn man es von der Konsole aus startet

Die Löschroutine

protected function removeDeleted($dryRun)
{
  // Register page
  $pageIdUnsubscribed = $this->settings['newsletter']['pid']['unsubscribedAddressFolder'];

  // Traverse tables of records that belongs to page
  $tableName = 'tt_address';

  // Select all records belonging to page:
  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($tableName);
  $queryBuilder->getRestrictions()->removeAll();
  $constraints = [];
  $constraints[] = $queryBuilder->expr()->eq(
    'pid',
    $queryBuilder->createNamedParameter($pageIdUnsubscribed, \PDO::PARAM_INT)
  );
  $constraints[] = $queryBuilder->expr()->eq(
    'deleted',
    $queryBuilder->createNamedParameter(1, \PDO::PARAM_INT)
  );
  $result = $queryBuilder
    ->select('*')
    ->from($tableName)
    ->where(...$constraints)
    ->execute();

  $addressesDeleted = array();
  while ($row = $result->fetch()) {
    if(isset($row['email'])) {
      $entry = array();
      $entry['email'] = $row['email'];
      $entry['uid'] = $row['uid'];
      $entry['pid'] = $row['pid'];
      $entry['date'] = date('d.m.Y H:i', $row['tstamp']);
      $entry['tstamp'] =  $row['tstamp'];
      $addressesDeleted[] =  $entry;
    }
  }

  // delete !
  if(! $dryRun) {
    try {
       $queryBuilder->delete($tableName)
         ->where(...$constraints)
         ->execute();
    } catch (\Doctrine\DBAL\DBALException $e) {
    }
  }
  return $addressesDeleted;
}

Zurück kommt ein Array der gelöschten Adressen zur weiteren Verarbeitung, z.B: eine Mail versenden.

Ausführen

Scheduler

Im Scheduler eine Task anlegen, dann auswählen Konsolenbefehle ausführen. Dann kann man nach dem speichern unten den Befehl auswählen (Planbarer Befehl. Speichern und erneut öffnen, um Argumente zu definieren ):

rsystemplate_bootstrap:cleanadresses: Clean address records for non-confirmed addresses to be deleted.

Kommandozeile

Zum Debuggen, oder direkt per Cron kann man den Befehl ausführen wie folgt:

php typo3/sysext/core/bin/typo3  rsystemplate_bootstrap:cleanadresses

Erstellt: 03/2023| Geändert: 03/2023