From c8a17c6fa2dd0907b1bf00444b17693494ffe466 Mon Sep 17 00:00:00 2001 From: Daniel Siepmann Date: Mon, 19 Aug 2024 15:22:56 +0200 Subject: [PATCH] WIP|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 | 32 +- .../TCA/tx_events_domain_model_event.php | 1 - Documentation/Changelog/5.0.0.rst | 35 +++ Documentation/Index.rst | 2 + Documentation/Maintenance.rst | 16 + Documentation/Settings.cfg | 11 - Documentation/guides.xml | 21 ++ .../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 + .../UrlFactoryTest.php | 8 +- composer.json | 25 +- ext_emconf.php | 2 +- ext_localconf.php | 28 +- phpstan-baseline.neon | 9 +- 62 files changed, 667 insertions(+), 405 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 @@ +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 @@ +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 @@ +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 @@ + + * + * 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 @@ - - Options - + Options array - - 1 - - - select - selectSingle - - - Start - start - - - End - end - - - - + 1 + + + select + selectSingle + + + Start + start + + + End + end + + + - - 1 - - - select - selectSingle - - - - Ascending - - ASC + 1 + + + select + selectSingle + + + + Ascending - - - Descending - - DESC + ASC + + + + Descending - - ASC - - + DESC + + + ASC + - - 1 - - - input - 10 - 30 - trim - - + 1 + + + input + 10 + 30 + trim + - - 1 - - - check - 0 - - + 1 + + + check + 0 + - - 1 - - - check - 0 - - + 1 + + + check + 0 + - - 1 - - - check - 0 - - + 1 + + + check + 0 + - - 1 - - - group - db - pages - 1 - 1 - 0 - 1 - - + 1 + + + group + pages + 1 + 1 + 0 + 1 + - - Template - + Template array @@ -133,20 +114,20 @@ selectSingle - Default - default + Default + default - Costum - costum + Custom + costum - Table - table + Table + table - Grid - grid + Grid + grid default @@ -157,34 +138,29 @@ - - Regions & Categories - + Regions & Categories array - - - - select - selectSingle - - - Alle - - - - tx_events_domain_model_region - AND tx_events_domain_model_region.deleted = 0 AND tx_events_domain_model_region.hidden = 0 - 1 - 0 - 1 - - + + + select + selectSingle + + + Alle + + + + tx_events_domain_model_region + AND tx_events_domain_model_region.deleted = 0 AND tx_events_domain_model_region.hidden = 0 + 1 + 0 + 1 + - 1 @@ -192,54 +168,49 @@ selectSingle - And - 0 + And + 0 - Or - 1 + Or + 1 0 - - - 1 - - - select - selectTree - 20 - sys_category - AND sys_category.sys_language_uid IN (-1, 0) ORDER BY sys_category.title ASC - 1 - tree - 8 - - - 1 - 1 - - parent - - - + 1 + + + select + selectTree + 20 + sys_category + AND sys_category.sys_language_uid IN (-1, 0) ORDER BY sys_category.title ASC + 1 + tree + 8 + + + 1 + 1 + + parent + + - 1 check 0 - 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 @@ - - Options - + Options array - - 1 - - - group - db - pages - 1 - 1 - 0 - 1 - - + 1 + + + group + pages + 1 + 1 + 0 + 1 + - - 1 - - - check - 0 - - + 1 + + + check + 0 + - \ No newline at end of file + 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 @@ - - Options - + Options array - 1 group - db pages 1 1 0 1 - - + - - Template - + Template array @@ -39,12 +32,12 @@ select - Default - default + Default + default - Costum - costum + Custom + costum default @@ -54,4 +47,4 @@ - \ No newline at end of file + 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 @@ array - - 1 - - - group - db - tx_events_domain_model_event - 1 - 1 - - + 1 + + + group + tx_events_domain_model_event + 1 + 1 + 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 @@ + [ + '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..27a366b 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' ); - $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' ); - $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' ); - $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' ); - $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..9ed17c0 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' => [ 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 @@ + + + + + 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' => ' 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' => ' 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' => ' 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/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 -