WIP|Add TYPO3 13 LTS Support

Relates: #11322
This commit is contained in:
Daniel Siepmann 2024-08-19 15:22:56 +02:00 committed by Daniel Siepmann
parent 60b752e4b2
commit c8a17c6fa2
SSH key fingerprint: SHA256:nAjx3Dpp8kuAC+S7QXj8BWmqw+KI1Miu+5e40BP3LXA
62 changed files with 667 additions and 405 deletions

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -75,7 +75,7 @@ final class CategoryRepository extends Repository
return $this->dataMapper->map(
Category::class,
$qb->executeQuery()->fetchAll()
$qb->executeQuery()->fetchAllAssociative()
);
}

View file

@ -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(

View file

@ -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;
}
}

View file

@ -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;

View file

@ -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);
}
}

View file

@ -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);

View file

@ -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] ?? [];

View file

@ -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;
}

View file

@ -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(

View file

@ -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'] ?? '';
}
}

View file

@ -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;
}

View file

@ -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;
}
}

View file

@ -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;
}

View file

@ -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)

View file

@ -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;
}

View file

@ -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;
}
}

View file

@ -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) {

View file

@ -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.';
}
}

View file

@ -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>

View file

@ -2,35 +2,28 @@
<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>

View file

@ -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>

View file

@ -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>

16
Configuration/Icons.php Normal file
View file

@ -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',
],
];

View file

@ -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

View file

@ -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');

View file

@ -346,7 +346,6 @@ return [
'config' => [
'type' => 'category',
'minitems' => 0,
'multiple' => true,
],
],
'features' => [

View file

@ -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

View file

@ -43,6 +43,8 @@ Table of Contents
Settings
Changelog
Maintenance
.. toctree::
:hidden:

View file

@ -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.

View file

@ -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/

21
Documentation/guides.xml Normal file
View file

@ -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>

View file

@ -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);

View file

@ -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.');
}

View file

@ -7,8 +7,7 @@ return [
0 => [
'uid' => '1',
'pid' => '1',
'CType' => 'list',
'list_type' => 'events_dateshow',
'CType' => 'events_dateshow',
'header' => 'Singleview',
],
],

View file

@ -7,8 +7,7 @@ return [
0 => [
'uid' => '1',
'pid' => '1',
'CType' => 'list',
'list_type' => 'events_dateshow',
'CType' => 'events_dateshow',
'header' => 'Singleview',
],
],

View file

@ -7,8 +7,7 @@ return [
0 => [
'uid' => '1',
'pid' => '1',
'CType' => 'list',
'list_type' => 'events_dateshow',
'CType' => 'events_dateshow',
'header' => 'Singleview',
],
],

View file

@ -7,8 +7,7 @@ return [
0 => [
'uid' => '1',
'pid' => '1',
'CType' => 'list',
'list_type' => 'events_dateshow',
'CType' => 'events_dateshow',
'header' => 'Singleview',
],
],

View file

@ -7,8 +7,7 @@ return [
0 => [
'uid' => '1',
'pid' => '1',
'CType' => 'list',
'list_type' => 'events_dateshow',
'CType' => 'events_dateshow',
'header' => 'Singleview',
],
],

View file

@ -7,8 +7,7 @@ return [
0 => [
'uid' => '1',
'pid' => '1',
'CType' => 'list',
'list_type' => 'events_datelist',
'CType' => 'events_datelist',
'header' => 'All Dates',
],
],

View file

@ -7,8 +7,7 @@ return [
0 => [
'uid' => '1',
'pid' => '1',
'CType' => 'list',
'list_type' => 'events_datelist',
'CType' => 'events_datelist',
'header' => 'All Dates',
],
],

View file

@ -7,8 +7,7 @@ return [
[
'uid' => 1,
'pid' => 1,
'CType' => 'list',
'list_type' => 'events_datelist',
'CType' => 'events_datelist',
'header' => 'Upcoming Dates',
],
],

View file

@ -7,8 +7,7 @@ return [
0 => [
'uid' => '1',
'pid' => '1',
'CType' => 'list',
'list_type' => 'events_eventshow',
'CType' => 'events_eventshow',
'header' => 'Singleview',
],
],

View file

@ -7,8 +7,7 @@ return [
0 => [
'uid' => '1',
'pid' => '1',
'CType' => 'list',
'list_type' => 'events_eventshow',
'CType' => 'events_eventshow',
'header' => 'Singleview',
],
],

View file

@ -7,8 +7,7 @@ return [
0 => [
'uid' => '1',
'pid' => '1',
'CType' => 'list',
'list_type' => 'events_eventshow',
'CType' => 'events_eventshow',
'header' => 'Singleview',
],
],

View file

@ -7,8 +7,7 @@ return [
0 => [
'uid' => '1',
'pid' => '1',
'CType' => 'list',
'list_type' => 'events_eventshow',
'CType' => 'events_eventshow',
'header' => 'Singleview',
],
],

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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

View file

@ -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,
);

View file

@ -11,6 +11,7 @@ return [
'storage_pid' => '2',
'features_pid' => '3',
'features_parent' => '4',
'files_folder' => '1:/staedte/beispielstadt/events/',
],
],
'pages' => [

View file

@ -9,6 +9,7 @@ return [
'pid' => '2',
'title' => 'Example for test',
'storage_pid' => '2',
'files_folder' => '1:/staedte/beispielstadt/events/',
],
],
'pages' => [

View file

@ -10,6 +10,7 @@ return [
'title' => 'Example import configuration',
'storage_pid' => '2',
'rest_experience' => 'beispielstadt',
'files_folder' => '1:/staedte/beispielstadt/events/',
],
],
];

View file

@ -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

View file

@ -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": {

View file

@ -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' => '',

View file

@ -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']
);
});

View file

@ -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
-