BREAKING: TYPO3 v12 support (#44)

* Migrated all fixtures to PHP.
* Removed version specific adjustments.
This commit is contained in:
Daniel Siepmann 2023-11-27 10:04:42 +01:00 committed by GitHub
parent a9f3f108e3
commit 81065f5c67
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
208 changed files with 4394 additions and 3438 deletions

1
.gitattributes vendored
View file

@ -1,4 +1,5 @@
Tests export-ignore Tests export-ignore
Patches export-ignore
.gitlab-ci.yml export-ignore .gitlab-ci.yml export-ignore
shell.nix export-ignore shell.nix export-ignore

View file

@ -15,12 +15,9 @@ jobs:
strategy: strategy:
matrix: matrix:
php-version: php-version:
- 7.2
- 7.3
- 7.4
- 8.0
- 8.1 - 8.1
- 8.2 - 8.2
- 8.3
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v3 uses: actions/checkout@v3
@ -43,7 +40,7 @@ jobs:
- name: Install PHP - name: Install PHP
uses: shivammathur/setup-php@v2 uses: shivammathur/setup-php@v2
with: with:
php-version: "7.4" php-version: "8.2"
tools: composer:v2 tools: composer:v2
- name: Install xmllint - name: Install xmllint
@ -71,14 +68,14 @@ jobs:
- name: Install PHP - name: Install PHP
uses: shivammathur/setup-php@v2 uses: shivammathur/setup-php@v2
with: with:
php-version: "8.1" php-version: "8.2"
tools: composer:v2 tools: composer:v2
- name: Install dependencies - name: Install dependencies
run: composer install --prefer-dist --no-progress --no-suggest run: composer install --prefer-dist --no-progress --no-suggest
- name: Coding Guideline - name: Coding Guideline
run: ./vendor/bin/php-cs-fixer fix run: ./vendor/bin/php-cs-fixer fix --dry-run --diff
code-quality: code-quality:
runs-on: ubuntu-latest runs-on: ubuntu-latest
@ -87,20 +84,12 @@ jobs:
strategy: strategy:
matrix: matrix:
include: include:
- php-version: '7.2'
typo3-version: '^10.4'
- php-version: '7.3'
typo3-version: '^10.4'
- php-version: '7.4'
typo3-version: '^10.4'
- php-version: '7.4'
typo3-version: '^11.5'
- php-version: '8.0'
typo3-version: '^11.5'
- php-version: '8.1' - php-version: '8.1'
typo3-version: '^11.5' typo3-version: '^12.4'
- php-version: '8.2' - php-version: '8.2'
typo3-version: '^11.5' typo3-version: '^12.4'
- php-version: '8.3'
typo3-version: '^12.4'
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
@ -124,20 +113,12 @@ jobs:
strategy: strategy:
matrix: matrix:
include: include:
- php-version: '7.2'
typo3-version: '^10.4'
- php-version: '7.3'
typo3-version: '^10.4'
- php-version: '7.4'
typo3-version: '^10.4'
- php-version: '7.4'
typo3-version: '^11.5'
- php-version: '8.0'
typo3-version: '^11.5'
- php-version: '8.1' - php-version: '8.1'
typo3-version: '^11.5' typo3-version: '^12.4'
- php-version: '8.2' - php-version: '8.2'
typo3-version: '^11.5' typo3-version: '^12.4'
- php-version: '8.3'
typo3-version: '^12.4'
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
@ -151,4 +132,4 @@ jobs:
run: composer require --no-interaction --prefer-dist --no-progress "typo3/cms-core:${{ matrix.typo3-version }}" "typo3/cms-extbase:${{ matrix.typo3-version }}" "typo3/cms-frontend:${{ matrix.typo3-version }}" "typo3/cms-fluid:${{ matrix.typo3-version }}" "typo3/cms-filelist:${{ matrix.typo3-version }}" "typo3/cms-backend:${{ matrix.typo3-version }}" "typo3/cms-fluid-styled-content:${{ matrix.typo3-version }}" run: composer require --no-interaction --prefer-dist --no-progress "typo3/cms-core:${{ matrix.typo3-version }}" "typo3/cms-extbase:${{ matrix.typo3-version }}" "typo3/cms-frontend:${{ matrix.typo3-version }}" "typo3/cms-fluid:${{ matrix.typo3-version }}" "typo3/cms-filelist:${{ matrix.typo3-version }}" "typo3/cms-backend:${{ matrix.typo3-version }}" "typo3/cms-fluid-styled-content:${{ matrix.typo3-version }}"
- name: PHPUnit Tests - name: PHPUnit Tests
run: ./vendor/bin/phpunit --testdox run: ./vendor/bin/phpunit --display-incomplete --display-skipped --display-deprecations --display-errors --display-notices --display-warnings

View file

@ -9,20 +9,26 @@ return (new \PhpCsFixer\Config())
->setRules([ ->setRules([
'@DoctrineAnnotation' => true, '@DoctrineAnnotation' => true,
'@PSR2' => true, '@PSR2' => true,
'array_indentation' => true,
'array_syntax' => ['syntax' => 'short'], 'array_syntax' => ['syntax' => 'short'],
'attribute_empty_parentheses' => true,
'blank_line_after_opening_tag' => true, 'blank_line_after_opening_tag' => true,
'braces' => ['allow_single_line_closure' => true], 'braces' => ['allow_single_line_closure' => true],
'cast_spaces' => ['space' => 'none'], 'cast_spaces' => ['space' => 'none'],
'compact_nullable_typehint' => true, 'compact_nullable_typehint' => true,
'concat_space' => ['spacing' => 'one'], 'concat_space' => ['spacing' => 'one'],
'declare_equal_normalize' => ['space' => 'none'], 'declare_equal_normalize' => ['space' => 'none'],
'declare_strict_types' => true,
'dir_constant' => true, 'dir_constant' => true,
'fully_qualified_strict_types' => false,
'function_to_constant' => ['functions' => ['get_called_class', 'get_class', 'get_class_this', 'php_sapi_name', 'phpversion', 'pi']], 'function_to_constant' => ['functions' => ['get_called_class', 'get_class', 'get_class_this', 'php_sapi_name', 'phpversion', 'pi']],
'function_typehint_space' => true, 'function_typehint_space' => true,
'global_namespace_import' => ['import_classes' => true, 'import_constants' => true, 'import_functions' => true],
'lowercase_cast' => true, 'lowercase_cast' => true,
'method_argument_space' => ['on_multiline' => 'ensure_fully_multiline'], 'method_argument_space' => ['on_multiline' => 'ensure_fully_multiline'],
'modernize_strpos' => true, 'modernize_strpos' => true,
'modernize_types_casting' => true, 'modernize_types_casting' => true,
'multiline_whitespace_before_semicolons' => ['strategy' => 'new_line_for_chained_calls'],
'native_function_casing' => true, 'native_function_casing' => true,
'new_with_braces' => true, 'new_with_braces' => true,
'no_alias_functions' => true, 'no_alias_functions' => true,
@ -32,12 +38,14 @@ return (new \PhpCsFixer\Config())
'no_extra_blank_lines' => true, 'no_extra_blank_lines' => true,
'no_leading_import_slash' => true, 'no_leading_import_slash' => true,
'no_leading_namespace_whitespace' => true, 'no_leading_namespace_whitespace' => true,
'no_multiline_whitespace_around_double_arrow' => true,
'no_null_property_initialization' => true, 'no_null_property_initialization' => true,
'no_short_bool_cast' => true, 'no_short_bool_cast' => true,
'no_singleline_whitespace_before_semicolons' => true, 'no_singleline_whitespace_before_semicolons' => true,
'no_superfluous_elseif' => true, 'no_superfluous_elseif' => true,
'no_trailing_comma_in_singleline_array' => true, 'no_trailing_comma_in_singleline_array' => true,
'no_unneeded_control_parentheses' => true, 'no_unneeded_control_parentheses' => true,
'no_unneeded_import_alias' => true,
'no_unused_imports' => true, 'no_unused_imports' => true,
'no_useless_else' => true, 'no_useless_else' => true,
'no_whitespace_in_blank_line' => true, 'no_whitespace_in_blank_line' => true,
@ -54,8 +62,8 @@ return (new \PhpCsFixer\Config())
'phpdoc_types' => true, 'phpdoc_types' => true,
'phpdoc_types_order' => ['null_adjustment' => 'always_last', 'sort_algorithm' => 'none'], 'phpdoc_types_order' => ['null_adjustment' => 'always_last', 'sort_algorithm' => 'none'],
'return_type_declaration' => ['space_before' => 'none'], 'return_type_declaration' => ['space_before' => 'none'],
'single_quote' => true,
'single_line_comment_style' => ['comment_types' => ['hash']], 'single_line_comment_style' => ['comment_types' => ['hash']],
'single_quote' => true,
'single_trait_insert_per_statement' => true, 'single_trait_insert_per_statement' => true,
'trailing_comma_in_multiline' => ['elements' => ['arrays']], 'trailing_comma_in_multiline' => ['elements' => ['arrays']],
'whitespace_after_comma_in_array' => true, 'whitespace_after_comma_in_array' => true,

View file

@ -1,178 +0,0 @@
<?php
declare(strict_types=1);
namespace WerkraumMedia\Events\Backports\V12\Pagination;
// Original source: https://github.com/TYPO3/typo3/blob/b60cf59fbe7875aff5ee1ba4c56155301694d6b8/typo3/sysext/core/Classes/Pagination/SlidingWindowPagination.php
// Remove once we have v12 as minimum version.
use TYPO3\CMS\Core\Pagination\PaginationInterface;
use TYPO3\CMS\Core\Pagination\PaginatorInterface;
/*
* This file is part of the TYPO3 CMS project.
*
* It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2
* of the License, or any later version.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*
* The TYPO3 project - inspiring people to share!
*/
final class SlidingWindowPagination implements PaginationInterface
{
/**
* @var int
*/
protected $displayRangeStart = 0;
/**
* @var int
*/
protected $displayRangeEnd = 0;
/**
* @var bool
*/
protected $hasLessPages = false;
/**
* @var bool
*/
protected $hasMorePages = false;
/**
* @var int
*/
protected $maximumNumberOfLinks = 0;
/**
* @var PaginatorInterface
*/
protected $paginator;
public function __construct(PaginatorInterface $paginator, int $maximumNumberOfLinks = 0)
{
$this->paginator = $paginator;
if ($maximumNumberOfLinks > 0) {
$this->maximumNumberOfLinks = $maximumNumberOfLinks;
}
$this->calculateDisplayRange();
}
public function getPreviousPageNumber(): ?int
{
$previousPage = $this->paginator->getCurrentPageNumber() - 1;
if ($previousPage > $this->paginator->getNumberOfPages()) {
return null;
}
return $previousPage >= $this->getFirstPageNumber() ? $previousPage : null;
}
public function getNextPageNumber(): ?int
{
$nextPage = $this->paginator->getCurrentPageNumber() + 1;
return $nextPage <= $this->paginator->getNumberOfPages() ? $nextPage : null;
}
public function getFirstPageNumber(): int
{
return 1;
}
public function getLastPageNumber(): int
{
return $this->paginator->getNumberOfPages();
}
public function getStartRecordNumber(): int
{
if ($this->paginator->getCurrentPageNumber() > $this->paginator->getNumberOfPages()) {
return 0;
}
return $this->paginator->getKeyOfFirstPaginatedItem() + 1;
}
public function getEndRecordNumber(): int
{
if ($this->paginator->getCurrentPageNumber() > $this->paginator->getNumberOfPages()) {
return 0;
}
return $this->paginator->getKeyOfLastPaginatedItem() + 1;
}
public function getAllPageNumbers(): array
{
return range($this->displayRangeStart, $this->displayRangeEnd);
}
public function getDisplayRangeStart(): int
{
return $this->displayRangeStart;
}
public function getDisplayRangeEnd(): int
{
return $this->displayRangeEnd;
}
public function getHasLessPages(): bool
{
return $this->hasLessPages;
}
public function getHasMorePages(): bool
{
return $this->hasMorePages;
}
public function getMaximumNumberOfLinks(): int
{
return $this->maximumNumberOfLinks;
}
public function getPaginator(): PaginatorInterface
{
return $this->paginator;
}
protected function calculateDisplayRange(): void
{
$maximumNumberOfLinks = $this->maximumNumberOfLinks;
$numberOfPages = $this->paginator->getNumberOfPages();
if ($maximumNumberOfLinks > $numberOfPages) {
$maximumNumberOfLinks = $numberOfPages;
}
$currentPage = $this->paginator->getCurrentPageNumber();
$delta = floor($maximumNumberOfLinks / 2);
$this->displayRangeStart = (int)($currentPage - $delta);
$this->displayRangeEnd = (int)($currentPage + $delta - ($maximumNumberOfLinks % 2 === 0 ? 1 : 0));
if ($this->displayRangeStart < 1) {
$this->displayRangeEnd -= $this->displayRangeStart - 1;
}
if ($this->displayRangeEnd > $numberOfPages) {
$this->displayRangeStart -= $this->displayRangeEnd - $numberOfPages;
}
$this->displayRangeStart = (int)max($this->displayRangeStart, 1);
$this->displayRangeEnd = (int)min($this->displayRangeEnd, $numberOfPages);
$this->hasLessPages = $this->displayRangeStart > 2;
$this->hasMorePages = $this->displayRangeEnd + 1 < $this->paginator->getNumberOfPages();
}
}

View file

@ -28,15 +28,7 @@ use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
class CacheManager class CacheManager
{ {
/** private array $tags = [
* @var Typo3CacheManager
*/
private $cacheManager;
/**
* @var array
*/
private $tags = [
'tx_events_domain_model_date', 'tx_events_domain_model_date',
'tx_events_domain_model_event', 'tx_events_domain_model_event',
'tx_events_domain_model_organizer', 'tx_events_domain_model_organizer',
@ -45,9 +37,8 @@ class CacheManager
]; ];
public function __construct( public function __construct(
Typo3CacheManager $cacheManager private readonly Typo3CacheManager $cacheManager
) { ) {
$this->cacheManager = $cacheManager;
} }
public function addAllCacheTagsToPage(ContentObjectRenderer $cObject): void public function addAllCacheTagsToPage(ContentObjectRenderer $cObject): void

View file

@ -30,6 +30,7 @@ use TYPO3\CMS\Core\Cache\CacheManager;
use TYPO3\CMS\Core\Cache\Frontend\FrontendInterface; use TYPO3\CMS\Core\Cache\Frontend\FrontendInterface;
use TYPO3\CMS\Core\Context\Context; use TYPO3\CMS\Core\Context\Context;
use TYPO3\CMS\Core\SingletonInterface; use TYPO3\CMS\Core\SingletonInterface;
use TYPO3\CMS\Frontend\Event\ModifyCacheLifetimeForPageEvent;
use WerkraumMedia\Events\Domain\Model\Date; use WerkraumMedia\Events\Domain\Model\Date;
use WerkraumMedia\Events\Events\Controller\DateListVariables; use WerkraumMedia\Events\Events\Controller\DateListVariables;
@ -41,40 +42,30 @@ use WerkraumMedia\Events\Events\Controller\DateListVariables;
*/ */
class PageCacheTimeout implements SingletonInterface class PageCacheTimeout implements SingletonInterface
{ {
/** private ?DateTimeImmutable $timeout = null;
* @var DateTimeImmutable|null
*/
private $timeout;
/** private FrontendInterface $runtimeCache;
* @var FrontendInterface
*/
private $runtimeCache;
/**
* @var Context
*/
private $context;
public function __construct( public function __construct(
CacheManager $cacheManager, CacheManager $cacheManager,
Context $context private readonly Context $context
) { ) {
$this->runtimeCache = $cacheManager->getCache('runtime'); $this->runtimeCache = $cacheManager->getCache('runtime');
$this->context = $context;
} }
public function calculateCacheTimout( public function modifyCacheLifetimeForPage(ModifyCacheLifetimeForPageEvent $event): void
array $parameters {
): int {
$typo3Timeout = $parameters['cacheTimeout'];
$ourTimeout = $this->getTimeout(); $ourTimeout = $this->getTimeout();
if ($ourTimeout === null) { if ($ourTimeout === null) {
return $typo3Timeout; return;
} }
return min($typo3Timeout, $ourTimeout); $event->setCacheLifetime(
min(
$event->getCacheLifetime(),
$ourTimeout
)
);
} }
public function trackDates(DateListVariables $event): void public function trackDates(DateListVariables $event): void
@ -85,14 +76,10 @@ class PageCacheTimeout implements SingletonInterface
} }
if ($event->getDemand()->shouldShowUpcoming()) { if ($event->getDemand()->shouldShowUpcoming()) {
$this->trackTimeoutByDate($event, static function (Date $date) { $this->trackTimeoutByDate($event, static fn (Date $date) => $date->getStart());
return $date->getStart();
});
} }
$this->trackTimeoutByDate($event, static function (Date $date) { $this->trackTimeoutByDate($event, static fn (Date $date) => $date->getEnd());
return $date->getEnd();
});
} }
/** /**
@ -126,7 +113,8 @@ class PageCacheTimeout implements SingletonInterface
return; return;
} }
$this->runtimeCache->remove('core-tslib_fe-get_cache_timeout'); $id = $GLOBALS['TYPO3_REQUEST']->getAttribute('routing')->getPageId();
$this->runtimeCache->remove('cacheLifeTimeForPage_' . $id);
$this->timeout = $newTimeout; $this->timeout = $newTimeout;
} }
@ -149,9 +137,4 @@ class PageCacheTimeout implements SingletonInterface
return $execution; return $execution;
} }
public static function register(): void
{
$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_fe.php']['get_cache_timeout']['events'] = self::class . '->calculateCacheTimout';
}
} }

View file

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
namespace WerkraumMedia\Events\Command; namespace WerkraumMedia\Events\Command;
use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Command\Command;
@ -11,23 +13,11 @@ use WerkraumMedia\Events\Service\DestinationDataImportService;
class ImportDestinationDataViaAllConfigruationsCommand extends Command class ImportDestinationDataViaAllConfigruationsCommand extends Command
{ {
/**
* @var DestinationDataImportService
*/
private $destinationDataImportService;
/**
* @var ImportFactory
*/
private $importFactory;
public function __construct( public function __construct(
DestinationDataImportService $destinationDataImportService, private readonly DestinationDataImportService $destinationDataImportService,
ImportFactory $importFactory private readonly ImportFactory $importFactory
) { ) {
parent::__construct(); parent::__construct();
$this->destinationDataImportService = $destinationDataImportService;
$this->importFactory = $importFactory;
} }
public function configure(): void public function configure(): void

View file

@ -1,7 +1,10 @@
<?php <?php
declare(strict_types=1);
namespace WerkraumMedia\Events\Command; namespace WerkraumMedia\Events\Command;
use Exception;
use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputInterface;
@ -12,23 +15,11 @@ use WerkraumMedia\Events\Service\DestinationDataImportService;
class ImportDestinationDataViaConfigruationCommand extends Command class ImportDestinationDataViaConfigruationCommand extends Command
{ {
/**
* @var DestinationDataImportService
*/
private $destinationDataImportService;
/**
* @var ImportFactory
*/
private $importFactory;
public function __construct( public function __construct(
DestinationDataImportService $destinationDataImportService, private readonly DestinationDataImportService $destinationDataImportService,
ImportFactory $importFactory private readonly ImportFactory $importFactory
) { ) {
parent::__construct(); parent::__construct();
$this->destinationDataImportService = $destinationDataImportService;
$this->importFactory = $importFactory;
} }
public function configure(): void public function configure(): void
@ -51,7 +42,7 @@ class ImportDestinationDataViaConfigruationCommand extends Command
if (is_numeric($configurationUid)) { if (is_numeric($configurationUid)) {
$configurationUid = (int)$configurationUid; $configurationUid = (int)$configurationUid;
} else { } else {
throw new \Exception('No numeric uid for configuration provided.', 1643267138); throw new Exception('No numeric uid for configuration provided.', 1643267138);
} }
$import = $this->importFactory->createFromUid( $import = $this->importFactory->createFromUid(

View file

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
namespace WerkraumMedia\Events\Command; namespace WerkraumMedia\Events\Command;
use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Command\Command;
@ -10,16 +12,9 @@ use WerkraumMedia\Events\Service\CleanupService;
class RemoveAllCommand extends Command class RemoveAllCommand extends Command
{ {
/**
* @var CleanupService
*/
private $cleanupService;
public function __construct( public function __construct(
CleanupService $cleanupService private readonly CleanupService $cleanupService
) { ) {
$this->cleanupService = $cleanupService;
parent::__construct(); parent::__construct();
} }

View file

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
namespace WerkraumMedia\Events\Command; namespace WerkraumMedia\Events\Command;
use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Command\Command;
@ -10,16 +12,9 @@ use WerkraumMedia\Events\Service\CleanupService;
class RemovePastCommand extends Command class RemovePastCommand extends Command
{ {
/**
* @var CleanupService
*/
private $cleanupService;
public function __construct( public function __construct(
CleanupService $cleanupService private readonly CleanupService $cleanupService
) { ) {
$this->cleanupService = $cleanupService;
parent::__construct(); parent::__construct();
} }

View file

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
namespace WerkraumMedia\Events\Controller; namespace WerkraumMedia\Events\Controller;
/* /*
@ -21,12 +23,12 @@ namespace WerkraumMedia\Events\Controller;
* 02110-1301, USA. * 02110-1301, USA.
*/ */
use TYPO3\CMS\Core\Http\ImmediateResponseException;
use TYPO3\CMS\Core\Http\PropagateResponseException; use TYPO3\CMS\Core\Http\PropagateResponseException;
use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Extbase\Mvc\Controller\ActionController; use TYPO3\CMS\Extbase\Mvc\Controller\ActionController;
use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer; use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
use TYPO3\CMS\Frontend\Controller\ErrorController; use TYPO3\CMS\Frontend\Controller\ErrorController;
use TYPO3Fluid\Fluid\View\ViewInterface;
use WerkraumMedia\Events\Caching\CacheManager; use WerkraumMedia\Events\Caching\CacheManager;
class AbstractController extends ActionController class AbstractController extends ActionController
@ -49,7 +51,7 @@ class AbstractController extends ActionController
{ {
parent::initializeAction(); parent::initializeAction();
$cObject = $this->configurationManager->getContentObject(); $cObject = $this->request->getAttribute('currentContentObject');
if ($cObject instanceof ContentObjectRenderer) { if ($cObject instanceof ContentObjectRenderer) {
$this->cacheManager->addAllCacheTagsToPage($cObject); $this->cacheManager->addAllCacheTagsToPage($cObject);
} }
@ -58,12 +60,12 @@ class AbstractController extends ActionController
/** /**
* Extend original to also add data from current cobject if available. * Extend original to also add data from current cobject if available.
*/ */
protected function resolveView() protected function resolveView(): ViewInterface
{ {
$view = parent::resolveView(); $view = parent::resolveView();
$view->assign('data', []); $view->assign('data', []);
$cObject = $this->configurationManager->getContentObject(); $cObject = $this->request->getAttribute('currentContentObject');
if ($cObject instanceof ContentObjectRenderer && is_array($cObject->data)) { if ($cObject instanceof ContentObjectRenderer && is_array($cObject->data)) {
$view->assign('data', $cObject->data); $view->assign('data', $cObject->data);
} }
@ -73,17 +75,9 @@ class AbstractController extends ActionController
protected function trigger404(string $message): void protected function trigger404(string $message): void
{ {
$errorController = GeneralUtility::makeInstance(ErrorController::class);
if (class_exists(ImmediateResponseException::class)) {
throw new ImmediateResponseException(
$errorController->pageNotFoundAction($GLOBALS['TYPO3_REQUEST'], $message),
1695881164
);
}
throw new PropagateResponseException( throw new PropagateResponseException(
$errorController->pageNotFoundAction($this->request, $message), GeneralUtility::makeInstance(ErrorController::class)
->pageNotFoundAction($this->request, $message),
1695881170 1695881170
); );
} }

View file

@ -1,9 +1,12 @@
<?php <?php
declare(strict_types=1);
namespace WerkraumMedia\Events\Controller; namespace WerkraumMedia\Events\Controller;
use Exception;
use Psr\Http\Message\ResponseInterface;
use Throwable; use Throwable;
use TYPO3\CMS\Core\EventDispatcher\EventDispatcher;
use TYPO3\CMS\Extbase\Annotation as Extbase; use TYPO3\CMS\Extbase\Annotation as Extbase;
use TYPO3\CMS\Extbase\Service\ExtensionService; use TYPO3\CMS\Extbase\Service\ExtensionService;
use WerkraumMedia\Events\Domain\Model\Date; use WerkraumMedia\Events\Domain\Model\Date;
@ -16,73 +19,24 @@ use WerkraumMedia\Events\Events\Controller\DateSearchVariables;
use WerkraumMedia\Events\Pagination\Factory; use WerkraumMedia\Events\Pagination\Factory;
use WerkraumMedia\Events\Service\DataProcessingForModels; use WerkraumMedia\Events\Service\DataProcessingForModels;
class DateController extends AbstractController final class DateController extends AbstractController
{ {
/**
* @var DateDemandFactory
*/
protected $demandFactory;
/**
* @var dateRepository
*/
protected $dateRepository;
/**
* @var regionRepository
*/
protected $regionRepository;
/**
* @var CategoryRepository
*/
protected $categoryRepository;
/**
* @var Factory
*/
protected $paginationFactory;
/**
* @var DataProcessingForModels
*/
protected $dataProcessing;
/**
* @var EventDispatcher
*/
protected $eventDispatcher;
/**
* @var ExtensionService
*/
protected $extensionService;
public function __construct( public function __construct(
DateDemandFactory $demandFactory, private readonly DateDemandFactory $demandFactory,
DateRepository $dateRepository, private readonly DateRepository $dateRepository,
RegionRepository $regionRepository, private readonly RegionRepository $regionRepository,
CategoryRepository $categoryRepository, private readonly CategoryRepository $categoryRepository,
Factory $paginationFactory, private readonly Factory $paginationFactory,
DataProcessingForModels $dataProcessing, private readonly DataProcessingForModels $dataProcessing,
EventDispatcher $eventDispatcher, private readonly ExtensionService $extensionService
ExtensionService $extensionService
) { ) {
$this->demandFactory = $demandFactory;
$this->dateRepository = $dateRepository;
$this->regionRepository = $regionRepository;
$this->categoryRepository = $categoryRepository;
$this->paginationFactory = $paginationFactory;
$this->dataProcessing = $dataProcessing;
$this->eventDispatcher = $eventDispatcher;
$this->extensionService = $extensionService;
} }
protected function initializeAction(): void protected function initializeAction(): void
{ {
parent::initializeAction(); parent::initializeAction();
$contentObject = $this->configurationManager->getContentObject(); $contentObject = $this->request->getAttribute('currentContentObject');
if ($contentObject !== null) { if ($contentObject !== null) {
$this->demandFactory->setContentObjectRenderer($contentObject); $this->demandFactory->setContentObjectRenderer($contentObject);
} }
@ -91,14 +45,10 @@ class DateController extends AbstractController
$this->handlePostRequest(); $this->handlePostRequest();
} }
/**
* @param array $search
* @param int $currentPage
*/
public function listAction( public function listAction(
array $search = [], array $search = [],
int $currentPage = 1 int $currentPage = 1
): void { ): ResponseInterface {
$demand = $this->demandFactory->fromSettings($this->settings); $demand = $this->demandFactory->fromSettings($this->settings);
if ($search !== []) { if ($search !== []) {
$demand = $this->demandFactory->createFromRequestValues($search, $this->settings); $demand = $this->demandFactory->createFromRequestValues($search, $this->settings);
@ -117,15 +67,13 @@ class DateController extends AbstractController
) )
)); ));
if (!$event instanceof DateListVariables) { if (!$event instanceof DateListVariables) {
throw new \Exception('Did not retrieve DateSearchVariables from event dispatcher, got: ' . get_class($event), 1657542318); throw new Exception('Did not retrieve DateSearchVariables from event dispatcher, got: ' . $event::class, 1657542318);
} }
$this->view->assignMultiple($event->getVariablesForView()); $this->view->assignMultiple($event->getVariablesForView());
return $this->htmlResponse();
} }
/** public function searchAction(array $search = []): ResponseInterface
* @param array $search
*/
public function searchAction(array $search = []): void
{ {
$demand = $this->demandFactory->fromSettings($this->settings); $demand = $this->demandFactory->fromSettings($this->settings);
if ($search !== []) { if ($search !== []) {
@ -136,33 +84,34 @@ class DateController extends AbstractController
$search, $search,
$demand, $demand,
$this->regionRepository->findAll(), $this->regionRepository->findAll(),
$this->categoryRepository->findAllCurrentlyAssigned($this->settings['uids']['categoriesParent'] ?? 0, 'categories'), $this->categoryRepository->findAllCurrentlyAssigned((int)($this->settings['uids']['categoriesParent'] ?? 0), 'categories'),
$this->categoryRepository->findAllCurrentlyAssigned($this->settings['uids']['featuresParent'] ?? 0, 'features') $this->categoryRepository->findAllCurrentlyAssigned((int)($this->settings['uids']['featuresParent'] ?? 0), 'features')
)); ));
if (!$event instanceof DateSearchVariables) { if (!$event instanceof DateSearchVariables) {
throw new \Exception('Did not retrieve DateSearchVariables from event dispatcher, got: ' . get_class($event), 1657542318); throw new Exception('Did not retrieve DateSearchVariables from event dispatcher, got: ' . $event::class, 1657542318);
} }
$this->view->assignMultiple($event->getVariablesForView()); $this->view->assignMultiple($event->getVariablesForView());
return $this->htmlResponse();
} }
public function teaserAction(): void public function teaserAction(): ResponseInterface
{ {
$dates = $this->dateRepository->findByUids($this->settings['eventUids']); $dates = $this->dateRepository->findByUids($this->settings['eventUids']);
$this->view->assign('dates', $dates); $this->view->assign('dates', $dates);
return $this->htmlResponse();
} }
/** #[Extbase\IgnoreValidation(['value' => 'date'])]
* @Extbase\IgnoreValidation("date") public function showAction(Date $date): ResponseInterface
*/
public function showAction(Date $date): void
{ {
try { try {
$date->getEvent(); $date->getEvent();
} catch (Throwable $e) { } catch (Throwable) {
$this->trigger404('No event found for requested date.'); $this->trigger404('No event found for requested date.');
} }
$this->view->assign('date', $date); $this->view->assign('date', $date);
return $this->htmlResponse();
} }
/** /**
@ -178,7 +127,7 @@ class DateController extends AbstractController
&& is_array($this->request->getArgument('search')) && is_array($this->request->getArgument('search'))
) { ) {
$namespace = $this->extensionService->getPluginNamespace(null, null); $namespace = $this->extensionService->getPluginNamespace(null, null);
$this->redirectToUri($this->configurationManager->getContentObject()->typoLink_URL([ $this->redirectToUri($this->request->getAttribute('currentContentObject')->typoLink_URL([
'parameter' => 't3://page?uid=current', 'parameter' => 't3://page?uid=current',
'additionalParams' => '&' . http_build_query([ 'additionalParams' => '&' . http_build_query([
$namespace => [ $namespace => [

View file

@ -1,38 +1,23 @@
<?php <?php
declare(strict_types=1);
namespace WerkraumMedia\Events\Controller; namespace WerkraumMedia\Events\Controller;
use Psr\Http\Message\ResponseInterface;
use TYPO3\CMS\Extbase\Annotation as Extbase; use TYPO3\CMS\Extbase\Annotation as Extbase;
use WerkraumMedia\Events\Domain\Model\Dto\EventDemandFactory; use WerkraumMedia\Events\Domain\Model\Dto\EventDemandFactory;
use WerkraumMedia\Events\Domain\Model\Event; use WerkraumMedia\Events\Domain\Model\Event;
use WerkraumMedia\Events\Domain\Repository\EventRepository; use WerkraumMedia\Events\Domain\Repository\EventRepository;
use WerkraumMedia\Events\Service\DataProcessingForModels; use WerkraumMedia\Events\Service\DataProcessingForModels;
class EventController extends AbstractController final class EventController extends AbstractController
{ {
/**
* @var EventRepository
*/
protected $eventRepository;
/**
* @var DataProcessingForModels
*/
protected $dataProcessing;
/**
* @var EventDemandFactory
*/
protected $demandFactory;
public function __construct( public function __construct(
EventRepository $eventRepository, private readonly EventRepository $eventRepository,
DataProcessingForModels $dataProcessing, private readonly DataProcessingForModels $dataProcessing,
EventDemandFactory $demandFactory private readonly EventDemandFactory $demandFactory
) { ) {
$this->eventRepository = $eventRepository;
$this->dataProcessing = $dataProcessing;
$this->demandFactory = $demandFactory;
} }
protected function initializeAction(): void protected function initializeAction(): void
@ -42,35 +27,37 @@ class EventController extends AbstractController
$this->dataProcessing->setConfigurationManager($this->configurationManager); $this->dataProcessing->setConfigurationManager($this->configurationManager);
} }
public function listAction(): void public function listAction(): ResponseInterface
{ {
$demand = $this->demandFactory->fromSettings($this->settings); $demand = $this->demandFactory->fromSettings($this->settings);
$events = $this->eventRepository->findByDemand($demand); $events = $this->eventRepository->findByDemand($demand);
$this->view->assign('events', $events); $this->view->assign('events', $events);
return $this->htmlResponse();
} }
/** #[Extbase\IgnoreValidation(['value' => 'event'])]
* @Extbase\IgnoreValidation("event") public function showAction(Event $event): ResponseInterface
*/
public function showAction(Event $event): void
{ {
$this->view->assign('event', $event); $this->view->assign('event', $event);
return $this->htmlResponse();
} }
/** /**
* @deprecated Use listAction instead and configure settings properly. * @deprecated Use listAction instead and configure settings properly.
* Use Settings or something else to switch between list and teaser rendering. * Use Settings or something else to switch between list and teaser rendering.
*/ */
public function teaserAction(): void public function teaserAction(): ResponseInterface
{ {
$this->view->assignMultiple([ $this->view->assignMultiple([
'events' => $this->eventRepository->findByUids($this->settings['eventUids']), 'events' => $this->eventRepository->findByUids($this->settings['eventUids']),
]); ]);
return $this->htmlResponse();
} }
public function searchAction(string $search = ''): void public function searchAction(string $search = ''): ResponseInterface
{ {
$this->view->assign('search', $search); $this->view->assign('search', $search);
$this->view->assign('events', $this->eventRepository->findSearchWord($search)); $this->view->assign('events', $this->eventRepository->findSearchWord($search));
return $this->htmlResponse();
} }
} }

View file

@ -1,7 +1,11 @@
<?php <?php
declare(strict_types=1);
namespace WerkraumMedia\Events\Domain\DestinationData; namespace WerkraumMedia\Events\Domain\DestinationData;
use Exception;
use PDO;
use TYPO3\CMS\Core\Database\ConnectionPool; use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\Resource\Folder; use TYPO3\CMS\Core\Resource\Folder;
use TYPO3\CMS\Core\Resource\ResourceFactory; use TYPO3\CMS\Core\Resource\ResourceFactory;
@ -9,43 +13,19 @@ use TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper;
use TYPO3\CMS\Extbase\Persistence\Generic\Session; use TYPO3\CMS\Extbase\Persistence\Generic\Session;
use WerkraumMedia\Events\Domain\Model\Import; use WerkraumMedia\Events\Domain\Model\Import;
class ImportFactory final class ImportFactory
{ {
/**
* @var ConnectionPool
*/
private $connectionPool;
/**
* @var Session
*/
private $extbasePersistenceSession;
/**
* @var DataMapper
*/
private $dataMapper;
/**
* @var ResourceFactory
*/
private $resourceFactory;
/** /**
* @var Folder * @var Folder
*/ */
private $folderInstance; private $folderInstance;
public function __construct( public function __construct(
ConnectionPool $connectionPool, private readonly ConnectionPool $connectionPool,
Session $extbasePersistenceSession, private readonly Session $extbasePersistenceSession,
DataMapper $dataMapper, private readonly DataMapper $dataMapper,
ResourceFactory $resourceFactory private readonly ResourceFactory $resourceFactory
) { ) {
$this->connectionPool = $connectionPool;
$this->extbasePersistenceSession = $extbasePersistenceSession;
$this->dataMapper = $dataMapper;
$this->resourceFactory = $resourceFactory;
} }
public function createFromUid(int $uid): Import public function createFromUid(int $uid): Import
@ -59,7 +39,7 @@ class ImportFactory
public function createAll(): array public function createAll(): array
{ {
return array_map( return array_map(
[$this, 'create'], $this->create(...),
$this->fetchImportRecords() $this->fetchImportRecords()
); );
} }
@ -69,11 +49,11 @@ class ImportFactory
$qb = $this->connectionPool->getQueryBuilderForTable('tx_events_domain_model_import'); $qb = $this->connectionPool->getQueryBuilderForTable('tx_events_domain_model_import');
$qb->select('*'); $qb->select('*');
$qb->from('tx_events_domain_model_import'); $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, PDO::PARAM_INT)));
$result = $qb->execute()->fetch(); $result = $qb->executeQuery()->fetch();
if (is_array($result) === false) { if (is_array($result) === false) {
throw new \Exception('Could not fetch import record with uid "' . $uid . '".', 1643267492); throw new Exception('Could not fetch import record with uid "' . $uid . '".', 1643267492);
} }
$result = array_map('strval', $result); $result = array_map('strval', $result);
@ -87,9 +67,9 @@ class ImportFactory
$qb->select('*'); $qb->select('*');
$qb->from('tx_events_domain_model_import'); $qb->from('tx_events_domain_model_import');
$result = $qb->execute()->fetchAll(); $result = $qb->executeQuery()->fetchAll();
if (count($result) === 0) { if (count($result) === 0) {
throw new \Exception('Could not fetch any import record.', 1643267492); throw new Exception('Could not fetch any import record.', 1643267492);
} }
foreach ($result as $key => $entry) { foreach ($result as $key => $entry) {

View file

@ -1,8 +1,10 @@
<?php <?php
declare(strict_types=1);
namespace WerkraumMedia\Events\Domain\Model; namespace WerkraumMedia\Events\Domain\Model;
use TYPO3\CMS\Extbase\Annotation as Extbase; use TYPO3\CMS\Extbase\Annotation\ORM\Lazy;
use TYPO3\CMS\Extbase\DomainObject\AbstractEntity; use TYPO3\CMS\Extbase\DomainObject\AbstractEntity;
use TYPO3\CMS\Extbase\Persistence\Generic\LazyLoadingProxy; use TYPO3\CMS\Extbase\Persistence\Generic\LazyLoadingProxy;
@ -13,41 +15,22 @@ use TYPO3\CMS\Extbase\Persistence\Generic\LazyLoadingProxy;
*/ */
class Category extends AbstractEntity class Category extends AbstractEntity
{ {
/** protected int $sorting = 0;
* @var string
*/
protected $title = '';
/**
* @var int
*/
protected $sorting = 0;
/**
* @var bool
*/
protected $hidden = false;
/** /**
* @var Category|null * @var Category|null
*
* @Extbase\ORM\Lazy
*/ */
#[Lazy]
protected $parent; protected $parent;
/**
* @param Category|null $parent
*/
public function __construct( public function __construct(
$parent, ?Category $parent,
int $pid, int $pid,
string $title, protected string $title,
bool $hidden protected bool $hidden
) { ) {
$this->parent = $parent; $this->parent = $parent;
$this->pid = $pid; $this->pid = $pid;
$this->title = $title;
$this->hidden = $hidden;
} }
public function getTitle(): string public function getTitle(): string
@ -60,10 +43,7 @@ class Category extends AbstractEntity
return $this->sorting; return $this->sorting;
} }
/** public function getParent(): ?Category
* @return Category|null
*/
public function getParent()
{ {
if ($this->parent instanceof LazyLoadingProxy) { if ($this->parent instanceof LazyLoadingProxy) {
$this->parent->_loadRealInstance(); $this->parent->_loadRealInstance();

View file

@ -1,7 +1,12 @@
<?php <?php
declare(strict_types=1);
namespace WerkraumMedia\Events\Domain\Model; namespace WerkraumMedia\Events\Domain\Model;
use DateTime;
use DateTimeImmutable;
use DateTimeZone;
use TYPO3\CMS\Extbase\DomainObject\AbstractEntity; use TYPO3\CMS\Extbase\DomainObject\AbstractEntity;
/** /**
@ -9,60 +14,26 @@ use TYPO3\CMS\Extbase\DomainObject\AbstractEntity;
*/ */
class Date extends AbstractEntity class Date extends AbstractEntity
{ {
/** protected DateTime $start;
* @var \DateTime
*/
protected $start;
/** protected ?DateTime $end = null;
* @var \DateTime|null
*/
protected $end;
/** protected string $canceled = 'no';
* @var string
*/
protected $canceled = 'no';
/** protected ?Date $postponedDate = null;
* @var Date|null
*/
protected $postponedDate;
/** protected ?Date $originalDate = null;
* @var Date|null
*/
protected $originalDate;
/** protected Event $event;
* @var \WerkraumMedia\Events\Domain\Model\Event
*/
protected $event;
/** protected string $canceledLink = '';
* @var string
*/
protected $canceledLink = '';
/** public function getStart(): DateTime
* @var int
*/
protected $_languageUid;
/**
* @return \DateTime $start
*/
public function getStart()
{ {
return $this->start; return $this->start;
} }
/** public function setStart(DateTime $start): void
* @param \DateTime $start
*
* @return void
*/
public function setStart(\DateTime $start)
{ {
$this->start = $start; $this->start = $start;
} }
@ -72,20 +43,12 @@ class Date extends AbstractEntity
return $this->getStart()->format('H:i') !== '00:00'; return $this->getStart()->format('H:i') !== '00:00';
} }
/** public function getEnd(): ?DateTime
* @return \DateTime|null end
*/
public function getEnd()
{ {
return $this->end; return $this->end;
} }
/** public function setEnd(?DateTime $end): void
* @param \DateTime|null $end
*
* @return void
*/
public function setEnd($end)
{ {
$this->end = $end; $this->end = $end;
} }
@ -102,55 +65,33 @@ class Date extends AbstractEntity
return $end && $this->getStart()->format('Y-m-d') === $end->format('Y-m-d'); return $end && $this->getStart()->format('Y-m-d') === $end->format('Y-m-d');
} }
/**
* @return Event
*/
public function getEvent(): Event public function getEvent(): Event
{ {
return $this->event; return $this->event;
} }
/**
* @param Event $event
*/
public function setEvent(Event $event): self public function setEvent(Event $event): self
{ {
$this->event = $event; $this->event = $event;
return $this; return $this;
} }
/** public function setLanguageUid(int $languageUid): void
* @param int $languageUid
*
* @return void
*/
public function setLanguageUid($languageUid)
{ {
$this->_languageUid = $languageUid; $this->_languageUid = $languageUid;
} }
/** public function getLanguageUid(): int
* @return int
*/
public function getLanguageUid()
{ {
return $this->_languageUid; return $this->_languageUid;
} }
/**
* @return string
*/
public function getCanceled(): string public function getCanceled(): string
{ {
return $this->canceled; return $this->canceled;
} }
/** public function setCanceled(string $canceled): void
* @param string $canceled
*
* @return void
*/
public function setCanceled(string $canceled)
{ {
$this->canceled = $canceled; $this->canceled = $canceled;
} }
@ -183,22 +124,22 @@ class Date extends AbstractEntity
bool $canceled bool $canceled
): self { ): self {
return self::createFromDestinationData( return self::createFromDestinationData(
new \DateTimeImmutable($date['start'], new \DateTimeZone($date['tz'])), new DateTimeImmutable($date['start'], new DateTimeZone($date['tz'])),
new \DateTimeImmutable($date['end'], new \DateTimeZone($date['tz'])), new DateTimeImmutable($date['end'], new DateTimeZone($date['tz'])),
$canceled $canceled
); );
} }
public static function createFromDestinationData( public static function createFromDestinationData(
\DateTimeImmutable $start, DateTimeImmutable $start,
\DateTimeImmutable $end, DateTimeImmutable $end,
bool $canceled bool $canceled
): self { ): self {
$date = new Date(); $date = new Date();
$date->setLanguageUid(-1); $date->setLanguageUid(-1);
$date->setStart(new \DateTime($start->format(\DateTime::W3C), $start->getTimezone())); $date->setStart(new DateTime($start->format(DateTime::W3C), $start->getTimezone()));
$date->setEnd(new \DateTime($end->format(\DateTime::W3C), $end->getTimezone())); $date->setEnd(new DateTime($end->format(DateTime::W3C), $end->getTimezone()));
if ($canceled) { if ($canceled) {
$date->setCanceled('canceled'); $date->setCanceled('canceled');

View file

@ -1,118 +1,79 @@
<?php <?php
declare(strict_types=1);
namespace WerkraumMedia\Events\Domain\Model\Dto; namespace WerkraumMedia\Events\Domain\Model\Dto;
use DateTimeImmutable;
use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Core\Utility\GeneralUtility;
class DateDemand class DateDemand
{ {
/** protected string $sortBy = '';
* @var string
*/
protected $sortBy = '';
/** protected string $sortOrder = '';
* @var string
*/
protected $sortOrder = '';
/** protected string $categories = '';
* @var string
*/
protected $categories = '';
/** /**
* @var int[] * @var int[]
*/ */
protected $userCategories = []; protected array $userCategories = [];
/** /**
* @var int[] * @var int[]
*/ */
protected $features = []; protected array $features = [];
/** protected bool $includeSubCategories = false;
* @var bool
*/
protected $includeSubCategories = false;
/** protected string $categoryCombination = '';
* @var string
*/
protected $categoryCombination = '';
/** /**
* @var int[] * @var int[]
*/ */
protected $regions = []; protected array $regions = [];
/** /**
* @var int[] * @var int[]
*/ */
protected $locations = []; protected array $locations = [];
/** /**
* @var int[] * @var int[]
*/ */
protected $organizers = []; protected array $organizers = [];
/** protected bool $highlight = false;
* @var bool
*/
protected $highlight = false;
/** protected string $limit = '';
* @var string
*/
protected $limit = '';
/** protected ?DateTimeImmutable $startObject = null;
* @var \DateTimeImmutable|null
*/
protected $startObject;
/** protected ?DateTimeImmutable $endObject = null;
* @var \DateTimeImmutable|null
*/
protected $endObject;
/** /**
* Use midnight as "start". * Use midnight as "start".
*
* @var bool
*/ */
protected $useMidnight = true; protected bool $useMidnight = true;
/** /**
* Only show dates that have not started yet. * Only show dates that have not started yet.
*
* @var bool
*/ */
protected $upcoming = false; protected bool $upcoming = false;
protected string $searchword = '';
/** /**
* @var string
*/
protected $searchword = '';
/**
* @var array
*
* Synonym1 => ['word1', 'word2', ], * Synonym1 => ['word1', 'word2', ],
* Synonym2 => ['word3', 'word4', ], * Synonym2 => ['word3', 'word4', ],
* *
*/ */
protected $synonyms = []; protected array$synonyms = [];
/** protected bool $considerDate = false;
* @var bool
*/
protected $considerDate = false;
/** protected string $queryCallback = '';
* @var string
*/
protected $queryCallback = '';
public function getSortBy(): string public function getSortBy(): string
{ {
@ -165,7 +126,7 @@ class DateDemand
*/ */
public function setFeatures(array $categories): void public function setFeatures(array $categories): void
{ {
$this->features = array_map('intval', $categories); $this->features = array_map('intval', array_filter($categories));
} }
/** /**
@ -303,7 +264,7 @@ class DateDemand
return $this->synonyms[$searchWord] ?? []; return $this->synonyms[$searchWord] ?? [];
} }
public function getStartObject(): ?\DateTimeImmutable public function getStartObject(): ?DateTimeImmutable
{ {
return $this->startObject; return $this->startObject;
} }
@ -327,10 +288,10 @@ class DateDemand
if ($start === null) { if ($start === null) {
return; return;
} }
$this->startObject = new \DateTimeImmutable(date('Y-m-d H:i', $start)); $this->startObject = new DateTimeImmutable(date('Y-m-d H:i', $start));
} }
public function getEndObject(): ?\DateTimeImmutable public function getEndObject(): ?DateTimeImmutable
{ {
return $this->endObject; return $this->endObject;
} }
@ -364,7 +325,7 @@ class DateDemand
return; return;
} }
$this->endObject = new \DateTimeImmutable(date('Y-m-d H:i', $end)); $this->endObject = new DateTimeImmutable(date('Y-m-d H:i', $end));
} }
public function setUseMidnight(bool $useMidnight): void public function setUseMidnight(bool $useMidnight): void
@ -387,8 +348,7 @@ class DateDemand
return $this->getStartObject() === null return $this->getStartObject() === null
&& $this->getEndObject() === null && $this->getEndObject() === null
&& $this->useMidnight === false && $this->useMidnight === false
&& $this->upcoming === false && $this->upcoming === false;
;
} }
public function shouldShowFromMidnight(): bool public function shouldShowFromMidnight(): bool

View file

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
namespace WerkraumMedia\Events\Domain\Model\Dto; namespace WerkraumMedia\Events\Domain\Model\Dto;
/* /*
@ -27,20 +29,11 @@ use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
class DateDemandFactory class DateDemandFactory
{ {
/** private ?ContentObjectRenderer $contentObjectRenderer = null;
* @var TypoScriptService
*/
private $typoScriptService;
/**
* @var contentObjectRenderer
*/
private $contentObjectRenderer;
public function __construct( public function __construct(
TypoScriptService $typoScriptService private readonly TypoScriptService $typoScriptService
) { ) {
$this->typoScriptService = $typoScriptService;
} }
public function setContentObjectRenderer( public function setContentObjectRenderer(

View file

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
namespace WerkraumMedia\Events\Domain\Model\Dto; namespace WerkraumMedia\Events\Domain\Model\Dto;
class EventDemand class EventDemand

View file

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
namespace WerkraumMedia\Events\Domain\Model\Dto; namespace WerkraumMedia\Events\Domain\Model\Dto;
/* /*

View file

@ -1,8 +1,11 @@
<?php <?php
declare(strict_types=1);
namespace WerkraumMedia\Events\Domain\Model; namespace WerkraumMedia\Events\Domain\Model;
use TYPO3\CMS\Extbase\Annotation as Extbase; use TYPO3\CMS\Extbase\Annotation\ORM\Cascade;
use TYPO3\CMS\Extbase\Annotation\ORM\Lazy;
use TYPO3\CMS\Extbase\Domain\Model\FileReference; use TYPO3\CMS\Extbase\Domain\Model\FileReference;
use TYPO3\CMS\Extbase\DomainObject\AbstractEntity; use TYPO3\CMS\Extbase\DomainObject\AbstractEntity;
use TYPO3\CMS\Extbase\Persistence\ObjectStorage; use TYPO3\CMS\Extbase\Persistence\ObjectStorage;
@ -10,154 +13,84 @@ use WerkraumMedia\Events\Service\DataProcessingForModels;
class Event extends AbstractEntity class Event extends AbstractEntity
{ {
/** protected string $title = '';
* @var string
*/
protected $title = '';
/** protected string $subtitle = '';
* @var string
*/
protected $subtitle = '';
/** protected string $globalId = '';
* @var string
*/
protected $globalId = '';
/** protected string $slug = '';
* @var string
*/
protected $slug = '';
/** protected bool $highlight = false;
* @var bool
*/
protected $highlight = false;
/** protected string $teaser = '';
* @var string
*/
protected $teaser = '';
/** protected string $details = '';
* @var string
*/
protected $details = '';
/** protected string $priceInfo = '';
* @var string
*/
protected $priceInfo = '';
/** protected string $web = '';
* @var string
*/
protected $web = '';
/** protected string $ticket = '';
* @var string
*/
protected $ticket = '';
/** protected string $facebook = '';
* @var string
*/
protected $facebook = '';
/** protected string $youtube = '';
* @var string
*/
protected $youtube = '';
/** protected string $instagram = '';
* @var string
*/
protected $instagram = '';
/** /**
* @var ObjectStorage<FileReference> * @var ObjectStorage<FileReference>
*
* @Extbase\ORM\Cascade remove
*/ */
protected $images; #[Cascade(['value' => 'remove'])]
protected ObjectStorage $images;
/** /**
* @var ObjectStorage<Date> * @var ObjectStorage<Date>
*
* @Extbase\ORM\Cascade remove
* @Extbase\ORM\Lazy
*/ */
protected $dates; #[Cascade(['value' => 'remove'])]
#[Lazy]
protected ObjectStorage $dates;
/** protected ?Location $location = null;
* @var Location|null
*/
protected $location;
/** protected ?Organizer $organizer = null;
* @var Organizer|null
*/
protected $organizer;
/** protected ?Region $region = null;
* @var Region|null
*/
protected $region;
/** protected string $pages = '';
* @var string
*/
protected $pages = '';
/** /**
* @var ObjectStorage<Category> * @var ObjectStorage<Category>
*/ */
protected $categories; protected ObjectStorage $categories;
/** /**
* @var ObjectStorage<Category> * @var ObjectStorage<Category>
*/ */
protected $features; protected ObjectStorage $features;
/** /**
* @var ObjectStorage<Partner> * @var ObjectStorage<Partner>
*/ */
protected $partner; protected ObjectStorage $partner;
/** /**
* @var ObjectStorage<Event> * @var ObjectStorage<Event>
*/ */
protected $referencesEvents; protected ObjectStorage $referencesEvents;
/** protected DataProcessingForModels $dataProcessing;
* @var int
*/
protected $_languageUid;
/** protected string $sourceName = '';
* @var DataProcessingForModels
*/
protected $dataProcessing;
/** protected string $sourceUrl = '';
* @var string
*/
protected $sourceName = '';
/**
* @var string
*/
protected $sourceUrl = '';
public function __construct() public function __construct()
{ {
$this->initStorageObjects(); $this->initStorageObjects();
} }
/**
* @param DataProcessingForModels $dataProcessing
*/
public function injectDataProcessingForModels(DataProcessingForModels $dataProcessing): void public function injectDataProcessingForModels(DataProcessingForModels $dataProcessing): void
{ {
$this->dataProcessing = $dataProcessing; $this->dataProcessing = $dataProcessing;
@ -289,7 +222,7 @@ class Event extends AbstractEntity
} }
/** /**
* @return ObjectStorage<FileReference> $images * @return ObjectStorage<FileReference>
*/ */
public function getImages(): ObjectStorage public function getImages(): ObjectStorage
{ {
@ -466,9 +399,7 @@ class Event extends AbstractEntity
{ {
$categories = $categories->toArray(); $categories = $categories->toArray();
usort($categories, function (Category $catA, Category $catB) { usort($categories, fn (Category $catA, Category $catB) => $catA->getSorting() <=> $catB->getSorting());
return $catA->getSorting() <=> $catB->getSorting();
});
return $categories; return $categories;
} }

View file

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
namespace WerkraumMedia\Events\Domain\Model; namespace WerkraumMedia\Events\Domain\Model;
use TYPO3\CMS\Core\Resource\Folder; use TYPO3\CMS\Core\Resource\Folder;
@ -11,83 +13,32 @@ use TYPO3\CMS\Extbase\DomainObject\AbstractDomainObject;
*/ */
class Import extends AbstractDomainObject class Import extends AbstractDomainObject
{ {
/** protected ?int $categoriesPid;
* @var int
*/
protected $storagePid;
/** protected ?int $featuresPid;
* @var Folder
*/
protected $filesFolder;
/**
* @var int|null
*/
protected $categoriesPid;
/**
* @var Category|null
*/
protected $categoryParent;
/**
* @var int|null
*/
protected $featuresPid;
/**
* @var Category|null
*/
protected $featuresParent;
/**
* @var Region|null
*/
protected $region;
/**
* @var string
*/
protected $restExperience;
/**
* @var string
*/
protected $restSearchQuery;
public function __construct( public function __construct(
Folder $filesFolder, protected Folder $filesFolder,
int $storagePid, protected int $storagePid,
string $restExperience, protected string $restExperience,
string $restSearchQuery = '', protected string $restSearchQuery = '',
int $categoriesPid = 0, int $categoriesPid = 0,
?Category $categoryParent = null, protected ?Category $categoryParent = null,
int $featuresPid = 0, int $featuresPid = 0,
?Category $featuresParent = null, protected ?Category $featuresParent = null,
?Region $region = null protected ?Region $region = null
) { ) {
$this->filesFolder = $filesFolder;
$this->storagePid = $storagePid;
// Do not allow categories on pid 0 // Do not allow categories on pid 0
if ($categoriesPid === 0) { if ($categoriesPid === 0) {
$categoriesPid = null; $categoriesPid = null;
} }
$this->categoriesPid = $categoriesPid; $this->categoriesPid = $categoriesPid;
$this->categoryParent = $categoryParent;
// Do not allow features on pid 0 // Do not allow features on pid 0
if ($featuresPid === 0) { if ($featuresPid === 0) {
$featuresPid = null; $featuresPid = null;
} }
$this->featuresPid = $featuresPid; $this->featuresPid = $featuresPid;
$this->featuresParent = $featuresParent;
$this->restExperience = $restExperience;
$this->restSearchQuery = $restSearchQuery;
$this->region = $region;
} }
public function getStoragePid(): int public function getStoragePid(): int

View file

@ -1,80 +1,27 @@
<?php <?php
declare(strict_types=1);
namespace WerkraumMedia\Events\Domain\Model; namespace WerkraumMedia\Events\Domain\Model;
use TYPO3\CMS\Extbase\DomainObject\AbstractEntity; use TYPO3\CMS\Extbase\DomainObject\AbstractEntity;
class Location extends AbstractEntity class Location extends AbstractEntity
{ {
/** protected string $globalId = '';
* @var string
*/
protected $name = '';
/**
* @var string
*/
protected $street = '';
/**
* @var string
*/
protected $zip = '';
/**
* @var string
*/
protected $city = '';
/**
* @var string
*/
protected $district = '';
/**
* @var string
*/
protected $country = '';
/**
* @var string
*/
protected $phone = '';
/**
* @var string
*/
protected $latitude = '';
/**
* @var string
*/
protected $longitude = '';
/**
* @var string
*/
protected $globalId = '';
public function __construct( public function __construct(
string $name, protected string $name,
string $street, protected string $street,
string $zip, protected string $zip,
string $city, protected string $city,
string $district, protected string $district,
string $country, protected string $country,
string $phone, protected string $phone,
string $latitude, protected string $latitude,
string $longitude, protected string $longitude,
int $languageUid int $languageUid
) { ) {
$this->name = $name;
$this->street = $street;
$this->zip = $zip;
$this->city = $city;
$this->district = $district;
$this->country = $country;
$this->phone = $phone;
$this->latitude = $this->normalizeGeocoordinate($latitude); $this->latitude = $this->normalizeGeocoordinate($latitude);
$this->longitude = $this->normalizeGeocoordinate($longitude); $this->longitude = $this->normalizeGeocoordinate($longitude);
$this->_languageUid = $languageUid; $this->_languageUid = $languageUid;
@ -153,8 +100,7 @@ class Location extends AbstractEntity
|| $this->city !== '' || $this->city !== ''
|| $this->district !== '' || $this->district !== ''
|| $this->country !== '' || $this->country !== ''
|| $this->phone !== '' || $this->phone !== '';
;
} }
private function generateGlobalId(): string private function generateGlobalId(): string

View file

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
namespace WerkraumMedia\Events\Domain\Model; namespace WerkraumMedia\Events\Domain\Model;
/* /*
@ -17,50 +19,21 @@ use TYPO3\CMS\Extbase\DomainObject\AbstractEntity;
class Organizer extends AbstractEntity class Organizer extends AbstractEntity
{ {
/** protected string $name = '';
* @var string
*/
protected $name = '';
/** protected string $street = '';
* @var string
*/
protected $street = '';
/** protected string $district = '';
* @var string
*/
protected $district = '';
/** protected string $city = '';
* @var string
*/
protected $city = '';
/** protected string $zip = '';
* @var string
*/
protected $zip = '';
/** protected string $phone = '';
* @var string
*/
protected $phone = '';
/** protected string $web = '';
* @var string
*/
protected $web = '';
/** protected string $email = '';
* @var string
*/
protected $email = '';
/**
* @var int
*/
protected $_languageUid;
public function getName(): string public function getName(): string
{ {

View file

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
namespace WerkraumMedia\Events\Domain\Model; namespace WerkraumMedia\Events\Domain\Model;
/* /*
@ -27,20 +29,14 @@ use TYPO3\CMS\Extbase\Persistence\ObjectStorage;
class Partner extends AbstractEntity class Partner extends AbstractEntity
{ {
/** protected string $title = '';
* @var string
*/
protected $title = '';
/** protected string $link = '';
* @var string
*/
protected $link = '';
/** /**
* @var ObjectStorage<FileReference> * @var ObjectStorage<FileReference>
*/ */
protected $images; protected ObjectStorage $images;
public function getTitle(): string public function getTitle(): string
{ {

View file

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
namespace WerkraumMedia\Events\Domain\Model; namespace WerkraumMedia\Events\Domain\Model;
/* /*
@ -17,15 +19,7 @@ use TYPO3\CMS\Extbase\DomainObject\AbstractEntity;
class Region extends AbstractEntity class Region extends AbstractEntity
{ {
/** protected string $title = '';
* @var string
*/
protected $title = '';
/**
* @var int
*/
protected $_languageUid;
public function getTitle(): string public function getTitle(): string
{ {

View file

@ -28,26 +28,13 @@ use TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper;
use TYPO3\CMS\Extbase\Persistence\Repository; use TYPO3\CMS\Extbase\Persistence\Repository;
use WerkraumMedia\Events\Domain\Model\Category; use WerkraumMedia\Events\Domain\Model\Category;
class CategoryRepository extends Repository final class CategoryRepository extends Repository
{ {
/** public function __construct(
* @var ConnectionPool private readonly ConnectionPool $connectionPool,
*/ private readonly DataMapper $dataMapper,
protected $connectionPool; ) {
parent::__construct();
/**
* @var DataMapper
*/
protected $dataMapper;
public function injectConnectionPool(ConnectionPool $connectionPool): void
{
$this->connectionPool = $connectionPool;
}
public function injectDataMapper(DataMapper $dataMapper): void
{
$this->dataMapper = $dataMapper;
} }
/** /**
@ -88,7 +75,7 @@ class CategoryRepository extends Repository
return $this->dataMapper->map( return $this->dataMapper->map(
Category::class, Category::class,
$qb->execute()->fetchAll() $qb->executeQuery()->fetchAll()
); );
} }
@ -105,10 +92,10 @@ class CategoryRepository extends Repository
$query->getQuerySettings()->setIgnoreEnableFields(true); $query->getQuerySettings()->setIgnoreEnableFields(true);
$query->getQuerySettings()->setEnableFieldsToBeIgnored(['disabled']); $query->getQuerySettings()->setEnableFieldsToBeIgnored(['disabled']);
$query->matching($query->logicalAnd([ $query->matching($query->logicalAnd(
$query->equals('parent', $parentCategory), $query->equals('parent', $parentCategory),
$query->equals('title', $title), $query->equals('title', $title),
])); ));
$query->setLimit(1); $query->setLimit(1);

View file

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
namespace WerkraumMedia\Events\Domain\Repository; namespace WerkraumMedia\Events\Domain\Repository;
use DateTimeImmutable; use DateTimeImmutable;
@ -15,16 +17,12 @@ use UnexpectedValueException;
use WerkraumMedia\Events\Domain\Model\Dto\DateDemand; use WerkraumMedia\Events\Domain\Model\Dto\DateDemand;
use WerkraumMedia\Events\Service\CategoryService; use WerkraumMedia\Events\Service\CategoryService;
class DateRepository extends Repository final class DateRepository extends Repository
{ {
/** public function __construct(
* @var Context private readonly Context $context
*/ ) {
protected $context; parent::__construct();
public function injectContext(Context $context): void
{
$this->context = $context;
} }
public function findByUids(string $uids): QueryResult public function findByUids(string $uids): QueryResult
@ -95,27 +93,27 @@ class DateRepository extends Repository
$now = $now->modify('midnight'); $now = $now->modify('midnight');
} }
$constraints['nowAndFuture'] = $query->logicalOr([ $constraints['nowAndFuture'] = $query->logicalOr(
$query->greaterThanOrEqual('start', $now), $query->greaterThanOrEqual('start', $now),
$query->greaterThanOrEqual('end', $now), $query->greaterThanOrEqual('end', $now),
]); );
} elseif ($demand->shouldShowUpcoming()) { } elseif ($demand->shouldShowUpcoming()) {
$now = $this->getNow(); $now = $this->getNow();
$constraints['future'] = $query->logicalAnd([ $constraints['future'] = $query->logicalAnd(
$query->greaterThan('start', $now), $query->greaterThan('start', $now),
$query->logicalOr([ $query->logicalOr(
$query->equals('end', 0), $query->equals('end', 0),
$query->greaterThan('end', $now), $query->greaterThan('end', $now),
]), ),
]); );
} }
if ($demand->getLimit() !== '') { if ($demand->getLimit() !== '') {
$query->setLimit((int)$demand->getLimit()); $query->setLimit((int)$demand->getLimit());
} }
$query->matching($query->logicalAnd($constraints)); $query->matching($query->logicalAnd(... $constraints));
if ($demand->getSortBy() && $demand->getSortOrder()) { if ($demand->getSortBy() && $demand->getSortOrder()) {
$query->setOrderings([$demand->getSortBy() => $demand->getSortOrder()]); $query->setOrderings([$demand->getSortBy() => $demand->getSortOrder()]);
@ -146,8 +144,9 @@ class DateRepository extends Repository
$wordsToSearch[] = $demand->getSearchword(); $wordsToSearch[] = $demand->getSearchword();
$constraints = []; $constraints = [];
$queryBuilder = $this->objectManager->get(ConnectionPool::class) $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
->getQueryBuilderForTable('tx_events_domain_model_date'); ->getQueryBuilderForTable('tx_events_domain_model_date')
;
foreach ($wordsToSearch as $word) { foreach ($wordsToSearch as $word) {
foreach ($fieldsToSearch as $field) { foreach ($fieldsToSearch as $field) {
@ -155,7 +154,7 @@ class DateRepository extends Repository
} }
} }
return $query->logicalOr($constraints); return $query->logicalOr(... $constraints);
} }
protected function createCategoryConstraint( protected function createCategoryConstraint(
@ -170,7 +169,8 @@ class DateRepository extends Repository
if ($demand->getIncludeSubCategories()) { if ($demand->getIncludeSubCategories()) {
$categories = GeneralUtility::makeInstance(CategoryService::class) $categories = GeneralUtility::makeInstance(CategoryService::class)
->getChildrenCategories($categories); ->getChildrenCategories($categories)
;
} }
$categories = GeneralUtility::intExplode(',', $categories, true); $categories = GeneralUtility::intExplode(',', $categories, true);
@ -183,10 +183,10 @@ class DateRepository extends Repository
} }
if ($demand->getCategoryCombination() === 'or') { if ($demand->getCategoryCombination() === 'or') {
return $query->logicalOr($constraints); return $query->logicalOr(... $constraints);
} }
return $query->logicalAnd($constraints); return $query->logicalAnd(... $constraints);
} }
private function createTimingConstraint( private function createTimingConstraint(
@ -196,42 +196,42 @@ class DateRepository extends Repository
// Dates might have end of 0 if only start exists. // Dates might have end of 0 if only start exists.
if ($demand->getStartObject() !== null && $demand->getEndObject() === null) { if ($demand->getStartObject() !== null && $demand->getEndObject() === null) {
return $query->logicalOr([ return $query->logicalOr(
$query->greaterThanOrEqual('start', $demand->getStartObject()), $query->greaterThanOrEqual('start', $demand->getStartObject()),
$query->greaterThanOrEqual('end', $demand->getStartObject()), $query->greaterThanOrEqual('end', $demand->getStartObject()),
]); );
} }
if ($demand->getStartObject() === null && $demand->getEndObject() !== null) { if ($demand->getStartObject() === null && $demand->getEndObject() !== null) {
return $query->logicalOr([ return $query->logicalOr(
$query->logicalAnd([ $query->logicalAnd(
$query->lessThanOrEqual('end', $demand->getEndObject()), $query->lessThanOrEqual('end', $demand->getEndObject()),
$query->greaterThan('end', 0), $query->greaterThan('end', 0),
]), ),
$query->lessThanOrEqual('start', $demand->getEndObject()), $query->lessThanOrEqual('start', $demand->getEndObject()),
]); );
} }
if ($demand->getStartObject() !== null && $demand->getEndObject() !== null) { if ($demand->getStartObject() !== null && $demand->getEndObject() !== null) {
return $query->logicalOr([ return $query->logicalOr(
$query->logicalAnd([ $query->logicalAnd(
$query->logicalOr([ $query->logicalOr(
$query->greaterThanOrEqual('start', $demand->getStartObject()), $query->greaterThanOrEqual('start', $demand->getStartObject()),
$query->greaterThanOrEqual('end', $demand->getStartObject()), $query->greaterThanOrEqual('end', $demand->getStartObject()),
]), ),
$query->logicalOr([ $query->logicalOr(
$query->lessThanOrEqual('start', $demand->getEndObject()), $query->lessThanOrEqual('start', $demand->getEndObject()),
$query->logicalAnd([ $query->logicalAnd(
$query->lessThanOrEqual('end', $demand->getEndObject()), $query->lessThanOrEqual('end', $demand->getEndObject()),
$query->greaterThan('end', 0), $query->greaterThan('end', 0),
]), ),
]), ),
]), ),
$query->logicalAnd([ $query->logicalAnd(
$query->lessThanOrEqual('start', $demand->getStartObject()), $query->lessThanOrEqual('start', $demand->getStartObject()),
$query->greaterThanOrEqual('end', $demand->getEndObject()), $query->greaterThanOrEqual('end', $demand->getEndObject()),
]), ),
]); );
} }
return null; return null;
@ -247,13 +247,14 @@ class DateRepository extends Repository
$constraints[] = $query->contains('event.features', $feature); $constraints[] = $query->contains('event.features', $feature);
} }
return $query->logicalAnd($constraints); return $query->logicalAnd(... $constraints);
} }
public function findSearchWord(string $search): array public function findSearchWord(string $search): array
{ {
$connection = GeneralUtility::makeInstance(ConnectionPool::class) $connection = GeneralUtility::makeInstance(ConnectionPool::class)
->getConnectionForTable('tx_events_domain_model_date'); ->getConnectionForTable('tx_events_domain_model_date')
;
$queryBuilder = $connection->createQueryBuilder(); $queryBuilder = $connection->createQueryBuilder();
@ -270,9 +271,10 @@ class DateRepository extends Repository
) )
)->where( )->where(
$queryBuilder->expr()->like('event.title', $queryBuilder->createNamedParameter('%' . $search . '%')) $queryBuilder->expr()->like('event.title', $queryBuilder->createNamedParameter('%' . $search . '%'))
)->orderBy('tx_events_domain_model_date.start'); )->orderBy('tx_events_domain_model_date.start')
;
return $statement->execute()->fetchAll(); return $statement->executeQuery()->fetchAll();
} }
private function createEventConstraint( private function createEventConstraint(

View file

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
namespace WerkraumMedia\Events\Domain\Repository; namespace WerkraumMedia\Events\Domain\Repository;
/* /*
@ -24,7 +26,7 @@ use WerkraumMedia\Events\Domain\Model\Dto\EventDemand;
use WerkraumMedia\Events\Domain\Model\Event; use WerkraumMedia\Events\Domain\Model\Event;
use WerkraumMedia\Events\Service\CategoryService; use WerkraumMedia\Events\Service\CategoryService;
class EventRepository extends Repository final class EventRepository extends Repository
{ {
public function findByUids(string $uids): QueryResult public function findByUids(string $uids): QueryResult
{ {
@ -55,7 +57,7 @@ class EventRepository extends Repository
$constraints = $this->getConstraints($query, $demand); $constraints = $this->getConstraints($query, $demand);
if (!empty($constraints)) { if (!empty($constraints)) {
$query->matching($query->logicalAnd($constraints)); $query->matching($query->logicalAnd(... $constraints));
} }
if ($demand->getLimit() !== '') { if ($demand->getLimit() !== '') {
@ -148,9 +150,9 @@ class EventRepository extends Repository
} }
if ($demand->getCategoryCombination() === 'or') { if ($demand->getCategoryCombination() === 'or') {
return $query->logicalOr($constraints); return $query->logicalOr(... $constraints);
} }
return $query->logicalAnd($constraints); return $query->logicalAnd(... $constraints);
} }
public function findSearchWord(string $search): QueryResult public function findSearchWord(string $search): QueryResult

View file

@ -1,11 +1,13 @@
<?php <?php
declare(strict_types=1);
namespace WerkraumMedia\Events\Domain\Repository; namespace WerkraumMedia\Events\Domain\Repository;
use TYPO3\CMS\Extbase\Persistence\Repository; use TYPO3\CMS\Extbase\Persistence\Repository;
use WerkraumMedia\Events\Domain\Model\Location; use WerkraumMedia\Events\Domain\Model\Location;
class LocationRepository extends Repository final class LocationRepository extends Repository
{ {
public function findOneByGlobalId(string $globalId): ?Location public function findOneByGlobalId(string $globalId): ?Location
{ {

View file

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
namespace WerkraumMedia\Events\Domain\Repository; namespace WerkraumMedia\Events\Domain\Repository;
/* /*
@ -17,6 +19,6 @@ namespace WerkraumMedia\Events\Domain\Repository;
use TYPO3\CMS\Extbase\Persistence\Repository; use TYPO3\CMS\Extbase\Persistence\Repository;
class OrganizerRepository extends Repository final class OrganizerRepository extends Repository
{ {
} }

View file

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
namespace WerkraumMedia\Events\Domain\Repository; namespace WerkraumMedia\Events\Domain\Repository;
/* /*
@ -17,6 +19,6 @@ namespace WerkraumMedia\Events\Domain\Repository;
use TYPO3\CMS\Extbase\Persistence\Repository; use TYPO3\CMS\Extbase\Persistence\Repository;
class RegionRepository extends Repository final class RegionRepository extends Repository
{ {
} }

View file

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
namespace WerkraumMedia\Events\Events\Controller; namespace WerkraumMedia\Events\Events\Controller;
use TYPO3\CMS\Core\Pagination\PaginationInterface; use TYPO3\CMS\Core\Pagination\PaginationInterface;
@ -9,41 +11,17 @@ use WerkraumMedia\Events\Domain\Model\Dto\DateDemand;
final class DateListVariables final class DateListVariables
{ {
/** private array $variables = [];
* @var array
*/
private $search;
/**
* @var DateDemand
*/
private $demand;
/**
* @var QueryResult<Date>
*/
private $dates;
/**
* @var PaginationInterface
*/
private $pagination;
/**
* @var array
*/
private $variables = [];
public function __construct( public function __construct(
array $search, private readonly array $search,
DateDemand $demand, private readonly DateDemand $demand,
QueryResult $dates, /**
PaginationInterface $pagination * @var QueryResult<Date>
*/
private readonly QueryResult $dates,
private readonly PaginationInterface $pagination
) { ) {
$this->search = $search;
$this->demand = $demand;
$this->dates = $dates;
$this->pagination = $pagination;
} }
public function getSearch(): array public function getSearch(): array
@ -64,21 +42,19 @@ final class DateListVariables
return $this->dates; return $this->dates;
} }
/** public function addVariable(string $key, mixed $value): void
* @param mixed $value
*/
public function addVariable(string $key, $value): void
{ {
$this->variables[$key] = $value; $this->variables[$key] = $value;
} }
public function getVariablesForView(): array public function getVariablesForView(): array
{ {
return array_merge([ return [
'search' => $this->search, 'search' => $this->search,
'demand' => $this->demand, 'demand' => $this->demand,
'dates' => $this->dates, 'dates' => $this->dates,
'pagination' => $this->pagination, 'pagination' => $this->pagination,
], $this->variables); ...$this->variables,
];
} }
} }

View file

@ -1,59 +1,30 @@
<?php <?php
declare(strict_types=1);
namespace WerkraumMedia\Events\Events\Controller; namespace WerkraumMedia\Events\Events\Controller;
use TYPO3\CMS\Extbase\Domain\Model\Category;
use TYPO3\CMS\Extbase\Persistence\QueryResultInterface; use TYPO3\CMS\Extbase\Persistence\QueryResultInterface;
use WerkraumMedia\Events\Domain\Model\Category;
use WerkraumMedia\Events\Domain\Model\Dto\DateDemand; use WerkraumMedia\Events\Domain\Model\Dto\DateDemand;
use WerkraumMedia\Events\Domain\Model\Region; use WerkraumMedia\Events\Domain\Model\Region;
class DateSearchVariables final class DateSearchVariables
{ {
/** private array $variables = [];
* @var array
*/
private $search;
/**
* @var DateDemand
*/
private $demand;
/**
* @var QueryResultInterface<Region>
*/
private $regions;
/**
* @var array<Category>
*/
private $categories;
/**
* @var array<Category>
*/
private $features;
/**
* @var array
*/
private $variables = [];
/** /**
* @param QueryResultInterface<Region> $regions * @param QueryResultInterface<Region> $regions
* @param array<Category> $categories
* @param array<Category> $features
*/ */
public function __construct( public function __construct(
array $search, private readonly array $search,
DateDemand $demand, private readonly DateDemand $demand,
QueryResultInterface $regions, private readonly QueryResultInterface $regions,
array $categories, private readonly array $categories,
array $features private readonly array $features
) { ) {
$this->search = $search;
$this->demand = $demand;
$this->regions = $regions;
$this->categories = $categories;
$this->features = $features;
} }
public function getSearch(): array public function getSearch(): array
@ -84,22 +55,20 @@ class DateSearchVariables
return $this->features; return $this->features;
} }
/** public function addVariable(string $key, mixed $value): void
* @param mixed $value
*/
public function addVariable(string $key, $value): void
{ {
$this->variables[$key] = $value; $this->variables[$key] = $value;
} }
public function getVariablesForView(): array public function getVariablesForView(): array
{ {
return array_merge([ return [
'search' => $this->search, 'search' => $this->search,
'demand' => $this->demand, 'demand' => $this->demand,
'regions' => $this->regions, 'regions' => $this->regions,
'categories' => $this->categories, 'categories' => $this->categories,
'features' => $this->features, 'features' => $this->features,
], $this->variables); ...$this->variables,
];
} }
} }

View file

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
namespace WerkraumMedia\Events\Extbase; namespace WerkraumMedia\Events\Extbase;
/* /*
@ -26,37 +28,22 @@ use TYPO3\CMS\Extbase\Event\Persistence\AfterObjectThawedEvent;
use TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper; use TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper;
use WerkraumMedia\Events\Domain\Model\Date; use WerkraumMedia\Events\Domain\Model\Date;
class AddSpecialProperties final class AddSpecialProperties
{ {
/**
* @var ConnectionPool
*/
private $connectionPool;
/**
* @var DataMapper
*/
private $dataMapper;
/** /**
* Internal info to speed things up if we know there are none. * Internal info to speed things up if we know there are none.
*
* @var bool
*/ */
private $doPostponedDatesExist = true; private bool $doPostponedDatesExist = true;
public function __construct( public function __construct(
ConnectionPool $connectionPool, private readonly ConnectionPool $connectionPool,
DataMapper $dataMapper private readonly DataMapper $dataMapper
) { ) {
$this->connectionPool = $connectionPool;
$this->dataMapper = $dataMapper;
$qb = $this->connectionPool->getQueryBuilderForTable('tx_events_domain_model_date'); $qb = $this->connectionPool->getQueryBuilderForTable('tx_events_domain_model_date');
$qb->count('uid'); $qb->count('uid');
$qb->from('tx_events_domain_model_date'); $qb->from('tx_events_domain_model_date');
$qb->where($qb->expr()->gt('postponed_date', $qb->createNamedParameter(0))); $qb->where($qb->expr()->gt('postponed_date', $qb->createNamedParameter(0)));
$this->doPostponedDatesExist = $qb->execute()->fetchColumn() > 0; $this->doPostponedDatesExist = $qb->executeQuery()->fetchOne() > 0;
} }
public function __invoke(AfterObjectThawedEvent $event): void public function __invoke(AfterObjectThawedEvent $event): void
@ -85,7 +72,7 @@ class AddSpecialProperties
$qb->where($qb->expr()->eq('postponed_date', $uidOfReferencedDate)); $qb->where($qb->expr()->eq('postponed_date', $uidOfReferencedDate));
$qb->setMaxResults(1); $qb->setMaxResults(1);
$result = $qb->execute()->fetch(); $result = $qb->executeQuery()->fetch();
if ($result === false) { if ($result === false) {
return null; return null;

View file

@ -5,11 +5,11 @@ declare(strict_types=1);
namespace WerkraumMedia\Events\Pagination; namespace WerkraumMedia\Events\Pagination;
use TYPO3\CMS\Core\Pagination\PaginationInterface; use TYPO3\CMS\Core\Pagination\PaginationInterface;
use TYPO3\CMS\Core\Pagination\SlidingWindowPagination;
use TYPO3\CMS\Extbase\Pagination\QueryResultPaginator; use TYPO3\CMS\Extbase\Pagination\QueryResultPaginator;
use TYPO3\CMS\Extbase\Persistence\QueryResultInterface; use TYPO3\CMS\Extbase\Persistence\QueryResultInterface;
use WerkraumMedia\Events\Backports\V12\Pagination\SlidingWindowPagination;
class Factory final class Factory
{ {
public function create( public function create(
int $currentPage, int $currentPage,

View file

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
namespace WerkraumMedia\Events\Service; namespace WerkraumMedia\Events\Service;
use TYPO3\CMS\Core\Cache\CacheManager; use TYPO3\CMS\Core\Cache\CacheManager;
@ -9,13 +11,11 @@ use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\TimeTracker\TimeTracker; use TYPO3\CMS\Core\TimeTracker\TimeTracker;
use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Core\Utility\GeneralUtility;
class CategoryService final class CategoryService
{ {
/** @var TimeTracker */ private TimeTracker $timeTracker;
protected $timeTracker;
/** @var FrontendInterface */ private FrontendInterface $cache;
protected $cache;
public function __construct() public function __construct()
{ {
@ -28,7 +28,6 @@ class CategoryService
* and using the caching framework to save some queries * and using the caching framework to save some queries
* *
* @param string $idList list of category ids to start * @param string $idList list of category ids to start
* @param int $counter
* *
* @return string comma separated list of category ids * @return string comma separated list of category ids
*/ */
@ -66,7 +65,8 @@ class CategoryService
} }
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class) $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
->getQueryBuilderForTable('sys_category'); ->getQueryBuilderForTable('sys_category')
;
$res = $queryBuilder $res = $queryBuilder
->select('uid') ->select('uid')
->from('sys_category') ->from('sys_category')
@ -74,7 +74,8 @@ class CategoryService
'parent', 'parent',
$queryBuilder->createNamedParameter(explode(',', $idList), Connection::PARAM_INT_ARRAY) $queryBuilder->createNamedParameter(explode(',', $idList), Connection::PARAM_INT_ARRAY)
)) ))
->execute(); ->executeQuery()
;
while ($row = $res->fetch()) { while ($row = $res->fetch()) {
if (is_array($row) === false) { if (is_array($row) === false) {
@ -96,16 +97,13 @@ class CategoryService
/** /**
* Fetch ids again from DB to avoid false positives * Fetch ids again from DB to avoid false positives
*
* @param string $idList
*
* @return string
*/ */
protected function getUidListFromRecords(string $idList): string protected function getUidListFromRecords(string $idList): string
{ {
$list = []; $list = [];
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class) $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
->getQueryBuilderForTable('sys_category'); ->getQueryBuilderForTable('sys_category')
;
$rows = $queryBuilder $rows = $queryBuilder
->select('uid') ->select('uid')
->from('sys_category') ->from('sys_category')
@ -113,8 +111,9 @@ class CategoryService
'uid', 'uid',
$queryBuilder->createNamedParameter(explode(',', $idList), Connection::PARAM_INT_ARRAY) $queryBuilder->createNamedParameter(explode(',', $idList), Connection::PARAM_INT_ARRAY)
)) ))
->execute() ->executeQuery()
->fetchAll(); ->fetchAll()
;
foreach ($rows as $row) { foreach ($rows as $row) {
if (is_array($row) === false) { if (is_array($row) === false) {
continue; continue;

View file

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
namespace WerkraumMedia\Events\Service\Cleanup; namespace WerkraumMedia\Events\Service\Cleanup;
/* /*
@ -21,24 +23,20 @@ namespace WerkraumMedia\Events\Service\Cleanup;
* 02110-1301, USA. * 02110-1301, USA.
*/ */
use DateTimeImmutable;
use PDO;
use TYPO3\CMS\Core\Database\Connection; use TYPO3\CMS\Core\Database\Connection;
use TYPO3\CMS\Core\Database\ConnectionPool; use TYPO3\CMS\Core\Database\ConnectionPool;
class Database final class Database
{ {
/**
* @var ConnectionPool
*/
private $connectionPool;
private const DATE_TABLE = 'tx_events_domain_model_date'; private const DATE_TABLE = 'tx_events_domain_model_date';
private const EVENT_TABLE = 'tx_events_domain_model_event'; private const EVENT_TABLE = 'tx_events_domain_model_event';
private const ORGANIZER_TABLE = 'tx_events_domain_model_organizer'; private const ORGANIZER_TABLE = 'tx_events_domain_model_organizer';
public function __construct( public function __construct(
ConnectionPool $connectionPool private readonly ConnectionPool $connectionPool
) { ) {
$this->connectionPool = $connectionPool;
} }
public function truncateTables(): void public function truncateTables(): void
@ -52,48 +50,46 @@ class Database
foreach ($tableNames as $tableName) { foreach ($tableNames as $tableName) {
$this->connectionPool $this->connectionPool
->getConnectionForTable($tableName) ->getConnectionForTable($tableName)
->truncate($tableName); ->truncate($tableName)
;
} }
$queryBuilder = $this->connectionPool->getQueryBuilderForTable('sys_category_record_mm'); $queryBuilder = $this->connectionPool->getQueryBuilderForTable('sys_category_record_mm');
$queryBuilder->delete('sys_category_record_mm') $queryBuilder->delete('sys_category_record_mm')->where($queryBuilder->expr()->like(
->where($queryBuilder->expr()->like( 'tablenames',
'tablenames', $queryBuilder->createNamedParameter('tx_events_domain_model_%')
$queryBuilder->createNamedParameter('tx_events_domain_model_%') ))->executeStatement();
))
->execute();
} }
public function deletePastDates(): void public function deletePastDates(): void
{ {
$queryBuilder = $this->connectionPool $queryBuilder = $this->connectionPool
->getConnectionForTable(self::DATE_TABLE) ->getConnectionForTable(self::DATE_TABLE)
->createQueryBuilder(); ->createQueryBuilder()
;
$queryBuilder->getRestrictions()->removeAll(); $queryBuilder->getRestrictions()->removeAll();
$midnightToday = new \DateTimeImmutable('midnight today'); $midnightToday = new DateTimeImmutable('midnight today');
$queryBuilder->delete(self::DATE_TABLE) $queryBuilder->delete(self::DATE_TABLE)->where($queryBuilder->expr()->lte(
->where($queryBuilder->expr()->lte( 'end',
'end', $queryBuilder->createNamedParameter($midnightToday->format('U'))
$queryBuilder->createNamedParameter($midnightToday->format('U')) ))->executeStatement();
))
->execute();
} }
public function deleteEventsWithoutDates(): void public function deleteEventsWithoutDates(): void
{ {
$queryBuilder = $this->connectionPool $queryBuilder = $this->connectionPool
->getConnectionForTable(self::EVENT_TABLE) ->getConnectionForTable(self::EVENT_TABLE)
->createQueryBuilder(); ->createQueryBuilder()
;
$queryBuilder->getRestrictions()->removeAll(); $queryBuilder->getRestrictions()->removeAll();
$recordUids = $queryBuilder->select('event.uid') $recordUids = $queryBuilder->select('event.uid')
->from(self::EVENT_TABLE, 'event') ->from(self::EVENT_TABLE, 'event')
->leftJoin('event', self::DATE_TABLE, 'date', $queryBuilder->expr()->eq('date.event', 'event.uid')) ->leftJoin('event', self::DATE_TABLE, 'date', $queryBuilder->expr()->eq('date.event', 'event.uid'))->where($queryBuilder->expr()->isNull('date.uid'))->executeQuery()
->where($queryBuilder->expr()->isNull('date.uid')) ->fetchAll(PDO::FETCH_COLUMN)
->execute() ;
->fetchAll(\PDO::FETCH_COLUMN);
$queryBuilder = $this->connectionPool->getQueryBuilderForTable(self::EVENT_TABLE); $queryBuilder = $this->connectionPool->getQueryBuilderForTable(self::EVENT_TABLE);
$queryBuilder->delete(self::EVENT_TABLE); $queryBuilder->delete(self::EVENT_TABLE);
@ -101,20 +97,15 @@ class Database
'uid', 'uid',
$queryBuilder->createNamedParameter($recordUids, Connection::PARAM_INT_ARRAY) $queryBuilder->createNamedParameter($recordUids, Connection::PARAM_INT_ARRAY)
)); ));
$queryBuilder->execute(); $queryBuilder->executeStatement();
$queryBuilder = $this->connectionPool->getQueryBuilderForTable('sys_category_record_mm'); $queryBuilder = $this->connectionPool->getQueryBuilderForTable('sys_category_record_mm');
$queryBuilder->delete('sys_category_record_mm') $queryBuilder->delete('sys_category_record_mm')->where($queryBuilder->expr()->and($queryBuilder->expr()->like(
->where($queryBuilder->expr()->andX( 'tablenames',
$queryBuilder->expr()->like( $queryBuilder->createNamedParameter('tx_events_domain_model_%')
'tablenames', ), $queryBuilder->expr()->in(
$queryBuilder->createNamedParameter('tx_events_domain_model_%') 'uid_foreign',
), $queryBuilder->createNamedParameter($recordUids, Connection::PARAM_INT_ARRAY)
$queryBuilder->expr()->in( )))->executeStatement();
'uid_foreign',
$queryBuilder->createNamedParameter($recordUids, Connection::PARAM_INT_ARRAY)
)
))
->execute();
} }
} }

View file

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
namespace WerkraumMedia\Events\Service\Cleanup; namespace WerkraumMedia\Events\Service\Cleanup;
/* /*
@ -21,28 +23,17 @@ namespace WerkraumMedia\Events\Service\Cleanup;
* 02110-1301, USA. * 02110-1301, USA.
*/ */
use PDO;
use TYPO3\CMS\Core\Database\Connection; use TYPO3\CMS\Core\Database\Connection;
use TYPO3\CMS\Core\Database\ConnectionPool; use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\Resource\StorageRepository; use TYPO3\CMS\Core\Resource\StorageRepository;
class Files final class Files
{ {
/**
* @var ConnectionPool
*/
private $connectionPool;
/**
* @var StorageRepository
*/
private $storageRepository;
public function __construct( public function __construct(
ConnectionPool $connectionPool, private readonly ConnectionPool $connectionPool,
StorageRepository $storageRepository private readonly StorageRepository $storageRepository
) { ) {
$this->connectionPool = $connectionPool;
$this->storageRepository = $storageRepository;
} }
public function deleteDangling(): void public function deleteDangling(): void
@ -54,7 +45,8 @@ class Files
private function markFileReferencesDeletedIfForeignRecordIsMissing(): void private function markFileReferencesDeletedIfForeignRecordIsMissing(): void
{ {
$referencesQuery = $this->connectionPool $referencesQuery = $this->connectionPool
->getQueryBuilderForTable('sys_file_reference'); ->getQueryBuilderForTable('sys_file_reference')
;
$referencesQuery->getRestrictions()->removeAll(); $referencesQuery->getRestrictions()->removeAll();
$referencesQuery->select( $referencesQuery->select(
'uid', 'uid',
@ -70,7 +62,7 @@ class Files
); );
// Remove file relations removed via import // Remove file relations removed via import
$referencesQuery->orWhere( $referencesQuery->orWhere(
$referencesQuery->expr()->andX( $referencesQuery->expr()->and(
$referencesQuery->expr()->eq( $referencesQuery->expr()->eq(
'tablenames', 'tablenames',
$referencesQuery->createNamedParameter('') $referencesQuery->createNamedParameter('')
@ -92,7 +84,7 @@ class Files
$referencesQuery->orderBy('tablenames'); $referencesQuery->orderBy('tablenames');
$referencesQuery->addOrderBy('uid_foreign'); $referencesQuery->addOrderBy('uid_foreign');
$references = $referencesQuery->execute(); $references = $referencesQuery->executeQuery();
$uidsPerTable = []; $uidsPerTable = [];
$referenceUidsToMarkAsDeleted = []; $referenceUidsToMarkAsDeleted = [];
@ -116,10 +108,13 @@ class Files
$queryBuilder->select('uid'); $queryBuilder->select('uid');
$queryBuilder->from($tableName); $queryBuilder->from($tableName);
$queryBuilder->where($queryBuilder->expr()->in('uid', $records)); $queryBuilder->where($queryBuilder->expr()->in('uid', $records));
$referenceUidsToMarkAsDeleted = array_merge( $referenceUidsToMarkAsDeleted = [
$referenceUidsToMarkAsDeleted, ...$referenceUidsToMarkAsDeleted,
array_keys(array_diff($records, $queryBuilder->execute()->fetchAll(\PDO::FETCH_COLUMN))) ...array_keys(array_diff(
); $records,
$queryBuilder->executeQuery()->fetchAll(PDO::FETCH_COLUMN)
)),
];
} }
if ($referenceUidsToMarkAsDeleted === []) { if ($referenceUidsToMarkAsDeleted === []) {
@ -130,7 +125,7 @@ class Files
$updateQuery->update('sys_file_reference'); $updateQuery->update('sys_file_reference');
$updateQuery->where($updateQuery->expr()->in('uid', $referenceUidsToMarkAsDeleted)); $updateQuery->where($updateQuery->expr()->in('uid', $referenceUidsToMarkAsDeleted));
$updateQuery->set('deleted', '1'); $updateQuery->set('deleted', '1');
$updateQuery->execute(); $updateQuery->executeStatement();
} }
private function deleteFilesWithoutProperReference(): void private function deleteFilesWithoutProperReference(): void
@ -160,14 +155,16 @@ class Files
$queryBuilder = $this->connectionPool->getQueryBuilderForTable('sys_file'); $queryBuilder = $this->connectionPool->getQueryBuilderForTable('sys_file');
$queryBuilder->delete('sys_file') $queryBuilder->delete('sys_file')
->where('uid in (:uids)') ->where('uid in (:uids)')
->setParameter(':uids', $uids, Connection::PARAM_INT_ARRAY) ->setParameter('uids', $uids, Connection::PARAM_INT_ARRAY)
->execute(); ->executeStatement()
;
$queryBuilder = $this->connectionPool->getQueryBuilderForTable('sys_file_metadata'); $queryBuilder = $this->connectionPool->getQueryBuilderForTable('sys_file_metadata');
$queryBuilder->delete('sys_file_metadata') $queryBuilder->delete('sys_file_metadata')
->where('file in (:uids)') ->where('file in (:uids)')
->setParameter(':uids', $uids, Connection::PARAM_INT_ARRAY) ->setParameter('uids', $uids, Connection::PARAM_INT_ARRAY)
->execute(); ->executeStatement()
;
$this->deleteReferences(); $this->deleteReferences();
} }
@ -179,7 +176,7 @@ class Files
$queryBuilder $queryBuilder
->delete('sys_file_reference') ->delete('sys_file_reference')
->where( ->where(
$queryBuilder->expr()->orX( $queryBuilder->expr()->or(
$queryBuilder->expr()->like( $queryBuilder->expr()->like(
'tablenames', 'tablenames',
$queryBuilder->createNamedParameter('tx_events_domain_model_%') $queryBuilder->createNamedParameter('tx_events_domain_model_%')
@ -195,7 +192,7 @@ class Files
1 1
)) ))
; ;
$queryBuilder->execute(); $queryBuilder->executeStatement();
} }
/** /**
@ -225,7 +222,7 @@ class Files
->groupBy('file.uid') ->groupBy('file.uid')
; ;
return $queryBuilder->execute()->fetchAllAssociativeIndexed(); return $queryBuilder->executeQuery()->fetchAllAssociativeIndexed();
} }
/** /**
@ -249,13 +246,13 @@ class Files
)) ))
; ;
foreach ($queryBuilder->execute() as $reference) { foreach ($queryBuilder->executeQuery()->iterateAssociative() as $reference) {
$file = []; $file = [];
$fileUid = (int)$reference['uid_local']; $fileUid = (int)$reference['uid_local'];
if ( if (
( (
str_starts_with($reference['tablenames'], 'tx_events_domain_model_') str_starts_with((string)$reference['tablenames'], 'tx_events_domain_model_')
|| $reference['tablenames'] === '' || $reference['tablenames'] === ''
) && $reference['deleted'] == 1 ) && $reference['deleted'] == 1
) { ) {

View file

@ -1,26 +1,18 @@
<?php <?php
declare(strict_types=1);
namespace WerkraumMedia\Events\Service; namespace WerkraumMedia\Events\Service;
use WerkraumMedia\Events\Service\Cleanup\Database; use WerkraumMedia\Events\Service\Cleanup\Database;
use WerkraumMedia\Events\Service\Cleanup\Files; use WerkraumMedia\Events\Service\Cleanup\Files;
class CleanupService final class CleanupService
{ {
/** public function __construct(
* @var Database private readonly Database $database,
*/ private readonly Files $files
private $database; ) {
/**
* @var Files
*/
private $files;
public function __construct(Database $database, Files $files)
{
$this->database = $database;
$this->files = $files;
} }
public function deleteAllData(): void public function deleteAllData(): void

View file

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
namespace WerkraumMedia\Events\Service; namespace WerkraumMedia\Events\Service;
/* /*
@ -67,49 +69,22 @@ use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
* *
* - Event->getPages() * - Event->getPages()
*/ */
class DataProcessingForModels implements SingletonInterface final class DataProcessingForModels implements SingletonInterface
{ {
/** private readonly ContentObjectRenderer $cObject;
* @var ContentObjectRenderer
*/
private $cObject;
/** private readonly Connection $connection;
* @var ContentDataProcessor
*/
private $processorHandler;
/** private ?ConfigurationManagerInterface $configurationManager = null;
* @var Connection
*/
private $connection;
/**
* @var DataMapFactory
*/
private $dataMapFactory;
/**
* @var ConfigurationManagerInterface|null
*/
private $configurationManager;
/**
* @var TypoScriptService
*/
private $typoScriptService;
public function __construct( public function __construct(
ContentDataProcessor $processorHandler, private readonly ContentDataProcessor $processorHandler,
ConnectionPool $connectionPool, ConnectionPool $connectionPool,
DataMapFactory $dataMapFactory, private readonly DataMapFactory $dataMapFactory,
TypoScriptService $typoScriptService private readonly TypoScriptService $typoScriptService
) { ) {
$this->cObject = GeneralUtility::makeInstance(ContentObjectRenderer::class); $this->cObject = GeneralUtility::makeInstance(ContentObjectRenderer::class);
$this->processorHandler = $processorHandler;
$this->connection = $connectionPool->getConnectionByName('Default'); $this->connection = $connectionPool->getConnectionByName('Default');
$this->dataMapFactory = $dataMapFactory;
$this->typoScriptService = $typoScriptService;
} }
/** /**
@ -148,7 +123,7 @@ class DataProcessingForModels implements SingletonInterface
private function getTable(AbstractEntity $entity): string private function getTable(AbstractEntity $entity): string
{ {
$dataMap = $this->dataMapFactory->buildDataMap(get_class($entity)); $dataMap = $this->dataMapFactory->buildDataMap($entity::class);
return $dataMap->getTableName(); return $dataMap->getTableName();
} }
@ -158,7 +133,7 @@ class DataProcessingForModels implements SingletonInterface
return []; return [];
} }
$className = get_class($entity); $className = $entity::class;
$settings = $this->configurationManager->getConfiguration( $settings = $this->configurationManager->getConfiguration(
ConfigurationManagerInterface::CONFIGURATION_TYPE_SETTINGS ConfigurationManagerInterface::CONFIGURATION_TYPE_SETTINGS
); );

View file

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
namespace WerkraumMedia\Events\Service; namespace WerkraumMedia\Events\Service;
use Exception; use Exception;
@ -9,7 +11,6 @@ use TYPO3\CMS\Core\Log\LogManager;
use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Extbase\Configuration\ConfigurationManager; use TYPO3\CMS\Extbase\Configuration\ConfigurationManager;
use TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface; use TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface;
use TYPO3\CMS\Extbase\Object\ObjectManager;
use TYPO3\CMS\Extbase\Persistence\Generic\PersistenceManager; use TYPO3\CMS\Extbase\Persistence\Generic\PersistenceManager;
use WerkraumMedia\Events\Caching\CacheManager; use WerkraumMedia\Events\Caching\CacheManager;
use WerkraumMedia\Events\Domain\Model\Event; use WerkraumMedia\Events\Domain\Model\Event;
@ -31,148 +32,36 @@ use WerkraumMedia\Events\Service\DestinationDataImportService\FilesAssignment;
use WerkraumMedia\Events\Service\DestinationDataImportService\LocationAssignment; use WerkraumMedia\Events\Service\DestinationDataImportService\LocationAssignment;
use WerkraumMedia\Events\Service\DestinationDataImportService\Slugger; use WerkraumMedia\Events\Service\DestinationDataImportService\Slugger;
class DestinationDataImportService final class DestinationDataImportService
{ {
/** private Import $import;
* @var Import
*/
private $import;
/** private Event $tmpCurrentEvent;
* @var Event
*/
private $tmpCurrentEvent;
/** /**
* @var Logger * @var Logger
*/ */
private $logger; private $logger;
/**
* @var EventRepository
*/
private $eventRepository;
/**
* @var OrganizerRepository
*/
private $organizerRepository;
/**
* @var DateRepository
*/
private $dateRepository;
/**
* @var ConfigurationManager
*/
private $configurationManager;
/**
* @var ObjectManager
*/
private $objectManager;
/**
* @var PersistenceManager
*/
private $persistenceManager;
/**
* @var DataFetcher
*/
private $dataFetcher;
/**
* @var DatesFactory
*/
private $datesFactory;
/**
* @var FilesAssignment
*/
private $filesAssignment;
/**
* @var CategoriesAssignment
*/
private $categoriesAssignment;
/**
* @var LocationAssignment
*/
private $locationAssignment;
/**
* @var Slugger
*/
private $slugger;
/**
* @var CacheManager
*/
private $cacheManager;
/**
* @var DataHandler
*/
private $dataHandler;
/**
* @var EventDispatcher
*/
private $eventDispatcher;
/** /**
* ImportService constructor. * ImportService constructor.
*
* @param EventRepository $eventRepository
* @param OrganizerRepository $organizerRepository
* @param DateRepository $dateRepository
* @param ConfigurationManager $configurationManager
* @param PersistenceManager $persistenceManager
* @param ObjectManager $objectManager
* @param DataFetcher $dataFetcher
* @param FilesAssignment $filesAssignment
* @param CategoriesAssignment $categoriesAssignment
* @param LocationAssignment $locationAssignment
* @param Slugger $slugger
* @param CacheManager $cacheManager
* @param DataHandler $dataHandler
* @param EventDispatcher $eventDispatcher
*/ */
public function __construct( public function __construct(
EventRepository $eventRepository, private readonly EventRepository $eventRepository,
OrganizerRepository $organizerRepository, private readonly OrganizerRepository $organizerRepository,
DateRepository $dateRepository, private readonly DateRepository $dateRepository,
ConfigurationManager $configurationManager, private readonly ConfigurationManager $configurationManager,
PersistenceManager $persistenceManager, private readonly PersistenceManager $persistenceManager,
ObjectManager $objectManager, private readonly DataFetcher $dataFetcher,
DataFetcher $dataFetcher, private readonly DatesFactory $datesFactory,
DatesFactory $datesFactory, private readonly FilesAssignment $filesAssignment,
FilesAssignment $filesAssignment, private readonly CategoriesAssignment $categoriesAssignment,
CategoriesAssignment $categoriesAssignment, private readonly LocationAssignment $locationAssignment,
LocationAssignment $locationAssignment, private readonly Slugger $slugger,
Slugger $slugger, private readonly CacheManager $cacheManager,
CacheManager $cacheManager, private readonly DataHandler $dataHandler,
DataHandler $dataHandler, private readonly EventDispatcher $eventDispatcher
EventDispatcher $eventDispatcher
) { ) {
$this->eventRepository = $eventRepository;
$this->organizerRepository = $organizerRepository;
$this->dateRepository = $dateRepository;
$this->configurationManager = $configurationManager;
$this->persistenceManager = $persistenceManager;
$this->objectManager = $objectManager;
$this->dataFetcher = $dataFetcher;
$this->datesFactory = $datesFactory;
$this->filesAssignment = $filesAssignment;
$this->categoriesAssignment = $categoriesAssignment;
$this->locationAssignment = $locationAssignment;
$this->slugger = $slugger;
$this->cacheManager = $cacheManager;
$this->dataHandler = $dataHandler;
$this->eventDispatcher = $eventDispatcher;
} }
public function import( public function import(
@ -194,12 +83,12 @@ class DestinationDataImportService
// Set Configuration // Set Configuration
$this->configurationManager->setConfiguration(array_merge($frameworkConfiguration, $persistenceConfiguration)); $this->configurationManager->setConfiguration(array_merge($frameworkConfiguration, $persistenceConfiguration));
$this->logger = GeneralUtility::makeInstance(LogManager::class)->getLogger(__CLASS__); $this->logger = GeneralUtility::makeInstance(LogManager::class)->getLogger(self::class);
$this->logger->info('Starting Destination Data Import Service'); $this->logger->info('Starting Destination Data Import Service');
try { try {
$data = $this->dataFetcher->fetchSearchResult($import); $data = $this->dataFetcher->fetchSearchResult($import);
} catch (Exception $e) { } catch (Exception) {
$this->logger->error('Could not receive data.'); $this->logger->error('Could not receive data.');
return 1; return 1;
} }
@ -215,7 +104,7 @@ class DestinationDataImportService
$selectedRegion = $this->import->getRegion(); $selectedRegion = $this->import->getRegion();
foreach ($data['items'] as $event) { foreach ($data['items'] as $event) {
$this->logger->info('Processing event ' . substr($event['title'], 0, 20)); $this->logger->info('Processing event ' . substr((string)$event['title'], 0, 20));
// Event already exists? If not create one! // Event already exists? If not create one!
$this->tmpCurrentEvent = $this->getOrCreateEvent($event['global_id'], $event['title']); $this->tmpCurrentEvent = $this->getOrCreateEvent($event['global_id'], $event['title']);
@ -230,7 +119,7 @@ class DestinationDataImportService
} }
// Set Title // Set Title
$this->tmpCurrentEvent->setTitle(substr($event['title'], 0, 254)); $this->tmpCurrentEvent->setTitle(substr((string)$event['title'], 0, 254));
// Set Highlight (Is only set in rest if true) // Set Highlight (Is only set in rest if true)
if ($event['highlight'] ?? false) { if ($event['highlight'] ?? false) {
@ -382,7 +271,7 @@ class DestinationDataImportService
$this->tmpCurrentEvent->setOrganizer($tmpOrganizer); $this->tmpCurrentEvent->setOrganizer($tmpOrganizer);
continue; continue;
} }
$tmpOrganizer = $this->objectManager->get(Organizer::class); $tmpOrganizer = GeneralUtility::makeInstance(Organizer::class);
$tmpOrganizer->setLanguageUid(-1); $tmpOrganizer->setLanguageUid(-1);
$tmpOrganizer->setName($address['name'] ?? ''); $tmpOrganizer->setName($address['name'] ?? '');
$tmpOrganizer->setCity($address['city'] ?? ''); $tmpOrganizer->setCity($address['city'] ?? '');
@ -398,9 +287,6 @@ class DestinationDataImportService
} }
} }
/**
* @param array $media
*/
private function setSocial(array $media): void private function setSocial(array $media): void
{ {
foreach ($media as $link) { foreach ($media as $link) {
@ -470,13 +356,13 @@ class DestinationDataImportService
} }
if ($text['rel'] == 'details' && $text['type'] == 'text/plain') { if ($text['rel'] == 'details' && $text['type'] == 'text/plain') {
$this->tmpCurrentEvent->setDetails(str_replace("\n\n", "\n", $text['value'])); $this->tmpCurrentEvent->setDetails(str_replace("\n\n", "\n", (string)$text['value']));
} }
if ($text['rel'] == 'teaser' && $text['type'] == 'text/plain') { if ($text['rel'] == 'teaser' && $text['type'] == 'text/plain') {
$this->tmpCurrentEvent->setTeaser(str_replace("\n\n", "\n", $text['value'])); $this->tmpCurrentEvent->setTeaser(str_replace("\n\n", "\n", (string)$text['value']));
} }
if ($text['rel'] == 'PRICE_INFO' && $text['type'] == 'text/plain') { if ($text['rel'] == 'PRICE_INFO' && $text['type'] == 'text/plain') {
$this->tmpCurrentEvent->setPriceInfo(str_replace("\n\n", "\n", $text['value'])); $this->tmpCurrentEvent->setPriceInfo(str_replace("\n\n", "\n", (string)$text['value']));
} }
} }
} }
@ -494,7 +380,7 @@ class DestinationDataImportService
// New event is created // New event is created
$this->logger->info(substr($title, 0, 20) . ' does not exist'); $this->logger->info(substr($title, 0, 20) . ' does not exist');
$event = $this->objectManager->get(Event::class); $event = GeneralUtility::makeInstance(Event::class);
// Create event and persist // Create event and persist
$event->setGlobalId($globalId); $event->setGlobalId($globalId);
$this->eventRepository->add($event); $this->eventRepository->add($event);

View file

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
namespace WerkraumMedia\Events\Service\DestinationDataImportService; namespace WerkraumMedia\Events\Service\DestinationDataImportService;
use TYPO3\CMS\Extbase\Persistence\Generic\PersistenceManager; use TYPO3\CMS\Extbase\Persistence\Generic\PersistenceManager;
@ -14,24 +16,12 @@ use WerkraumMedia\Events\Service\DestinationDataImportService\CategoriesAssignme
* Categories mean TYPO3 sys_category records. * Categories mean TYPO3 sys_category records.
* Those are used for multiple records within destination data. E.g. categories or features. * Those are used for multiple records within destination data. E.g. categories or features.
*/ */
class CategoriesAssignment final class CategoriesAssignment
{ {
/**
* @var CategoryRepository
*/
private $repository;
/**
* @var PersistenceManager
*/
private $persistenceManager;
public function __construct( public function __construct(
CategoryRepository $repository, private readonly CategoryRepository $repository,
PersistenceManager $persistenceManager private readonly PersistenceManager $persistenceManager
) { ) {
$this->repository = $repository;
$this->persistenceManager = $persistenceManager;
} }
/** /**

View file

@ -1,41 +1,19 @@
<?php <?php
declare(strict_types=1);
namespace WerkraumMedia\Events\Service\DestinationDataImportService\CategoriesAssignment; namespace WerkraumMedia\Events\Service\DestinationDataImportService\CategoriesAssignment;
use WerkraumMedia\Events\Domain\Model\Category; use WerkraumMedia\Events\Domain\Model\Category;
class Import final class Import
{ {
/**
* @var Category|null
*/
private $parentCategory;
/**
* @var int|null
*/
private $pid;
/**
* @var array
*/
private $categoryTitles;
/**
* @var bool
*/
private $hideByDefault;
public function __construct( public function __construct(
?Category $parentCategory, private readonly ?Category $parentCategory,
?int $pid, private readonly ?int $pid,
array $categoryTitles, private readonly array $categoryTitles,
bool $hideByDefault = false private readonly bool $hideByDefault = false
) { ) {
$this->parentCategory = $parentCategory;
$this->pid = $pid;
$this->categoryTitles = $categoryTitles;
$this->hideByDefault = $hideByDefault;
} }
public function getParentCategory(): ?Category public function getParentCategory(): ?Category

View file

@ -1,12 +1,15 @@
<?php <?php
declare(strict_types=1);
namespace WerkraumMedia\Events\Service\DestinationDataImportService; namespace WerkraumMedia\Events\Service\DestinationDataImportService;
use Exception;
use GuzzleHttp\ClientInterface as GuzzleClientInterface; use GuzzleHttp\ClientInterface as GuzzleClientInterface;
use Psr\Http\Client\ClientInterface; use Psr\Http\Client\ClientInterface;
use Psr\Http\Message\RequestFactoryInterface; use Psr\Http\Message\RequestFactoryInterface;
use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ResponseInterface;
use TYPO3\CMS\Core\Log\Logger; use Psr\Log\LoggerInterface;
use TYPO3\CMS\Core\Log\LogManager; use TYPO3\CMS\Core\Log\LogManager;
use WerkraumMedia\Events\Domain\Model\Import; use WerkraumMedia\Events\Domain\Model\Import;
@ -16,39 +19,17 @@ use WerkraumMedia\Events\Domain\Model\Import;
* Only partially migrated from service to here. * Only partially migrated from service to here.
* Further calls need to be migrated. * Further calls need to be migrated.
*/ */
class DataFetcher final class DataFetcher
{ {
/** private readonly LoggerInterface $logger;
* @var UrlFactory
*/
private $urlFactory;
/**
* @var RequestFactoryInterface
*/
private $requestFactory;
/**
* @var GuzzleClientInterface
*/
private $client;
/**
* @var Logger
*/
private $logger;
public function __construct( public function __construct(
UrlFactory $urlFactory, private readonly UrlFactory $urlFactory,
LogManager $logManager, LogManager $logManager,
RequestFactoryInterface $requestFactory, private readonly RequestFactoryInterface $requestFactory,
GuzzleClientInterface $client private readonly GuzzleClientInterface $client
) { ) {
$this->urlFactory = $urlFactory; $this->logger = $logManager->getLogger(self::class);
$this->requestFactory = $requestFactory;
$this->client = $client;
$this->logger = $logManager->getLogger(__CLASS__);
} }
public function fetchSearchResult(Import $import): array public function fetchSearchResult(Import $import): array
@ -76,9 +57,9 @@ class DataFetcher
$jsonContent = $response->getBody()->__toString(); $jsonContent = $response->getBody()->__toString();
$jsonResponse = json_decode($jsonContent, true); $jsonResponse = json_decode($jsonContent, true, 512, JSON_THROW_ON_ERROR);
if (is_array($jsonResponse) === false) { if (is_array($jsonResponse) === false) {
throw new \Exception('No valid JSON fetched, got: "' . $jsonContent . '".', 1639495835); throw new Exception('No valid JSON fetched, got: "' . $jsonContent . '".', 1639495835);
} }
$this->logger->info('Received data with ' . count($jsonResponse['items']) . ' items'); $this->logger->info('Received data with ' . count($jsonResponse['items']) . ' items');

View file

@ -23,23 +23,20 @@ declare(strict_types=1);
namespace WerkraumMedia\Events\Service\DestinationDataImportService; namespace WerkraumMedia\Events\Service\DestinationDataImportService;
use Psr\Log\LoggerInterface;
use TYPO3\CMS\Core\DataHandling\DataHandler as Typo3DataHandler; use TYPO3\CMS\Core\DataHandling\DataHandler as Typo3DataHandler;
use TYPO3\CMS\Core\Log\Logger;
use TYPO3\CMS\Core\Log\LogManager; use TYPO3\CMS\Core\Log\LogManager;
use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Core\Utility\GeneralUtility;
use WerkraumMedia\Events\Service\DestinationDataImportService\DataHandler\Assignment; use WerkraumMedia\Events\Service\DestinationDataImportService\DataHandler\Assignment;
final class DataHandler final class DataHandler
{ {
/** private readonly LoggerInterface $logger;
* @var Logger
*/
private $logger;
public function __construct( public function __construct(
LogManager $logManager LogManager $logManager
) { ) {
$this->logger = $logManager->getLogger(__CLASS__); $this->logger = $logManager->getLogger(self::class);
} }
public function storeAssignments( public function storeAssignments(

View file

@ -28,31 +28,26 @@ use TYPO3\CMS\Extbase\DomainObject\AbstractDomainObject;
final class Assignment final class Assignment
{ {
/** private readonly int $uid;
* @var int
*/
private $uid;
/**
* @var string
*/
private $columnName;
/** /**
* @var int[] * @var int[]
*/ */
private $uids; private readonly array $uids;
/** /**
* @param AbstractDomainObject[] $assignments * @param AbstractDomainObject[] $assignments
*/ */
public function __construct( public function __construct(
int $uid, ?int $uid,
string $columnName, private readonly string $columnName,
array $assignments array $assignments
) { ) {
if (is_int($uid) === false) {
throw new InvalidArgumentException('Only integer allowed as uid, need a persisted entity.', 1699352008);
}
$this->uid = $uid; $this->uid = $uid;
$this->columnName = $columnName;
$this->uids = array_map(static function (AbstractDomainObject $model): int { $this->uids = array_map(static function (AbstractDomainObject $model): int {
$uid = $model->getUid(); $uid = $model->getUid();
if (is_int($uid) === false) { if (is_int($uid) === false) {

View file

@ -1,50 +1,42 @@
<?php <?php
declare(strict_types=1);
namespace WerkraumMedia\Events\Service\DestinationDataImportService; namespace WerkraumMedia\Events\Service\DestinationDataImportService;
use DateInterval;
use DatePeriod;
use DateTimeImmutable;
use DateTimeZone;
use Generator;
use Psr\Log\LoggerInterface;
use TYPO3\CMS\Core\Context\Context; use TYPO3\CMS\Core\Context\Context;
use TYPO3\CMS\Core\Log\Logger;
use TYPO3\CMS\Core\Log\LogManager; use TYPO3\CMS\Core\Log\LogManager;
use TYPO3\CMS\Extbase\Configuration\ConfigurationManager; use TYPO3\CMS\Extbase\Configuration\ConfigurationManager;
use WerkraumMedia\Events\Domain\Model\Date; use WerkraumMedia\Events\Domain\Model\Date;
class DatesFactory final class DatesFactory
{ {
/** private readonly LoggerInterface $logger;
* @var Context
*/
private $context;
/**
* @var ConfigurationManager
*/
private $configurationManager;
/**
* @var Logger
*/
private $logger;
public function __construct( public function __construct(
Context $context, private readonly Context $context,
ConfigurationManager $configurationManager, private readonly ConfigurationManager $configurationManager,
LogManager $logManager LogManager $logManager
) { ) {
$this->context = $context; $this->logger = $logManager->getLogger(self::class);
$this->configurationManager = $configurationManager;
$this->logger = $logManager->getLogger(__CLASS__);
} }
/** /**
* @return \Generator<Date> * @return Generator<Date>
*/ */
public function createDates( public function createDates(
array $timeIntervals, array $timeIntervals,
bool $canceled bool $canceled
): \Generator { ): Generator {
foreach ($timeIntervals as $date) { foreach ($timeIntervals as $date) {
$dates = $this->createDate($date, $canceled); $dates = $this->createDate($date, $canceled);
if (!$dates instanceof \Generator) { if (!$dates instanceof Generator) {
return null; return null;
} }
@ -55,12 +47,12 @@ class DatesFactory
} }
/** /**
* @return \Generator<Date>|null * @return Generator<Date>|null
*/ */
private function createDate( private function createDate(
array $date, array $date,
bool $canceled bool $canceled
): ?\Generator { ): ?Generator {
if ($this->isDateSingleDate($date)) { if ($this->isDateSingleDate($date)) {
$this->logger->info('Is single date', ['date' => $date]); $this->logger->info('Is single date', ['date' => $date]);
return $this->createSingleDate($date, $canceled); return $this->createSingleDate($date, $canceled);
@ -99,24 +91,24 @@ class DatesFactory
} }
/** /**
* @return \Generator<Date> * @return Generator<Date>
*/ */
private function createSingleDate( private function createSingleDate(
array $date, array $date,
bool $canceled bool $canceled
): \Generator { ): Generator {
if (new \DateTimeImmutable($date['start']) > $this->getToday()) { if (new DateTimeImmutable($date['start']) > $this->getToday()) {
yield Date::createFromDestinationDataDate($date, $canceled); yield Date::createFromDestinationDataDate($date, $canceled);
} }
} }
/** /**
* @return \Generator<Date>|null * @return Generator<Date>|null
*/ */
private function createDateFromInterval( private function createDateFromInterval(
array $date, array $date,
bool $canceled bool $canceled
): ?\Generator { ): ?Generator {
$date = $this->ensureRepeatUntil($date); $date = $this->ensureRepeatUntil($date);
if ($date['freq'] == 'Daily') { if ($date['freq'] == 'Daily') {
@ -149,19 +141,19 @@ class DatesFactory
} }
/** /**
* @return \Generator<Date> * @return Generator<Date>
*/ */
private function createDailyDates( private function createDailyDates(
array $date, array $date,
bool $canceled bool $canceled
): \Generator { ): Generator {
$today = $this->getToday(); $today = $this->getToday();
$timeZone = new \DateTimeZone($date['tz']); $timeZone = new DateTimeZone($date['tz']);
$start = new \DateTimeImmutable($date['start'], $timeZone); $start = new DateTimeImmutable($date['start'], $timeZone);
$end = new \DateTimeImmutable($date['end'], $timeZone); $end = new DateTimeImmutable($date['end'], $timeZone);
$until = new \DateTimeImmutable($date['repeatUntil'], $timeZone); $until = new DateTimeImmutable($date['repeatUntil'], $timeZone);
$period = new \DatePeriod($start, new \DateInterval('P1D'), $until); $period = new DatePeriod($start, new DateInterval('P1D'), $until);
foreach ($period as $day) { foreach ($period as $day) {
$day = $day->setTimezone($timeZone); $day = $day->setTimezone($timeZone);
if ($day < $today) { if ($day < $today) {
@ -179,23 +171,23 @@ class DatesFactory
} }
/** /**
* @return \Generator<Date> * @return Generator<Date>
*/ */
private function createWeeklyDates( private function createWeeklyDates(
array $date, array $date,
bool $canceled bool $canceled
): \Generator { ): Generator {
$today = $this->getToday(); $today = $this->getToday();
$timeZone = new \DateTimeZone($date['tz']); $timeZone = new DateTimeZone($date['tz']);
$start = new \DateTimeImmutable($date['start'], $timeZone); $start = new DateTimeImmutable($date['start'], $timeZone);
$end = new \DateTimeImmutable($date['end'], $timeZone); $end = new DateTimeImmutable($date['end'], $timeZone);
$until = new \DateTimeImmutable($date['repeatUntil'], $timeZone); $until = new DateTimeImmutable($date['repeatUntil'], $timeZone);
foreach ($date['weekdays'] as $day) { foreach ($date['weekdays'] as $day) {
$dateToUse = $start->modify($day); $dateToUse = $start->modify($day);
$dateToUse = $dateToUse->setTime((int)$start->format('H'), (int)$start->format('i')); $dateToUse = $dateToUse->setTime((int)$start->format('H'), (int)$start->format('i'));
$period = new \DatePeriod($dateToUse, new \DateInterval('P1W'), $until); $period = new DatePeriod($dateToUse, new DateInterval('P1W'), $until);
foreach ($period as $day) { foreach ($period as $day) {
$day = $day->setTimezone($timeZone); $day = $day->setTimezone($timeZone);
if ($day < $today) { if ($day < $today) {
@ -214,9 +206,9 @@ class DatesFactory
} }
private function createDateFromStartAndEnd( private function createDateFromStartAndEnd(
\DateTimeImmutable $dateToUse, DateTimeImmutable $dateToUse,
\DateTimeImmutable $start, DateTimeImmutable $start,
\DateTimeImmutable $end, DateTimeImmutable $end,
bool $canceled bool $canceled
): Date { ): Date {
return Date::createFromDestinationData( return Date::createFromDestinationData(
@ -226,11 +218,11 @@ class DatesFactory
); );
} }
private function getToday(): \DateTimeImmutable private function getToday(): DateTimeImmutable
{ {
$today = $this->context->getPropertyFromAspect('date', 'full', new \DateTimeImmutable()); $today = $this->context->getPropertyFromAspect('date', 'full', new DateTimeImmutable());
if (!$today instanceof \DateTimeImmutable) { if (!$today instanceof DateTimeImmutable) {
$today = new \DateTimeImmutable(); $today = new DateTimeImmutable();
} }
return $today->modify('midnight'); return $today->modify('midnight');

View file

@ -29,24 +29,18 @@ use WerkraumMedia\Events\Domain\Model\Event;
final class CategoriesAssignEvent final class CategoriesAssignEvent
{ {
/**
* @var Event
*/
private $event;
/** /**
* @var ObjectStorage<Category> * @var ObjectStorage<Category>
*/ */
private $categories; private ObjectStorage $categories;
/** /**
* @param ObjectStorage<Category> $categories * @param ObjectStorage<Category> $categories
*/ */
public function __construct( public function __construct(
Event $event, private readonly Event $event,
ObjectStorage $categories ObjectStorage $categories
) { ) {
$this->event = $event;
$this->setCategories($categories); $this->setCategories($categories);
} }

View file

@ -27,22 +27,10 @@ use WerkraumMedia\Events\Domain\Model\Event;
final class EventImportEvent final class EventImportEvent
{ {
/**
* @var Event
*/
private $existingEvent;
/**
* @var Event
*/
private $eventToImport;
public function __construct( public function __construct(
Event $existingEvent, private readonly Event $existingEvent,
Event $eventToImport private readonly Event $eventToImport
) { ) {
$this->existingEvent = $existingEvent;
$this->eventToImport = $eventToImport;
} }
public function getBaseEvent(): Event public function getBaseEvent(): Event

View file

@ -25,6 +25,7 @@ namespace WerkraumMedia\Events\Service\DestinationDataImportService;
use Exception; use Exception;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
use SplFileInfo;
use TYPO3\CMS\Core\Log\LogManager; use TYPO3\CMS\Core\Log\LogManager;
use TYPO3\CMS\Core\Resource\DuplicationBehavior; use TYPO3\CMS\Core\Resource\DuplicationBehavior;
use TYPO3\CMS\Core\Resource\File; use TYPO3\CMS\Core\Resource\File;
@ -36,38 +37,17 @@ use TYPO3\CMS\Extbase\Persistence\ObjectStorage;
use WerkraumMedia\Events\Domain\Model\Event; use WerkraumMedia\Events\Domain\Model\Event;
use WerkraumMedia\Events\Domain\Model\Import; use WerkraumMedia\Events\Domain\Model\Import;
class FilesAssignment final class FilesAssignment
{ {
/** private readonly LoggerInterface $logger;
* @var LoggerInterface
*/
private $logger;
/**
* @var DataFetcher
*/
private $dataFetcher;
/**
* @var ResourceFactory
*/
private $resourceFactory;
/**
* @var MetaDataRepository
*/
private $metaDataRepository;
public function __construct( public function __construct(
LogManager $logManager, LogManager $logManager,
DataFetcher $dataFetcher, private readonly DataFetcher $dataFetcher,
ResourceFactory $resourceFactory, private readonly ResourceFactory $resourceFactory,
MetaDataRepository $metaDataRepository private readonly MetaDataRepository $metaDataRepository
) { ) {
$this->logger = $logManager->getLogger(self::class); $this->logger = $logManager->getLogger(self::class);
$this->dataFetcher = $dataFetcher;
$this->resourceFactory = $resourceFactory;
$this->metaDataRepository = $metaDataRepository;
} }
/** /**
@ -86,7 +66,7 @@ class FilesAssignment
continue; continue;
} }
$fileUrl = urldecode($mediaObject['url']); $fileUrl = urldecode((string)$mediaObject['url']);
$orgFileNameSanitized = $importFolder->getStorage()->sanitizeFileName(basename($fileUrl)); $orgFileNameSanitized = $importFolder->getStorage()->sanitizeFileName(basename($fileUrl));
$this->logger->info('File attached.', [$fileUrl, $orgFileNameSanitized]); $this->logger->info('File attached.', [$fileUrl, $orgFileNameSanitized]);
@ -124,7 +104,7 @@ class FilesAssignment
try { try {
$response = $this->dataFetcher->fetchImage($fileUrl); $response = $this->dataFetcher->fetchImage($fileUrl);
} catch (Exception $e) { } catch (Exception) {
$this->logger->error('Cannot load file.', [$fileUrl]); $this->logger->error('Cannot load file.', [$fileUrl]);
return ''; return '';
} }
@ -134,7 +114,7 @@ class FilesAssignment
return ''; return '';
} }
$file = new \SplFileInfo($fileUrl); $file = new SplFileInfo($fileUrl);
$temporaryFilename = GeneralUtility::tempnam($file->getBasename()); $temporaryFilename = GeneralUtility::tempnam($file->getBasename());
$writeResult = GeneralUtility::writeFile($temporaryFilename, $response->getBody()->__toString(), true); $writeResult = GeneralUtility::writeFile($temporaryFilename, $response->getBody()->__toString(), true);
if ($writeResult === false) { if ($writeResult === false) {
@ -204,7 +184,6 @@ class FilesAssignment
]; ];
return ((string)$mediaObject['rel']) === 'default' return ((string)$mediaObject['rel']) === 'default'
&& in_array($mediaObject['type'], $allowedMimeTypes) && in_array($mediaObject['type'], $allowedMimeTypes);
;
} }
} }

View file

@ -1,21 +1,17 @@
<?php <?php
declare(strict_types=1);
namespace WerkraumMedia\Events\Service\DestinationDataImportService; namespace WerkraumMedia\Events\Service\DestinationDataImportService;
use WerkraumMedia\Events\Domain\Model\Location; use WerkraumMedia\Events\Domain\Model\Location;
use WerkraumMedia\Events\Domain\Repository\LocationRepository; use WerkraumMedia\Events\Domain\Repository\LocationRepository;
class LocationAssignment final class LocationAssignment
{ {
/**
* @var LocationRepository
*/
private $repository;
public function __construct( public function __construct(
LocationRepository $repository private readonly LocationRepository $repository
) { ) {
$this->repository = $repository;
} }
public function getLocation(array $event): ?Location public function getLocation(array $event): ?Location
@ -28,8 +24,8 @@ class LocationAssignment
$event['district'] ?? '', $event['district'] ?? '',
$event['country'] ?? '', $event['country'] ?? '',
$event['phone'] ?? '', $event['phone'] ?? '',
$event['geo']['main']['latitude'] ?? '', (string)($event['geo']['main']['latitude'] ?? ''),
$event['geo']['main']['longitude'] ?? '', (string)($event['geo']['main']['longitude'] ?? ''),
-1 -1
); );

View file

@ -23,6 +23,8 @@ declare(strict_types=1);
namespace WerkraumMedia\Events\Service\DestinationDataImportService; namespace WerkraumMedia\Events\Service\DestinationDataImportService;
use Generator;
use PDO;
use TYPO3\CMS\Core\Database\ConnectionPool; use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\Database\Query\QueryBuilder; use TYPO3\CMS\Core\Database\Query\QueryBuilder;
use TYPO3\CMS\Core\DataHandling\SlugHelper; use TYPO3\CMS\Core\DataHandling\SlugHelper;
@ -30,24 +32,12 @@ use TYPO3\CMS\Core\Utility\GeneralUtility;
use WerkraumMedia\Events\Service\DestinationDataImportService\Slugger\Registry; use WerkraumMedia\Events\Service\DestinationDataImportService\Slugger\Registry;
use WerkraumMedia\Events\Service\DestinationDataImportService\Slugger\SluggerType; use WerkraumMedia\Events\Service\DestinationDataImportService\Slugger\SluggerType;
class Slugger final class Slugger
{ {
/**
* @var Registry
*/
private $registry;
/**
* @var ConnectionPool
*/
private $connectionPool;
public function __construct( public function __construct(
Registry $registry, private readonly Registry $registry,
ConnectionPool $connectionPool private readonly ConnectionPool $connectionPool
) { ) {
$this->registry = $registry;
$this->connectionPool = $connectionPool;
} }
public function update(string $tableName): void public function update(string $tableName): void
@ -59,9 +49,9 @@ class Slugger
} }
/** /**
* @return \Generator<array> * @return Generator<array>
*/ */
private function getRecords(SluggerType $sluggerType): \Generator private function getRecords(SluggerType $sluggerType): Generator
{ {
$tableName = $sluggerType->getSupportedTableName(); $tableName = $sluggerType->getSupportedTableName();
$slugColumn = $sluggerType->getSlugColumn(); $slugColumn = $sluggerType->getSlugColumn();
@ -70,12 +60,13 @@ class Slugger
$statement = $queryBuilder->select('*') $statement = $queryBuilder->select('*')
->from($tableName) ->from($tableName)
->where( ->where(
$queryBuilder->expr()->orX( $queryBuilder->expr()->or(
$queryBuilder->expr()->eq($slugColumn, $queryBuilder->createNamedParameter('', \PDO::PARAM_STR)), $queryBuilder->expr()->eq($slugColumn, $queryBuilder->createNamedParameter('', PDO::PARAM_STR)),
$queryBuilder->expr()->isNull($slugColumn) $queryBuilder->expr()->isNull($slugColumn)
) )
) )
->execute(); ->executeQuery()
;
while ($record = $statement->fetch()) { while ($record = $statement->fetch()) {
if (is_array($record) === false) { if (is_array($record) === false) {
@ -97,11 +88,12 @@ class Slugger
->where( ->where(
$queryBuilder->expr()->eq( $queryBuilder->expr()->eq(
'uid', 'uid',
$queryBuilder->createNamedParameter($record['uid'], \PDO::PARAM_INT) $queryBuilder->createNamedParameter($record['uid'], PDO::PARAM_INT)
) )
) )
->set($sluggerType->getSlugColumn(), $slug); ->set($sluggerType->getSlugColumn(), $slug)
$queryBuilder->execute(); ;
$queryBuilder->executeStatement();
} }
private function getSlugHelper( private function getSlugHelper(

View file

@ -23,24 +23,19 @@ declare(strict_types=1);
namespace WerkraumMedia\Events\Service\DestinationDataImportService\Slugger; namespace WerkraumMedia\Events\Service\DestinationDataImportService\Slugger;
use DateTimeImmutable;
use TYPO3\CMS\Core\Database\ConnectionPool; use TYPO3\CMS\Core\Database\ConnectionPool;
class Date implements SluggerType final class Date implements SluggerType
{ {
/**
* @var ConnectionPool
*/
private $connectionPool;
public function __construct( public function __construct(
ConnectionPool $connectionPool private readonly ConnectionPool $connectionPool
) { ) {
$this->connectionPool = $connectionPool;
} }
public function prepareRecordForSlugGeneration(array $record): array public function prepareRecordForSlugGeneration(array $record): array
{ {
$start = new \DateTimeImmutable('@' . $record['start']); $start = new DateTimeImmutable('@' . $record['start']);
$record['event-title'] = $this->getEventTitle((int)$record['event']); $record['event-title'] = $this->getEventTitle((int)$record['event']);
$record['start'] = $start->format('Y-m-d'); $record['start'] = $start->format('Y-m-d');
@ -64,7 +59,7 @@ class Date implements SluggerType
$qb->select('title'); $qb->select('title');
$qb->from('tx_events_domain_model_event'); $qb->from('tx_events_domain_model_event');
$qb->where($qb->expr()->eq('uid', $eventUid)); $qb->where($qb->expr()->eq('uid', $eventUid));
$title = $qb->execute()->fetchOne(); $title = $qb->executeQuery()->fetchOne();
if (is_string($title)) { if (is_string($title)) {
return $title; return $title;
} }

View file

@ -23,7 +23,7 @@ declare(strict_types=1);
namespace WerkraumMedia\Events\Service\DestinationDataImportService\Slugger; namespace WerkraumMedia\Events\Service\DestinationDataImportService\Slugger;
class Event implements SluggerType final class Event implements SluggerType
{ {
public function prepareRecordForSlugGeneration(array $record): array public function prepareRecordForSlugGeneration(array $record): array
{ {

View file

@ -23,17 +23,19 @@ declare(strict_types=1);
namespace WerkraumMedia\Events\Service\DestinationDataImportService\Slugger; namespace WerkraumMedia\Events\Service\DestinationDataImportService\Slugger;
class Registry use Exception;
final class Registry
{ {
/** /**
* @var SluggerType[] * @var SluggerType[]
*/ */
private $sluggers = []; private array $sluggers = [];
public function get(string $tableName): SluggerType public function get(string $tableName): SluggerType
{ {
if (!isset($this->sluggers[$tableName])) { if (!isset($this->sluggers[$tableName])) {
throw new \Exception( throw new Exception(
sprintf( sprintf(
'No slugger registered for table "%s", only for tables: "%s".', 'No slugger registered for table "%s", only for tables: "%s".',
$tableName, $tableName,

View file

@ -1,16 +1,17 @@
<?php <?php
declare(strict_types=1);
namespace WerkraumMedia\Events\Service\DestinationDataImportService; namespace WerkraumMedia\Events\Service\DestinationDataImportService;
use TYPO3\CMS\Core\Http\Uri; use TYPO3\CMS\Core\Http\Uri;
use TYPO3\CMS\Extbase\Configuration\ConfigurationManager; use TYPO3\CMS\Extbase\Configuration\BackendConfigurationManager;
use TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface;
use WerkraumMedia\Events\Domain\Model\Import; use WerkraumMedia\Events\Domain\Model\Import;
/** /**
* Factory to create URLs used during import of Destination Data. * Factory to create URLs used during import of Destination Data.
*/ */
class UrlFactory final class UrlFactory
{ {
/** /**
* @var array * @var array
@ -18,13 +19,12 @@ class UrlFactory
private $settings = []; private $settings = [];
public function __construct( public function __construct(
ConfigurationManager $configurationManager BackendConfigurationManager $configurationManager
) { ) {
$this->settings = $configurationManager->getConfiguration( $this->settings = $configurationManager->getConfiguration(
ConfigurationManagerInterface::CONFIGURATION_TYPE_SETTINGS,
'Events', 'Events',
'Pi1' 'Pi1'
)['destinationData'] ?? []; )['settings']['destinationData'] ?? [];
} }
/** /**

View file

@ -1,54 +0,0 @@
<?php
declare(strict_types=1);
/*
* Copyright (C) 2023 Daniel Siepmann <coding@daniel-siepmann.de>
*
* 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\Testing;
use TYPO3\CMS\Core\SingletonInterface;
use TYPO3\CMS\Core\TypoScript\TemplateService;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\TestingFramework\Core\Functional\Framework\Frontend\Hook\TypoScriptInstructionModifier as Typo3TypoScriptInstructionModifier;
use TYPO3\TestingFramework\Core\Functional\Framework\Frontend\RequestBootstrap;
/**
* Wrap original code to check whether internal request exists.
* It does not exist during import.
*
* No PR upstream as this is probably an unusual use case.
* But we call frontend, import, frontend so have a mix.
*/
class TypoScriptInstructionModifier implements SingletonInterface
{
public function apply(array $parameters, TemplateService $service): void
{
$request = RequestBootstrap::getInternalRequest();
if ($request === null) {
return;
}
GeneralUtility::callUserFunction(
Typo3TypoScriptInstructionModifier::class . '->apply',
$parameters,
$service
);
}
}

View file

@ -26,20 +26,16 @@ namespace WerkraumMedia\Events\Updates;
use Generator; use Generator;
use TYPO3\CMS\Core\Database\Connection; use TYPO3\CMS\Core\Database\Connection;
use TYPO3\CMS\Core\Database\ConnectionPool; use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Install\Attribute\UpgradeWizard;
use TYPO3\CMS\Install\Updates\UpgradeWizardInterface; use TYPO3\CMS\Install\Updates\UpgradeWizardInterface;
use WerkraumMedia\Events\Domain\Model\Location; use WerkraumMedia\Events\Domain\Model\Location;
#[UpgradeWizard(MigrateDuplicateLocations::class)]
final class MigrateDuplicateLocations implements UpgradeWizardInterface final class MigrateDuplicateLocations implements UpgradeWizardInterface
{ {
/**
* @var ConnectionPool
*/
private $connectionPool;
public function __construct( public function __construct(
ConnectionPool $connectionPool private readonly ConnectionPool $connectionPool
) { ) {
$this->connectionPool = $connectionPool;
} }
public function getIdentifier(): string public function getIdentifier(): string
@ -98,11 +94,6 @@ final class MigrateDuplicateLocations implements UpgradeWizardInterface
return []; return [];
} }
public static function register(): void
{
$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install']['update'][self::class] = self::class;
}
/** /**
* @return Generator<array> * @return Generator<array>
*/ */
@ -125,7 +116,7 @@ final class MigrateDuplicateLocations implements UpgradeWizardInterface
); );
$queryBuilder->from('tx_events_domain_model_location'); $queryBuilder->from('tx_events_domain_model_location');
$queryBuilder->orderBy('uid', 'asc'); $queryBuilder->orderBy('uid', 'asc');
$result = $queryBuilder->execute(); $result = $queryBuilder->executeQuery();
foreach ($result->fetchAllAssociative() as $location) { foreach ($result->fetchAllAssociative() as $location) {
yield $location; yield $location;
@ -143,7 +134,7 @@ final class MigrateDuplicateLocations implements UpgradeWizardInterface
$queryBuilder->andWhere($queryBuilder->expr()->neq('uid', $queryBuilder->createNamedParameter($uid))); $queryBuilder->andWhere($queryBuilder->expr()->neq('uid', $queryBuilder->createNamedParameter($uid)));
$queryBuilder->setMaxResults(1); $queryBuilder->setMaxResults(1);
$uid = $queryBuilder->execute()->fetchOne(); $uid = $queryBuilder->executeQuery()->fetchOne();
if (is_numeric($uid) === false) { if (is_numeric($uid) === false) {
return 0; return 0;
} }
@ -175,7 +166,7 @@ final class MigrateDuplicateLocations implements UpgradeWizardInterface
$queryBuilder->set('global_id', $location->getGlobalId()); $queryBuilder->set('global_id', $location->getGlobalId());
$queryBuilder->set('latitude', $location->getLatitude()); $queryBuilder->set('latitude', $location->getLatitude());
$queryBuilder->set('longitude', $location->getLongitude()); $queryBuilder->set('longitude', $location->getLongitude());
$queryBuilder->execute(); $queryBuilder->executeStatement();
} }
/** /**
@ -186,7 +177,7 @@ final class MigrateDuplicateLocations implements UpgradeWizardInterface
$queryBuilder = $this->connectionPool->getQueryBuilderForTable('tx_events_domain_model_location'); $queryBuilder = $this->connectionPool->getQueryBuilderForTable('tx_events_domain_model_location');
$queryBuilder->delete('tx_events_domain_model_location'); $queryBuilder->delete('tx_events_domain_model_location');
$queryBuilder->where($queryBuilder->expr()->in('uid', $queryBuilder->createNamedParameter($uids, Connection::PARAM_INT_ARRAY))); $queryBuilder->where($queryBuilder->expr()->in('uid', $queryBuilder->createNamedParameter($uids, Connection::PARAM_INT_ARRAY)));
$queryBuilder->execute(); $queryBuilder->executeStatement();
} }
private function updateRelations(array $migration): void private function updateRelations(array $migration): void
@ -198,7 +189,7 @@ final class MigrateDuplicateLocations implements UpgradeWizardInterface
$finalBuilder = clone $queryBuilder; $finalBuilder = clone $queryBuilder;
$finalBuilder->where($finalBuilder->expr()->eq('location', $finalBuilder->createNamedParameter($legacyLocationUid))); $finalBuilder->where($finalBuilder->expr()->eq('location', $finalBuilder->createNamedParameter($legacyLocationUid)));
$finalBuilder->set('location', $newLocationUid); $finalBuilder->set('location', $newLocationUid);
$finalBuilder->execute(); $finalBuilder->executeStatement();
} }
} }
} }

View file

@ -23,43 +23,28 @@ declare(strict_types=1);
namespace WerkraumMedia\Events\Updates; namespace WerkraumMedia\Events\Updates;
use Exception;
use TYPO3\CMS\Core\Database\ConnectionPool; use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\Database\Query\QueryBuilder; use TYPO3\CMS\Core\Database\Query\QueryBuilder;
use TYPO3\CMS\Core\DataHandling\DataHandler; use TYPO3\CMS\Core\DataHandling\DataHandler;
use TYPO3\CMS\Core\Log\Logger; use TYPO3\CMS\Core\Log\Logger;
use TYPO3\CMS\Core\Log\LogManager; use TYPO3\CMS\Core\Log\LogManager;
use TYPO3\CMS\Install\Attribute\UpgradeWizard;
use TYPO3\CMS\Install\Updates\DatabaseUpdatedPrerequisite; use TYPO3\CMS\Install\Updates\DatabaseUpdatedPrerequisite;
use TYPO3\CMS\Install\Updates\UpgradeWizardInterface; use TYPO3\CMS\Install\Updates\UpgradeWizardInterface;
#[UpgradeWizard(MigrateOldLocations::class)]
class MigrateOldLocations implements UpgradeWizardInterface class MigrateOldLocations implements UpgradeWizardInterface
{ {
/** private readonly Logger $logger;
* @var ConnectionPool
*/
private $connectionPool;
/** private array $uidsForTranslation = [];
* @var DataHandler
*/
private $dataHandler;
/**
* @var Logger
*/
private $logger;
/**
* @var array
*/
private $uidsForTranslation = [];
public function __construct( public function __construct(
ConnectionPool $connectionPool, private readonly ConnectionPool $connectionPool,
DataHandler $dataHandler, private readonly DataHandler $dataHandler,
LogManager $logManager LogManager $logManager
) { ) {
$this->connectionPool = $connectionPool;
$this->dataHandler = $dataHandler;
$this->logger = $logManager->getLogger(self::class); $this->logger = $logManager->getLogger(self::class);
} }
@ -76,16 +61,12 @@ class MigrateOldLocations implements UpgradeWizardInterface
public function updateNecessary(): bool public function updateNecessary(): bool
{ {
return $this->hasOldColumns() return $this->hasOldColumns()
&& $this->getQueryBuilder() && $this->getQueryBuilder()->count('*')->executeQuery()->fetchOne() > 0;
->count('*')
->execute()
->fetchOne() > 0
;
} }
public function executeUpdate(): bool public function executeUpdate(): bool
{ {
$result = $this->getQueryBuilder()->execute(); $result = $this->getQueryBuilder()->executeQuery()->iterateAssociative();
foreach ($result as $eventRecord) { foreach ($result as $eventRecord) {
$this->logger->info('Updating event record.', ['record' => $eventRecord]); $this->logger->info('Updating event record.', ['record' => $eventRecord]);
$eventRecord['location'] = $this->getLocationUid($eventRecord); $eventRecord['location'] = $this->getLocationUid($eventRecord);
@ -127,7 +108,7 @@ class MigrateOldLocations implements UpgradeWizardInterface
$qb->andWhere($qb->expr()->eq($column, $qb->createNamedParameter($event[$column]))); $qb->andWhere($qb->expr()->eq($column, $qb->createNamedParameter($event[$column])));
} }
$uids = $qb->execute()->fetchAssociative(); $uids = $qb->executeQuery()->fetchAssociative();
if (is_bool($uids)) { if (is_bool($uids)) {
return 0; return 0;
} }
@ -203,7 +184,7 @@ class MigrateOldLocations implements UpgradeWizardInterface
return $l10nParentUid; return $l10nParentUid;
} }
throw new \Exception('Could not create location: ' . implode(', ', $dataHandler->errorLog), 1672916613); throw new Exception('Could not create location: ' . implode(', ', $dataHandler->errorLog), 1672916613);
} }
private function updateEvent(array $event): void private function updateEvent(array $event): void
@ -255,7 +236,8 @@ class MigrateOldLocations implements UpgradeWizardInterface
->getConnectionForTable('tx_events_domain_model_event') ->getConnectionForTable('tx_events_domain_model_event')
->getSchemaManager() ->getSchemaManager()
->createSchema() ->createSchema()
->getTable('tx_events_domain_model_event'); ->getTable('tx_events_domain_model_event')
;
foreach ($this->columnsToFetch() as $column) { foreach ($this->columnsToFetch() as $column) {
if ($schema->hasColumn($column) === false) { if ($schema->hasColumn($column) === false) {
@ -283,9 +265,4 @@ class MigrateOldLocations implements UpgradeWizardInterface
'longitude', 'longitude',
]; ];
} }
public static function register(): void
{
$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install']['update'][self::class] = self::class;
}
} }

View file

@ -2,8 +2,10 @@
declare(strict_types=1); declare(strict_types=1);
use WerkraumMedia\Events\Domain\Model\Category;
return [ return [
\WerkraumMedia\Events\Domain\Model\Category::class => [ Category::class => [
'tableName' => 'sys_category', 'tableName' => 'sys_category',
], ],
]; ];

View file

@ -48,3 +48,6 @@ services:
- name: event.listener - name: event.listener
event: WerkraumMedia\Events\Events\Controller\DateListVariables event: WerkraumMedia\Events\Events\Controller\DateListVariables
method: 'trackDates' method: 'trackDates'
- name: event.listener
event: TYPO3\CMS\Frontend\Event\ModifyCacheLifetimeForPageEvent
method: 'modifyCacheLifetimeForPage'

View file

@ -1,11 +1,16 @@
<?php <?php
declare(strict_types=1);
use TYPO3\CMS\Core\Utility\ArrayUtility;
use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
defined('TYPO3') or die(); defined('TYPO3') or die();
(static function (string $extensionKey, string $tableName) { (static function (string $extensionKey, string $tableName) {
$languagePath = 'LLL:EXT:events/Resources/Private/Language/locallang_db.xlf:' . $tableName; $languagePath = 'LLL:EXT:events/Resources/Private/Language/locallang_db.xlf:' . $tableName;
\TYPO3\CMS\Core\Utility\ArrayUtility::mergeRecursiveWithOverrule($GLOBALS['TCA'][$tableName], [ ArrayUtility::mergeRecursiveWithOverrule($GLOBALS['TCA'][$tableName], [
'ctrl' => [ 'ctrl' => [
'typeicon_classes' => [ 'typeicon_classes' => [
'contains-events' => 'pages-module-events', 'contains-events' => 'pages-module-events',
@ -13,13 +18,13 @@ defined('TYPO3') or die();
], ],
]); ]);
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addTcaSelectItem( ExtensionManagementUtility::addTcaSelectItem(
$tableName, $tableName,
'module', 'module',
[ [
0 => $languagePath . '.module.events', 'label' => $languagePath . '.module.events',
1 => 'events', 'value' => 'events',
2 => 'pages-module-events', 'icon' => 'pages-module-events',
] ]
); );
})('events', 'pages'); })('events', 'pages');

View file

@ -1,7 +1,11 @@
<?php <?php
declare(strict_types=1);
use TYPO3\CMS\Core\Utility\ArrayUtility;
(function (string $extKey, string $table) { (function (string $extKey, string $table) {
\TYPO3\CMS\Core\Utility\ArrayUtility::mergeRecursiveWithOverrule($GLOBALS['TCA'][$table], [ ArrayUtility::mergeRecursiveWithOverrule($GLOBALS['TCA'][$table], [
'columns' => [ 'columns' => [
'sorting' => [ 'sorting' => [
'config' => [ 'config' => [

View file

@ -1,9 +1,13 @@
<?php <?php
declare(strict_types=1);
use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
defined('TYPO3') or die(); defined('TYPO3') or die();
(static function (string $extensionKey, string $tableName) { (static function (string $extensionKey, string $tableName) {
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addStaticFile( ExtensionManagementUtility::addStaticFile(
$extensionKey, $extensionKey,
'Configuration/TypoScript', 'Configuration/TypoScript',
'Events' 'Events'

View file

@ -1,54 +1,59 @@
<?php <?php
declare(strict_types=1);
use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
use TYPO3\CMS\Extbase\Utility\ExtensionUtility;
(function (string $extKey, string $table) { (function (string $extKey, string $table) {
/* Search Plugin */ /* Search Plugin */
\TYPO3\CMS\Extbase\Utility\ExtensionUtility::registerPlugin( ExtensionUtility::registerPlugin(
'Events', 'Events',
'DateSearch', 'DateSearch',
'Events: Date Search', 'Events: Date Search',
'EXT:events/Resources/Public/Icons/Extension.svg' 'EXT:events/Resources/Public/Icons/Extension.svg'
); );
$GLOBALS['TCA'][$table]['types']['list']['subtypes_addlist']['events_datesearch'] = 'pi_flexform'; $GLOBALS['TCA'][$table]['types']['list']['subtypes_addlist']['events_datesearch'] = 'pi_flexform';
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addPiFlexFormValue( ExtensionManagementUtility::addPiFlexFormValue(
'events_datesearch', 'events_datesearch',
'FILE:EXT:events/Configuration/FlexForms/DateSearch.xml' 'FILE:EXT:events/Configuration/FlexForms/DateSearch.xml'
); );
/* Date List Plugin */ /* Date List Plugin */
\TYPO3\CMS\Extbase\Utility\ExtensionUtility::registerPlugin( ExtensionUtility::registerPlugin(
'Events', 'Events',
'DateList', 'DateList',
'Events: Date List', 'Events: Date List',
'EXT:events/Resources/Public/Icons/Extension.svg' 'EXT:events/Resources/Public/Icons/Extension.svg'
); );
$GLOBALS['TCA'][$table]['types']['list']['subtypes_addlist']['events_datelist'] = 'pi_flexform'; $GLOBALS['TCA'][$table]['types']['list']['subtypes_addlist']['events_datelist'] = 'pi_flexform';
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addPiFlexFormValue( ExtensionManagementUtility::addPiFlexFormValue(
'events_datelist', 'events_datelist',
'FILE:EXT:events/Configuration/FlexForms/DateList.xml' 'FILE:EXT:events/Configuration/FlexForms/DateList.xml'
); );
/* Date Show Plugin */ /* Date Show Plugin */
\TYPO3\CMS\Extbase\Utility\ExtensionUtility::registerPlugin( ExtensionUtility::registerPlugin(
'Events', 'Events',
'DateShow', 'DateShow',
'Events: Date Show', 'Events: Date Show',
'EXT:events/Resources/Public/Icons/Extension.svg' 'EXT:events/Resources/Public/Icons/Extension.svg'
); );
$GLOBALS['TCA'][$table]['types']['list']['subtypes_addlist']['events_dateshow'] = 'pi_flexform'; $GLOBALS['TCA'][$table]['types']['list']['subtypes_addlist']['events_dateshow'] = 'pi_flexform';
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addPiFlexFormValue( ExtensionManagementUtility::addPiFlexFormValue(
'events_dateshow', 'events_dateshow',
'FILE:EXT:events/Configuration/FlexForms/DateShow.xml' 'FILE:EXT:events/Configuration/FlexForms/DateShow.xml'
); );
/* Event Selected Plugin */ /* Event Selected Plugin */
\TYPO3\CMS\Extbase\Utility\ExtensionUtility::registerPlugin( ExtensionUtility::registerPlugin(
'Events', 'Events',
'Selected', 'Selected',
'Events: Show selected', 'Events: Show selected',
'EXT:events/Resources/Public/Icons/Extension.svg' 'EXT:events/Resources/Public/Icons/Extension.svg'
); );
$GLOBALS['TCA'][$table]['types']['list']['subtypes_addlist']['events_selected'] = 'pi_flexform'; $GLOBALS['TCA'][$table]['types']['list']['subtypes_addlist']['events_selected'] = 'pi_flexform';
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addPiFlexFormValue( ExtensionManagementUtility::addPiFlexFormValue(
'events_selected', 'events_selected',
'FILE:EXT:events/Configuration/FlexForms/Selected.xml' 'FILE:EXT:events/Configuration/FlexForms/Selected.xml'
); );

View file

@ -1,29 +0,0 @@
<?php
(function (string $extKey, string $table) {
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::makeCategorizable(
$extKey,
$table,
'categories',
[
'label' => 'Categories',
'fieldConfiguration' => [
'minitems' => 0,
'multiple' => true,
],
]
);
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::makeCategorizable(
$extKey,
$table,
'features',
[
'label' => 'Features',
'fieldConfiguration' => [
'minitems' => 0,
'multiple' => true,
],
]
);
})('events', 'tx_events_domain_model_event');

View file

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
return [ return [
'ctrl' => [ 'ctrl' => [
'title' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_date.xlf:tx_events_domain_model_date', 'title' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_date.xlf:tx_events_domain_model_date',
@ -8,7 +10,6 @@ return [
'label_alt_force' => true, 'label_alt_force' => true,
'tstamp' => 'tstamp', 'tstamp' => 'tstamp',
'crdate' => 'crdate', 'crdate' => 'crdate',
'cruser_id' => 'cruser_id',
'versioningWS' => true, 'versioningWS' => true,
'languageField' => 'sys_language_uid', 'languageField' => 'sys_language_uid',
'transOrigPointerField' => 'l10n_parent', 'transOrigPointerField' => 'l10n_parent',
@ -29,19 +30,7 @@ return [
'sys_language_uid' => [ 'sys_language_uid' => [
'exclude' => true, 'exclude' => true,
'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.language', 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.language',
'config' => [ 'config' => ['type' => 'language'],
'type' => 'select',
'renderType' => 'selectSingle',
'special' => 'languages',
'items' => [
[
'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.allLanguages',
-1,
'flags-multiple',
],
],
'default' => 0,
],
], ],
'l10n_parent' => [ 'l10n_parent' => [
'displayCond' => 'FIELD:sys_language_uid:>:0', 'displayCond' => 'FIELD:sys_language_uid:>:0',
@ -51,7 +40,7 @@ return [
'renderType' => 'selectSingle', 'renderType' => 'selectSingle',
'default' => 0, 'default' => 0,
'items' => [ 'items' => [
['', 0], ['label' => '', 'value' => 0],
], ],
'foreign_table' => 'tx_events_domain_model_date', 'foreign_table' => 'tx_events_domain_model_date',
'foreign_table_where' => 'AND {#tx_events_domain_model_date}.{#pid}=###CURRENT_PID### AND {#tx_events_domain_model_date}.{#sys_language_uid} IN (-1,0)', 'foreign_table_where' => 'AND {#tx_events_domain_model_date}.{#pid}=###CURRENT_PID### AND {#tx_events_domain_model_date}.{#sys_language_uid} IN (-1,0)',
@ -78,8 +67,7 @@ return [
'renderType' => 'checkboxToggle', 'renderType' => 'checkboxToggle',
'items' => [ 'items' => [
[ [
0 => '', 'label' => '',
1 => '',
'invertStateDisplay' => true, 'invertStateDisplay' => true,
], ],
], ],
@ -89,10 +77,8 @@ return [
'exclude' => true, 'exclude' => true,
'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.starttime', 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.starttime',
'config' => [ 'config' => [
'type' => 'input', 'type' => 'datetime',
'renderType' => 'inputDateTime', 'format' => 'datetime',
'eval' => 'datetime,int',
'default' => 0,
'behaviour' => [ 'behaviour' => [
'allowLanguageSynchronization' => true, 'allowLanguageSynchronization' => true,
], ],
@ -102,13 +88,8 @@ return [
'exclude' => true, 'exclude' => true,
'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.endtime', 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.endtime',
'config' => [ 'config' => [
'type' => 'input', 'type' => 'datetime',
'renderType' => 'inputDateTime', 'format' => 'datetime',
'eval' => 'datetime,int',
'default' => 0,
'range' => [
'upper' => mktime(0, 0, 0, 1, 1, 2038),
],
'behaviour' => [ 'behaviour' => [
'allowLanguageSynchronization' => true, 'allowLanguageSynchronization' => true,
], ],
@ -119,11 +100,9 @@ return [
'exclude' => true, 'exclude' => true,
'label' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_date.xlf:tx_events_domain_model_date.start', 'label' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_date.xlf:tx_events_domain_model_date.start',
'config' => [ 'config' => [
//'dbType' => 'datetime', 'type' => 'datetime',
'type' => 'input', 'format' => 'datetime',
'renderType' => 'inputDateTime',
'size' => 12, 'size' => 12,
'eval' => 'datetime',
'default' => null, 'default' => null,
], ],
], ],
@ -131,11 +110,9 @@ return [
'exclude' => true, 'exclude' => true,
'label' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_date.xlf:tx_events_domain_model_date.end', 'label' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_date.xlf:tx_events_domain_model_date.end',
'config' => [ 'config' => [
//'dbType' => 'datetime', 'type' => 'datetime',
'type' => 'input', 'format' => 'datetime',
'renderType' => 'inputDateTime',
'size' => 12, 'size' => 12,
'eval' => 'datetime',
'default' => null, 'default' => null,
], ],
], ],
@ -148,16 +125,16 @@ return [
'default' => 'no', 'default' => 'no',
'items' => [ 'items' => [
'0' => [ '0' => [
'0' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_date.xlf:tx_events_domain_model_date.canceled.options.no', 'label' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_date.xlf:tx_events_domain_model_date.canceled.options.no',
'1' => 'no', 'value' => 'no',
], ],
'1' => [ '1' => [
'0' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_date.xlf:tx_events_domain_model_date.canceled.options.canceled', 'label' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_date.xlf:tx_events_domain_model_date.canceled.options.canceled',
'1' => 'canceled', 'value' => 'canceled',
], ],
'2' => [ '2' => [
'0' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_date.xlf:tx_events_domain_model_date.canceled.options.postponed', 'label' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_date.xlf:tx_events_domain_model_date.canceled.options.postponed',
'1' => 'postponed', 'value' => 'postponed',
], ],
], ],
], ],
@ -174,8 +151,8 @@ return [
'default' => '0', 'default' => '0',
'items' => [ 'items' => [
'0' => [ '0' => [
'0' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_date.xlf:tx_events_domain_model_date.postponed_date.0', 'label' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_date.xlf:tx_events_domain_model_date.postponed_date.0',
'1' => '0', 'value' => '0',
], ],
], ],
], ],
@ -185,18 +162,7 @@ return [
'label' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_date.xlf:tx_events_domain_model_date.canceled_link', 'label' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_date.xlf:tx_events_domain_model_date.canceled_link',
'displayCond' => 'FIELD:canceled:=:canceled', 'displayCond' => 'FIELD:canceled:=:canceled',
'config' => [ 'config' => [
'type' => 'input', 'type' => 'link',
'softref' => 'typolink',
'renderType' => 'inputLink',
'max' => 1024,
'eval' => 'trim',
'fieldControl' => [
'linkPopup' => [
'options' => [
'title' => 'LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:header_link_formlabel',
],
],
],
], ],
], ],
'slug' => [ 'slug' => [

View file

@ -1,7 +1,11 @@
<?php <?php
declare(strict_types=1);
use TYPO3\CMS\Core\Resource\File;
$l10nPathGeneral = 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf'; $l10nPathGeneral = 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf';
$l10nPathLang = 'LLL:EXT:lang/locallang_core.xlf'; $l10nPathLang = 'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf';
$l10nPathFE = 'LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf'; $l10nPathFE = 'LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf';
$l10nPath = 'LLL:EXT:events/Resources/Private/Language/locallang_csh_event.xlf'; $l10nPath = 'LLL:EXT:events/Resources/Private/Language/locallang_csh_event.xlf';
$l10nLocationPath = 'LLL:EXT:events/Resources/Private/Language/locallang_csh_location.xlf'; $l10nLocationPath = 'LLL:EXT:events/Resources/Private/Language/locallang_csh_location.xlf';
@ -12,7 +16,6 @@ return [
'label' => 'title', 'label' => 'title',
'tstamp' => 'tstamp', 'tstamp' => 'tstamp',
'crdate' => 'crdate', 'crdate' => 'crdate',
'cruser_id' => 'cruser_id',
'versioningWS' => true, 'versioningWS' => true,
'languageField' => 'sys_language_uid', 'languageField' => 'sys_language_uid',
'transOrigPointerField' => 'l10n_parent', 'transOrigPointerField' => 'l10n_parent',
@ -78,19 +81,7 @@ return [
'sys_language_uid' => [ 'sys_language_uid' => [
'exclude' => true, 'exclude' => true,
'label' => $l10nPathGeneral . ':LGL.language', 'label' => $l10nPathGeneral . ':LGL.language',
'config' => [ 'config' => ['type' => 'language'],
'type' => 'select',
'renderType' => 'selectSingle',
'special' => 'languages',
'items' => [
[
$l10nPathGeneral . ':LGL.allLanguages',
-1,
'flags-multiple',
],
],
'default' => 0,
],
], ],
'l10n_parent' => [ 'l10n_parent' => [
'displayCond' => 'FIELD:sys_language_uid:>:0', 'displayCond' => 'FIELD:sys_language_uid:>:0',
@ -100,7 +91,7 @@ return [
'renderType' => 'selectSingle', 'renderType' => 'selectSingle',
'default' => 0, 'default' => 0,
'items' => [ 'items' => [
['', 0], ['label' => '', 'value' => 0],
], ],
'foreign_table' => 'tx_events_domain_model_event', 'foreign_table' => 'tx_events_domain_model_event',
'foreign_table_where' => 'AND {#tx_events_domain_model_event}.{#pid}=###CURRENT_PID### AND {#tx_events_domain_model_event}.{#sys_language_uid} IN (-1,0)', 'foreign_table_where' => 'AND {#tx_events_domain_model_event}.{#pid}=###CURRENT_PID### AND {#tx_events_domain_model_event}.{#sys_language_uid} IN (-1,0)',
@ -127,8 +118,7 @@ return [
'renderType' => 'checkboxToggle', 'renderType' => 'checkboxToggle',
'items' => [ 'items' => [
[ [
0 => '', 'label' => '',
1 => '',
'invertStateDisplay' => true, 'invertStateDisplay' => true,
], ],
], ],
@ -138,10 +128,8 @@ return [
'exclude' => true, 'exclude' => true,
'label' => $l10nPathGeneral . ':LGL.starttime', 'label' => $l10nPathGeneral . ':LGL.starttime',
'config' => [ 'config' => [
'type' => 'input', 'type' => 'datetime',
'renderType' => 'inputDateTime', 'format' => 'datetime',
'eval' => 'datetime,int',
'default' => 0,
'behaviour' => [ 'behaviour' => [
'allowLanguageSynchronization' => true, 'allowLanguageSynchronization' => true,
], ],
@ -151,13 +139,8 @@ return [
'exclude' => true, 'exclude' => true,
'label' => $l10nPathGeneral . ':LGL.endtime', 'label' => $l10nPathGeneral . ':LGL.endtime',
'config' => [ 'config' => [
'type' => 'input', 'type' => 'datetime',
'renderType' => 'inputDateTime', 'format' => 'datetime',
'eval' => 'datetime,int',
'default' => 0,
'range' => [
'upper' => mktime(0, 0, 0, 1, 1, 2038),
],
'behaviour' => [ 'behaviour' => [
'allowLanguageSynchronization' => true, 'allowLanguageSynchronization' => true,
], ],
@ -205,9 +188,7 @@ return [
'exclude' => true, 'exclude' => true,
'label' => $l10nPath . ':tx_events_domain_model_event.source_url', 'label' => $l10nPath . ':tx_events_domain_model_event.source_url',
'config' => [ 'config' => [
'type' => 'input', 'type' => 'link',
'renderType' => 'inputLink',
'softref' => 'typolink',
'readOnly' => true, 'readOnly' => true,
], ],
], ],
@ -235,8 +216,7 @@ return [
'renderType' => 'checkboxToggle', 'renderType' => 'checkboxToggle',
'items' => [ 'items' => [
[ [
0 => '', 'label' => '',
1 => '',
'invertStateDisplay' => false, 'invertStateDisplay' => false,
], ],
], ],
@ -293,12 +273,8 @@ return [
'exclude' => true, 'exclude' => true,
'label' => $l10nPath . ':tx_events_domain_model_event.ticket', 'label' => $l10nPath . ':tx_events_domain_model_event.ticket',
'config' => [ 'config' => [
'type' => 'input', 'type' => 'link',
'renderType' => 'inputLink',
'eval' => 'trim',
'max' => 1024,
'size' => 50, 'size' => 50,
'softref' => 'typolink',
], ],
], ],
'facebook' => [ 'facebook' => [
@ -331,57 +307,27 @@ return [
'images' => [ 'images' => [
'exclude' => true, 'exclude' => true,
'label' => $l10nPath . ':tx_events_domain_model_event.images', 'label' => $l10nPath . ':tx_events_domain_model_event.images',
'config' => \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::getFileFieldTCAConfig( 'config' => [
'images', 'type' => 'file',
[ 'maxitems' => 8,
'appearance' => [ 'allowed' => 'common-image-types',
'createNewRelationLinkTitle' => $l10nPathFE . ':images.addFileReference', // custom configuration for displaying fields in the overlay/reference table
'showPossibleLocalizationRecords' => true, // to use the imageoverlayPalette instead of the basicoverlayPalette
'showRemovedLocalizationRecords' => true, 'overrideChildTca' => [
'showAllLocalizationLink' => true, 'types' => [
'showSynchronizationLink' => true,
],
'foreign_match_fields' => [
'fieldname' => 'images',
'tablenames' => 'tx_events_domain_model_event',
'table_local' => 'sys_file',
],
'foreign_types' => [
'0' => [ '0' => [
'showitem' => ' 'showitem' => '
--palette--;' . $l10nPathFE . ':sys_file_reference.imageoverlayPalette;imageoverlayPalette, --palette--;;imageoverlayPalette,
--palette--;;filePalette', --palette--;;filePalette',
], ],
\TYPO3\CMS\Core\Resource\File::FILETYPE_TEXT => [ File::FILETYPE_IMAGE => [
'showitem' => ' 'showitem' => '
--palette--;' . $l10nPathFE . ':sys_file_reference.imageoverlayPalette;imageoverlayPalette, --palette--;;imageoverlayPalette,
--palette--;;filePalette', --palette--;;filePalette',
],
\TYPO3\CMS\Core\Resource\File::FILETYPE_IMAGE => [
'showitem' => '
--palette--;' . $l10nPathFE . ':sys_file_reference.imageoverlayPalette;imageoverlayPalette,
--palette--;;filePalette',
],
\TYPO3\CMS\Core\Resource\File::FILETYPE_AUDIO => [
'showitem' => '
--palette--;' . $l10nPathFE . ':sys_file_reference.imageoverlayPalette;imageoverlayPalette,
--palette--;;filePalette',
],
\TYPO3\CMS\Core\Resource\File::FILETYPE_VIDEO => [
'showitem' => '
--palette--;' . $l10nPathFE . ':sys_file_reference.imageoverlayPalette;imageoverlayPalette,
--palette--;;filePalette',
],
\TYPO3\CMS\Core\Resource\File::FILETYPE_APPLICATION => [
'showitem' => '
--palette--;' . $l10nPathFE . ':sys_file_reference.imageoverlayPalette;imageoverlayPalette,
--palette--;;filePalette',
], ],
], ],
'maxitems' => 8,
], ],
$GLOBALS['TYPO3_CONF_VARS']['GFX']['imagefile_ext'] ],
),
], ],
'pages' => [ 'pages' => [
@ -389,16 +335,27 @@ return [
'label' => $l10nPath . ':tx_events_domain_model_event.pages', 'label' => $l10nPath . ':tx_events_domain_model_event.pages',
'config' => [ 'config' => [
'type' => 'group', 'type' => 'group',
'internal_type' => 'db',
'allowed' => 'pages', 'allowed' => 'pages',
], ],
], ],
'categories' => [ 'categories' => [
'exclude' => true, 'exclude' => true,
'label' => 'Categories',
'config' => [
'type' => 'category',
'minitems' => 0,
'multiple' => true,
],
], ],
'features' => [ 'features' => [
'exclude' => true, 'exclude' => true,
'label' => 'Features',
'config' => [
'type' => 'category',
'minitems' => 0,
'multiple' => true,
],
], ],
'dates' => [ 'dates' => [
@ -424,7 +381,6 @@ return [
], ],
'levelLinksPosition' => 'top', 'levelLinksPosition' => 'top',
'showPossibleLocalizationRecords' => false, 'showPossibleLocalizationRecords' => false,
'showRemovedLocalizationRecords' => false,
'showSynchronizationLink' => false, 'showSynchronizationLink' => false,
'showAllLocalizationLink' => false, 'showAllLocalizationLink' => false,
], ],
@ -475,7 +431,6 @@ return [
'label' => $l10nPath . ':tx_events_domain_model_event.references_events', 'label' => $l10nPath . ':tx_events_domain_model_event.references_events',
'config' => [ 'config' => [
'type' => 'group', 'type' => 'group',
'internal_type' => 'db',
'allowed' => 'tx_events_domain_model_event', 'allowed' => 'tx_events_domain_model_event',
'suggestOptions' => [ 'suggestOptions' => [
'tx_events_domain_model_event' => [ 'tx_events_domain_model_event' => [
@ -490,7 +445,6 @@ return [
'label' => $l10nPath . ':tx_events_domain_model_event.partner', 'label' => $l10nPath . ':tx_events_domain_model_event.partner',
'config' => [ 'config' => [
'type' => 'group', 'type' => 'group',
'internal_type' => 'db',
'allowed' => 'tx_events_domain_model_partner', 'allowed' => 'tx_events_domain_model_partner',
'fieldControl' => [ 'fieldControl' => [
'addRecord' => [ 'addRecord' => [

View file

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
return [ return [
'ctrl' => [ 'ctrl' => [
'title' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_import.xlf:tx_events_domain_model_import', 'title' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_import.xlf:tx_events_domain_model_import',
@ -8,7 +10,6 @@ return [
'label_alt_force' => true, 'label_alt_force' => true,
'tstamp' => 'tstamp', 'tstamp' => 'tstamp',
'crdate' => 'crdate', 'crdate' => 'crdate',
'cruser_id' => 'cruser_id',
'delete' => 'deleted', 'delete' => 'deleted',
'enablecolumns' => [ 'enablecolumns' => [
'disabled' => 'hidden', 'disabled' => 'hidden',
@ -48,8 +49,7 @@ return [
'renderType' => 'checkboxToggle', 'renderType' => 'checkboxToggle',
'items' => [ 'items' => [
[ [
0 => '', 'label' => '',
1 => '',
'invertStateDisplay' => true, 'invertStateDisplay' => true,
], ],
], ],
@ -72,7 +72,6 @@ return [
'description' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_import.xlf:tx_events_domain_model_import.storage_pid.description', 'description' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_import.xlf:tx_events_domain_model_import.storage_pid.description',
'config' => [ 'config' => [
'type' => 'group', 'type' => 'group',
'internal_type' => 'db',
'allowed' => 'pages', 'allowed' => 'pages',
'size' => 1, 'size' => 1,
'maxitems' => 1, 'maxitems' => 1,
@ -84,7 +83,6 @@ return [
'label' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_import.xlf:tx_events_domain_model_import.region', 'label' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_import.xlf:tx_events_domain_model_import.region',
'config' => [ 'config' => [
'type' => 'group', 'type' => 'group',
'internal_type' => 'db',
'allowed' => 'tx_events_domain_model_region', 'allowed' => 'tx_events_domain_model_region',
'size' => 1, 'size' => 1,
'maxitems' => 1, 'maxitems' => 1,
@ -97,7 +95,6 @@ return [
'description' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_import.xlf:tx_events_domain_model_import.categories_pid.description', 'description' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_import.xlf:tx_events_domain_model_import.categories_pid.description',
'config' => [ 'config' => [
'type' => 'group', 'type' => 'group',
'internal_type' => 'db',
'allowed' => 'pages', 'allowed' => 'pages',
'size' => 1, 'size' => 1,
'maxitems' => 1, 'maxitems' => 1,
@ -110,7 +107,6 @@ return [
'description' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_import.xlf:tx_events_domain_model_import.category_parent.description', 'description' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_import.xlf:tx_events_domain_model_import.category_parent.description',
'config' => [ 'config' => [
'type' => 'group', 'type' => 'group',
'internal_type' => 'db',
'allowed' => 'sys_category', 'allowed' => 'sys_category',
'size' => 1, 'size' => 1,
'maxitems' => 1, 'maxitems' => 1,
@ -123,7 +119,6 @@ return [
'description' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_import.xlf:tx_events_domain_model_import.features_pid.description', 'description' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_import.xlf:tx_events_domain_model_import.features_pid.description',
'config' => [ 'config' => [
'type' => 'group', 'type' => 'group',
'internal_type' => 'db',
'allowed' => 'pages', 'allowed' => 'pages',
'size' => 1, 'size' => 1,
'maxitems' => 1, 'maxitems' => 1,
@ -136,7 +131,6 @@ return [
'description' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_import.xlf:tx_events_domain_model_import.features_parent.description', 'description' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_import.xlf:tx_events_domain_model_import.features_parent.description',
'config' => [ 'config' => [
'type' => 'group', 'type' => 'group',
'internal_type' => 'db',
'allowed' => 'sys_category', 'allowed' => 'sys_category',
'size' => 1, 'size' => 1,
'maxitems' => 1, 'maxitems' => 1,
@ -148,8 +142,7 @@ return [
'label' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_import.xlf:tx_events_domain_model_import.files_folder', 'label' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_import.xlf:tx_events_domain_model_import.files_folder',
'description' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_import.xlf:tx_events_domain_model_import.files_folder.description', 'description' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_import.xlf:tx_events_domain_model_import.files_folder.description',
'config' => [ 'config' => [
'type' => 'group', 'type' => 'folder',
'internal_type' => 'folder',
'size' => 1, 'size' => 1,
'maxitems' => 1, 'maxitems' => 1,
'minitems' => 1, 'minitems' => 1,

View file

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
$l10nPathGeneral = 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf'; $l10nPathGeneral = 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf';
$l10nPath = 'LLL:EXT:events/Resources/Private/Language/locallang_csh_location.xlf'; $l10nPath = 'LLL:EXT:events/Resources/Private/Language/locallang_csh_location.xlf';
@ -9,7 +11,6 @@ return [
'label' => 'name', 'label' => 'name',
'tstamp' => 'tstamp', 'tstamp' => 'tstamp',
'crdate' => 'crdate', 'crdate' => 'crdate',
'cruser_id' => 'cruser_id',
'versioningWS' => true, 'versioningWS' => true,
'languageField' => 'sys_language_uid', 'languageField' => 'sys_language_uid',
'transOrigPointerField' => 'l10n_parent', 'transOrigPointerField' => 'l10n_parent',
@ -50,19 +51,7 @@ return [
'sys_language_uid' => [ 'sys_language_uid' => [
'exclude' => true, 'exclude' => true,
'label' => $l10nPathGeneral . ':LGL.language', 'label' => $l10nPathGeneral . ':LGL.language',
'config' => [ 'config' => ['type' => 'language'],
'type' => 'select',
'renderType' => 'selectSingle',
'special' => 'languages',
'items' => [
[
$l10nPathGeneral . ':LGL.allLanguages',
-1,
'flags-multiple',
],
],
'default' => 0,
],
], ],
'l10n_parent' => [ 'l10n_parent' => [
'displayCond' => 'FIELD:sys_language_uid:>:0', 'displayCond' => 'FIELD:sys_language_uid:>:0',
@ -72,7 +61,7 @@ return [
'renderType' => 'selectSingle', 'renderType' => 'selectSingle',
'default' => 0, 'default' => 0,
'items' => [ 'items' => [
['', 0], ['label' => '', 'value' => 0],
], ],
'foreign_table' => 'tx_events_domain_model_location', 'foreign_table' => 'tx_events_domain_model_location',
'foreign_table_where' => 'AND {#tx_events_domain_model_location}.{#pid}=###CURRENT_PID### AND {#tx_events_domain_model_location}.{#sys_language_uid} IN (-1,0)', 'foreign_table_where' => 'AND {#tx_events_domain_model_location}.{#pid}=###CURRENT_PID### AND {#tx_events_domain_model_location}.{#sys_language_uid} IN (-1,0)',
@ -99,8 +88,7 @@ return [
'renderType' => 'checkboxToggle', 'renderType' => 'checkboxToggle',
'items' => [ 'items' => [
[ [
0 => '', 'label' => '',
1 => '',
'invertStateDisplay' => true, 'invertStateDisplay' => true,
], ],
], ],
@ -110,10 +98,8 @@ return [
'exclude' => true, 'exclude' => true,
'label' => $l10nPathGeneral . ':LGL.starttime', 'label' => $l10nPathGeneral . ':LGL.starttime',
'config' => [ 'config' => [
'type' => 'input', 'type' => 'datetime',
'renderType' => 'inputDateTime', 'format' => 'datetime',
'eval' => 'datetime,int',
'default' => 0,
'behaviour' => [ 'behaviour' => [
'allowLanguageSynchronization' => true, 'allowLanguageSynchronization' => true,
], ],
@ -123,13 +109,8 @@ return [
'exclude' => true, 'exclude' => true,
'label' => $l10nPathGeneral . ':LGL.endtime', 'label' => $l10nPathGeneral . ':LGL.endtime',
'config' => [ 'config' => [
'type' => 'input', 'type' => 'datetime',
'renderType' => 'inputDateTime', 'format' => 'datetime',
'eval' => 'datetime,int',
'default' => 0,
'range' => [
'upper' => mktime(0, 0, 0, 1, 1, 2038),
],
'behaviour' => [ 'behaviour' => [
'allowLanguageSynchronization' => true, 'allowLanguageSynchronization' => true,
], ],

View file

@ -1,12 +1,13 @@
<?php <?php
declare(strict_types=1);
return [ return [
'ctrl' => [ 'ctrl' => [
'title' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_organizer.xlf:tx_events_domain_model_organizer', 'title' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_organizer.xlf:tx_events_domain_model_organizer',
'label' => 'name', 'label' => 'name',
'tstamp' => 'tstamp', 'tstamp' => 'tstamp',
'crdate' => 'crdate', 'crdate' => 'crdate',
'cruser_id' => 'cruser_id',
'versioningWS' => true, 'versioningWS' => true,
'languageField' => 'sys_language_uid', 'languageField' => 'sys_language_uid',
'transOrigPointerField' => 'l10n_parent', 'transOrigPointerField' => 'l10n_parent',
@ -27,19 +28,7 @@ return [
'sys_language_uid' => [ 'sys_language_uid' => [
'exclude' => true, 'exclude' => true,
'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.language', 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.language',
'config' => [ 'config' => ['type' => 'language'],
'type' => 'select',
'renderType' => 'selectSingle',
'special' => 'languages',
'items' => [
[
'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.allLanguages',
-1,
'flags-multiple',
],
],
'default' => 0,
],
], ],
'l10n_parent' => [ 'l10n_parent' => [
'displayCond' => 'FIELD:sys_language_uid:>:0', 'displayCond' => 'FIELD:sys_language_uid:>:0',
@ -49,7 +38,7 @@ return [
'renderType' => 'selectSingle', 'renderType' => 'selectSingle',
'default' => 0, 'default' => 0,
'items' => [ 'items' => [
['', 0], ['label' => '', 'value' => 0],
], ],
'foreign_table' => 'tx_events_domain_model_organizer', 'foreign_table' => 'tx_events_domain_model_organizer',
'foreign_table_where' => 'AND {#tx_events_domain_model_organizer}.{#pid}=###CURRENT_PID### AND {#tx_events_domain_model_organizer}.{#sys_language_uid} IN (-1,0)', 'foreign_table_where' => 'AND {#tx_events_domain_model_organizer}.{#pid}=###CURRENT_PID### AND {#tx_events_domain_model_organizer}.{#sys_language_uid} IN (-1,0)',
@ -76,8 +65,7 @@ return [
'renderType' => 'checkboxToggle', 'renderType' => 'checkboxToggle',
'items' => [ 'items' => [
[ [
0 => '', 'label' => '',
1 => '',
'invertStateDisplay' => true, 'invertStateDisplay' => true,
], ],
], ],
@ -87,10 +75,8 @@ return [
'exclude' => true, 'exclude' => true,
'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.starttime', 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.starttime',
'config' => [ 'config' => [
'type' => 'input', 'type' => 'datetime',
'renderType' => 'inputDateTime', 'format' => 'datetime',
'eval' => 'datetime,int',
'default' => 0,
'behaviour' => [ 'behaviour' => [
'allowLanguageSynchronization' => true, 'allowLanguageSynchronization' => true,
], ],
@ -100,13 +86,8 @@ return [
'exclude' => true, 'exclude' => true,
'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.endtime', 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.endtime',
'config' => [ 'config' => [
'type' => 'input', 'type' => 'datetime',
'renderType' => 'inputDateTime', 'format' => 'datetime',
'eval' => 'datetime,int',
'default' => 0,
'range' => [
'upper' => mktime(0, 0, 0, 1, 1, 2038),
],
'behaviour' => [ 'behaviour' => [
'allowLanguageSynchronization' => true, 'allowLanguageSynchronization' => true,
], ],

View file

@ -1,12 +1,15 @@
<?php <?php
declare(strict_types=1);
use TYPO3\CMS\Core\Resource\File;
return [ return [
'ctrl' => [ 'ctrl' => [
'title' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_partner.xlf:tx_events_domain_model_partner', 'title' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_partner.xlf:tx_events_domain_model_partner',
'label' => 'title', 'label' => 'title',
'tstamp' => 'tstamp', 'tstamp' => 'tstamp',
'crdate' => 'crdate', 'crdate' => 'crdate',
'cruser_id' => 'cruser_id',
'versioningWS' => true, 'versioningWS' => true,
'languageField' => 'sys_language_uid', 'languageField' => 'sys_language_uid',
'transOrigPointerField' => 'l10n_parent', 'transOrigPointerField' => 'l10n_parent',
@ -25,19 +28,7 @@ return [
'sys_language_uid' => [ 'sys_language_uid' => [
'exclude' => true, 'exclude' => true,
'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.language', 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.language',
'config' => [ 'config' => ['type' => 'language'],
'type' => 'select',
'renderType' => 'selectSingle',
'special' => 'languages',
'items' => [
[
'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.allLanguages',
-1,
'flags-multiple',
],
],
'default' => 0,
],
], ],
'l10n_parent' => [ 'l10n_parent' => [
'displayCond' => 'FIELD:sys_language_uid:>:0', 'displayCond' => 'FIELD:sys_language_uid:>:0',
@ -47,7 +38,7 @@ return [
'renderType' => 'selectSingle', 'renderType' => 'selectSingle',
'default' => 0, 'default' => 0,
'items' => [ 'items' => [
['', 0], ['label' => '', 'value' => 0],
], ],
'foreign_table' => 'tx_events_domain_model_partner', 'foreign_table' => 'tx_events_domain_model_partner',
'foreign_table_where' => 'AND {#tx_events_domain_model_partner}.{#pid}=###CURRENT_PID### AND {#tx_events_domain_model_partner}.{#sys_language_uid} IN (-1,0)', 'foreign_table_where' => 'AND {#tx_events_domain_model_partner}.{#pid}=###CURRENT_PID### AND {#tx_events_domain_model_partner}.{#sys_language_uid} IN (-1,0)',
@ -74,8 +65,7 @@ return [
'renderType' => 'checkboxToggle', 'renderType' => 'checkboxToggle',
'items' => [ 'items' => [
[ [
0 => '', 'label' => '',
1 => '',
'invertStateDisplay' => true, 'invertStateDisplay' => true,
], ],
], ],
@ -95,21 +85,15 @@ return [
'exclude' => true, 'exclude' => true,
'label' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_partner.xlf:tx_events_domain_model_partner.link', 'label' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_partner.xlf:tx_events_domain_model_partner.link',
'config' => [ 'config' => [
'type' => 'input', 'type' => 'link',
'renderType' => 'inputLink',
'eval' => 'trim',
'max' => 1024,
'size' => 50,
'softref' => 'typolink',
], ],
], ],
'images' => [ 'images' => [
'exclude' => true, 'exclude' => true,
'label' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_partner.xlf:tx_events_domain_model_partner.images', 'label' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_partner.xlf:tx_events_domain_model_partner.images',
'config' => \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::getFileFieldTCAConfig('images', [ 'config' => [
'appearance' => [ 'type' => 'file',
'createNewRelationLinkTitle' => 'LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:images.addFileReference', 'allowed' => 'common-image-types',
],
// custom configuration for displaying fields in the overlay/reference table // custom configuration for displaying fields in the overlay/reference table
// to use the imageoverlayPalette instead of the basicoverlayPalette // to use the imageoverlayPalette instead of the basicoverlayPalette
'overrideChildTca' => [ 'overrideChildTca' => [
@ -119,14 +103,14 @@ return [
--palette--;;imageoverlayPalette, --palette--;;imageoverlayPalette,
--palette--;;filePalette', --palette--;;filePalette',
], ],
\TYPO3\CMS\Core\Resource\File::FILETYPE_IMAGE => [ File::FILETYPE_IMAGE => [
'showitem' => ' 'showitem' => '
--palette--;;imageoverlayPalette, --palette--;;imageoverlayPalette,
--palette--;;filePalette', --palette--;;filePalette',
], ],
], ],
], ],
], $GLOBALS['TYPO3_CONF_VARS']['GFX']['imagefile_ext']), ],
], ],
], ],
]; ];

View file

@ -1,12 +1,13 @@
<?php <?php
declare(strict_types=1);
return [ return [
'ctrl' => [ 'ctrl' => [
'title' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_region.xlf:tx_events_domain_model_region', 'title' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_region.xlf:tx_events_domain_model_region',
'label' => 'title', 'label' => 'title',
'tstamp' => 'tstamp', 'tstamp' => 'tstamp',
'crdate' => 'crdate', 'crdate' => 'crdate',
'cruser_id' => 'cruser_id',
'versioningWS' => true, 'versioningWS' => true,
'languageField' => 'sys_language_uid', 'languageField' => 'sys_language_uid',
'transOrigPointerField' => 'l10n_parent', 'transOrigPointerField' => 'l10n_parent',
@ -27,19 +28,7 @@ return [
'sys_language_uid' => [ 'sys_language_uid' => [
'exclude' => true, 'exclude' => true,
'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.language', 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.language',
'config' => [ 'config' => ['type' => 'language'],
'type' => 'select',
'renderType' => 'selectSingle',
'special' => 'languages',
'items' => [
[
'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.allLanguages',
-1,
'flags-multiple',
],
],
'default' => 0,
],
], ],
'l10n_parent' => [ 'l10n_parent' => [
'displayCond' => 'FIELD:sys_language_uid:>:0', 'displayCond' => 'FIELD:sys_language_uid:>:0',
@ -49,7 +38,7 @@ return [
'renderType' => 'selectSingle', 'renderType' => 'selectSingle',
'default' => 0, 'default' => 0,
'items' => [ 'items' => [
['', 0], ['label' => '', 'value' => 0],
], ],
'foreign_table' => 'tx_events_domain_model_region', 'foreign_table' => 'tx_events_domain_model_region',
'foreign_table_where' => 'AND {#tx_events_domain_model_region}.{#pid}=###CURRENT_PID### AND {#tx_events_domain_model_region}.{#sys_language_uid} IN (-1,0)', 'foreign_table_where' => 'AND {#tx_events_domain_model_region}.{#pid}=###CURRENT_PID### AND {#tx_events_domain_model_region}.{#sys_language_uid} IN (-1,0)',
@ -76,8 +65,7 @@ return [
'renderType' => 'checkboxToggle', 'renderType' => 'checkboxToggle',
'items' => [ 'items' => [
[ [
0 => '', 'label' => '',
1 => '',
'invertStateDisplay' => true, 'invertStateDisplay' => true,
], ],
], ],
@ -87,10 +75,8 @@ return [
'exclude' => true, 'exclude' => true,
'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.starttime', 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.starttime',
'config' => [ 'config' => [
'type' => 'input', 'type' => 'datetime',
'renderType' => 'inputDateTime', 'format' => 'datetime',
'eval' => 'datetime,int',
'default' => 0,
'behaviour' => [ 'behaviour' => [
'allowLanguageSynchronization' => true, 'allowLanguageSynchronization' => true,
], ],
@ -100,13 +86,8 @@ return [
'exclude' => true, 'exclude' => true,
'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.endtime', 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.endtime',
'config' => [ 'config' => [
'type' => 'input', 'type' => 'datetime',
'renderType' => 'inputDateTime', 'format' => 'datetime',
'eval' => 'datetime,int',
'default' => 0,
'range' => [
'upper' => mktime(0, 0, 0, 1, 1, 2038),
],
'behaviour' => [ 'behaviour' => [
'allowLanguageSynchronization' => true, 'allowLanguageSynchronization' => true,
], ],

View file

@ -24,10 +24,6 @@ plugin.tx_events {
recursive = 1 recursive = 1
} }
features {
skipDefaultArguments = 1
}
mvc { mvc {
callDefaultActionIfActionCantBeResolved = 1 callDefaultActionIfActionCantBeResolved = 1
} }

View file

@ -4,6 +4,11 @@
Breaking Breaking
-------- --------
* Drop support of TYPO3 and PHP versions.
We drop support for any TYPO3 version below 12.
We drop support for PHP versions not supported by TYPO3 v12.
That eases the maintenance of the extension.
* Change of vendor/namespace. * Change of vendor/namespace.
The vendor was renamed from `wrm` to `werkraummedia`. The vendor was renamed from `wrm` to `werkraummedia`.
And the namespace vendor was renamed from `Wrm` to `WerkraumMedia`. And the namespace vendor was renamed from `Wrm` to `WerkraumMedia`.
@ -11,10 +16,15 @@ Breaking
That way all references to PHP classes as well as the package name itself need to That way all references to PHP classes as well as the package name itself need to
be adjusted. be adjusted.
* No longer allow records on standard pages.
Please use TCA Overrides in case you need this none default TYPO3 behaviour.
Features Features
-------- --------
Nothing * Support TYPO3 v12.
* Support PHP 8.1, 8.2, 8.3.
Fixes Fixes
----- -----

View file

@ -42,7 +42,6 @@ Table of Contents
Commands Commands
Settings Settings
Changelog Changelog
Maintenance
.. toctree:: .. toctree::
:hidden: :hidden:

View file

@ -1,16 +0,0 @@
.. _maintenance:
Maintenance
===========
List of changes that need to be done for maintenance reasons.
E.g. changes once we drop a certain TYPO3 version.
We might have new code backported for compatibility in older TYPO3 versions.
Those changes are documented so we know what to do once we drop an older version.
.. toctree::
:glob:
:reversed:
Maintenance/TYPO3/*

View file

@ -1,17 +0,0 @@
TYPO3 V10
=========
Changes that should happen once we drop TYPO3 v10.
Remove fetching cached page stage from body from tests
------------------------------------------------------
We have different assertions based on TYPO3 version, due to how TYPO3 exposes the info.
We can remove the condition with its content once we drop v10.
Remove condition for page not found handling
--------------------------------------------
The :php:`AbstractController->trigger404()` method has a condition to handle 404 differently for TYPO3 v10.
The condition can be removed.

View file

@ -1,12 +0,0 @@
TYPO3 V11
=========
Changes that should happen once we drop TYPO3 v11.
Remove ``SlidingWindowPagination`` backport.
--------------------------------------------
We backported https://docs.typo3.org/c/typo3/cms-core/main/en-us/Changelog/12.0/Feature-94625-IntroduceSlidingWindowPagination.html.
That allowed us to use the new Code compatible with v12 onwards.
We should remove the file ``Classes/Backports/V12/Pagination/SlidingWindowPagination.php`` and switch to TYPO3 native class within ``WerkraumMedia\Events\Pagination\Factory``.

View file

@ -0,0 +1,30 @@
Issue: https://github.com/TYPO3/testing-framework/issues/517
PR: https://github.com/TYPO3/testing-framework/pull/518
diff --git a/Classes/Core/Functional/Framework/FrameworkState.php b/Classes/Core/Functional/Framework/FrameworkState.php
index 93716fc..f900539 100644
--- a/Classes/Core/Functional/Framework/FrameworkState.php
+++ b/Classes/Core/Functional/Framework/FrameworkState.php
@@ -50,6 +50,7 @@ class FrameworkState
// different. And code that runs after that within the test scope may fail (eg. the referenceIndex check in tearDown() that
// relies on TCA). So we back up TCA for now before executing frontend tests.
$state['globals-tca'] = $GLOBALS['TCA'];
+ $state['request'] = $GLOBALS['TYPO3_REQUEST'] ?? null;
// Can be dropped when GeneralUtility::getIndpEnv() is abandoned
$generalUtilityReflection = new \ReflectionClass(GeneralUtility::class);
@@ -67,6 +68,7 @@ class FrameworkState
public static function reset()
{
unset($GLOBALS['BE_USER']);
+ unset($GLOBALS['TYPO3_REQUEST']);
$generalUtilityReflection = new \ReflectionClass(GeneralUtility::class);
$generalUtilityIndpEnvCache = $generalUtilityReflection->getProperty('indpEnvCache');
@@ -91,6 +93,7 @@ class FrameworkState
}
$GLOBALS['TCA'] = $state['globals-tca'];
+ $GLOBALS['TYPO3_REQUEST'] = $state['request'];
$generalUtilityReflection = new \ReflectionClass(GeneralUtility::class);
$generalUtilityIndpEnvCache = $generalUtilityReflection->getProperty('indpEnvCache');

View file

@ -0,0 +1,18 @@
Use "same" value for tstamp and crdate.
Otherwise TYPO3 will have different cache identifier if multiple requests with same instruction are given.
diff --git a/Resources/Core/Functional/Extensions/json_response/Classes/EventListener/AddTypoScriptFromInternalRequest.php b/Resources/Core/Functional/Extensions/json_response/Classes/EventListener/AddTypoScriptFromInternalRequest.php
index 111a997..504a899 100644
--- a/Resources/Core/Functional/Extensions/json_response/Classes/EventListener/AddTypoScriptFromInternalRequest.php
+++ b/Resources/Core/Functional/Extensions/json_response/Classes/EventListener/AddTypoScriptFromInternalRequest.php
@@ -49,8 +49,8 @@ final class AddTypoScriptFromInternalRequest
$newTemplateRow = [
'uid' => PHP_INT_MAX,
'pid' => PHP_INT_MAX,
- 'tstamp' => time(),
- 'crdate' => time(),
+ 'tstamp' => (new \DateTimeImmutable('midnight'))->format('U'),
+ 'crdate' => (new \DateTimeImmutable('midnight'))->format('U'),
'deleted' => 0,
'starttime' => 0,
'endtime' => 0,

View file

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
namespace WerkraumMedia\Events\Tests; namespace WerkraumMedia\Events\Tests;
use GuzzleHttp\Client; use GuzzleHttp\Client;

View file

@ -30,16 +30,16 @@ use Psr\Http\Client\ClientInterface;
use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Tester\CommandTester; use Symfony\Component\Console\Tester\CommandTester;
use Symfony\Component\DependencyInjection\Container; use Symfony\Component\DependencyInjection\Container;
use TypeError;
use TYPO3\CMS\Core\Context\Context; use TYPO3\CMS\Core\Context\Context;
use TYPO3\CMS\Core\Context\DateTimeAspect; use TYPO3\CMS\Core\Context\DateTimeAspect;
use TYPO3\CMS\Core\Localization\LanguageServiceFactory; use TYPO3\CMS\Core\Localization\LanguageServiceFactory;
use TYPO3\CMS\Core\TypoScript\TemplateService;
use TYPO3\CMS\Core\Utility\ArrayUtility; use TYPO3\CMS\Core\Utility\ArrayUtility;
use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\TestingFramework\Core\Functional\Framework\Frontend\Internal\TypoScriptInstruction; use TYPO3\TestingFramework\Core\Functional\Framework\Frontend\Internal\TypoScriptInstruction;
use TYPO3\TestingFramework\Core\Functional\FunctionalTestCase; use TYPO3\TestingFramework\Core\Functional\FunctionalTestCase;
use UnexpectedValueException;
use WerkraumMedia\Events\Command\ImportDestinationDataViaConfigruationCommand; use WerkraumMedia\Events\Command\ImportDestinationDataViaConfigruationCommand;
use WerkraumMedia\Events\Testing\TypoScriptInstructionModifier;
use WerkraumMedia\Events\Tests\ClientFactory; use WerkraumMedia\Events\Tests\ClientFactory;
abstract class AbstractFunctionalTestCase extends FunctionalTestCase abstract class AbstractFunctionalTestCase extends FunctionalTestCase
@ -55,18 +55,21 @@ abstract class AbstractFunctionalTestCase extends FunctionalTestCase
protected function setUp(): void protected function setUp(): void
{ {
$this->coreExtensionsToLoad = array_merge($this->coreExtensionsToLoad, [ $this->coreExtensionsToLoad = [
...$this->coreExtensionsToLoad,
'filelist', 'filelist',
'fluid_styled_content', 'fluid_styled_content',
]); ];
$this->testExtensionsToLoad = array_merge($this->testExtensionsToLoad, [ $this->testExtensionsToLoad = [
...$this->testExtensionsToLoad,
'typo3conf/ext/events', 'typo3conf/ext/events',
]); ];
$this->pathsToProvideInTestInstance = array_merge($this->pathsToProvideInTestInstance, [ $this->pathsToLinkInTestInstance = [
...$this->pathsToLinkInTestInstance,
'typo3conf/ext/events/Tests/Functional/Frontend/Fixtures/Sites/' => 'typo3conf/sites', 'typo3conf/ext/events/Tests/Functional/Frontend/Fixtures/Sites/' => 'typo3conf/sites',
]); ];
ArrayUtility::mergeRecursiveWithOverrule($this->configurationToUseInTestInstance, [ ArrayUtility::mergeRecursiveWithOverrule($this->configurationToUseInTestInstance, [
'FE' => [ 'FE' => [
@ -80,22 +83,16 @@ abstract class AbstractFunctionalTestCase extends FunctionalTestCase
'processor_path_lzw' => '/usr/bin/', 'processor_path_lzw' => '/usr/bin/',
'processor' => 'ImageMagick', 'processor' => 'ImageMagick',
], ],
'SC_OPTIONS' => [
'Core/TypoScript/TemplateService' => [
'runThroughTemplatesPostProcessing' => [
'FunctionalTest' => TypoScriptInstructionModifier::class . '->apply',
],
],
],
]); ]);
parent::setUp(); parent::setUp();
$this->setUpBackendUserFromFixture(1); $this->importPHPDataSet(__DIR__ . '/Fixtures/BeUsers.php');
$this->setUpBackendUser(1);
$languageServiceFactory = $this->getContainer()->get(LanguageServiceFactory::class); $languageServiceFactory = $this->getContainer()->get(LanguageServiceFactory::class);
if (!$languageServiceFactory instanceof LanguageServiceFactory) { if (!$languageServiceFactory instanceof LanguageServiceFactory) {
throw new \UnexpectedValueException('Did not retrieve LanguageServiceFactory.', 1637847250); throw new UnexpectedValueException('Did not retrieve LanguageServiceFactory.', 1637847250);
} }
$GLOBALS['LANG'] = $languageServiceFactory->create('default'); $GLOBALS['LANG'] = $languageServiceFactory->create('default');
@ -114,7 +111,7 @@ abstract class AbstractFunctionalTestCase extends FunctionalTestCase
protected function getTypoScriptInstruction(): TypoScriptInstruction protected function getTypoScriptInstruction(): TypoScriptInstruction
{ {
return new TypoScriptInstruction(TemplateService::class); return new TypoScriptInstruction();
} }
protected function setUpConfiguration( protected function setUpConfiguration(
@ -152,7 +149,7 @@ abstract class AbstractFunctionalTestCase extends FunctionalTestCase
array $argumentsAndOptions = ['configurationUid' => '1'], array $argumentsAndOptions = ['configurationUid' => '1'],
string $command = ImportDestinationDataViaConfigruationCommand::class string $command = ImportDestinationDataViaConfigruationCommand::class
): CommandTester { ): CommandTester {
$subject = $this->getContainer()->get($command); $subject = $this->get($command);
self::assertInstanceOf(Command::class, $subject); self::assertInstanceOf(Command::class, $subject);
$tester = new CommandTester($subject); $tester = new CommandTester($subject);
@ -192,7 +189,7 @@ abstract class AbstractFunctionalTestCase extends FunctionalTestCase
{ {
$context = $this->getContainer()->get(Context::class); $context = $this->getContainer()->get(Context::class);
if (!$context instanceof Context) { if (!$context instanceof Context) {
throw new \TypeError('Retrieved context was of unexpected type.', 1638182021); throw new TypeError('Retrieved context was of unexpected type.', 1638182021);
} }
$aspect = new DateTimeAspect($dateTime); $aspect = new DateTimeAspect($dateTime);

View file

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
return [ return [
'pages' => [ 'pages' => [
[ [
@ -45,7 +47,6 @@ return [
'pid' => '0', 'pid' => '0',
'tstamp' => '1423209858', 'tstamp' => '1423209858',
'crdate' => '1370878372', 'crdate' => '1370878372',
'cruser_id' => '0',
'deleted' => '0', 'deleted' => '0',
'name' => 'fileadmin/ (auto-created)', 'name' => 'fileadmin/ (auto-created)',
'description' => 'This is the local fileadmin/ directory. This storage mount has been created automatically by TYPO3.', 'description' => 'This is the local fileadmin/ directory. This storage mount has been created automatically by TYPO3.',
@ -126,7 +127,6 @@ return [
'pid' => '0', 'pid' => '0',
'tstamp' => '1371467047', 'tstamp' => '1371467047',
'crdate' => '1371467047', 'crdate' => '1371467047',
'cruser_id' => '1',
'file' => '1', 'file' => '1',
], ],
[ [
@ -134,7 +134,6 @@ return [
'pid' => '0', 'pid' => '0',
'tstamp' => '1371467047', 'tstamp' => '1371467047',
'crdate' => '1371467047', 'crdate' => '1371467047',
'cruser_id' => '1',
'file' => '2', 'file' => '2',
], ],
], ],
@ -144,7 +143,6 @@ return [
'pid' => '2', 'pid' => '2',
'tstamp' => '1373537480', 'tstamp' => '1373537480',
'crdate' => '1371484347', 'crdate' => '1371484347',
'cruser_id' => '1',
'deleted' => '0', 'deleted' => '0',
'hidden' => '0', 'hidden' => '0',
'sys_language_uid' => '0', 'sys_language_uid' => '0',
@ -153,14 +151,12 @@ return [
'tablenames' => 'tx_events_domain_model_event', 'tablenames' => 'tx_events_domain_model_event',
'fieldname' => 'images', 'fieldname' => 'images',
'sorting_foreign' => '1', 'sorting_foreign' => '1',
'table_local' => 'sys_file',
], ],
[ [
'uid' => '2', 'uid' => '2',
'pid' => '2', 'pid' => '2',
'tstamp' => '1373537480', 'tstamp' => '1373537480',
'crdate' => '1371484347', 'crdate' => '1371484347',
'cruser_id' => '1',
'deleted' => '0', 'deleted' => '0',
'hidden' => '0', 'hidden' => '0',
'sys_language_uid' => '0', 'sys_language_uid' => '0',
@ -169,7 +165,6 @@ return [
'tablenames' => 'tx_events_domain_model_partner', 'tablenames' => 'tx_events_domain_model_partner',
'fieldname' => 'images', 'fieldname' => 'images',
'sorting_foreign' => '1', 'sorting_foreign' => '1',
'table_local' => 'sys_file',
], ],
], ],
'tx_events_domain_model_region' => [ 'tx_events_domain_model_region' => [

View file

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
return [ return [
'pages' => [ 'pages' => [
[ [
@ -51,7 +53,6 @@ return [
'pid' => '0', 'pid' => '0',
'tstamp' => '1423209858', 'tstamp' => '1423209858',
'crdate' => '1370878372', 'crdate' => '1370878372',
'cruser_id' => '0',
'deleted' => '0', 'deleted' => '0',
'name' => 'fileadmin/ (auto-created)', 'name' => 'fileadmin/ (auto-created)',
'description' => 'This is the local fileadmin/ directory. This storage mount has been created automatically by TYPO3.', 'description' => 'This is the local fileadmin/ directory. This storage mount has been created automatically by TYPO3.',
@ -212,7 +213,6 @@ return [
'pid' => '0', 'pid' => '0',
'tstamp' => '1371467047', 'tstamp' => '1371467047',
'crdate' => '1371467047', 'crdate' => '1371467047',
'cruser_id' => '1',
'file' => '1', 'file' => '1',
], ],
[ [
@ -220,7 +220,6 @@ return [
'pid' => '0', 'pid' => '0',
'tstamp' => '1371467047', 'tstamp' => '1371467047',
'crdate' => '1371467047', 'crdate' => '1371467047',
'cruser_id' => '1',
'file' => '2', 'file' => '2',
], ],
[ [
@ -228,7 +227,6 @@ return [
'pid' => '0', 'pid' => '0',
'tstamp' => '1371467047', 'tstamp' => '1371467047',
'crdate' => '1371467047', 'crdate' => '1371467047',
'cruser_id' => '1',
'file' => '3', 'file' => '3',
], ],
[ [
@ -236,7 +234,6 @@ return [
'pid' => '0', 'pid' => '0',
'tstamp' => '1371467047', 'tstamp' => '1371467047',
'crdate' => '1371467047', 'crdate' => '1371467047',
'cruser_id' => '1',
'file' => '4', 'file' => '4',
], ],
[ [
@ -244,7 +241,6 @@ return [
'pid' => '0', 'pid' => '0',
'tstamp' => '1371467047', 'tstamp' => '1371467047',
'crdate' => '1371467047', 'crdate' => '1371467047',
'cruser_id' => '1',
'file' => '5', 'file' => '5',
], ],
[ [
@ -252,7 +248,6 @@ return [
'pid' => '0', 'pid' => '0',
'tstamp' => '1371467047', 'tstamp' => '1371467047',
'crdate' => '1371467047', 'crdate' => '1371467047',
'cruser_id' => '1',
'file' => '6', 'file' => '6',
], ],
], ],
@ -262,7 +257,6 @@ return [
'pid' => '2', 'pid' => '2',
'tstamp' => '1373537480', 'tstamp' => '1373537480',
'crdate' => '1371484347', 'crdate' => '1371484347',
'cruser_id' => '1',
'deleted' => '0', 'deleted' => '0',
'hidden' => '0', 'hidden' => '0',
'sys_language_uid' => '0', 'sys_language_uid' => '0',
@ -271,14 +265,12 @@ return [
'tablenames' => 'tx_events_domain_model_event', 'tablenames' => 'tx_events_domain_model_event',
'fieldname' => 'images', 'fieldname' => 'images',
'sorting_foreign' => '1', 'sorting_foreign' => '1',
'table_local' => 'sys_file',
], ],
[ [
'uid' => '2', 'uid' => '2',
'pid' => '2', 'pid' => '2',
'tstamp' => '1373537480', 'tstamp' => '1373537480',
'crdate' => '1371484347', 'crdate' => '1371484347',
'cruser_id' => '1',
'deleted' => '0', 'deleted' => '0',
'hidden' => '0', 'hidden' => '0',
'sys_language_uid' => '0', 'sys_language_uid' => '0',
@ -287,14 +279,12 @@ return [
'tablenames' => 'tx_events_domain_model_partner', 'tablenames' => 'tx_events_domain_model_partner',
'fieldname' => 'images', 'fieldname' => 'images',
'sorting_foreign' => '1', 'sorting_foreign' => '1',
'table_local' => 'sys_file',
], ],
[ [
'uid' => '3', 'uid' => '3',
'pid' => '2', 'pid' => '2',
'tstamp' => '1373537480', 'tstamp' => '1373537480',
'crdate' => '1371484347', 'crdate' => '1371484347',
'cruser_id' => '1',
'deleted' => '0', 'deleted' => '0',
'hidden' => '0', 'hidden' => '0',
'sys_language_uid' => '0', 'sys_language_uid' => '0',
@ -303,14 +293,12 @@ return [
'tablenames' => 'tx_events_domain_model_event', 'tablenames' => 'tx_events_domain_model_event',
'fieldname' => 'images', 'fieldname' => 'images',
'sorting_foreign' => '1', 'sorting_foreign' => '1',
'table_local' => 'sys_file',
], ],
[ [
'uid' => '4', 'uid' => '4',
'pid' => '2', 'pid' => '2',
'tstamp' => '1373537480', 'tstamp' => '1373537480',
'crdate' => '1371484347', 'crdate' => '1371484347',
'cruser_id' => '1',
'deleted' => '1', 'deleted' => '1',
'hidden' => '0', 'hidden' => '0',
'sys_language_uid' => '0', 'sys_language_uid' => '0',
@ -319,14 +307,12 @@ return [
'tablenames' => 'tt_content', 'tablenames' => 'tt_content',
'fieldname' => 'images', 'fieldname' => 'images',
'sorting_foreign' => '1', 'sorting_foreign' => '1',
'table_local' => 'sys_file',
], ],
[ [
'uid' => '5', 'uid' => '5',
'pid' => '2', 'pid' => '2',
'tstamp' => '1373537480', 'tstamp' => '1373537480',
'crdate' => '1371484347', 'crdate' => '1371484347',
'cruser_id' => '1',
'deleted' => '0', 'deleted' => '0',
'hidden' => '0', 'hidden' => '0',
'sys_language_uid' => '0', 'sys_language_uid' => '0',
@ -335,14 +321,12 @@ return [
'tablenames' => 'tx_events_domain_model_event', 'tablenames' => 'tx_events_domain_model_event',
'fieldname' => 'images', 'fieldname' => 'images',
'sorting_foreign' => '1', 'sorting_foreign' => '1',
'table_local' => 'sys_file',
], ],
[ [
'uid' => '6', 'uid' => '6',
'pid' => '2', 'pid' => '2',
'tstamp' => '1373537480', 'tstamp' => '1373537480',
'crdate' => '1371484347', 'crdate' => '1371484347',
'cruser_id' => '1',
'deleted' => '0', 'deleted' => '0',
'hidden' => '0', 'hidden' => '0',
'sys_language_uid' => '0', 'sys_language_uid' => '0',
@ -351,14 +335,12 @@ return [
'tablenames' => '', 'tablenames' => '',
'fieldname' => '', 'fieldname' => '',
'sorting_foreign' => '0', 'sorting_foreign' => '0',
'table_local' => 'sys_file',
], ],
[ [
'uid' => '7', 'uid' => '7',
'pid' => '0', 'pid' => '0',
'tstamp' => '1373537480', 'tstamp' => '1373537480',
'crdate' => '1371484347', 'crdate' => '1371484347',
'cruser_id' => '1',
'deleted' => '0', 'deleted' => '0',
'hidden' => '0', 'hidden' => '0',
'sys_language_uid' => '0', 'sys_language_uid' => '0',
@ -367,14 +349,12 @@ return [
'tablenames' => 'pages', 'tablenames' => 'pages',
'fieldname' => 'media', 'fieldname' => 'media',
'sorting_foreign' => '0', 'sorting_foreign' => '0',
'table_local' => 'sys_file',
], ],
[ [
'uid' => '8', 'uid' => '8',
'pid' => '0', 'pid' => '0',
'tstamp' => '1373537480', 'tstamp' => '1373537480',
'crdate' => '1371484347', 'crdate' => '1371484347',
'cruser_id' => '1',
'deleted' => '0', 'deleted' => '0',
'hidden' => '0', 'hidden' => '0',
'sys_language_uid' => '0', 'sys_language_uid' => '0',
@ -383,7 +363,6 @@ return [
'tablenames' => 'tx_events_domain_model_event', 'tablenames' => 'tx_events_domain_model_event',
'fieldname' => 'images', 'fieldname' => 'images',
'sorting_foreign' => '2', 'sorting_foreign' => '2',
'table_local' => 'sys_file',
], ],
], ],
'tx_events_domain_model_region' => [ 'tx_events_domain_model_region' => [

View file

@ -1,16 +1,18 @@
<?php <?php
declare(strict_types=1);
namespace WerkraumMedia\Events\Tests\Functional\Cleanup; namespace WerkraumMedia\Events\Tests\Functional\Cleanup;
use PHPUnit\Framework\Attributes\Test;
use PHPUnit\Framework\Attributes\TestDox;
use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Tester\CommandTester; use Symfony\Component\Console\Tester\CommandTester;
use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Core\Utility\GeneralUtility;
use WerkraumMedia\Events\Command\RemoveAllCommand; use WerkraumMedia\Events\Command\RemoveAllCommand;
use WerkraumMedia\Events\Tests\Functional\AbstractFunctionalTestCase; use WerkraumMedia\Events\Tests\Functional\AbstractFunctionalTestCase;
/** #[TestDox('Cleanup RemoveAll')]
* @testdox Cleanup RemoveAll
*/
class RemoveAllTest extends AbstractFunctionalTestCase class RemoveAllTest extends AbstractFunctionalTestCase
{ {
protected function setUp(): void protected function setUp(): void
@ -22,9 +24,7 @@ class RemoveAllTest extends AbstractFunctionalTestCase
parent::setUp(); parent::setUp();
} }
/** #[Test]
* @test
*/
public function removesAllData(): void public function removesAllData(): void
{ {
$this->importPHPDataSet(__DIR__ . '/Fixtures/RemoveAllTestDatabase.php'); $this->importPHPDataSet(__DIR__ . '/Fixtures/RemoveAllTestDatabase.php');

View file

@ -1,16 +1,18 @@
<?php <?php
declare(strict_types=1);
namespace WerkraumMedia\Events\Tests\Functional\Cleanup; namespace WerkraumMedia\Events\Tests\Functional\Cleanup;
use PHPUnit\Framework\Attributes\Test;
use PHPUnit\Framework\Attributes\TestDox;
use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Tester\CommandTester; use Symfony\Component\Console\Tester\CommandTester;
use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Core\Utility\GeneralUtility;
use WerkraumMedia\Events\Command\RemovePastCommand; use WerkraumMedia\Events\Command\RemovePastCommand;
use WerkraumMedia\Events\Tests\Functional\AbstractFunctionalTestCase; use WerkraumMedia\Events\Tests\Functional\AbstractFunctionalTestCase;
/** #[TestDox('Cleanup RemovePast')]
* @testdox Cleanup RemovePast
*/
class RemovePastTest extends AbstractFunctionalTestCase class RemovePastTest extends AbstractFunctionalTestCase
{ {
protected function setUp(): void protected function setUp(): void
@ -22,9 +24,7 @@ class RemovePastTest extends AbstractFunctionalTestCase
parent::setUp(); parent::setUp();
} }
/** #[Test]
* @test
*/
public function removesPastData(): void public function removesPastData(): void
{ {
$this->importPHPDataSet(__DIR__ . '/Fixtures/RemovePastTestDatabase.php'); $this->importPHPDataSet(__DIR__ . '/Fixtures/RemovePastTestDatabase.php');

View file

@ -0,0 +1,19 @@
<?php
declare(strict_types=1);
return [
'be_users' => [
[
'uid' => 1,
'pid' => 0,
'tstamp' => 1366642540,
'username' => 'admin',
'password' => '$1$tCrlLajZ$C0sikFQQ3SWaFAZ1Me0Z/1', // password
'admin' => 1,
'disable' => 0,
'crdate' => 1366642540,
'deleted' => 0,
],
],
];

View file

@ -27,14 +27,14 @@ use Codappix\Typo3PhpDatasets\PhpDataSet;
use DateTimeImmutable; use DateTimeImmutable;
use DateTimeZone; use DateTimeZone;
use GuzzleHttp\Psr7\Response; use GuzzleHttp\Psr7\Response;
use PHPUnit\Framework\Attributes\Test;
use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ResponseInterface;
use TYPO3\CMS\Core\Cache\Backend\SimpleFileBackend;
use TYPO3\CMS\Core\Cache\CacheManager;
use TYPO3\CMS\Core\Information\Typo3Version; use TYPO3\CMS\Core\Information\Typo3Version;
use TYPO3\TestingFramework\Core\Functional\Framework\Frontend\InternalRequest; use TYPO3\TestingFramework\Core\Functional\Framework\Frontend\InternalRequest;
use WerkraumMedia\Events\Tests\Functional\AbstractFunctionalTestCase; use WerkraumMedia\Events\Tests\Functional\AbstractFunctionalTestCase;
/**
* @covers \WerkraumMedia\Events\Caching\PageCacheTimeout
*/
class CacheTest extends AbstractFunctionalTestCase class CacheTest extends AbstractFunctionalTestCase
{ {
protected function setUp(): void protected function setUp(): void
@ -42,9 +42,28 @@ class CacheTest extends AbstractFunctionalTestCase
$this->testExtensionsToLoad = [ $this->testExtensionsToLoad = [
'typo3conf/ext/events/Tests/Functional/Frontend/Fixtures/Extensions/example', 'typo3conf/ext/events/Tests/Functional/Frontend/Fixtures/Extensions/example',
]; ];
$this->configurationToUseInTestInstance = [
'SYS' => [
// Combined with flushCaches.
// Ensures that we have expected TYPO3 caching within each test.
// But we don't keep caches from one test to the other.
'caching' => [
'cacheConfigurations' => [
'pages' => [
'backend' => SimpleFileBackend::class,
'options' => [
'compression' => '__UNSET',
],
],
],
],
],
];
parent::setUp(); parent::setUp();
$this->get(CacheManager::class)->flushCaches();
$this->importPHPDataSet(__DIR__ . '/Fixtures/Database/SiteStructure.php'); $this->importPHPDataSet(__DIR__ . '/Fixtures/Database/SiteStructure.php');
(new PhpDataSet())->import(['tt_content' => [[ (new PhpDataSet())->import(['tt_content' => [[
'uid' => '1', 'uid' => '1',
@ -56,21 +75,17 @@ class CacheTest extends AbstractFunctionalTestCase
$this->setUpFrontendRendering(); $this->setUpFrontendRendering();
} }
/** #[Test]
* @test
*/
public function returnsSystemDefaults(): void public function returnsSystemDefaults(): void
{ {
$response = $this->executeFrontendRequest($this->getRequestWithSleep()); $response = $this->executeFrontendSubRequest($this->getRequestWithSleep());
self::assertSame(200, $response->getStatusCode()); self::assertSame(200, $response->getStatusCode());
self::assertSame('max-age=86400', $response->getHeaderLine('Cache-Control')); self::assertSame('max-age=86400', $response->getHeaderLine('Cache-Control'));
self::assertSame('public', $response->getHeaderLine('Pragma')); self::assertSame('public', $response->getHeaderLine('Pragma'));
} }
/** #[Test]
* @test
*/
public function returnsDefaultsIfEventsEndLater(): void public function returnsDefaultsIfEventsEndLater(): void
{ {
(new PhpDataSet())->import([ (new PhpDataSet())->import([
@ -89,16 +104,14 @@ class CacheTest extends AbstractFunctionalTestCase
], ],
]); ]);
$response = $this->executeFrontendRequest($this->getRequestWithSleep()); $response = $this->executeFrontendSubRequest($this->getRequestWithSleep());
self::assertSame(200, $response->getStatusCode()); self::assertSame(200, $response->getStatusCode());
self::assertSame('max-age=86400', $response->getHeaderLine('Cache-Control')); self::assertSame('max-age=86400', $response->getHeaderLine('Cache-Control'));
self::assertSame('public', $response->getHeaderLine('Pragma')); self::assertSame('public', $response->getHeaderLine('Pragma'));
} }
/** #[Test]
* @test
*/
public function returnsEarlierIfEventsEndEarlier(): void public function returnsEarlierIfEventsEndEarlier(): void
{ {
$end = (new DateTimeImmutable('tomorrow midnight', new DateTimeZone('UTC')))->modify('+2 hours'); $end = (new DateTimeImmutable('tomorrow midnight', new DateTimeZone('UTC')))->modify('+2 hours');
@ -121,15 +134,13 @@ class CacheTest extends AbstractFunctionalTestCase
], ],
]); ]);
$response = $this->executeFrontendRequest($this->getRequestWithSleep()); $response = $this->executeFrontendSubRequest($this->getRequestWithSleep());
self::assertSame(200, $response->getStatusCode()); self::assertSame(200, $response->getStatusCode());
self::assertCacheHeaders($end, $response); self::assertCacheHeaders($end, $response);
} }
/** #[Test]
* @test
*/
public function returnsEarlierIfStartEndEalierAndIsUpcoming(): void public function returnsEarlierIfStartEndEalierAndIsUpcoming(): void
{ {
$end = (new DateTimeImmutable('now', new DateTimeZone('UTC')))->modify('+2 hours'); $end = (new DateTimeImmutable('now', new DateTimeZone('UTC')))->modify('+2 hours');
@ -152,7 +163,7 @@ class CacheTest extends AbstractFunctionalTestCase
], ],
]); ]);
$response = $this->executeFrontendRequest($this->getRequestWithSleep([ $response = $this->executeFrontendSubRequest($this->getRequestWithSleep([
'plugin.' => [ 'plugin.' => [
'tx_events.' => [ 'tx_events.' => [
'settings.' => [ 'settings.' => [
@ -166,9 +177,7 @@ class CacheTest extends AbstractFunctionalTestCase
self::assertCacheHeaders($end, $response); self::assertCacheHeaders($end, $response);
} }
/** #[Test]
* @test
*/
public function usesEarliestTimeout(): void public function usesEarliestTimeout(): void
{ {
$end = (new DateTimeImmutable('now', new DateTimeZone('UTC')))->modify('+2 hours'); $end = (new DateTimeImmutable('now', new DateTimeZone('UTC')))->modify('+2 hours');
@ -202,7 +211,7 @@ class CacheTest extends AbstractFunctionalTestCase
], ],
]); ]);
$response = $this->executeFrontendRequest($this->getRequestWithSleep([ $response = $this->executeFrontendSubRequest($this->getRequestWithSleep([
'plugin.' => [ 'plugin.' => [
'tx_events.' => [ 'tx_events.' => [
'settings.' => [ 'settings.' => [
@ -216,9 +225,7 @@ class CacheTest extends AbstractFunctionalTestCase
self::assertCacheHeaders($end, $response); self::assertCacheHeaders($end, $response);
} }
/** #[Test]
* @test
*/
public function returnsMidnightIfConfigured(): void public function returnsMidnightIfConfigured(): void
{ {
$midnight = (new DateTimeImmutable('tomorrow midnight', new DateTimeZone('UTC'))); $midnight = (new DateTimeImmutable('tomorrow midnight', new DateTimeZone('UTC')));
@ -247,21 +254,19 @@ class CacheTest extends AbstractFunctionalTestCase
], ],
])); ]));
$response = $this->executeFrontendRequest($this->getRequestWithSleep()); $response = $this->executeFrontendSubRequest($this->getRequestWithSleep());
self::assertSame(200, $response->getStatusCode()); self::assertSame(200, $response->getStatusCode());
self::assertCacheHeaders($midnight, $response); self::assertCacheHeaders($midnight, $response);
self::assertSame('public', $response->getHeaderLine('Pragma')); self::assertSame('public', $response->getHeaderLine('Pragma'));
} }
/** #[Test]
* @test
*/
public function cachesAreClearedByImport(): void public function cachesAreClearedByImport(): void
{ {
// Assert frontend is cached // Assert frontend is cached
$this->assertResponseIsNotCached($this->executeFrontendRequest($this->getRequestWithSleep())); $this->assertResponseIsNotCached($this->executeFrontendSubRequest($this->getRequestWithSleep()));
$this->assertResponseIsCached($this->executeFrontendRequest($this->getRequestWithSleep())); $this->assertResponseIsCached($this->executeFrontendSubRequest($this->getRequestWithSleep()));
// Import // Import
$this->importPHPDataSet(__DIR__ . '/../Import/DestinationDataTest/Fixtures/Database/DefaultImportConfiguration.php'); $this->importPHPDataSet(__DIR__ . '/../Import/DestinationDataTest/Fixtures/Database/DefaultImportConfiguration.php');
@ -281,8 +286,8 @@ class CacheTest extends AbstractFunctionalTestCase
// Assert frontend is not cached on first hit // Assert frontend is not cached on first hit
$this->setUpFrontendRendering(); $this->setUpFrontendRendering();
$this->assertResponseIsNotCached($this->executeFrontendRequest($this->getRequestWithSleep())); $this->assertResponseIsNotCached($this->executeFrontendSubRequest($this->getRequestWithSleep()));
$this->assertResponseIsCached($this->executeFrontendRequest($this->getRequestWithSleep())); $this->assertResponseIsCached($this->executeFrontendSubRequest($this->getRequestWithSleep()));
} }
private static function assertCacheHeaders(DateTimeImmutable $end, ResponseInterface $response): void private static function assertCacheHeaders(DateTimeImmutable $end, ResponseInterface $response): void
@ -316,10 +321,6 @@ class CacheTest extends AbstractFunctionalTestCase
private function assertResponseIsCached(ResponseInterface $response): void private function assertResponseIsCached(ResponseInterface $response): void
{ {
if ((new Typo3Version())->getMajorVersion() < 11) {
self::assertStringContainsString('Cached page', $response->getBody()->__toString());
return;
}
self::assertStringStartsWith('Cached page', $response->getHeaderLine('X-TYPO3-Debug-Cache')); self::assertStringStartsWith('Cached page', $response->getHeaderLine('X-TYPO3-Debug-Cache'));
} }

View file

@ -23,13 +23,11 @@ declare(strict_types=1);
namespace WerkraumMedia\Events\Tests\Functional\Frontend; namespace WerkraumMedia\Events\Tests\Functional\Frontend;
use PHPUnit\Framework\Attributes\Test;
use TYPO3\TestingFramework\Core\Functional\Framework\Frontend\InternalRequest; use TYPO3\TestingFramework\Core\Functional\Framework\Frontend\InternalRequest;
use WerkraumMedia\Events\Frontend\Dates; use WerkraumMedia\Events\Frontend\Dates;
use WerkraumMedia\Events\Tests\Functional\AbstractFunctionalTestCase; use WerkraumMedia\Events\Tests\Functional\AbstractFunctionalTestCase;
/**
* @covers \WerkraumMedia\Events\Frontend\Dates
*/
class DatesTest extends AbstractFunctionalTestCase class DatesTest extends AbstractFunctionalTestCase
{ {
protected function setUp(): void protected function setUp(): void
@ -46,16 +44,15 @@ class DatesTest extends AbstractFunctionalTestCase
* Dates don't make any sense without an event, as they not even have a name. * Dates don't make any sense without an event, as they not even have a name.
* *
* They therefore should not be fetched from persistence. * They therefore should not be fetched from persistence.
*
* @test
*/ */
#[Test]
public function returnsOnlyDatesWithAvailableEventByDemand(): void public function returnsOnlyDatesWithAvailableEventByDemand(): void
{ {
$this->importCSVDataSet(__DIR__ . '/DatesTestFixtures/ReturnsOnlyDatesWithAvailableEventByDemand.csv'); $this->importPHPDataSet(__DIR__ . '/DatesTestFixtures/ReturnsOnlyDatesWithAvailableEventByDemand.php');
$request = new InternalRequest(); $request = new InternalRequest();
$request = $request->withPageId(1); $request = $request->withPageId(1);
$response = $this->executeFrontendRequest($request); $response = $this->executeFrontendSubRequest($request);
self::assertSame(200, $response->getStatusCode()); self::assertSame(200, $response->getStatusCode());
$html = (string)$response->getBody(); $html = (string)$response->getBody();
@ -64,19 +61,17 @@ class DatesTest extends AbstractFunctionalTestCase
self::assertStringContainsString('Event 2 visible', $html); self::assertStringContainsString('Event 2 visible', $html);
} }
/** #[Test]
* @test
*/
public function returnsDateAfterStart(): void public function returnsDateAfterStart(): void
{ {
$this->importCSVDataSet(__DIR__ . '/DatesTestFixtures/ReturnsDateWithinTimeSpan.csv'); $this->importPHPDataSet(__DIR__ . '/DatesTestFixtures/ReturnsDateWithinTimeSpan.php');
$request = new InternalRequest(); $request = new InternalRequest();
$request = $request->withPageId(1); $request = $request->withPageId(1);
$request = $request->withQueryParameters([ $request = $request->withQueryParameters([
'events_search[search][start]' => '2023-02-16', 'events_search[search][start]' => '2023-02-16',
]); ]);
$response = $this->executeFrontendRequest($request); $response = $this->executeFrontendSubRequest($request);
self::assertSame(200, $response->getStatusCode()); self::assertSame(200, $response->getStatusCode());
$html = (string)$response->getBody(); $html = (string)$response->getBody();
@ -92,19 +87,17 @@ class DatesTest extends AbstractFunctionalTestCase
self::assertStringContainsString('Event 9', $html); self::assertStringContainsString('Event 9', $html);
} }
/** #[Test]
* @test
*/
public function returnsDateBeforeEnd(): void public function returnsDateBeforeEnd(): void
{ {
$this->importCSVDataSet(__DIR__ . '/DatesTestFixtures/ReturnsDateWithinTimeSpan.csv'); $this->importPHPDataSet(__DIR__ . '/DatesTestFixtures/ReturnsDateWithinTimeSpan.php');
$request = new InternalRequest(); $request = new InternalRequest();
$request = $request->withPageId(1); $request = $request->withPageId(1);
$request = $request->withQueryParameters([ $request = $request->withQueryParameters([
'events_search[search][end]' => '2023-02-17', 'events_search[search][end]' => '2023-02-17',
]); ]);
$response = $this->executeFrontendRequest($request); $response = $this->executeFrontendSubRequest($request);
self::assertSame(200, $response->getStatusCode()); self::assertSame(200, $response->getStatusCode());
$html = (string)$response->getBody(); $html = (string)$response->getBody();
@ -124,12 +117,11 @@ class DatesTest extends AbstractFunctionalTestCase
* Covers issue https://redmine.werkraum-media.de/issues/10350. * Covers issue https://redmine.werkraum-media.de/issues/10350.
* A date can span multiple dates. * A date can span multiple dates.
* The visitor might search a time frame within the spaned dates and expects the date to be shown. * The visitor might search a time frame within the spaned dates and expects the date to be shown.
*
* @test
*/ */
#[Test]
public function returnsDateWithinTimeSpan(): void public function returnsDateWithinTimeSpan(): void
{ {
$this->importCSVDataSet(__DIR__ . '/DatesTestFixtures/ReturnsDateWithinTimeSpan.csv'); $this->importPHPDataSet(__DIR__ . '/DatesTestFixtures/ReturnsDateWithinTimeSpan.php');
$request = new InternalRequest(); $request = new InternalRequest();
$request = $request->withPageId(1); $request = $request->withPageId(1);
@ -137,7 +129,7 @@ class DatesTest extends AbstractFunctionalTestCase
'events_search[search][start]' => '2023-02-16', 'events_search[search][start]' => '2023-02-16',
'events_search[search][end]' => '2023-02-17', 'events_search[search][end]' => '2023-02-17',
]); ]);
$response = $this->executeFrontendRequest($request); $response = $this->executeFrontendSubRequest($request);
self::assertSame(200, $response->getStatusCode()); self::assertSame(200, $response->getStatusCode());
$html = (string)$response->getBody(); $html = (string)$response->getBody();
@ -153,26 +145,22 @@ class DatesTest extends AbstractFunctionalTestCase
self::assertStringContainsString('Event 9', $html); self::assertStringContainsString('Event 9', $html);
} }
/** #[Test]
* @test
*/
public function returns404IfEventIsHidden(): void public function returns404IfEventIsHidden(): void
{ {
$this->importCSVDataSet(__DIR__ . '/DatesTestFixtures/Returns404IfEventIsHidden.csv'); $this->importPHPDataSet(__DIR__ . '/DatesTestFixtures/Returns404IfEventIsHidden.php');
$request = new InternalRequest(); $request = new InternalRequest();
$request = $request->withPageId(1); $request = $request->withPageId(1);
$request = $request->withQueryParameters([ $request = $request->withQueryParameters([
'tx_events_dateshow[date]' => '1', 'tx_events_dateshow[date]' => '1',
]); ]);
$response = $this->executeFrontendRequest($request); $response = $this->executeFrontendSubRequest($request);
self::assertSame(404, $response->getStatusCode()); self::assertSame(404, $response->getStatusCode());
} }
/** #[Test]
* @test
*/
public function returnsUpcomingDates(): void public function returnsUpcomingDates(): void
{ {
$this->importPHPDataSet(__DIR__ . '/DatesTestFixtures/ReturnsUpcomingDates.php'); $this->importPHPDataSet(__DIR__ . '/DatesTestFixtures/ReturnsUpcomingDates.php');
@ -191,7 +179,7 @@ class DatesTest extends AbstractFunctionalTestCase
], ],
]), ]),
]); ]);
$response = $this->executeFrontendRequest($request); $response = $this->executeFrontendSubRequest($request);
self::assertSame(200, $response->getStatusCode()); self::assertSame(200, $response->getStatusCode());
$html = (string)$response->getBody(); $html = (string)$response->getBody();

View file

@ -1,9 +0,0 @@
tt_content
,uid,pid,CType,list_type,header
,1,1,list,events_dateshow,Singleview
tx_events_domain_model_event
,uid,pid,title,hidden
,1,2,"Event 1 starts before search, ends before search",1
tx_events_domain_model_date
,uid,pid,event,start,end
,1,2,1,1676419200,1676484000
Can't render this file because it has a wrong number of fields in line 2.

View file

@ -0,0 +1,32 @@
<?php
declare(strict_types=1);
return [
'tt_content' => [
0 => [
'uid' => '1',
'pid' => '1',
'CType' => 'list',
'list_type' => 'events_dateshow',
'header' => 'Singleview',
],
],
'tx_events_domain_model_event' => [
0 => [
'uid' => '1',
'pid' => '2',
'title' => 'Event 1 starts before search, ends before search',
'hidden' => '1',
],
],
'tx_events_domain_model_date' => [
0 => [
'uid' => '1',
'pid' => '2',
'event' => '1',
'start' => '1676419200',
'end' => '1676484000',
],
],
];

View file

@ -1,25 +0,0 @@
tt_content
,uid,pid,CType,list_type,header
,1,1,list,events_datelist,All Dates
tx_events_domain_model_event
,uid,pid,title
,1,2,Event 1 starts before search, ends before search
,2,2,Event 2 starts before search, no end
,3,2,Event 3 starts after search, ends after search
,4,2,Event 4 starts after search, no end
,5,2,Event 5 starts before search, ends after search
,6,2,Event 6 starts inside search, ends inside search
,7,2,Event 7 starts inside search, ends after search
,8,2,Event 8 starts inside search, no end
,9,2,Event 9 starts before search, ends inside search
tx_events_domain_model_date
,uid,pid,event,start,end
,1,2,1,1676419200,1676484000
,2,2,2,1676419200,"\NULL"
,3,2,3,1676678400,1676743200
,4,2,4,1676678400,"\NULL"
,5,2,5,1676419200,1676678400
,6,2,6,1676559600,1676570400
,7,2,7,1676559600,1676678400
,8,2,8,1676559600,"\NULL"
,9,2,9,1676419200,1676570400
Can't render this file because it has a wrong number of fields in line 2.

View file

@ -0,0 +1,127 @@
<?php
declare(strict_types=1);
return [
'tt_content' => [
0 => [
'uid' => '1',
'pid' => '1',
'CType' => 'list',
'list_type' => 'events_datelist',
'header' => 'All Dates',
],
],
'tx_events_domain_model_event' => [
0 => [
'uid' => '1',
'pid' => '2',
'title' => 'Event 1 starts before search, ends before search',
],
1 => [
'uid' => '2',
'pid' => '2',
'title' => 'Event 2 starts before search, no end',
],
2 => [
'uid' => '3',
'pid' => '2',
'title' => 'Event 3 starts after search, ends after search',
],
3 => [
'uid' => '4',
'pid' => '2',
'title' => 'Event 4 starts after search, no end',
],
4 => [
'uid' => '5',
'pid' => '2',
'title' => 'Event 5 starts before search, ends after search',
],
5 => [
'uid' => '6',
'pid' => '2',
'title' => 'Event 6 starts inside search, ends inside search',
],
6 => [
'uid' => '7',
'pid' => '2',
'title' => 'Event 7 starts inside search, ends after search',
],
7 => [
'uid' => '8',
'pid' => '2',
'title' => 'Event 8 starts inside search, no end',
],
8 => [
'uid' => '9',
'pid' => '2',
'title' => 'Event 9 starts before search, ends inside search',
],
],
'tx_events_domain_model_date' => [
0 => [
'uid' => '1',
'pid' => '2',
'event' => '1',
'start' => '1676419200',
'end' => '1676484000',
],
1 => [
'uid' => '2',
'pid' => '2',
'event' => '2',
'start' => '1676419200',
'end' => '\\NULL',
],
2 => [
'uid' => '3',
'pid' => '2',
'event' => '3',
'start' => '1676678400',
'end' => '1676743200',
],
3 => [
'uid' => '4',
'pid' => '2',
'event' => '4',
'start' => '1676678400',
'end' => '\\NULL',
],
4 => [
'uid' => '5',
'pid' => '2',
'event' => '5',
'start' => '1676419200',
'end' => '1676678400',
],
5 => [
'uid' => '6',
'pid' => '2',
'event' => '6',
'start' => '1676559600',
'end' => '1676570400',
],
6 => [
'uid' => '7',
'pid' => '2',
'event' => '7',
'start' => '1676559600',
'end' => '1676678400',
],
7 => [
'uid' => '8',
'pid' => '2',
'event' => '8',
'start' => '1676559600',
'end' => '\\NULL',
],
8 => [
'uid' => '9',
'pid' => '2',
'event' => '9',
'start' => '1676419200',
'end' => '1676570400',
],
],
];

View file

@ -1,11 +0,0 @@
tt_content
,uid,pid,CType,list_type,header
,1,1,list,events_datelist,All Dates
tx_events_domain_model_event
,uid,pid,title,hidden
,1,2,Event 1 hidden,1
,2,2,Event 2 visible,0
tx_events_domain_model_date
,uid,pid,event,start,end
,1,2,1,1662458400,1662469200
,2,2,2,1662458400,1662469200
1 tt_content
2 ,uid,pid,CType,list_type,header
3 ,1,1,list,events_datelist,All Dates
4 tx_events_domain_model_event
5 ,uid,pid,title,hidden
6 ,1,2,Event 1 hidden,1
7 ,2,2,Event 2 visible,0
8 tx_events_domain_model_date
9 ,uid,pid,event,start,end
10 ,1,2,1,1662458400,1662469200
11 ,2,2,2,1662458400,1662469200

View file

@ -0,0 +1,45 @@
<?php
declare(strict_types=1);
return [
'tt_content' => [
0 => [
'uid' => '1',
'pid' => '1',
'CType' => 'list',
'list_type' => 'events_datelist',
'header' => 'All Dates',
],
],
'tx_events_domain_model_event' => [
0 => [
'uid' => '1',
'pid' => '2',
'title' => 'Event 1 hidden',
'hidden' => '1',
],
1 => [
'uid' => '2',
'pid' => '2',
'title' => 'Event 2 visible',
'hidden' => '0',
],
],
'tx_events_domain_model_date' => [
0 => [
'uid' => '1',
'pid' => '2',
'event' => '1',
'start' => '1662458400',
'end' => '1662469200',
],
1 => [
'uid' => '2',
'pid' => '2',
'event' => '2',
'start' => '1662458400',
'end' => '1662469200',
],
],
];

View file

@ -1,6 +1,6 @@
<?php <?php
use DateTimeImmutable; declare(strict_types=1);
return [ return [
'tt_content' => [ 'tt_content' => [

View file

@ -4,13 +4,10 @@ declare(strict_types=1);
namespace WerkraumMedia\Events\Tests\Functional\Frontend; namespace WerkraumMedia\Events\Tests\Functional\Frontend;
use PHPUnit\Framework\Attributes\Test;
use TYPO3\TestingFramework\Core\Functional\Framework\Frontend\InternalRequest; use TYPO3\TestingFramework\Core\Functional\Framework\Frontend\InternalRequest;
use WerkraumMedia\Events\Tests\Functional\AbstractFunctionalTestCase; use WerkraumMedia\Events\Tests\Functional\AbstractFunctionalTestCase;
/**
* @covers \WerkraumMedia\Events\Controller\DateController
* @covers \WerkraumMedia\Events\Domain\Repository\DateRepository
*/
class FilterTest extends AbstractFunctionalTestCase class FilterTest extends AbstractFunctionalTestCase
{ {
protected function setUp(): void protected function setUp(): void
@ -21,16 +18,14 @@ class FilterTest extends AbstractFunctionalTestCase
$this->setUpFrontendRendering(); $this->setUpFrontendRendering();
} }
/** #[Test]
* @test
*/
public function canFilterByASingleLocationViaFlexform(): void public function canFilterByASingleLocationViaFlexform(): void
{ {
$this->importPHPDataSet(__DIR__ . '/Fixtures/Database/FilterByASingleLocationViaFlexform.php'); $this->importPHPDataSet(__DIR__ . '/Fixtures/Database/FilterByASingleLocationViaFlexform.php');
$request = new InternalRequest(); $request = new InternalRequest();
$request = $request->withPageId(1); $request = $request->withPageId(1);
$response = $this->executeFrontendRequest($request); $response = $this->executeFrontendSubRequest($request);
self::assertSame(200, $response->getStatusCode()); self::assertSame(200, $response->getStatusCode());
$html = (string)$response->getBody(); $html = (string)$response->getBody();
@ -39,16 +34,14 @@ class FilterTest extends AbstractFunctionalTestCase
self::assertStringContainsString('Was hat das Universum mit mir zu tun?', $html); self::assertStringContainsString('Was hat das Universum mit mir zu tun?', $html);
} }
/** #[Test]
* @test
*/
public function canFilterByTwoLocationsViaFlexform(): void public function canFilterByTwoLocationsViaFlexform(): void
{ {
$this->importPHPDataSet(__DIR__ . '/Fixtures/Database/FilterByTwoLocationsViaFlexform.php'); $this->importPHPDataSet(__DIR__ . '/Fixtures/Database/FilterByTwoLocationsViaFlexform.php');
$request = new InternalRequest(); $request = new InternalRequest();
$request = $request->withPageId(1); $request = $request->withPageId(1);
$response = $this->executeFrontendRequest($request); $response = $this->executeFrontendSubRequest($request);
self::assertSame(200, $response->getStatusCode()); self::assertSame(200, $response->getStatusCode());
$html = (string)$response->getBody(); $html = (string)$response->getBody();

View file

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
return [ return [
'tt_content' => [ 'tt_content' => [
[ [

Some files were not shown because too many files have changed in this diff Show more