From db81cd4d88aec242d0f260304e0fe991d507db94 Mon Sep 17 00:00:00 2001
From: Daniel Siepmann <coding@daniel-siepmann.de>
Date: Mon, 19 Aug 2024 15:22:56 +0200
Subject: [PATCH] Add TYPO3 13 LTS Support

Relates: #11322
---
 .github/workflows/ci.yaml                     |   8 +
 Classes/Caching/PageCacheTimeout.php          |   8 +-
 Classes/Controller/AbstractController.php     |  11 +-
 .../Domain/DestinationData/ImportFactory.php  |  16 +-
 .../Domain/Repository/CategoryRepository.php  |   2 +-
 Classes/Domain/Repository/DateRepository.php  |   2 +-
 .../Domain/Repository/OrganizerRepository.php |  11 +
 Classes/Extbase/AddSpecialProperties.php      |   2 +-
 Classes/Service/CategoryService.php           |  32 +-
 Classes/Service/Cleanup/Database.php          |   3 +-
 Classes/Service/Cleanup/Files.php             |  21 +-
 Classes/Service/DataProcessingForModels.php   |   9 +-
 .../Service/DestinationDataImportService.php  |  15 +-
 .../ArrayBasedConfigurationService.php        |  43 +++
 .../ConfigurationServiceInterface.php         |  15 +
 .../ExtbaseConfigurationService.php           |  66 +++++
 .../FilesAssignment.php                       |  12 +-
 .../DestinationDataImportService/Slugger.php  |  11 +-
 .../UrlFactory.php                            |  24 +-
 .../ExtbaseConfigurationManagerService.php    |  41 +++
 Classes/Updates/MigrateOldLocations.php       |   5 +-
 .../Updates/MigratePluginsFromListToCtype.php |  59 ++++
 Configuration/FlexForms/DateList.xml          | 275 ++++++++----------
 Configuration/FlexForms/DateSearch.xml        |  43 ++-
 Configuration/FlexForms/DateShow.xml          |  23 +-
 Configuration/FlexForms/Selected.xml          |  19 +-
 Configuration/Icons.php                       |  16 +
 Configuration/Services.yaml                   |   5 +
 Configuration/TCA/Overrides/tt_content.php    |  40 +--
 .../TCA/tx_events_domain_model_event.php      |  20 +-
 .../TCA/tx_events_domain_model_import.php     |   2 +-
 Configuration/TypoScript/constants.typoscript |   2 +-
 Documentation/Changelog/5.0.0.rst             |  35 +++
 Documentation/Index.rst                       |   2 +
 Documentation/Maintenance.rst                 |  16 +
 Documentation/Settings.cfg                    |  11 -
 Documentation/guides.xml                      |  21 ++
 .../Language/de.locallang_csh_event.xlf       |  12 +
 .../Private/Language/locallang_csh_event.xlf  |   9 +
 .../Functional/AbstractFunctionalTestCase.php |   1 +
 Tests/Functional/Frontend/CacheTest.php       |   5 +-
 .../DatesTestFixtures/DateMetaTags.php        |   3 +-
 .../DatesTestFixtures/DateOpenGraphTags.php   |   3 +-
 .../DatesTestFixtures/DatePageTitle.php       |   3 +-
 .../DatesTestFixtures/DateSocialMediaTags.php |   3 +-
 .../Returns404IfEventIsHidden.php             |   3 +-
 .../ReturnsDateWithinTimeSpan.php             |   3 +-
 ...rnsOnlyDatesWithAvailableEventByDemand.php |   3 +-
 .../ReturnsUpcomingDates.php                  |   3 +-
 .../EventsTestFixtures/EventMetaTags.php      |   3 +-
 .../EventsTestFixtures/EventOpenGraphTags.php |   3 +-
 .../EventsTestFixtures/EventPageTitle.php     |   3 +-
 .../EventSocialMediaTags.php                  |   3 +-
 .../FilterByASingleLocationViaFlexform.php    |   3 +-
 .../FilterByTwoLocationsViaFlexform.php       |   3 +-
 ...FilterDatesByParentLocationViaFlexform.php |   3 +-
 .../Extensions/example/Classes/UserFunc.php   |  23 +-
 .../Extensions/example/ext_localconf.php      |   8 +-
 .../Database/FeaturesImportConfiguration.php  |   1 +
 ...ateOfRecurringDatesImportConfiguration.php |   1 +
 .../Database/MinimalImportConfiguration.php   |   1 +
 .../Model/Dto/DateDemandFactoryTest.php       |  34 +--
 Tests/Unit/Domain/Model/EventTest.php         |   4 +-
 Tests/Unit/Domain/Model/ImportTest.php        |  26 +-
 .../Controller/DateListVariablesTest.php      |  28 +-
 .../Controller/DateSearchVariablesTest.php    |  20 +-
 .../DatesFactoryTest.php                      |   6 +-
 .../LocationAssignmentTest.php                |   4 +-
 .../UrlFactoryTest.php                        |   8 +-
 composer.json                                 |  25 +-
 ext_emconf.php                                |   2 +-
 ext_localconf.php                             |  28 +-
 phpstan-baseline.neon                         |   9 +-
 73 files changed, 773 insertions(+), 473 deletions(-)
 create mode 100644 Classes/Service/DestinationDataImportService/ArrayBasedConfigurationService.php
 create mode 100644 Classes/Service/DestinationDataImportService/ConfigurationServiceInterface.php
 create mode 100644 Classes/Service/DestinationDataImportService/ExtbaseConfigurationService.php
 create mode 100644 Classes/Service/ExtbaseConfigurationManagerService.php
 create mode 100644 Classes/Updates/MigratePluginsFromListToCtype.php
 create mode 100644 Configuration/Icons.php
 create mode 100644 Documentation/Changelog/5.0.0.rst
 create mode 100644 Documentation/Maintenance.rst
 delete mode 100644 Documentation/Settings.cfg
 create mode 100644 Documentation/guides.xml

diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml
index c689855..8827529 100644
--- a/.github/workflows/ci.yaml
+++ b/.github/workflows/ci.yaml
@@ -90,6 +90,10 @@ jobs:
             typo3-version: '^12.4'
           - php-version: '8.3'
             typo3-version: '^12.4'
+          - php-version: '8.2'
+            typo3-version: '^13.4'
+          - php-version: '8.3'
+            typo3-version: '^13.4'
     steps:
       - uses: actions/checkout@v3
 
@@ -119,6 +123,10 @@ jobs:
             typo3-version: '^12.4'
           - php-version: '8.3'
             typo3-version: '^12.4'
+          - php-version: '8.2'
+            typo3-version: '^13.4'
+          - php-version: '8.3'
+            typo3-version: '^13.4'
     steps:
       - uses: actions/checkout@v3
 
diff --git a/Classes/Caching/PageCacheTimeout.php b/Classes/Caching/PageCacheTimeout.php
index 1492e89..1d309b6 100644
--- a/Classes/Caching/PageCacheTimeout.php
+++ b/Classes/Caching/PageCacheTimeout.php
@@ -26,7 +26,6 @@ namespace WerkraumMedia\Events\Caching;
 use DateTime;
 use DateTimeImmutable;
 use InvalidArgumentException;
-use TYPO3\CMS\Core\Cache\CacheManager;
 use TYPO3\CMS\Core\Cache\Frontend\FrontendInterface;
 use TYPO3\CMS\Core\Context\Context;
 use TYPO3\CMS\Core\SingletonInterface;
@@ -44,13 +43,10 @@ class PageCacheTimeout implements SingletonInterface
 {
     private ?DateTimeImmutable $timeout = null;
 
-    private FrontendInterface $runtimeCache;
-
     public function __construct(
-        CacheManager $cacheManager,
-        private readonly Context $context
+        private readonly FrontendInterface $runtimeCache,
+        private readonly Context $context,
     ) {
-        $this->runtimeCache = $cacheManager->getCache('runtime');
     }
 
     public function modifyCacheLifetimeForPage(ModifyCacheLifetimeForPageEvent $event): void
diff --git a/Classes/Controller/AbstractController.php b/Classes/Controller/AbstractController.php
index b674565..cfe7ac9 100644
--- a/Classes/Controller/AbstractController.php
+++ b/Classes/Controller/AbstractController.php
@@ -25,13 +25,14 @@ namespace WerkraumMedia\Events\Controller;
 
 use TYPO3\CMS\Core\Http\PropagateResponseException;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
+use TYPO3\CMS\Core\View\ViewInterface;
 use TYPO3\CMS\Extbase\Mvc\Controller\ActionController;
 use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
 use TYPO3\CMS\Frontend\Controller\ErrorController;
-use TYPO3Fluid\Fluid\View\ViewInterface;
+use TYPO3Fluid\Fluid\View\ViewInterface as FluidStandaloneViewInterface;
 use WerkraumMedia\Events\Caching\CacheManager;
 
-class AbstractController extends ActionController
+abstract class AbstractController extends ActionController
 {
     /**
      * @var CacheManager
@@ -60,17 +61,13 @@ class AbstractController extends ActionController
     /**
      * Extend original to also add data from current cobject if available.
      */
-    protected function resolveView(): ViewInterface
+    protected function initializeView(ViewInterface|FluidStandaloneViewInterface $view): void
     {
-        $view = parent::resolveView();
-
         $view->assign('data', []);
         $cObject = $this->request->getAttribute('currentContentObject');
         if ($cObject instanceof ContentObjectRenderer && is_array($cObject->data)) {
             $view->assign('data', $cObject->data);
         }
-
-        return $view;
     }
 
     protected function trigger404(string $message): void
diff --git a/Classes/Domain/DestinationData/ImportFactory.php b/Classes/Domain/DestinationData/ImportFactory.php
index 9bd5a56..30101e6 100644
--- a/Classes/Domain/DestinationData/ImportFactory.php
+++ b/Classes/Domain/DestinationData/ImportFactory.php
@@ -5,13 +5,13 @@ declare(strict_types=1);
 namespace WerkraumMedia\Events\Domain\DestinationData;
 
 use Exception;
-use PDO;
 use TYPO3\CMS\Core\Database\ConnectionPool;
 use TYPO3\CMS\Core\Resource\Folder;
 use TYPO3\CMS\Core\Resource\ResourceFactory;
 use TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper;
 use TYPO3\CMS\Extbase\Persistence\Generic\Session;
 use WerkraumMedia\Events\Domain\Model\Import;
+use WerkraumMedia\Events\Service\ExtbaseConfigurationManagerService;
 
 final class ImportFactory
 {
@@ -24,7 +24,8 @@ final class ImportFactory
         private readonly ConnectionPool $connectionPool,
         private readonly Session $extbasePersistenceSession,
         private readonly DataMapper $dataMapper,
-        private readonly ResourceFactory $resourceFactory
+        private readonly ResourceFactory $resourceFactory,
+        private readonly ExtbaseConfigurationManagerService $extbaseConfigurationManagerService,
     ) {
     }
 
@@ -49,14 +50,14 @@ final class ImportFactory
         $qb = $this->connectionPool->getQueryBuilderForTable('tx_events_domain_model_import');
         $qb->select('*');
         $qb->from('tx_events_domain_model_import');
-        $qb->where($qb->expr()->eq('uid', $qb->createNamedParameter($uid, PDO::PARAM_INT)));
+        $qb->where($qb->expr()->eq('uid', $qb->createNamedParameter($uid)));
 
-        $result = $qb->executeQuery()->fetch();
+        $result = $qb->executeQuery()->fetchAssociative();
         if (is_array($result) === false) {
             throw new Exception('Could not fetch import record with uid "' . $uid . '".', 1643267492);
         }
 
-        $result = array_map('strval', $result);
+        $result = array_map(strval(...), $result);
 
         return $result;
     }
@@ -67,13 +68,13 @@ final class ImportFactory
         $qb->select('*');
         $qb->from('tx_events_domain_model_import');
 
-        $result = $qb->executeQuery()->fetchAll();
+        $result = $qb->executeQuery()->fetchAllAssociative();
         if (count($result) === 0) {
             throw new Exception('Could not fetch any import record.', 1643267492);
         }
 
         foreach ($result as $key => $entry) {
-            $result[$key] = array_map('strval', $entry);
+            $result[$key] = array_map(strval(...), $entry);
         }
 
         return $result;
@@ -94,6 +95,7 @@ final class ImportFactory
     {
         $this->folderInstance = $this->resourceFactory->getFolderObjectFromCombinedIdentifier($data['files_folder']);
         $this->extbasePersistenceSession->registerObject($this->folderInstance, $data['files_folder']);
+        $this->extbaseConfigurationManagerService->configureForBackend();
     }
 
     private function cleanupWorkarounds(): void
diff --git a/Classes/Domain/Repository/CategoryRepository.php b/Classes/Domain/Repository/CategoryRepository.php
index 9838152..ddf3758 100644
--- a/Classes/Domain/Repository/CategoryRepository.php
+++ b/Classes/Domain/Repository/CategoryRepository.php
@@ -75,7 +75,7 @@ final class CategoryRepository extends Repository
 
         return $this->dataMapper->map(
             Category::class,
-            $qb->executeQuery()->fetchAll()
+            $qb->executeQuery()->fetchAllAssociative()
         );
     }
 
diff --git a/Classes/Domain/Repository/DateRepository.php b/Classes/Domain/Repository/DateRepository.php
index 0905bf6..0c5bc3e 100644
--- a/Classes/Domain/Repository/DateRepository.php
+++ b/Classes/Domain/Repository/DateRepository.php
@@ -304,7 +304,7 @@ final class DateRepository extends Repository
             )->orderBy('tx_events_domain_model_date.start')
         ;
 
-        return $statement->executeQuery()->fetchAll();
+        return $statement->executeQuery()->fetchAllAssociative();
     }
 
     private function createEventConstraint(
diff --git a/Classes/Domain/Repository/OrganizerRepository.php b/Classes/Domain/Repository/OrganizerRepository.php
index a07c0cb..202d685 100644
--- a/Classes/Domain/Repository/OrganizerRepository.php
+++ b/Classes/Domain/Repository/OrganizerRepository.php
@@ -18,7 +18,18 @@ namespace WerkraumMedia\Events\Domain\Repository;
  */
 
 use TYPO3\CMS\Extbase\Persistence\Repository;
+use WerkraumMedia\Events\Domain\Model\Organizer;
 
 final class OrganizerRepository extends Repository
 {
+    public function findOneByName(string $name): ?Organizer
+    {
+        $organizer = $this->findOneBy(['name' => $name]);
+
+        if ($organizer instanceof Organizer) {
+            return $organizer;
+        }
+
+        return null;
+    }
 }
diff --git a/Classes/Extbase/AddSpecialProperties.php b/Classes/Extbase/AddSpecialProperties.php
index 344713d..b752a5f 100644
--- a/Classes/Extbase/AddSpecialProperties.php
+++ b/Classes/Extbase/AddSpecialProperties.php
@@ -72,7 +72,7 @@ final class AddSpecialProperties
         $qb->where($qb->expr()->eq('postponed_date', $uidOfReferencedDate));
         $qb->setMaxResults(1);
 
-        $result = $qb->executeQuery()->fetch();
+        $result = $qb->executeQuery()->fetchAssociative();
 
         if ($result === false) {
             return null;
diff --git a/Classes/Service/CategoryService.php b/Classes/Service/CategoryService.php
index b42cb0c..9117b17 100644
--- a/Classes/Service/CategoryService.php
+++ b/Classes/Service/CategoryService.php
@@ -4,6 +4,7 @@ declare(strict_types=1);
 
 namespace WerkraumMedia\Events\Service;
 
+use RuntimeException;
 use TYPO3\CMS\Core\Cache\CacheManager;
 use TYPO3\CMS\Core\Cache\Frontend\FrontendInterface;
 use TYPO3\CMS\Core\Database\Connection;
@@ -13,9 +14,9 @@ use TYPO3\CMS\Core\Utility\GeneralUtility;
 
 final class CategoryService
 {
-    private TimeTracker $timeTracker;
+    private readonly TimeTracker $timeTracker;
 
-    private FrontendInterface $cache;
+    private readonly FrontendInterface $cache;
 
     public function __construct()
     {
@@ -77,17 +78,18 @@ final class CategoryService
             ->executeQuery()
         ;
 
-        while ($row = $res->fetch()) {
-            if (is_array($row) === false) {
-                continue;
-            }
-
+        foreach ($res->fetchAllAssociative() as $row) {
             $counter++;
             if ($counter > 10000) {
                 $this->timeTracker->setTSlogMessage('EXT:dd_events: one or more recursive categories where found');
                 return implode(',', $result);
             }
-            $subcategories = $this->getChildrenCategoriesRecursive($row['uid'], $counter);
+            $uid = $row['uid'];
+            if (is_numeric($uid) === false) {
+                throw new RuntimeException('Given uid was not numeric, which we never expect as UID column within DB is numeric.', 1728998121);
+            }
+
+            $subcategories = $this->getChildrenCategoriesRecursive((string)$uid, $counter);
             $result[] = $row['uid'] . ($subcategories ? ',' . $subcategories : '');
         }
 
@@ -100,11 +102,10 @@ final class CategoryService
      */
     protected function getUidListFromRecords(string $idList): string
     {
-        $list = [];
         $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
             ->getQueryBuilderForTable('sys_category')
         ;
-        $rows = $queryBuilder
+        $uids = $queryBuilder
             ->select('uid')
             ->from('sys_category')
             ->where($queryBuilder->expr()->in(
@@ -112,16 +113,9 @@ final class CategoryService
                 $queryBuilder->createNamedParameter(explode(',', $idList), Connection::PARAM_INT_ARRAY)
             ))
             ->executeQuery()
-            ->fetchAll()
+            ->fetchFirstColumn()
         ;
-        foreach ($rows as $row) {
-            if (is_array($row) === false) {
-                continue;
-            }
 
-            $list[] = $row['uid'];
-        }
-
-        return implode(',', $list);
+        return implode(',', $uids);
     }
 }
diff --git a/Classes/Service/Cleanup/Database.php b/Classes/Service/Cleanup/Database.php
index 4a6e642..9bb409e 100644
--- a/Classes/Service/Cleanup/Database.php
+++ b/Classes/Service/Cleanup/Database.php
@@ -24,7 +24,6 @@ namespace WerkraumMedia\Events\Service\Cleanup;
  */
 
 use DateTimeImmutable;
-use PDO;
 use TYPO3\CMS\Core\Database\Connection;
 use TYPO3\CMS\Core\Database\ConnectionPool;
 
@@ -88,7 +87,7 @@ final class Database
         $recordUids = $queryBuilder->select('event.uid')
             ->from(self::EVENT_TABLE, 'event')
             ->leftJoin('event', self::DATE_TABLE, 'date', $queryBuilder->expr()->eq('date.event', 'event.uid'))->where($queryBuilder->expr()->isNull('date.uid'))->executeQuery()
-            ->fetchAll(PDO::FETCH_COLUMN)
+            ->fetchFirstColumn()
         ;
 
         $queryBuilder = $this->connectionPool->getQueryBuilderForTable(self::EVENT_TABLE);
diff --git a/Classes/Service/Cleanup/Files.php b/Classes/Service/Cleanup/Files.php
index d5fd979..70f5919 100644
--- a/Classes/Service/Cleanup/Files.php
+++ b/Classes/Service/Cleanup/Files.php
@@ -23,7 +23,7 @@ namespace WerkraumMedia\Events\Service\Cleanup;
  * 02110-1301, USA.
  */
 
-use PDO;
+use RuntimeException;
 use TYPO3\CMS\Core\Database\Connection;
 use TYPO3\CMS\Core\Database\ConnectionPool;
 use TYPO3\CMS\Core\Resource\StorageRepository;
@@ -84,16 +84,12 @@ final class Files
         $referencesQuery->orderBy('tablenames');
         $referencesQuery->addOrderBy('uid_foreign');
 
-        $references = $referencesQuery->executeQuery();
+        $references = $referencesQuery->executeQuery()->fetchAllAssociative();
 
         $uidsPerTable = [];
         $referenceUidsToMarkAsDeleted = [];
 
-        while ($reference = $references->fetch()) {
-            if (is_array($reference) === false) {
-                continue;
-            }
-
+        foreach ($references as $reference) {
             if ($reference['tablenames'] === '') {
                 $referenceUidsToMarkAsDeleted[] = $reference['uid'];
                 continue;
@@ -112,7 +108,7 @@ final class Files
                 ...$referenceUidsToMarkAsDeleted,
                 ...array_keys(array_diff(
                     $records,
-                    $queryBuilder->executeQuery()->fetchAll(PDO::FETCH_COLUMN)
+                    $queryBuilder->executeQuery()->fetchFirstColumn()
                 )),
             ];
         }
@@ -249,11 +245,16 @@ final class Files
         foreach ($queryBuilder->executeQuery()->iterateAssociative() as $reference) {
             $file = [];
             $fileUid = (int)$reference['uid_local'];
+            $tableNames = $reference['tablenames'];
+
+            if (is_string($tableNames) === false) {
+                throw new RuntimeException('Fetched "tablenames" was not of type string. But it should be a string within the db.', 1728998600);
+            }
 
             if (
                 (
-                    str_starts_with((string)$reference['tablenames'], 'tx_events_domain_model_')
-                    || $reference['tablenames'] === ''
+                    str_starts_with($tableNames, 'tx_events_domain_model_')
+                    || $tableNames === ''
                 ) && $reference['deleted'] == 1
             ) {
                 $file = $files[$fileUid] ?? [];
diff --git a/Classes/Service/DataProcessingForModels.php b/Classes/Service/DataProcessingForModels.php
index a25d963..e72a223 100644
--- a/Classes/Service/DataProcessingForModels.php
+++ b/Classes/Service/DataProcessingForModels.php
@@ -113,7 +113,14 @@ final class DataProcessingForModels implements SingletonInterface
 
     private function getData(AbstractEntity $entity): array
     {
-        $row = $this->connection->select(['*'], $this->getTable($entity), ['uid' => $entity->getUid()])->fetch();
+        $row = $this->connection
+            ->select(
+                ['*'],
+                $this->getTable($entity),
+                ['uid' => $entity->getUid()]
+            )
+            ->fetchAssociative()
+        ;
         if (is_array($row)) {
             return $row;
         }
diff --git a/Classes/Service/DestinationDataImportService.php b/Classes/Service/DestinationDataImportService.php
index 36df56c..edf57a0 100644
--- a/Classes/Service/DestinationDataImportService.php
+++ b/Classes/Service/DestinationDataImportService.php
@@ -38,14 +38,8 @@ final class DestinationDataImportService
 
     private Event $tmpCurrentEvent;
 
-    /**
-     * @var Logger
-     */
-    private $logger;
+    private readonly Logger $logger;
 
-    /**
-     * ImportService constructor.
-     */
     public function __construct(
         private readonly EventRepository $eventRepository,
         private readonly OrganizerRepository $organizerRepository,
@@ -60,8 +54,10 @@ final class DestinationDataImportService
         private readonly Slugger $slugger,
         private readonly CacheManager $cacheManager,
         private readonly DataHandler $dataHandler,
-        private readonly EventDispatcher $eventDispatcher
+        private readonly EventDispatcher $eventDispatcher,
+        LogManager $logManager,
     ) {
+        $this->logger = $logManager->getLogger(self::class);
     }
 
     public function import(
@@ -83,7 +79,6 @@ final class DestinationDataImportService
 
         // Set Configuration
         $this->configurationManager->setConfiguration(array_merge($frameworkConfiguration, $persistenceConfiguration));
-        $this->logger = GeneralUtility::makeInstance(LogManager::class)->getLogger(self::class);
         $this->logger->info('Starting Destination Data Import Service');
 
         try {
@@ -412,7 +407,7 @@ final class DestinationDataImportService
 
     private function getOrCreateEvent(string $globalId, string $title): Event
     {
-        $event = $this->eventRepository->findOneByGlobalId($globalId);
+        $event = $this->eventRepository->findOneBy(['globalId' => $globalId]);
 
         if ($event instanceof Event) {
             $this->logger->info(
diff --git a/Classes/Service/DestinationDataImportService/ArrayBasedConfigurationService.php b/Classes/Service/DestinationDataImportService/ArrayBasedConfigurationService.php
new file mode 100644
index 0000000..35dc4cc
--- /dev/null
+++ b/Classes/Service/DestinationDataImportService/ArrayBasedConfigurationService.php
@@ -0,0 +1,43 @@
+<?php
+
+declare(strict_types=1);
+
+namespace WerkraumMedia\Events\Service\DestinationDataImportService;
+
+final class ArrayBasedConfigurationService implements ConfigurationServiceInterface
+{
+    public function __construct(
+        private readonly array $settings
+    ) {
+    }
+
+    public function getLicenseKey(): string
+    {
+        return $this->settings['license'] ?? '';
+    }
+
+    public function getRestType(): string
+    {
+        return $this->settings['restType'] ?? '';
+    }
+
+    public function getRestMode(): string
+    {
+        return $this->settings['restMode'] ?? '';
+    }
+
+    public function getRestLimit(): string
+    {
+        return $this->settings['restLimit'] ?? '';
+    }
+
+    public function getRestTemplate(): string
+    {
+        return $this->settings['restTemplate'] ?? '';
+    }
+
+    public function getRestUrl(): string
+    {
+        return $this->settings['restUrl'] ?? '';
+    }
+}
diff --git a/Classes/Service/DestinationDataImportService/ConfigurationServiceInterface.php b/Classes/Service/DestinationDataImportService/ConfigurationServiceInterface.php
new file mode 100644
index 0000000..6724bbe
--- /dev/null
+++ b/Classes/Service/DestinationDataImportService/ConfigurationServiceInterface.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace WerkraumMedia\Events\Service\DestinationDataImportService;
+
+interface ConfigurationServiceInterface
+{
+    public function getLicenseKey(): string;
+    public function getRestType(): string;
+    public function getRestMode(): string;
+    public function getRestLimit(): string;
+    public function getRestTemplate(): string;
+    public function getRestUrl(): string;
+}
diff --git a/Classes/Service/DestinationDataImportService/ExtbaseConfigurationService.php b/Classes/Service/DestinationDataImportService/ExtbaseConfigurationService.php
new file mode 100644
index 0000000..44b7e65
--- /dev/null
+++ b/Classes/Service/DestinationDataImportService/ExtbaseConfigurationService.php
@@ -0,0 +1,66 @@
+<?php
+
+declare(strict_types=1);
+
+namespace WerkraumMedia\Events\Service\DestinationDataImportService;
+
+use TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface;
+use WerkraumMedia\Events\Service\ExtbaseConfigurationManagerService;
+
+final class ExtbaseConfigurationService implements ConfigurationServiceInterface
+{
+    private array $settings = [];
+
+    public function __construct(
+        private ExtbaseConfigurationManagerService $configurationManager
+    ) {
+    }
+
+    public function getLicenseKey(): string
+    {
+        return $this->getSettings()['license'] ?? '';
+    }
+
+    public function getRestType(): string
+    {
+        return $this->getSettings()['restType'] ?? '';
+    }
+
+    public function getRestMode(): string
+    {
+        return $this->getSettings()['restMode'] ?? '';
+    }
+
+    public function getRestLimit(): string
+    {
+        return $this->getSettings()['restLimit'] ?? '';
+    }
+
+    public function getRestTemplate(): string
+    {
+        return $this->getSettings()['restTemplate'] ?? '';
+    }
+
+    public function getRestUrl(): string
+    {
+        return $this->getSettings()['restUrl'] ?? '';
+    }
+
+    private function getSettings(): array
+    {
+        if ($this->settings !== []) {
+            return $this->settings;
+        }
+
+        $fullTypoScript = $this->configurationManager
+            ->getInstanceWithBackendContext()
+            ->getConfiguration(ConfigurationManagerInterface::CONFIGURATION_TYPE_FULL_TYPOSCRIPT)
+        ;
+
+        $this->settings = $fullTypoScript['module.']['tx_events.']['settings.']['destinationData.']
+            ?? $fullTypoScript['module.']['tx_events_pi1.']['settings.']['destinationData.']
+            ?? [];
+
+        return $this->settings;
+    }
+}
diff --git a/Classes/Service/DestinationDataImportService/FilesAssignment.php b/Classes/Service/DestinationDataImportService/FilesAssignment.php
index 04c7c4d..306bb2a 100644
--- a/Classes/Service/DestinationDataImportService/FilesAssignment.php
+++ b/Classes/Service/DestinationDataImportService/FilesAssignment.php
@@ -27,7 +27,8 @@ use Exception;
 use Psr\Log\LoggerInterface;
 use SplFileInfo;
 use TYPO3\CMS\Core\Log\LogManager;
-use TYPO3\CMS\Core\Resource\DuplicationBehavior;
+use TYPO3\CMS\Core\Resource\DuplicationBehavior as OldDuplicationBehavior;
+use TYPO3\CMS\Core\Resource\Enum\DuplicationBehavior;
 use TYPO3\CMS\Core\Resource\File;
 use TYPO3\CMS\Core\Resource\Folder;
 use TYPO3\CMS\Core\Resource\Index\MetaDataRepository;
@@ -76,7 +77,14 @@ final class FilesAssignment
                 $this->logger->info('File already exists.', [$orgFileNameSanitized]);
             } elseif ($filename = $this->loadFile($fileUrl)) {
                 $this->logger->info('Adding file to FAL.', [$filename]);
-                $importFolder->addFile($filename, $orgFileNameSanitized, DuplicationBehavior::REPLACE);
+
+                // TODO: typo3/cms-core:14.0 Remove the fallback to old behaviour, only use new one.
+                $behaviour = OldDuplicationBehavior::REPLACE;
+                if (class_exists(DuplicationBehavior::class)) {
+                    $behaviour = DuplicationBehavior::REPLACE;
+                }
+
+                $importFolder->addFile($filename, $orgFileNameSanitized, $behaviour);
             } else {
                 continue;
             }
diff --git a/Classes/Service/DestinationDataImportService/Slugger.php b/Classes/Service/DestinationDataImportService/Slugger.php
index 2a068b1..d1bcdd9 100644
--- a/Classes/Service/DestinationDataImportService/Slugger.php
+++ b/Classes/Service/DestinationDataImportService/Slugger.php
@@ -24,7 +24,6 @@ declare(strict_types=1);
 namespace WerkraumMedia\Events\Service\DestinationDataImportService;
 
 use Generator;
-use PDO;
 use TYPO3\CMS\Core\Database\ConnectionPool;
 use TYPO3\CMS\Core\Database\Query\QueryBuilder;
 use TYPO3\CMS\Core\DataHandling\SlugHelper;
@@ -61,18 +60,14 @@ final class Slugger
             ->from($tableName)
             ->where(
                 $queryBuilder->expr()->or(
-                    $queryBuilder->expr()->eq($slugColumn, $queryBuilder->createNamedParameter('', PDO::PARAM_STR)),
+                    $queryBuilder->expr()->eq($slugColumn, $queryBuilder->createNamedParameter('')),
                     $queryBuilder->expr()->isNull($slugColumn)
                 )
             )
             ->executeQuery()
         ;
 
-        while ($record = $statement->fetch()) {
-            if (is_array($record) === false) {
-                continue;
-            }
-
+        foreach ($statement->iterateAssociative() as $record) {
             yield $record;
         }
     }
@@ -88,7 +83,7 @@ final class Slugger
             ->where(
                 $queryBuilder->expr()->eq(
                     'uid',
-                    $queryBuilder->createNamedParameter($record['uid'], PDO::PARAM_INT)
+                    $queryBuilder->createNamedParameter((int)$record['uid'])
                 )
             )
             ->set($sluggerType->getSlugColumn(), $slug)
diff --git a/Classes/Service/DestinationDataImportService/UrlFactory.php b/Classes/Service/DestinationDataImportService/UrlFactory.php
index 70117f5..9c1bd56 100644
--- a/Classes/Service/DestinationDataImportService/UrlFactory.php
+++ b/Classes/Service/DestinationDataImportService/UrlFactory.php
@@ -5,7 +5,6 @@ declare(strict_types=1);
 namespace WerkraumMedia\Events\Service\DestinationDataImportService;
 
 use TYPO3\CMS\Core\Http\Uri;
-use TYPO3\CMS\Extbase\Configuration\BackendConfigurationManager;
 use WerkraumMedia\Events\Domain\Model\Import;
 
 /**
@@ -13,18 +12,9 @@ use WerkraumMedia\Events\Domain\Model\Import;
  */
 final class UrlFactory
 {
-    /**
-     * @var array
-     */
-    private $settings = [];
-
     public function __construct(
-        BackendConfigurationManager $configurationManager
+        private readonly ConfigurationServiceInterface $configuration,
     ) {
-        $this->settings = $configurationManager->getConfiguration(
-            'Events',
-            'Pi1'
-        )['settings']['destinationData'] ?? [];
     }
 
     /**
@@ -35,17 +25,17 @@ final class UrlFactory
     ): string {
         $parameter = [
             'experience' => $import->getRestExperience(),
-            'licensekey' => $this->settings['license'] ?? '',
-            'type' => $this->settings['restType'] ?? '',
-            'mode' => $this->settings['restMode'] ?? '',
-            'limit' => $this->settings['restLimit'] ?? '',
-            'template' => $this->settings['restTemplate'] ?? '',
+            'licensekey' => $this->configuration->getLicenseKey(),
+            'type' => $this->configuration->getRestType(),
+            'mode' => $this->configuration->getRestMode(),
+            'limit' => $this->configuration->getRestLimit(),
+            'template' => $this->configuration->getRestTemplate(),
             'q' => $import->getSearchQuery(),
         ];
 
         $parameter = array_filter($parameter);
 
-        $url = new Uri($this->settings['restUrl']);
+        $url = new Uri($this->configuration->getRestUrl());
         $url = $url->withQuery(http_build_query($parameter));
         return (string)$url;
     }
diff --git a/Classes/Service/ExtbaseConfigurationManagerService.php b/Classes/Service/ExtbaseConfigurationManagerService.php
new file mode 100644
index 0000000..b9fc337
--- /dev/null
+++ b/Classes/Service/ExtbaseConfigurationManagerService.php
@@ -0,0 +1,41 @@
+<?php
+
+declare(strict_types=1);
+
+namespace WerkraumMedia\Events\Service;
+
+use TYPO3\CMS\Core\Core\SystemEnvironmentBuilder;
+use TYPO3\CMS\Core\Http\ServerRequest;
+use TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface;
+
+final class ExtbaseConfigurationManagerService
+{
+    public function __construct(
+        private readonly ConfigurationManagerInterface $configurationManager
+    ) {
+    }
+
+    /**
+     * The mapper uses queries, which rely an on the configuration manager.
+     * But import is without request, so we ensure it is properly initialized.
+     *
+     * This should vanish, see: Documentation/Maintenance.rst
+     */
+    public function configureForBackend(): void
+    {
+        // TODO: typo3/cms-core:14.0 Remove condition as this method is provided since 13.
+        if (method_exists($this->configurationManager, 'setRequest') === false) {
+            return;
+        }
+
+        $request = new ServerRequest();
+        $request = $request->withAttribute('applicationType', SystemEnvironmentBuilder::REQUESTTYPE_BE);
+        $this->configurationManager->setRequest($request);
+    }
+
+    public function getInstanceWithBackendContext(): ConfigurationManagerInterface
+    {
+        $this->configureForBackend();
+        return $this->configurationManager;
+    }
+}
diff --git a/Classes/Updates/MigrateOldLocations.php b/Classes/Updates/MigrateOldLocations.php
index a1705ad..f5e92a8 100644
--- a/Classes/Updates/MigrateOldLocations.php
+++ b/Classes/Updates/MigrateOldLocations.php
@@ -234,9 +234,8 @@ class MigrateOldLocations implements UpgradeWizardInterface
     {
         $schema = $this->connectionPool
             ->getConnectionForTable('tx_events_domain_model_event')
-            ->getSchemaManager()
-            ->createSchema()
-            ->getTable('tx_events_domain_model_event')
+            ->getSchemaInformation()
+            ->introspectTable('tx_events_domain_model_event')
         ;
 
         foreach ($this->columnsToFetch() as $column) {
diff --git a/Classes/Updates/MigratePluginsFromListToCtype.php b/Classes/Updates/MigratePluginsFromListToCtype.php
new file mode 100644
index 0000000..4c25cb1
--- /dev/null
+++ b/Classes/Updates/MigratePluginsFromListToCtype.php
@@ -0,0 +1,59 @@
+<?php
+
+declare(strict_types=1);
+
+/*
+ * Copyright (C) 2024 Daniel Siepmann <daniel.siepmann@codappix.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+namespace WerkraumMedia\Events\Updates;
+
+use TYPO3\CMS\Install\Attribute\UpgradeWizard;
+use TYPO3\CMS\Install\Updates\AbstractListTypeToCTypeUpdate;
+
+// TODO: typo3/cms-core:14.0 Remove condition as this class is provided since 13.
+if (class_exists(AbstractListTypeToCTypeUpdate::class) === false) {
+    final class MigratePluginsFromListToCtype
+    {
+    }
+    return;
+}
+
+#[UpgradeWizard(MigratePluginsFromListToCtype::class)]
+final class MigratePluginsFromListToCtype extends AbstractListTypeToCTypeUpdate
+{
+    protected function getListTypeToCTypeMapping(): array
+    {
+        return [
+            'events_datelist' => 'events_datelist',
+            'events_datesearch' => 'events_datesearch',
+            'events_dateshow ' => 'events_dateshow',
+            'events_selected ' => 'events_selected',
+        ];
+    }
+
+    public function getTitle(): string
+    {
+        return 'Migrate EXT:events content elements.';
+    }
+
+    public function getDescription(): string
+    {
+        return 'Migrate CType from list to dedicated plugins.';
+    }
+}
diff --git a/Configuration/FlexForms/DateList.xml b/Configuration/FlexForms/DateList.xml
index 9c000c9..886bdd7 100644
--- a/Configuration/FlexForms/DateList.xml
+++ b/Configuration/FlexForms/DateList.xml
@@ -2,127 +2,108 @@
     <sheets>
         <sDEF>
             <ROOT>
-                <TCEforms>
-                    <sheetTitle>Options</sheetTitle>
-                </TCEforms>
+                <sheetTitle>Options</sheetTitle>
                 <type>array</type>
                 <el>
                     <settings.sortByDate>
-                        <TCEforms>
-                            <exclude>1</exclude>
-                            <label>Sort By</label>
-                            <config>
-                                <type>select</type>
-                                <renderType>selectSingle</renderType>
-                                <items type="array">
-                                    <numIndex index="0" type="array">
-                                        <numIndex index="0">Start</numIndex>
-                                        <numIndex index="1">start</numIndex>
-                                    </numIndex>
-                                    <numIndex index="1" type="array">
-                                        <numIndex index="0">End</numIndex>
-                                        <numIndex index="1">end</numIndex>
-                                    </numIndex>
-                                </items>
-                            </config>
-                        </TCEforms>
+                        <exclude>1</exclude>
+                        <label>Sort By</label>
+                        <config>
+                            <type>select</type>
+                            <renderType>selectSingle</renderType>
+                            <items type="array">
+                                <numIndex index="0" type="array">
+                                    <numIndex index="label">Start</numIndex>
+                                    <numIndex index="value">start</numIndex>
+                                </numIndex>
+                                <numIndex index="1" type="array">
+                                    <numIndex index="label">End</numIndex>
+                                    <numIndex index="value">end</numIndex>
+                                </numIndex>
+                            </items>
+                        </config>
                     </settings.sortByDate>
 
                     <settings.sortOrder>
-                        <TCEforms>
-                            <exclude>1</exclude>
-                            <label>Sort Order</label>
-                            <config>
-                                <type>select</type>
-                                <renderType>selectSingle</renderType>
-                                <items type="array">
-                                    <numIndex index="0" type="array">
-                                        <numIndex index="0">
-                                            Ascending
-                                        </numIndex>
-                                        <numIndex index="1">ASC</numIndex>
+                        <exclude>1</exclude>
+                        <label>Sort Order</label>
+                        <config>
+                            <type>select</type>
+                            <renderType>selectSingle</renderType>
+                            <items type="array">
+                                <numIndex index="0" type="array">
+                                    <numIndex index="label">
+                                        Ascending
                                     </numIndex>
-                                    <numIndex index="1" type="array">
-                                        <numIndex index="0">
-                                            Descending
-                                        </numIndex>
-                                        <numIndex index="1">DESC</numIndex>
+                                    <numIndex index="value">ASC</numIndex>
+                                </numIndex>
+                                <numIndex index="1" type="array">
+                                    <numIndex index="label">
+                                        Descending
                                     </numIndex>
-                                </items>
-                                <default>ASC</default>
-                            </config>
-                        </TCEforms>
+                                    <numIndex index="value">DESC</numIndex>
+                                </numIndex>
+                            </items>
+                            <default>ASC</default>
+                        </config>
                     </settings.sortOrder>
 
                     <settings.limit>
-                        <TCEforms>
-                            <exclude>1</exclude>
-                            <label>Max Items</label>
-                            <config>
-                                <type>input</type>
-                                <size>10</size>
-                                <max>30</max>
-                                <eval>trim</eval>
-                            </config>
-                        </TCEforms>
+                        <exclude>1</exclude>
+                        <label>Max Items</label>
+                        <config>
+                            <type>input</type>
+                            <size>10</size>
+                            <max>30</max>
+                            <eval>trim</eval>
+                        </config>
                     </settings.limit>
 
                     <settings.highlight>
-                        <TCEforms>
-                            <exclude>1</exclude>
-                            <label>Highlights only</label>
-                            <config>
-                                <type>check</type>
-                                <default>0</default>
-                            </config>
-                        </TCEforms>
+                        <exclude>1</exclude>
+                        <label>Highlights only</label>
+                        <config>
+                            <type>check</type>
+                            <default>0</default>
+                        </config>
                     </settings.highlight>
 
                     <settings.todayOnly>
-                        <TCEforms>
-                            <exclude>1</exclude>
-                            <label>Today only</label>
-                            <config>
-                                <type>check</type>
-                                <default>0</default>
-                            </config>
-                        </TCEforms>
+                        <exclude>1</exclude>
+                        <label>Today only</label>
+                        <config>
+                            <type>check</type>
+                            <default>0</default>
+                        </config>
                     </settings.todayOnly>
 
                     <settings.pagination>
-                        <TCEforms>
-                            <exclude>1</exclude>
-                            <label>Show pagination</label>
-                            <config>
-                                <type>check</type>
-                                <default>0</default>
-                            </config>
-                        </TCEforms>
+                        <exclude>1</exclude>
+                        <label>Show pagination</label>
+                        <config>
+                            <type>check</type>
+                            <default>0</default>
+                        </config>
                     </settings.pagination>
 
                     <settings.showPID>
-                        <TCEforms>
-                            <exclude>1</exclude>
-                            <label>Detail page</label>
-                            <config>
-                                <type>group</type>
-                                <internal_type>db</internal_type>
-                                <allowed>pages</allowed>
-                                <size>1</size>
-                                <maxitems>1</maxitems>
-                                <minitems>0</minitems>
-                                <show_thumbs>1</show_thumbs>
-                            </config>
-                        </TCEforms>
+                        <exclude>1</exclude>
+                        <label>Detail page</label>
+                        <config>
+                            <type>group</type>
+                            <allowed>pages</allowed>
+                            <size>1</size>
+                            <maxitems>1</maxitems>
+                            <minitems>0</minitems>
+                            <show_thumbs>1</show_thumbs>
+                        </config>
                     </settings.showPID>
                 </el>
             </ROOT>
         </sDEF>
         <sTemplate>
             <ROOT>
-                <TCEforms>
-                    <sheetTitle>Template</sheetTitle>
-                </TCEforms>
+                <sheetTitle>Template</sheetTitle>
                 <type>array</type>
                 <el>
                     <settings.template>
@@ -133,20 +114,20 @@
                             <renderType>selectSingle</renderType>
                             <items type="array">
                                 <numIndex index="0" type="array">
-                                    <numIndex index="0">Default</numIndex>
-                                    <numIndex index="1">default</numIndex>
+                                    <numIndex index="label">Default</numIndex>
+                                    <numIndex index="value">default</numIndex>
                                 </numIndex>
                                 <numIndex index="1" type="array">
-                                    <numIndex index="0">Costum</numIndex>
-                                    <numIndex index="1">costum</numIndex>
+                                    <numIndex index="label">Custom</numIndex>
+                                    <numIndex index="value">costum</numIndex>
                                 </numIndex>
                                 <numIndex index="2" type="array">
-                                    <numIndex index="0">Table</numIndex>
-                                    <numIndex index="1">table</numIndex>
+                                    <numIndex index="label">Table</numIndex>
+                                    <numIndex index="value">table</numIndex>
                                 </numIndex>
                                 <numIndex index="3" type="array">
-                                    <numIndex index="0">Grid</numIndex>
-                                    <numIndex index="1">grid</numIndex>
+                                    <numIndex index="label">Grid</numIndex>
+                                    <numIndex index="value">grid</numIndex>
                                 </numIndex>
                             </items>
                             <default>default</default>
@@ -157,34 +138,29 @@
         </sTemplate>
         <sConstrains>
             <ROOT>
-                <TCEforms>
-                    <sheetTitle>Regions &amp; Categories</sheetTitle>
-                </TCEforms>
+                <sheetTitle>Regions &amp; Categories</sheetTitle>
                 <type>array</type>
                 <el>
                     <settings.region>
-                        <TCEforms>
-                            <label>Region</label>
-                            <config>
-                                <type>select</type>
-                                <renderType>selectSingle</renderType>
-                                <items type="array">
-                                    <numIndex index="0" type="array">
-                                        <numIndex index="0">Alle</numIndex>
-                                        <numIndex index="1"></numIndex>
-                                    </numIndex>
-                                </items>
-                                <foreign_table>tx_events_domain_model_region</foreign_table>
-                                <foreign_table_where>AND tx_events_domain_model_region.deleted = 0 AND tx_events_domain_model_region.hidden = 0</foreign_table_where>
-                                <size>1</size>
-                                <minitems>0</minitems>
-                                <maxitems>1</maxitems>
-                            </config>
-                        </TCEforms>
+                        <label>Region</label>
+                        <config>
+                            <type>select</type>
+                            <renderType>selectSingle</renderType>
+                            <items type="array">
+                                <numIndex index="0" type="array">
+                                    <numIndex index="label">Alle</numIndex>
+                                    <numIndex index="value"></numIndex>
+                                </numIndex>
+                            </items>
+                            <foreign_table>tx_events_domain_model_region</foreign_table>
+                            <foreign_table_where>AND tx_events_domain_model_region.deleted = 0 AND tx_events_domain_model_region.hidden = 0</foreign_table_where>
+                            <size>1</size>
+                            <minitems>0</minitems>
+                            <maxitems>1</maxitems>
+                        </config>
                     </settings.region>
 
                     <settings.categoryCombination>
-                        <TCEforms>
                             <exclude>1</exclude>
                             <label>Combination</label>
                             <config>
@@ -192,54 +168,49 @@
                                 <renderType>selectSingle</renderType>
                                 <items type="array">
                                     <numIndex index="0" type="array">
-                                        <numIndex index="0">And</numIndex>
-                                        <numIndex index="1">0</numIndex>
+                                        <numIndex index="label">And</numIndex>
+                                        <numIndex index="value">0</numIndex>
                                     </numIndex>
                                     <numIndex index="1" type="array">
-                                        <numIndex index="0">Or</numIndex>
-                                        <numIndex index="1">1</numIndex>
+                                        <numIndex index="label">Or</numIndex>
+                                        <numIndex index="value">1</numIndex>
                                     </numIndex>
                                 </items>
                                 <default>0</default>
                             </config>
-                        </TCEforms>
                     </settings.categoryCombination>
 
                     <settings.categories>
-                        <TCEforms>
-                            <exclude>1</exclude>
-                            <label>
-                                Category
-                            </label>
-                            <config>
-                                <type>select</type>
-                                <renderType>selectTree</renderType>
-                                <autoSizeMax>20</autoSizeMax>
-                                <foreign_table>sys_category</foreign_table>
-                                <foreign_table_where> AND sys_category.sys_language_uid IN (-1, 0) ORDER BY sys_category.title ASC</foreign_table_where>
-                                <maxitems>1</maxitems>
-                                <renderMode>tree</renderMode>
-                                <size>8</size>
-                                <treeConfig>
-                                    <appearance>
-                                        <expandAll>1</expandAll>
-                                        <showHeader>1</showHeader>
-                                    </appearance>
-                                    <parentField>parent</parentField>
-                                </treeConfig>
-                            </config>
-                        </TCEforms>
+                        <exclude>1</exclude>
+                        <label>
+                            Category
+                        </label>
+                        <config>
+                            <type>select</type>
+                            <renderType>selectTree</renderType>
+                            <autoSizeMax>20</autoSizeMax>
+                            <foreign_table>sys_category</foreign_table>
+                            <foreign_table_where> AND sys_category.sys_language_uid IN (-1, 0) ORDER BY sys_category.title ASC</foreign_table_where>
+                            <maxitems>1</maxitems>
+                            <renderMode>tree</renderMode>
+                            <size>8</size>
+                            <treeConfig>
+                                <appearance>
+                                    <expandAll>1</expandAll>
+                                    <showHeader>1</showHeader>
+                                </appearance>
+                                <parentField>parent</parentField>
+                            </treeConfig>
+                        </config>
                     </settings.categories>
 
                     <settings.includeSubcategories>
-                        <TCEforms>
                             <exclude>1</exclude>
                             <label>Include Subcategories</label>
                             <config>
                                 <type>check</type>
                                 <default>0</default>
                             </config>
-                        </TCEforms>
                     </settings.includeSubcategories>
                 </el>
             </ROOT>
diff --git a/Configuration/FlexForms/DateSearch.xml b/Configuration/FlexForms/DateSearch.xml
index ae07a9f..9f1d25b 100644
--- a/Configuration/FlexForms/DateSearch.xml
+++ b/Configuration/FlexForms/DateSearch.xml
@@ -2,38 +2,31 @@
     <sheets>
         <sSearch>
             <ROOT>
-                <TCEforms>
-                    <sheetTitle>Options</sheetTitle>
-                </TCEforms>
+                <sheetTitle>Options</sheetTitle>
                 <type>array</type>
                 <el>
                     <settings.pageUid>
-                        <TCEforms>
-                            <exclude>1</exclude>
-                            <label>Results page</label>
-                            <config>
-                                <type>group</type>
-                                <internal_type>db</internal_type>
-                                <allowed>pages</allowed>
-                                <size>1</size>
-                                <maxitems>1</maxitems>
-                                <minitems>0</minitems>
-                                <show_thumbs>1</show_thumbs>
-                            </config>
-                        </TCEforms>
+                        <exclude>1</exclude>
+                        <label>Results page</label>
+                        <config>
+                            <type>group</type>
+                            <allowed>pages</allowed>
+                            <size>1</size>
+                            <maxitems>1</maxitems>
+                            <minitems>0</minitems>
+                            <show_thumbs>1</show_thumbs>
+                        </config>
                     </settings.pageUid>
                     <settings.showRegions>
-                        <TCEforms>
-                            <exclude>1</exclude>
-                            <label>Show Regions</label>
-                            <config>
-                                <type>check</type>
-                                <default>0</default>
-                            </config>
-                        </TCEforms>
+                        <exclude>1</exclude>
+                        <label>Show Regions</label>
+                        <config>
+                            <type>check</type>
+                            <default>0</default>
+                        </config>
                     </settings.showRegions>
                 </el>
             </ROOT>
         </sSearch>
     </sheets>
-</T3DataStructure>
\ No newline at end of file
+</T3DataStructure>
diff --git a/Configuration/FlexForms/DateShow.xml b/Configuration/FlexForms/DateShow.xml
index b3eea3d..998671e 100644
--- a/Configuration/FlexForms/DateShow.xml
+++ b/Configuration/FlexForms/DateShow.xml
@@ -2,34 +2,27 @@
     <sheets>
         <sDEF>
             <ROOT>
-                <TCEforms>
-                    <sheetTitle>Options</sheetTitle>
-                </TCEforms>
+                <sheetTitle>Options</sheetTitle>
                 <type>array</type>
                 <el>
                     <settings.backPID>
-                        <TCEforms>
                             <exclude>1</exclude>
                             <label>Back page</label>
                             <config>
                                 <type>group</type>
-                                <internal_type>db</internal_type>
                                 <allowed>pages</allowed>
                                 <size>1</size>
                                 <maxitems>1</maxitems>
                                 <minitems>0</minitems>
                                 <show_thumbs>1</show_thumbs>
-                            </config>
-                        </TCEforms>
+                        </config>
                     </settings.backPID>
                 </el>
             </ROOT>
         </sDEF>
         <sTemplate>
             <ROOT>
-                <TCEforms>
-                    <sheetTitle>Template</sheetTitle>
-                </TCEforms>
+                <sheetTitle>Template</sheetTitle>
                 <type>array</type>
                 <el>
                     <settings.template>
@@ -39,12 +32,12 @@
                             <type>select</type>
                             <items type="array">
                                 <numIndex index="0" type="array">
-                                    <numIndex index="0">Default</numIndex>
-                                    <numIndex index="1">default</numIndex>
+                                    <numIndex index="label">Default</numIndex>
+                                    <numIndex index="value">default</numIndex>
                                 </numIndex>
                                 <numIndex index="1" type="array">
-                                    <numIndex index="0">Costum</numIndex>
-                                    <numIndex index="1">costum</numIndex>
+                                    <numIndex index="label">Custom</numIndex>
+                                    <numIndex index="value">costum</numIndex>
                                 </numIndex>
                             </items>
                             <default>default</default>
@@ -54,4 +47,4 @@
             </ROOT>
         </sTemplate>
     </sheets>
-</T3DataStructure>
\ No newline at end of file
+</T3DataStructure>
diff --git a/Configuration/FlexForms/Selected.xml b/Configuration/FlexForms/Selected.xml
index d4a590e..43cb7e4 100644
--- a/Configuration/FlexForms/Selected.xml
+++ b/Configuration/FlexForms/Selected.xml
@@ -5,17 +5,14 @@
                 <type>array</type>
                 <el>
                     <settings.selectedRecords>
-                        <TCEforms>
-                            <exclude>1</exclude>
-                            <label>LLL:EXT:events/Resources/Private/Language/de.locallang_db.xlf:tx_events.flexform.selected.selectedRecords</label>
-                            <config>
-                                <type>group</type>
-                                <internal_type>db</internal_type>
-                                <allowed>tx_events_domain_model_event</allowed>
-                                <minitems>1</minitems>
-                                <show_thumbs>1</show_thumbs>
-                            </config>
-                        </TCEforms>
+                        <exclude>1</exclude>
+                        <label>LLL:EXT:events/Resources/Private/Language/de.locallang_db.xlf:tx_events.flexform.selected.selectedRecords</label>
+                        <config>
+                            <type>group</type>
+                            <allowed>tx_events_domain_model_event</allowed>
+                            <minitems>1</minitems>
+                            <show_thumbs>1</show_thumbs>
+                        </config>
                     </settings.selectedRecords>
                 </el>
             </ROOT>
diff --git a/Configuration/Icons.php b/Configuration/Icons.php
new file mode 100644
index 0000000..3e2cb5d
--- /dev/null
+++ b/Configuration/Icons.php
@@ -0,0 +1,16 @@
+<?php
+
+declare(strict_types=1);
+
+use TYPO3\CMS\Core\Imaging\IconProvider\SvgIconProvider;
+
+return [
+    'events-plugin' => [
+        'provider' => SvgIconProvider::class,
+        'source' => 'EXT:events/Resources/Public/Icons/Extension.svg',
+    ],
+    'pages-module-events' => [
+        'provider' => SvgIconProvider::class,
+        'source' => 'EXT:events/Resources/Public/Icons/Folder.svg',
+    ],
+];
diff --git a/Configuration/Services.yaml b/Configuration/Services.yaml
index a5090de..cf06b5a 100644
--- a/Configuration/Services.yaml
+++ b/Configuration/Services.yaml
@@ -43,7 +43,12 @@ services:
   WerkraumMedia\Events\Updates\MigrateOldLocations:
     public: true
 
+  WerkraumMedia\Events\Service\DestinationDataImportService\ConfigurationServiceInterface:
+    alias: 'WerkraumMedia\Events\Service\DestinationDataImportService\ExtbaseConfigurationService'
+
   WerkraumMedia\Events\Caching\PageCacheTimeout:
+    arguments:
+      '$runtimeCache': '@cache.runtime'
     tags:
       - name: event.listener
         event: WerkraumMedia\Events\Events\Controller\DateListVariables
diff --git a/Configuration/TCA/Overrides/tt_content.php b/Configuration/TCA/Overrides/tt_content.php
index dcd3619..08a854a 100644
--- a/Configuration/TCA/Overrides/tt_content.php
+++ b/Configuration/TCA/Overrides/tt_content.php
@@ -7,54 +7,58 @@ use TYPO3\CMS\Extbase\Utility\ExtensionUtility;
 
 (function (string $extKey, string $table) {
     /* Search Plugin */
-    ExtensionUtility::registerPlugin(
+    $pluginSignature = ExtensionUtility::registerPlugin(
         'Events',
         'DateSearch',
         'Events: Date Search',
-        'EXT:events/Resources/Public/Icons/Extension.svg'
+        'events-plugin'
     );
-    $GLOBALS['TCA'][$table]['types']['list']['subtypes_addlist']['events_datesearch'] = 'pi_flexform';
+    ExtensionManagementUtility::addToAllTCAtypes($table, 'pi_flexform', $pluginSignature, 'after:subheader');
     ExtensionManagementUtility::addPiFlexFormValue(
-        'events_datesearch',
-        'FILE:EXT:events/Configuration/FlexForms/DateSearch.xml'
+        '*',
+        'FILE:EXT:events/Configuration/FlexForms/DateSearch.xml',
+        $pluginSignature,
     );
 
     /* Date List Plugin */
-    ExtensionUtility::registerPlugin(
+    $pluginSignature = ExtensionUtility::registerPlugin(
         'Events',
         'DateList',
         'Events: Date List',
-        'EXT:events/Resources/Public/Icons/Extension.svg'
+        'events-plugin'
     );
-    $GLOBALS['TCA'][$table]['types']['list']['subtypes_addlist']['events_datelist'] = 'pi_flexform';
+    ExtensionManagementUtility::addToAllTCAtypes($table, 'pi_flexform', $pluginSignature, 'after:subheader');
     ExtensionManagementUtility::addPiFlexFormValue(
-        'events_datelist',
-        'FILE:EXT:events/Configuration/FlexForms/DateList.xml'
+        '*',
+        'FILE:EXT:events/Configuration/FlexForms/DateList.xml',
+        $pluginSignature,
     );
 
     /* Date Show Plugin */
-    ExtensionUtility::registerPlugin(
+    $pluginSignature = ExtensionUtility::registerPlugin(
         'Events',
         'DateShow',
         'Events: Date Show',
-        'EXT:events/Resources/Public/Icons/Extension.svg'
+        'events-plugin'
     );
-    $GLOBALS['TCA'][$table]['types']['list']['subtypes_addlist']['events_dateshow'] = 'pi_flexform';
+    ExtensionManagementUtility::addToAllTCAtypes($table, 'pi_flexform', $pluginSignature, 'after:subheader');
     ExtensionManagementUtility::addPiFlexFormValue(
+        '*',
+        'FILE:EXT:events/Configuration/FlexForms/DateShow.xml',
         'events_dateshow',
-        'FILE:EXT:events/Configuration/FlexForms/DateShow.xml'
     );
 
     /* Event Selected Plugin */
-    ExtensionUtility::registerPlugin(
+    $pluginSignature = ExtensionUtility::registerPlugin(
         'Events',
         'Selected',
         'Events: Show selected',
-        'EXT:events/Resources/Public/Icons/Extension.svg'
+        'events-plugin'
     );
-    $GLOBALS['TCA'][$table]['types']['list']['subtypes_addlist']['events_selected'] = 'pi_flexform';
+    ExtensionManagementUtility::addToAllTCAtypes($table, 'pi_flexform', $pluginSignature, 'after:subheader');
     ExtensionManagementUtility::addPiFlexFormValue(
+        $pluginSignature,
+        'FILE:EXT:events/Configuration/FlexForms/Selected.xml',
         'events_selected',
-        'FILE:EXT:events/Configuration/FlexForms/Selected.xml'
     );
 })('events', 'tt_content');
diff --git a/Configuration/TCA/tx_events_domain_model_event.php b/Configuration/TCA/tx_events_domain_model_event.php
index 5d4f135..f4b9f1d 100644
--- a/Configuration/TCA/tx_events_domain_model_event.php
+++ b/Configuration/TCA/tx_events_domain_model_event.php
@@ -346,7 +346,6 @@ return [
             'config' => [
                 'type' => 'category',
                 'minitems' => 0,
-                'multiple' => true,
             ],
         ],
         'features' => [
@@ -355,7 +354,6 @@ return [
             'config' => [
                 'type' => 'category',
                 'minitems' => 0,
-                'multiple' => true,
             ],
         ],
         'keywords' => [
@@ -409,6 +407,12 @@ return [
                 'default' => 0,
                 'minitems' => 0,
                 'maxitems' => 1,
+                'items' => [
+                    [
+                        'value' => '0',
+                        'label' => $l10nPath . ':tx_events_domain_model_event.location.0',
+                    ],
+                ],
             ],
         ],
         'organizer' => [
@@ -421,6 +425,12 @@ return [
                 'default' => 0,
                 'minitems' => 0,
                 'maxitems' => 1,
+                'items' => [
+                    [
+                        'value' => '0',
+                        'label' => $l10nPath . ':tx_events_domain_model_event.location.0',
+                    ],
+                ],
             ],
         ],
         'region' => [
@@ -433,6 +443,12 @@ return [
                 'default' => 0,
                 'minitems' => 0,
                 'maxitems' => 1,
+                'items' => [
+                    [
+                        'value' => '0',
+                        'label' => $l10nPath . ':tx_events_domain_model_event.location.0',
+                    ],
+                ],
             ],
         ],
 
diff --git a/Configuration/TCA/tx_events_domain_model_import.php b/Configuration/TCA/tx_events_domain_model_import.php
index e7f93cc..bd987ec 100644
--- a/Configuration/TCA/tx_events_domain_model_import.php
+++ b/Configuration/TCA/tx_events_domain_model_import.php
@@ -26,7 +26,7 @@ return [
                 '--palette--;;typo3_storage',
                 '--palette--;;categories',
                 '--palette--;;features',
-                '-palette--;;relations',
+                '--palette--;;relations',
                 '--div--;LLL:EXT:events/Resources/Private/Language/locallang_csh_import.xlf:tx_events_domain_model_import.div.rest',
                 'rest_experience',
                 'rest_search_query',
diff --git a/Configuration/TypoScript/constants.typoscript b/Configuration/TypoScript/constants.typoscript
index 1f0ccc4..61310cd 100644
--- a/Configuration/TypoScript/constants.typoscript
+++ b/Configuration/TypoScript/constants.typoscript
@@ -14,7 +14,7 @@ plugin.tx_events {
     }
     settings {
         # cat=plugin.tx_events//a; type=string; label=Default Image
-        defaultImagePath = typo3conf/ext/events/Resources/Public/Images/default.jpg
+        defaultImagePath = EXT:events/Resources/Public/Images/default.jpg
         destinationData {
             # cat=plugin.tx_events//a; type=string; label=Rest Url
             restUrl = http://meta.et4.de/rest.ashx/search/
diff --git a/Documentation/Changelog/5.0.0.rst b/Documentation/Changelog/5.0.0.rst
new file mode 100644
index 0000000..961363b
--- /dev/null
+++ b/Documentation/Changelog/5.0.0.rst
@@ -0,0 +1,35 @@
+5.0.0
+=====
+
+Breaking
+--------
+
+* Only when being on 13.x or higher:
+
+  Content elements are no longer registered as `list` but with their own CType.
+  An upgrade wizard is provided that can be executed to migrate existing database
+  entries.
+
+  But custom TypoScript and modifications need to be adopted.
+  We recommend not to use the provided plugins but build your own tailored content
+  elements instead.
+
+Features
+--------
+
+* Add Support for TYPO3 v13.4 LTS.
+
+Fixes
+-----
+
+Nothing
+
+Tasks
+-----
+
+Nothing
+
+Deprecation
+-----------
+
+Nothing
diff --git a/Documentation/Index.rst b/Documentation/Index.rst
index 1b1626a..2d56ff9 100644
--- a/Documentation/Index.rst
+++ b/Documentation/Index.rst
@@ -43,6 +43,8 @@ Table of Contents
    Settings
    Changelog
 
+   Maintenance
+
 .. toctree::
    :hidden:
 
diff --git a/Documentation/Maintenance.rst b/Documentation/Maintenance.rst
new file mode 100644
index 0000000..66b4621
--- /dev/null
+++ b/Documentation/Maintenance.rst
@@ -0,0 +1,16 @@
+Maintenance
+===========
+
+Migrate to SiteSets
+-------------------
+
+We currently leverage TypoScript for some configuration during import.
+This is a bad idea, TypoScript is not intended for this usage.
+
+We should migrate to Site Sets in the future.
+The import should use the page uid for import records to resolve the site and fetch
+corresponding settings.
+That way the import can provide all the necessary information and can be passed down
+to all classes.
+
+
diff --git a/Documentation/Settings.cfg b/Documentation/Settings.cfg
deleted file mode 100644
index d05053f..0000000
--- a/Documentation/Settings.cfg
+++ /dev/null
@@ -1,11 +0,0 @@
-[general]
-project     = Events Extension
-copyright   = since 2019 by Dirk Koritnik and Daniel Siepmann
-
-[html_theme_options]
-github_branch        = main
-github_repository    = werkraum-media/events
-
-project_home         = https://github.com/werkraum-media/events/
-project_issues       = https://github.com/werkraum-media/events/issues
-project_repository   = https://github.com/werkraum-media/events/
diff --git a/Documentation/guides.xml b/Documentation/guides.xml
new file mode 100644
index 0000000..5a76e16
--- /dev/null
+++ b/Documentation/guides.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<guides
+    xmlns="https://www.phpdoc.org/guides"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="https://www.phpdoc.org/guides ../vendor/phpdocumentor/guides-cli/resources/schema/guides.xsd"
+    links-are-relative="true"
+>
+    <extension
+        class="\T3Docs\Typo3DocsTheme\DependencyInjection\Typo3DocsThemeExtension"
+        project-home="https://github.com/werkraum-media/events/"
+        project-repository="https://github.com/werkraum-media/events/"
+        project-issues="https://github.com/werkraum-media/events/issues"
+        edit-on-github-branch="main"
+        edit-on-github="werkraum-media/events"
+        typo3-core-preferred="stable"
+    />
+    <project
+        title="Events Extension"
+        copyright="since 2019 by Dirk Koritnik and Daniel Siepmann"
+    />
+</guides>
diff --git a/Resources/Private/Language/de.locallang_csh_event.xlf b/Resources/Private/Language/de.locallang_csh_event.xlf
index ef1cc27..149b3d2 100644
--- a/Resources/Private/Language/de.locallang_csh_event.xlf
+++ b/Resources/Private/Language/de.locallang_csh_event.xlf
@@ -123,14 +123,26 @@
                 <source>Location</source>
                 <target>Veranstaltungsort</target>
             </trans-unit>
+            <trans-unit id="tx_events_domain_model_event.location.0">
+                <source>None</source>
+                <target>Keine</target>
+            </trans-unit>
             <trans-unit id="tx_events_domain_model_event.organizer">
                 <source>Organizer</source>
                 <target>Organisator</target>
             </trans-unit>
+            <trans-unit id="tx_events_domain_model_event.organizer.0">
+                <source>None</source>
+                <target>Keiner</target>
+            </trans-unit>
             <trans-unit id="tx_events_domain_model_event.region">
                 <source>Region</source>
                 <target>Region</target>
             </trans-unit>
+            <trans-unit id="tx_events_domain_model_event.region.0">
+                <source>None</source>
+                <target>Keine</target>
+            </trans-unit>
             <trans-unit id="tx_events_domain_model_organizer">
                 <source>Organizer</source>
                 <target>Organisator</target>
diff --git a/Resources/Private/Language/locallang_csh_event.xlf b/Resources/Private/Language/locallang_csh_event.xlf
index 9ef979d..bd1575c 100644
--- a/Resources/Private/Language/locallang_csh_event.xlf
+++ b/Resources/Private/Language/locallang_csh_event.xlf
@@ -93,12 +93,21 @@
             <trans-unit id="tx_events_domain_model_event.location">
                 <source>Location</source>
             </trans-unit>
+            <trans-unit id="tx_events_domain_model_event.location.0">
+                <source>None</source>
+            </trans-unit>
             <trans-unit id="tx_events_domain_model_event.organizer">
                 <source>Organizer</source>
             </trans-unit>
+            <trans-unit id="tx_events_domain_model_event.organizer.0">
+                <source>None</source>
+            </trans-unit>
             <trans-unit id="tx_events_domain_model_event.region">
                 <source>Region</source>
             </trans-unit>
+            <trans-unit id="tx_events_domain_model_event.region.0">
+                <source>None</source>
+            </trans-unit>
             <trans-unit id="tx_events_domain_model_event.partner">
                 <source>Partner</source>
             </trans-unit>
diff --git a/Tests/Functional/AbstractFunctionalTestCase.php b/Tests/Functional/AbstractFunctionalTestCase.php
index 536ac7c..92d57b0 100644
--- a/Tests/Functional/AbstractFunctionalTestCase.php
+++ b/Tests/Functional/AbstractFunctionalTestCase.php
@@ -149,6 +149,7 @@ abstract class AbstractFunctionalTestCase extends FunctionalTestCase
         array $argumentsAndOptions = ['configurationUid' => '1'],
         string $command = ImportDestinationDataViaConfigruationCommand::class
     ): CommandTester {
+        GeneralUtility::setContainer($this->getcontainer());
         $subject = $this->get($command);
         self::assertInstanceOf(Command::class, $subject);
 
diff --git a/Tests/Functional/Frontend/CacheTest.php b/Tests/Functional/Frontend/CacheTest.php
index a2d7b32..c9a634d 100644
--- a/Tests/Functional/Frontend/CacheTest.php
+++ b/Tests/Functional/Frontend/CacheTest.php
@@ -68,8 +68,7 @@ class CacheTest extends AbstractFunctionalTestCase
         (new PhpDataSet())->import(['tt_content' => [[
             'uid' => '1',
             'pid' => '1',
-            'CType' => 'list',
-            'list_type' => 'events_datelisttest',
+            'CType' => 'events_datelisttest',
             'header' => 'All Dates',
         ]]]);
         $this->setUpFrontendRendering();
@@ -306,7 +305,7 @@ class CacheTest extends AbstractFunctionalTestCase
         // We might be seconds off due to our created offset within the rendering.
         $value = (int)$value;
         $age = ((int)$end->format('U')) - time();
-        self::assertLessThanOrEqual($age + 3, $value, 'Max age of cached response is higher than expected.');
+        self::assertLessThanOrEqual($age + 4, $value, 'Max age of cached response is higher than expected.');
         self::assertGreaterThanOrEqual($age - 3, $value, 'Max age of cached response is less than expected.');
     }
 
diff --git a/Tests/Functional/Frontend/DatesTestFixtures/DateMetaTags.php b/Tests/Functional/Frontend/DatesTestFixtures/DateMetaTags.php
index e6d7eff..610be32 100644
--- a/Tests/Functional/Frontend/DatesTestFixtures/DateMetaTags.php
+++ b/Tests/Functional/Frontend/DatesTestFixtures/DateMetaTags.php
@@ -7,8 +7,7 @@ return  [
         0 => [
             'uid' => '1',
             'pid' => '1',
-            'CType' => 'list',
-            'list_type' => 'events_dateshow',
+            'CType' => 'events_dateshow',
             'header' => 'Singleview',
         ],
     ],
diff --git a/Tests/Functional/Frontend/DatesTestFixtures/DateOpenGraphTags.php b/Tests/Functional/Frontend/DatesTestFixtures/DateOpenGraphTags.php
index 845d7e1..dc6aad1 100644
--- a/Tests/Functional/Frontend/DatesTestFixtures/DateOpenGraphTags.php
+++ b/Tests/Functional/Frontend/DatesTestFixtures/DateOpenGraphTags.php
@@ -7,8 +7,7 @@ return  [
         0 => [
             'uid' => '1',
             'pid' => '1',
-            'CType' => 'list',
-            'list_type' => 'events_dateshow',
+            'CType' => 'events_dateshow',
             'header' => 'Singleview',
         ],
     ],
diff --git a/Tests/Functional/Frontend/DatesTestFixtures/DatePageTitle.php b/Tests/Functional/Frontend/DatesTestFixtures/DatePageTitle.php
index ce6fbfd..b0e07c7 100644
--- a/Tests/Functional/Frontend/DatesTestFixtures/DatePageTitle.php
+++ b/Tests/Functional/Frontend/DatesTestFixtures/DatePageTitle.php
@@ -7,8 +7,7 @@ return  [
         0 => [
             'uid' => '1',
             'pid' => '1',
-            'CType' => 'list',
-            'list_type' => 'events_dateshow',
+            'CType' => 'events_dateshow',
             'header' => 'Singleview',
         ],
     ],
diff --git a/Tests/Functional/Frontend/DatesTestFixtures/DateSocialMediaTags.php b/Tests/Functional/Frontend/DatesTestFixtures/DateSocialMediaTags.php
index f98a775..88269de 100644
--- a/Tests/Functional/Frontend/DatesTestFixtures/DateSocialMediaTags.php
+++ b/Tests/Functional/Frontend/DatesTestFixtures/DateSocialMediaTags.php
@@ -7,8 +7,7 @@ return  [
         0 => [
             'uid' => '1',
             'pid' => '1',
-            'CType' => 'list',
-            'list_type' => 'events_dateshow',
+            'CType' => 'events_dateshow',
             'header' => 'Singleview',
         ],
     ],
diff --git a/Tests/Functional/Frontend/DatesTestFixtures/Returns404IfEventIsHidden.php b/Tests/Functional/Frontend/DatesTestFixtures/Returns404IfEventIsHidden.php
index 76806af..27002f1 100644
--- a/Tests/Functional/Frontend/DatesTestFixtures/Returns404IfEventIsHidden.php
+++ b/Tests/Functional/Frontend/DatesTestFixtures/Returns404IfEventIsHidden.php
@@ -7,8 +7,7 @@ return  [
         0 => [
             'uid' => '1',
             'pid' => '1',
-            'CType' => 'list',
-            'list_type' => 'events_dateshow',
+            'CType' => 'events_dateshow',
             'header' => 'Singleview',
         ],
     ],
diff --git a/Tests/Functional/Frontend/DatesTestFixtures/ReturnsDateWithinTimeSpan.php b/Tests/Functional/Frontend/DatesTestFixtures/ReturnsDateWithinTimeSpan.php
index f45d593..91ef7af 100644
--- a/Tests/Functional/Frontend/DatesTestFixtures/ReturnsDateWithinTimeSpan.php
+++ b/Tests/Functional/Frontend/DatesTestFixtures/ReturnsDateWithinTimeSpan.php
@@ -7,8 +7,7 @@ return  [
         0 => [
             'uid' => '1',
             'pid' => '1',
-            'CType' => 'list',
-            'list_type' => 'events_datelist',
+            'CType' => 'events_datelist',
             'header' => 'All Dates',
         ],
     ],
diff --git a/Tests/Functional/Frontend/DatesTestFixtures/ReturnsOnlyDatesWithAvailableEventByDemand.php b/Tests/Functional/Frontend/DatesTestFixtures/ReturnsOnlyDatesWithAvailableEventByDemand.php
index b3d290a..147f48d 100644
--- a/Tests/Functional/Frontend/DatesTestFixtures/ReturnsOnlyDatesWithAvailableEventByDemand.php
+++ b/Tests/Functional/Frontend/DatesTestFixtures/ReturnsOnlyDatesWithAvailableEventByDemand.php
@@ -7,8 +7,7 @@ return  [
         0 => [
             'uid' => '1',
             'pid' => '1',
-            'CType' => 'list',
-            'list_type' => 'events_datelist',
+            'CType' => 'events_datelist',
             'header' => 'All Dates',
         ],
     ],
diff --git a/Tests/Functional/Frontend/DatesTestFixtures/ReturnsUpcomingDates.php b/Tests/Functional/Frontend/DatesTestFixtures/ReturnsUpcomingDates.php
index 44309cb..fec3e8c 100644
--- a/Tests/Functional/Frontend/DatesTestFixtures/ReturnsUpcomingDates.php
+++ b/Tests/Functional/Frontend/DatesTestFixtures/ReturnsUpcomingDates.php
@@ -7,8 +7,7 @@ return [
         [
             'uid' => 1,
             'pid' => 1,
-            'CType' => 'list',
-            'list_type' => 'events_datelist',
+            'CType' => 'events_datelist',
             'header' => 'Upcoming Dates',
         ],
     ],
diff --git a/Tests/Functional/Frontend/EventsTestFixtures/EventMetaTags.php b/Tests/Functional/Frontend/EventsTestFixtures/EventMetaTags.php
index 34e69ca..06950a1 100644
--- a/Tests/Functional/Frontend/EventsTestFixtures/EventMetaTags.php
+++ b/Tests/Functional/Frontend/EventsTestFixtures/EventMetaTags.php
@@ -7,8 +7,7 @@ return  [
         0 => [
             'uid' => '1',
             'pid' => '1',
-            'CType' => 'list',
-            'list_type' => 'events_eventshow',
+            'CType' => 'events_eventshow',
             'header' => 'Singleview',
         ],
     ],
diff --git a/Tests/Functional/Frontend/EventsTestFixtures/EventOpenGraphTags.php b/Tests/Functional/Frontend/EventsTestFixtures/EventOpenGraphTags.php
index d0a22e2..43baf91 100644
--- a/Tests/Functional/Frontend/EventsTestFixtures/EventOpenGraphTags.php
+++ b/Tests/Functional/Frontend/EventsTestFixtures/EventOpenGraphTags.php
@@ -7,8 +7,7 @@ return  [
         0 => [
             'uid' => '1',
             'pid' => '1',
-            'CType' => 'list',
-            'list_type' => 'events_eventshow',
+            'CType' => 'events_eventshow',
             'header' => 'Singleview',
         ],
     ],
diff --git a/Tests/Functional/Frontend/EventsTestFixtures/EventPageTitle.php b/Tests/Functional/Frontend/EventsTestFixtures/EventPageTitle.php
index 0d3ff66..65c25af 100644
--- a/Tests/Functional/Frontend/EventsTestFixtures/EventPageTitle.php
+++ b/Tests/Functional/Frontend/EventsTestFixtures/EventPageTitle.php
@@ -7,8 +7,7 @@ return  [
         0 => [
             'uid' => '1',
             'pid' => '1',
-            'CType' => 'list',
-            'list_type' => 'events_eventshow',
+            'CType' => 'events_eventshow',
             'header' => 'Singleview',
         ],
     ],
diff --git a/Tests/Functional/Frontend/EventsTestFixtures/EventSocialMediaTags.php b/Tests/Functional/Frontend/EventsTestFixtures/EventSocialMediaTags.php
index 76be838..cc7d1cc 100644
--- a/Tests/Functional/Frontend/EventsTestFixtures/EventSocialMediaTags.php
+++ b/Tests/Functional/Frontend/EventsTestFixtures/EventSocialMediaTags.php
@@ -7,8 +7,7 @@ return  [
         0 => [
             'uid' => '1',
             'pid' => '1',
-            'CType' => 'list',
-            'list_type' => 'events_eventshow',
+            'CType' => 'events_eventshow',
             'header' => 'Singleview',
         ],
     ],
diff --git a/Tests/Functional/Frontend/Fixtures/Database/FilterByASingleLocationViaFlexform.php b/Tests/Functional/Frontend/Fixtures/Database/FilterByASingleLocationViaFlexform.php
index 8b2b415..57dfb84 100644
--- a/Tests/Functional/Frontend/Fixtures/Database/FilterByASingleLocationViaFlexform.php
+++ b/Tests/Functional/Frontend/Fixtures/Database/FilterByASingleLocationViaFlexform.php
@@ -7,8 +7,7 @@ return [
         [
             'pid' => '1',
             'uid' => '1',
-            'CType' => 'list',
-            'list_type' => 'events_datelist',
+            'CType' => 'events_datelist',
             'header' => 'Kino Events',
             'pi_flexform' => '<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
                 <T3FlexForms>
diff --git a/Tests/Functional/Frontend/Fixtures/Database/FilterByTwoLocationsViaFlexform.php b/Tests/Functional/Frontend/Fixtures/Database/FilterByTwoLocationsViaFlexform.php
index 3c9f90c..ea24c42 100644
--- a/Tests/Functional/Frontend/Fixtures/Database/FilterByTwoLocationsViaFlexform.php
+++ b/Tests/Functional/Frontend/Fixtures/Database/FilterByTwoLocationsViaFlexform.php
@@ -7,8 +7,7 @@ return [
         [
             'pid' => '1',
             'uid' => '1',
-            'CType' => 'list',
-            'list_type' => 'events_datelist',
+            'CType' => 'events_datelist',
             'header' => 'Kino Events',
             'pi_flexform' => '<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
                 <T3FlexForms>
diff --git a/Tests/Functional/Frontend/Fixtures/Database/FilterDatesByParentLocationViaFlexform.php b/Tests/Functional/Frontend/Fixtures/Database/FilterDatesByParentLocationViaFlexform.php
index 1301ee4..ca2385e 100644
--- a/Tests/Functional/Frontend/Fixtures/Database/FilterDatesByParentLocationViaFlexform.php
+++ b/Tests/Functional/Frontend/Fixtures/Database/FilterDatesByParentLocationViaFlexform.php
@@ -7,8 +7,7 @@ return [
         [
             'pid' => '1',
             'uid' => '1',
-            'CType' => 'list',
-            'list_type' => 'events_datelist',
+            'CType' => 'events_datelist',
             'header' => 'Kino Events',
             'pi_flexform' => '<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
                 <T3FlexForms>
diff --git a/Tests/Functional/Frontend/Fixtures/Extensions/example/Classes/UserFunc.php b/Tests/Functional/Frontend/Fixtures/Extensions/example/Classes/UserFunc.php
index 2f0c82e..b7458bc 100644
--- a/Tests/Functional/Frontend/Fixtures/Extensions/example/Classes/UserFunc.php
+++ b/Tests/Functional/Frontend/Fixtures/Extensions/example/Classes/UserFunc.php
@@ -23,6 +23,10 @@ declare(strict_types=1);
 
 namespace WerkraumMedia\EventsExample;
 
+use Psr\Http\Message\ServerRequestInterface;
+use TYPO3\CMS\Core\Context\Context;
+use TYPO3\CMS\Core\Utility\GeneralUtility;
+use TYPO3\CMS\Frontend\Cache\CacheLifetimeCalculator;
 use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
 use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController;
 
@@ -35,9 +39,24 @@ final class UserFunc
         $this->cObj = $cObj;
     }
 
-    public function accessTsfeTimeout(): string
+    public function accessTsfeTimeout(string $content, array $configuration, ServerRequestInterface $request): string
     {
-        return 'get_cache_timeout: ' . $this->getTsfe()->get_cache_timeout();
+        // TODO: typo3/cms-core:14.0 Remove this code block as this won't work since v13.x anymore
+        if (is_callable([$this->getTsfe(), 'get_cache_timeout'])) {
+            return 'get_cache_timeout: ' . $this->getTsfe()->get_cache_timeout();
+        }
+
+        $pageInformation = $request->getAttribute('frontend.page.information');
+        $typoScriptConfigArray = $request->getAttribute('frontend.typoscript')->getConfigArray();
+        return 'get_cache_timeout: ' . GeneralUtility::makeInstance(CacheLifetimeCalculator::class)
+            ->calculateLifetimeForPage(
+                $pageInformation->getId(),
+                $pageInformation->getPageRecord(),
+                $typoScriptConfigArray,
+                0,
+                GeneralUtility::makeInstance(Context::class)
+            )
+        ;
     }
 
     public function sleep(string $content, array $configuration): string
diff --git a/Tests/Functional/Frontend/Fixtures/Extensions/example/ext_localconf.php b/Tests/Functional/Frontend/Fixtures/Extensions/example/ext_localconf.php
index bc08afe..19900d1 100644
--- a/Tests/Functional/Frontend/Fixtures/Extensions/example/ext_localconf.php
+++ b/Tests/Functional/Frontend/Fixtures/Extensions/example/ext_localconf.php
@@ -9,11 +9,15 @@ use WerkraumMedia\Events\Controller\EventController;
 ExtensionUtility::configurePlugin(
     'Events',
     'DateListTest',
-    [DateController::class => 'list']
+    [DateController::class => 'list'],
+    [],
+    ExtensionUtility::PLUGIN_TYPE_CONTENT_ELEMENT,
 );
 
 ExtensionUtility::configurePlugin(
     'Events',
     'EventShow',
-    [EventController::class => 'show']
+    [EventController::class => 'show'],
+    [],
+    ExtensionUtility::PLUGIN_TYPE_CONTENT_ELEMENT,
 );
diff --git a/Tests/Functional/Import/DestinationDataTest/Fixtures/Database/FeaturesImportConfiguration.php b/Tests/Functional/Import/DestinationDataTest/Fixtures/Database/FeaturesImportConfiguration.php
index 37a5e0a..4e22a76 100644
--- a/Tests/Functional/Import/DestinationDataTest/Fixtures/Database/FeaturesImportConfiguration.php
+++ b/Tests/Functional/Import/DestinationDataTest/Fixtures/Database/FeaturesImportConfiguration.php
@@ -11,6 +11,7 @@ return [
             'storage_pid' => '2',
             'features_pid' => '3',
             'features_parent' => '4',
+            'files_folder' => '1:/staedte/beispielstadt/events/',
         ],
     ],
     'pages' => [
diff --git a/Tests/Functional/Import/DestinationDataTest/Fixtures/Database/FirstDateOfRecurringDatesImportConfiguration.php b/Tests/Functional/Import/DestinationDataTest/Fixtures/Database/FirstDateOfRecurringDatesImportConfiguration.php
index ff36a9d..7ad2dd2 100644
--- a/Tests/Functional/Import/DestinationDataTest/Fixtures/Database/FirstDateOfRecurringDatesImportConfiguration.php
+++ b/Tests/Functional/Import/DestinationDataTest/Fixtures/Database/FirstDateOfRecurringDatesImportConfiguration.php
@@ -9,6 +9,7 @@ return [
             'pid' => '2',
             'title' => 'Example for test',
             'storage_pid' => '2',
+            'files_folder' => '1:/staedte/beispielstadt/events/',
         ],
     ],
     'pages' => [
diff --git a/Tests/Functional/Import/DestinationDataTest/Fixtures/Database/MinimalImportConfiguration.php b/Tests/Functional/Import/DestinationDataTest/Fixtures/Database/MinimalImportConfiguration.php
index 8b1c6f8..1af5812 100644
--- a/Tests/Functional/Import/DestinationDataTest/Fixtures/Database/MinimalImportConfiguration.php
+++ b/Tests/Functional/Import/DestinationDataTest/Fixtures/Database/MinimalImportConfiguration.php
@@ -10,6 +10,7 @@ return [
             'title' => 'Example import configuration',
             'storage_pid' => '2',
             'rest_experience' => 'beispielstadt',
+            'files_folder' => '1:/staedte/beispielstadt/events/',
         ],
     ],
 ];
diff --git a/Tests/Unit/Domain/Model/Dto/DateDemandFactoryTest.php b/Tests/Unit/Domain/Model/Dto/DateDemandFactoryTest.php
index a02cf6d..1a5ee43 100644
--- a/Tests/Unit/Domain/Model/Dto/DateDemandFactoryTest.php
+++ b/Tests/Unit/Domain/Model/Dto/DateDemandFactoryTest.php
@@ -37,7 +37,7 @@ class DateDemandFactoryTest extends TestCase
     #[Test]
     public function canBeCreated(): void
     {
-        $typoScriptService = $this->createStub(TypoScriptService::class);
+        $typoScriptService = self::createStub(TypoScriptService::class);
 
         $subject = new DateDemandFactory(
             $typoScriptService
@@ -52,7 +52,7 @@ class DateDemandFactoryTest extends TestCase
     #[Test]
     public function fromSettingsDoesNotThrowUndefinedArrayKeyWarnings(): void
     {
-        $typoScriptService = $this->createStub(TypoScriptService::class);
+        $typoScriptService = self::createStub(TypoScriptService::class);
 
         $subject = new DateDemandFactory(
             $typoScriptService
@@ -69,7 +69,7 @@ class DateDemandFactoryTest extends TestCase
     #[Test]
     public function searchWordIsSetByRequest(): void
     {
-        $typoScriptService = $this->createStub(TypoScriptService::class);
+        $typoScriptService = self::createStub(TypoScriptService::class);
 
         $subject = new DateDemandFactory(
             $typoScriptService
@@ -91,7 +91,7 @@ class DateDemandFactoryTest extends TestCase
     #[Test]
     public function synonymsAreSetBySettings(): void
     {
-        $typoScriptService = $this->createStub(TypoScriptService::class);
+        $typoScriptService = self::createStub(TypoScriptService::class);
 
         $subject = new DateDemandFactory(
             $typoScriptService
@@ -130,7 +130,7 @@ class DateDemandFactoryTest extends TestCase
     #[Test]
     public function categoriesAreSetByRequest(): void
     {
-        $typoScriptService = $this->createStub(TypoScriptService::class);
+        $typoScriptService = self::createStub(TypoScriptService::class);
 
         $subject = new DateDemandFactory(
             $typoScriptService
@@ -157,7 +157,7 @@ class DateDemandFactoryTest extends TestCase
     #[Test]
     public function featuresAreSetByRequest(): void
     {
-        $typoScriptService = $this->createStub(TypoScriptService::class);
+        $typoScriptService = self::createStub(TypoScriptService::class);
 
         $subject = new DateDemandFactory(
             $typoScriptService
@@ -184,7 +184,7 @@ class DateDemandFactoryTest extends TestCase
     #[Test]
     public function regionIsSetByRequest(): void
     {
-        $typoScriptService = $this->createStub(TypoScriptService::class);
+        $typoScriptService = self::createStub(TypoScriptService::class);
 
         $subject = new DateDemandFactory(
             $typoScriptService
@@ -212,7 +212,7 @@ class DateDemandFactoryTest extends TestCase
     #[Test]
     public function regionsAreSetByRequest(): void
     {
-        $typoScriptService = $this->createStub(TypoScriptService::class);
+        $typoScriptService = self::createStub(TypoScriptService::class);
 
         $subject = new DateDemandFactory(
             $typoScriptService
@@ -243,7 +243,7 @@ class DateDemandFactoryTest extends TestCase
     #[Test]
     public function startIsSetByRequest(): void
     {
-        $typoScriptService = $this->createStub(TypoScriptService::class);
+        $typoScriptService = self::createStub(TypoScriptService::class);
 
         $subject = new DateDemandFactory(
             $typoScriptService
@@ -273,7 +273,7 @@ class DateDemandFactoryTest extends TestCase
     #[Test]
     public function endIsSetByRequest(): void
     {
-        $typoScriptService = $this->createStub(TypoScriptService::class);
+        $typoScriptService = self::createStub(TypoScriptService::class);
 
         $subject = new DateDemandFactory(
             $typoScriptService
@@ -306,7 +306,7 @@ class DateDemandFactoryTest extends TestCase
         string $start,
         string $end
     ): void {
-        $typoScriptService = $this->createStub(TypoScriptService::class);
+        $typoScriptService = self::createStub(TypoScriptService::class);
 
         $subject = new DateDemandFactory(
             $typoScriptService
@@ -344,7 +344,7 @@ class DateDemandFactoryTest extends TestCase
     #[Test]
     public function returnsEndsOnSameDayIfBothAreOnSameDay(): void
     {
-        $typoScriptService = $this->createStub(TypoScriptService::class);
+        $typoScriptService = self::createStub(TypoScriptService::class);
 
         $subject = new DateDemandFactory(
             $typoScriptService
@@ -366,7 +366,7 @@ class DateDemandFactoryTest extends TestCase
     #[Test]
     public function returnsEndsOnSameDayIfBothAreOnDifferentDays(): void
     {
-        $typoScriptService = $this->createStub(TypoScriptService::class);
+        $typoScriptService = self::createStub(TypoScriptService::class);
 
         $subject = new DateDemandFactory(
             $typoScriptService
@@ -389,7 +389,7 @@ class DateDemandFactoryTest extends TestCase
     #[Test]
     public function returnsHighlightIfSet(mixed $highlight): void
     {
-        $typoScriptService = $this->createStub(TypoScriptService::class);
+        $typoScriptService = self::createStub(TypoScriptService::class);
 
         $subject = new DateDemandFactory(
             $typoScriptService
@@ -416,7 +416,7 @@ class DateDemandFactoryTest extends TestCase
     #[Test]
     public function returnsNoHighlightIfNotSet(mixed $highlight): void
     {
-        $typoScriptService = $this->createStub(TypoScriptService::class);
+        $typoScriptService = self::createStub(TypoScriptService::class);
 
         $subject = new DateDemandFactory(
             $typoScriptService
@@ -443,7 +443,7 @@ class DateDemandFactoryTest extends TestCase
     #[Test]
     public function returnsOrganizersFromSettings(): void
     {
-        $typoScriptService = $this->createStub(TypoScriptService::class);
+        $typoScriptService = self::createStub(TypoScriptService::class);
 
         $subject = new DateDemandFactory(
             $typoScriptService
@@ -458,7 +458,7 @@ class DateDemandFactoryTest extends TestCase
     #[Test]
     public function returnsOrganizersFromRequest(): void
     {
-        $typoScriptService = $this->createStub(TypoScriptService::class);
+        $typoScriptService = self::createStub(TypoScriptService::class);
 
         $subject = new DateDemandFactory(
             $typoScriptService
diff --git a/Tests/Unit/Domain/Model/EventTest.php b/Tests/Unit/Domain/Model/EventTest.php
index 589da43..b2e4125 100644
--- a/Tests/Unit/Domain/Model/EventTest.php
+++ b/Tests/Unit/Domain/Model/EventTest.php
@@ -26,9 +26,9 @@ class EventTest extends TestCase
     #[Test]
     public function returnsSortedFeatures(): void
     {
-        $feature1 = $this->createStub(Category::class);
+        $feature1 = self::createStub(Category::class);
         $feature1->method('getSorting')->willReturn(10);
-        $feature2 = $this->createStub(Category::class);
+        $feature2 = self::createStub(Category::class);
         $feature2->method('getSorting')->willReturn(5);
 
         $storage = new ObjectStorage();
diff --git a/Tests/Unit/Domain/Model/ImportTest.php b/Tests/Unit/Domain/Model/ImportTest.php
index 9becf22..a17c8da 100644
--- a/Tests/Unit/Domain/Model/ImportTest.php
+++ b/Tests/Unit/Domain/Model/ImportTest.php
@@ -16,7 +16,7 @@ class ImportTest extends TestCase
     #[Test]
     public function canBeCreated(): void
     {
-        $folder = $this->createStub(Folder::class);
+        $folder = self::createStub(Folder::class);
 
         $subject = new Import(
             $folder,
@@ -33,7 +33,7 @@ class ImportTest extends TestCase
     #[Test]
     public function returnsRestExperience(): void
     {
-        $folder = $this->createStub(Folder::class);
+        $folder = self::createStub(Folder::class);
 
         $subject = new Import(
             $folder,
@@ -50,7 +50,7 @@ class ImportTest extends TestCase
     #[Test]
     public function returnsStoragePid(): void
     {
-        $folder = $this->createStub(Folder::class);
+        $folder = self::createStub(Folder::class);
 
         $subject = new Import(
             $folder,
@@ -67,8 +67,8 @@ class ImportTest extends TestCase
     #[Test]
     public function returnsRegion(): void
     {
-        $folder = $this->createStub(Folder::class);
-        $region = $this->createStub(Region::class);
+        $folder = self::createStub(Folder::class);
+        $region = self::createStub(Region::class);
 
         $subject = new Import(
             $folder,
@@ -91,7 +91,7 @@ class ImportTest extends TestCase
     #[Test]
     public function returnsFilesFolder(): void
     {
-        $folder = $this->createStub(Folder::class);
+        $folder = self::createStub(Folder::class);
 
         $subject = new Import(
             $folder,
@@ -108,7 +108,7 @@ class ImportTest extends TestCase
     #[Test]
     public function returnsCategoriesPid(): void
     {
-        $folder = $this->createStub(Folder::class);
+        $folder = self::createStub(Folder::class);
 
         $subject = new Import(
             $folder,
@@ -127,8 +127,8 @@ class ImportTest extends TestCase
     #[Test]
     public function returnsCategoryParent(): void
     {
-        $category = $this->createStub(Category::class);
-        $folder = $this->createStub(Folder::class);
+        $category = self::createStub(Category::class);
+        $folder = self::createStub(Folder::class);
 
         $subject = new Import(
             $folder,
@@ -148,7 +148,7 @@ class ImportTest extends TestCase
     #[Test]
     public function returnsFeaturesPid(): void
     {
-        $folder = $this->createStub(Folder::class);
+        $folder = self::createStub(Folder::class);
 
         $subject = new Import(
             $folder,
@@ -169,8 +169,8 @@ class ImportTest extends TestCase
     #[Test]
     public function returnsFeaturesParent(): void
     {
-        $feature = $this->createStub(Category::class);
-        $folder = $this->createStub(Folder::class);
+        $feature = self::createStub(Category::class);
+        $folder = self::createStub(Folder::class);
 
         $subject = new Import(
             $folder,
@@ -192,7 +192,7 @@ class ImportTest extends TestCase
     #[Test]
     public function returnsSearchQuery(): void
     {
-        $folder = $this->createStub(Folder::class);
+        $folder = self::createStub(Folder::class);
 
         $subject = new Import(
             $folder,
diff --git a/Tests/Unit/Events/Controller/DateListVariablesTest.php b/Tests/Unit/Events/Controller/DateListVariablesTest.php
index 89ccecb..87a2a6e 100644
--- a/Tests/Unit/Events/Controller/DateListVariablesTest.php
+++ b/Tests/Unit/Events/Controller/DateListVariablesTest.php
@@ -19,8 +19,8 @@ class DateListVariablesTest extends TestCase
         $subject = new DateListVariables(
             [],
             new DateDemand(),
-            $this->createStub(QueryResult::class),
-            $this->createStub(PaginationInterface::class)
+            self::createStub(QueryResult::class),
+            self::createStub(PaginationInterface::class)
         );
 
         self::assertInstanceOf(
@@ -37,8 +37,8 @@ class DateListVariablesTest extends TestCase
                 'executed' => '1',
             ],
             new DateDemand(),
-            $this->createStub(QueryResult::class),
-            $this->createStub(PaginationInterface::class)
+            self::createStub(QueryResult::class),
+            self::createStub(PaginationInterface::class)
         );
 
         self::assertSame(
@@ -57,8 +57,8 @@ class DateListVariablesTest extends TestCase
             [
             ],
             $demand,
-            $this->createStub(QueryResult::class),
-            $this->createStub(PaginationInterface::class)
+            self::createStub(QueryResult::class),
+            self::createStub(PaginationInterface::class)
         );
 
         self::assertSame(
@@ -70,13 +70,13 @@ class DateListVariablesTest extends TestCase
     #[Test]
     public function returnsInitialDates(): void
     {
-        $dates = $this->createStub(QueryResult::class);
+        $dates = self::createStub(QueryResult::class);
         $subject = new DateListVariables(
             [
             ],
             new DateDemand(),
             $dates,
-            $this->createStub(PaginationInterface::class)
+            self::createStub(PaginationInterface::class)
         );
 
         self::assertSame(
@@ -89,8 +89,8 @@ class DateListVariablesTest extends TestCase
     public function returnsInitialVariablesForView(): void
     {
         $demand = new DateDemand();
-        $dates = $this->createStub(QueryResult::class);
-        $pagination = $this->createStub(PaginationInterface::class);
+        $dates = self::createStub(QueryResult::class);
+        $pagination = self::createStub(PaginationInterface::class);
         $subject = new DateListVariables(
             [
                 'executed' => '1',
@@ -117,8 +117,8 @@ class DateListVariablesTest extends TestCase
     public function returnsVariablesForViewWithAddedVariables(): void
     {
         $demand = new DateDemand();
-        $dates = $this->createStub(QueryResult::class);
-        $pagination = $this->createStub(PaginationInterface::class);
+        $dates = self::createStub(QueryResult::class);
+        $pagination = self::createStub(PaginationInterface::class);
         $subject = new DateListVariables(
             [
                 'executed' => '1',
@@ -150,8 +150,8 @@ class DateListVariablesTest extends TestCase
     public function returnsVariablesForViewWithOverwrittenVariables(): void
     {
         $demand = new DateDemand();
-        $dates = $this->createStub(QueryResult::class);
-        $pagination = $this->createStub(PaginationInterface::class);
+        $dates = self::createStub(QueryResult::class);
+        $pagination = self::createStub(PaginationInterface::class);
         $subject = new DateListVariables(
             [
                 'executed' => '1',
diff --git a/Tests/Unit/Events/Controller/DateSearchVariablesTest.php b/Tests/Unit/Events/Controller/DateSearchVariablesTest.php
index cd82f1f..b61adc4 100644
--- a/Tests/Unit/Events/Controller/DateSearchVariablesTest.php
+++ b/Tests/Unit/Events/Controller/DateSearchVariablesTest.php
@@ -21,7 +21,7 @@ class DateSearchVariablesTest extends TestCase
             [
             ],
             new DateDemand(),
-            $this->createStub(QueryResult::class),
+            self::createStub(QueryResult::class),
             [],
             []
         );
@@ -42,7 +42,7 @@ class DateSearchVariablesTest extends TestCase
             [
             ],
             new DateDemand(),
-            $this->createStub(QueryResult::class),
+            self::createStub(QueryResult::class),
             [],
             []
         );
@@ -65,7 +65,7 @@ class DateSearchVariablesTest extends TestCase
                 'executed' => '1',
             ],
             new DateDemand(),
-            $this->createStub(QueryResult::class),
+            self::createStub(QueryResult::class),
             [],
             []
         );
@@ -88,7 +88,7 @@ class DateSearchVariablesTest extends TestCase
             [
             ],
             $demand,
-            $this->createStub(QueryResult::class),
+            self::createStub(QueryResult::class),
             [],
             []
         );
@@ -102,7 +102,7 @@ class DateSearchVariablesTest extends TestCase
     #[Test]
     public function returnsInitialRegions(): void
     {
-        $regions = $this->createStub(QueryResult::class);
+        $regions = self::createStub(QueryResult::class);
         $subject = new DateSearchVariables(
             [
             ],
@@ -129,7 +129,7 @@ class DateSearchVariablesTest extends TestCase
             [
             ],
             new DateDemand(),
-            $this->createStub(QueryResult::class),
+            self::createStub(QueryResult::class),
             [
                 ['example category'],
             ],
@@ -153,7 +153,7 @@ class DateSearchVariablesTest extends TestCase
             [
             ],
             new DateDemand(),
-            $this->createStub(QueryResult::class),
+            self::createStub(QueryResult::class),
             [
             ],
             [
@@ -173,7 +173,7 @@ class DateSearchVariablesTest extends TestCase
     public function returnsInitialVariablesForView(): void
     {
         $demand = new DateDemand();
-        $regions = $this->createStub(QueryResult::class);
+        $regions = self::createStub(QueryResult::class);
         $subject = new DateSearchVariables(
             [
             ],
@@ -212,7 +212,7 @@ class DateSearchVariablesTest extends TestCase
     public function returnsVariablesForViewWithAddedVariables(): void
     {
         $demand = new DateDemand();
-        $regions = $this->createStub(QueryResult::class);
+        $regions = self::createStub(QueryResult::class);
         $subject = new DateSearchVariables(
             [
             ],
@@ -256,7 +256,7 @@ class DateSearchVariablesTest extends TestCase
     public function returnsVariablesForViewWithOverwrittenVariables(): void
     {
         $demand = new DateDemand();
-        $regions = $this->createStub(QueryResult::class);
+        $regions = self::createStub(QueryResult::class);
         $subject = new DateSearchVariables(
             [
             ],
diff --git a/Tests/Unit/Service/DestinationDataImportService/DatesFactoryTest.php b/Tests/Unit/Service/DestinationDataImportService/DatesFactoryTest.php
index 561cd42..0067893 100644
--- a/Tests/Unit/Service/DestinationDataImportService/DatesFactoryTest.php
+++ b/Tests/Unit/Service/DestinationDataImportService/DatesFactoryTest.php
@@ -22,13 +22,13 @@ class DatesFactoryTest extends TestCase
     private function createTestSubject(
         string $contextDate
     ): DatesFactory {
-        $logger = $this->createStub(Logger::class);
-        $logManager = $this->createStub(LogManager::class);
+        $logger = self::createStub(Logger::class);
+        $logManager = self::createStub(LogManager::class);
         $logManager->method('getLogger')->willReturn($logger);
 
         return new DatesFactory(
             $this->createContext(new DateTimeImmutable($contextDate)),
-            $this->createStub(ConfigurationManager::class),
+            self::createStub(ConfigurationManager::class),
             $logManager
         );
     }
diff --git a/Tests/Unit/Service/DestinationDataImportService/LocationAssignmentTest.php b/Tests/Unit/Service/DestinationDataImportService/LocationAssignmentTest.php
index 7dae8ab..1d16aef 100644
--- a/Tests/Unit/Service/DestinationDataImportService/LocationAssignmentTest.php
+++ b/Tests/Unit/Service/DestinationDataImportService/LocationAssignmentTest.php
@@ -42,7 +42,7 @@ final class LocationAssignmentTest extends TestCase
     #[Test]
     public function canBeCreated(): void
     {
-        $repository = $this->createStub(LocationRepository::class);
+        $repository = self::createStub(LocationRepository::class);
         $subject = new LocationAssignment(
             $repository
         );
@@ -63,7 +63,7 @@ final class LocationAssignmentTest extends TestCase
         $latitude,
         $longitude
     ): void {
-        $repository = $this->createStub(LocationRepository::class);
+        $repository = self::createStub(LocationRepository::class);
         $repository->method('findOneByGlobalId')->willReturn(null);
 
         $subject = new LocationAssignment(
diff --git a/Tests/Unit/Service/DestinationDataImportService/UrlFactoryTest.php b/Tests/Unit/Service/DestinationDataImportService/UrlFactoryTest.php
index 8b9e678..df109fb 100644
--- a/Tests/Unit/Service/DestinationDataImportService/UrlFactoryTest.php
+++ b/Tests/Unit/Service/DestinationDataImportService/UrlFactoryTest.php
@@ -8,8 +8,8 @@ use PHPUnit\Framework\Attributes\DataProvider;
 use PHPUnit\Framework\Attributes\Test;
 use PHPUnit\Framework\MockObject\Stub;
 use PHPUnit\Framework\TestCase;
-use TYPO3\CMS\Extbase\Configuration\BackendConfigurationManager;
 use WerkraumMedia\Events\Domain\Model\Import;
+use WerkraumMedia\Events\Service\DestinationDataImportService\ArrayBasedConfigurationService;
 use WerkraumMedia\Events\Service\DestinationDataImportService\UrlFactory;
 
 class UrlFactoryTest extends TestCase
@@ -17,8 +17,7 @@ class UrlFactoryTest extends TestCase
     #[Test]
     public function canBeCreated(): void
     {
-        $configurationManager = $this->createStub(BackendConfigurationManager::class);
-        $configurationManager->method('getConfiguration')->willReturn([]);
+        $configurationManager = new ArrayBasedConfigurationService([]);
 
         $subject = new UrlFactory(
             $configurationManager
@@ -37,8 +36,7 @@ class UrlFactoryTest extends TestCase
         array $settings,
         string $expectedResult
     ): void {
-        $configurationManager = $this->createStub(BackendConfigurationManager::class);
-        $configurationManager->method('getConfiguration')->willReturn(['settings' => ['destinationData' => $settings]]);
+        $configurationManager = new ArrayBasedConfigurationService($settings);
 
         $subject = new UrlFactory(
             $configurationManager
diff --git a/composer.json b/composer.json
index 38ef959..2bce866 100644
--- a/composer.json
+++ b/composer.json
@@ -21,14 +21,14 @@
     "require": {
         "php": "~8.1.0 || ~8.2.0 || ~8.3.0",
         "symfony/console": "^6.4 || ^7.0",
-        "symfony/dependency-injection": "^6.4 || ^7.0",
-        "typo3/cms-core": "^12.4",
-        "typo3/cms-extbase": "^12.4",
-        "typo3/cms-filelist": "^12.4",
-        "typo3/cms-filemetadata": "^12.4",
-        "typo3/cms-fluid": "^12.4",
-        "typo3/cms-frontend": "^12.4",
-        "typo3/cms-install": "^12.4"
+        "symfony/dependency-injection": "^6.4 || ^7.0 || ^7.1",
+        "typo3/cms-core": "^12.4 || ^13.4",
+        "typo3/cms-extbase": "^12.4 || ^13.4",
+        "typo3/cms-filelist": "^12.4 || ^13.4",
+        "typo3/cms-filemetadata": "^12.4 || ^13.4",
+        "typo3/cms-fluid": "^12.4 || ^13.4",
+        "typo3/cms-frontend": "^12.4 || ^13.4",
+        "typo3/cms-install": "^12.4 || ^13.4"
     },
     "autoload": {
         "psr-4": {
@@ -69,10 +69,11 @@
         "phpstan/extension-installer": "^1.1",
         "phpstan/phpstan": "^1.10",
         "phpstan/phpstan-phpunit": "1.3.15",
-        "saschaegerer/phpstan-typo3": "1.9.0",
-        "typo3/cms-backend": "^12.4",
-        "typo3/cms-fluid-styled-content": "^12.4",
-        "typo3/cms-seo": "^12.4",
+        "saschaegerer/phpstan-typo3": "^1.10",
+        "staabm/phpstan-todo-by": "^0.1.28",
+        "typo3/cms-backend": "^12.4 || ^13.4",
+        "typo3/cms-fluid-styled-content": "^12.4 || ^13.4",
+        "typo3/cms-seo": "^12.4 || ^13.4",
         "typo3/testing-framework": "^8.0"
     },
     "config": {
diff --git a/ext_emconf.php b/ext_emconf.php
index a79d2f2..87ecdb4 100644
--- a/ext_emconf.php
+++ b/ext_emconf.php
@@ -9,7 +9,7 @@ $EM_CONF['events'] = [
     'author' => 'Dirk Koritnik, Daniel Siepmann',
     'author_email' => 'koritnik@werkraum-media.de, coding@daniel-siepmann.de',
     'state' => 'stable',
-    'version' => '4.2.1',
+    'version' => '5.0.0',
     'constraints' => [
         'depends' => [
             'typo3' => '',
diff --git a/ext_localconf.php b/ext_localconf.php
index 3f4aa83..c49e7a8 100644
--- a/ext_localconf.php
+++ b/ext_localconf.php
@@ -2,9 +2,6 @@
 
 declare(strict_types=1);
 
-use TYPO3\CMS\Core\Imaging\IconProvider\SvgIconProvider;
-use TYPO3\CMS\Core\Imaging\IconRegistry;
-use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Extbase\Utility\ExtensionUtility;
 use WerkraumMedia\Events\Controller\DateController;
 use WerkraumMedia\Events\Controller\EventController;
@@ -16,27 +13,32 @@ call_user_func(function () {
         'Events',
         'DateSearch',
         [DateController::class => 'search'],
-        [DateController::class => 'search']
+        [DateController::class => 'search'],
+        ExtensionUtility::PLUGIN_TYPE_CONTENT_ELEMENT
     );
 
     ExtensionUtility::configurePlugin(
         'Events',
         'DateList',
         [DateController::class => 'list'],
-        [DateController::class => 'list']
+        [DateController::class => 'list'],
+        ExtensionUtility::PLUGIN_TYPE_CONTENT_ELEMENT
     );
 
     ExtensionUtility::configurePlugin(
         'Events',
         'DateShow',
         [DateController::class => 'show'],
-        [DateController::class => 'show']
+        [DateController::class => 'show'],
+        ExtensionUtility::PLUGIN_TYPE_CONTENT_ELEMENT
     );
 
     ExtensionUtility::configurePlugin(
         'Events',
         'Selected',
-        [EventController::class => 'list']
+        [EventController::class => 'list'],
+        [],
+        ExtensionUtility::PLUGIN_TYPE_CONTENT_ELEMENT
     );
 
     if (
@@ -47,16 +49,4 @@ call_user_func(function () {
     }
 
     $GLOBALS['TYPO3_CONF_VARS']['FE']['cacheHash']['excludedParameters'][] = '^events_search';
-
-    $iconRegistry = GeneralUtility::makeInstance(IconRegistry::class);
-    $iconRegistry->registerIcon(
-        'events-plugin',
-        SvgIconProvider::class,
-        ['source' => 'EXT:events/Resources/Public/Icons/Extension.svg']
-    );
-    $iconRegistry->registerIcon(
-        'pages-module-events',
-        SvgIconProvider::class,
-        ['source' => 'EXT:events/Resources/Public/Icons/Folder.svg']
-    );
 });
diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon
index a19129b..0670f6e 100644
--- a/phpstan-baseline.neon
+++ b/phpstan-baseline.neon
@@ -6,13 +6,8 @@ parameters:
 			path: Classes/Controller/DateController.php
 
 		-
-			message: "#^Parameter \\#1 \\$callback of function array_map expects \\(callable\\(mixed\\)\\: mixed\\)\\|null, 'strval' given\\.$#"
-			count: 1
-			path: Classes/Domain/DestinationData/ImportFactory.php
-
-		-
-			message: "#^Parameter \\#2 \\$array of function array_map expects array, mixed given\\.$#"
-			count: 1
+			message: "#^Parameter \\#1 \\$callback of function array_map expects \\(callable\\(mixed\\)\\: mixed\\)\\|null, Closure\\(bool\\|float\\|int\\|resource\\|string\\|null\\)\\: string given\\.$#"
+			count: 2
 			path: Classes/Domain/DestinationData/ImportFactory.php
 
 		-