TYPO3 V12 Update (#116)

* Support TYPO3 v12 and PHP 8.3
This commit is contained in:
Daniel Siepmann 2023-12-05 09:43:55 +01:00 committed by GitHub
parent f69db97990
commit 54d244b804
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
228 changed files with 4711 additions and 4419 deletions

10
.gitattributes vendored Normal file
View file

@ -0,0 +1,10 @@
codeception.dist.yml export-ignore
.gitattributes export-ignore
.github export-ignore
.gitignore export-ignore
.php-cs-fixer.dist.php export-ignore
phpstan-baseline.neon export-ignore
phpstan.neon export-ignore
phpunit.xml.dist export-ignore
shell.nix export-ignore
Tests export-ignore

View file

@ -15,10 +15,9 @@ jobs:
strategy: strategy:
matrix: matrix:
php-version: php-version:
- 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
@ -41,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
@ -70,14 +69,14 @@ 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 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/ecs check run: ./vendor/bin/php-cs-fixer fix --dry-run --diff
code-quality: code-quality:
runs-on: ubuntu-latest runs-on: ubuntu-latest
@ -86,16 +85,12 @@ jobs:
strategy: strategy:
matrix: matrix:
include: include:
- 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
@ -121,23 +116,14 @@ jobs:
strategy: strategy:
matrix: matrix:
include: include:
- php-version: '7.4'
typo3-version: '^10.4'
db-version: '5.6'
- php-version: '7.4'
typo3-version: '^10.4'
db-version: '8'
- php-version: '7.4'
typo3-version: '^11.5'
db-version: '8'
- php-version: '8.0'
typo3-version: '^11.5'
db-version: '8'
- php-version: '8.1' - php-version: '8.1'
typo3-version: '^11.5' typo3-version: '^12.4'
db-version: '8' db-version: '8'
- php-version: '8.2' - php-version: '8.2'
typo3-version: '^11.5' typo3-version: '^12.4'
db-version: '8'
- php-version: '8.3'
typo3-version: '^12.4'
db-version: '8' db-version: '8'
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
@ -151,10 +137,16 @@ jobs:
- name: Setup MySQL - name: Setup MySQL
uses: mirromutth/mysql-action@v1.1 uses: mirromutth/mysql-action@v1.1
with: with:
mysql version: '5.7' mysql version: "${{ matrix.db-version }}"
mysql database: 'typo3' mysql database: 'typo3'
mysql root password: 'root' mysql root password: 'root'
- name: Wait for MySQL
run: |
while ! mysqladmin ping --host=127.0.0.1 --password=root --silent; do
sleep 1
done
- name: Install dependencies - name: Install dependencies
run: composer require --no-interaction --prefer-dist --no-progress "typo3/cms-backend:${{ matrix.typo3-version }}" "typo3/cms-core:${{ matrix.typo3-version }}" "typo3/cms-extbase:${{ matrix.typo3-version }}" "typo3/cms-frontend:${{ matrix.typo3-version }}" "typo3/cms-fluid-styled-content:${{ matrix.typo3-version }}" run: composer require --no-interaction --prefer-dist --no-progress "typo3/cms-backend:${{ matrix.typo3-version }}" "typo3/cms-core:${{ matrix.typo3-version }}" "typo3/cms-extbase:${{ matrix.typo3-version }}" "typo3/cms-frontend:${{ matrix.typo3-version }}" "typo3/cms-fluid-styled-content:${{ matrix.typo3-version }}"
@ -165,4 +157,16 @@ jobs:
export typo3DatabaseHost="127.0.0.1" export typo3DatabaseHost="127.0.0.1"
export typo3DatabaseUsername="root" export typo3DatabaseUsername="root"
export typo3DatabasePassword="root" export typo3DatabasePassword="root"
./vendor/bin/phpunit --testdox ./vendor/bin/phpunit
tests-acceptance:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: cachix/install-nix-action@v24
with:
nix_path: nixpkgs=channel:nixos-unstable
- name: Run Acceptance Tests
run: nix-shell --run project-test-acceptance

2
.gitignore vendored
View file

@ -1,3 +1,5 @@
/.Build/ /.Build/
/composer.lock /composer.lock
/.phpunit.cache
/Tests/Acceptance/Support/_generated
/vendor/ /vendor/

73
.php-cs-fixer.dist.php Normal file
View file

@ -0,0 +1,73 @@
<?php
$finder = (new PhpCsFixer\Finder())
->ignoreVCSIgnored(true)
->in(realpath(__DIR__))
;
return (new \PhpCsFixer\Config())
->setRiskyAllowed(true)
->setRules([
'@DoctrineAnnotation' => true,
'@PSR2' => true,
'array_indentation' => true,
'array_syntax' => ['syntax' => 'short'],
'attribute_empty_parentheses' => true,
'blank_line_after_opening_tag' => true,
'braces' => ['allow_single_line_closure' => true],
'cast_spaces' => ['space' => 'none'],
'compact_nullable_typehint' => true,
'concat_space' => ['spacing' => 'one'],
'declare_equal_normalize' => ['space' => 'none'],
'declare_strict_types' => 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_typehint_space' => true,
'global_namespace_import' => ['import_classes' => true, 'import_constants' => true, 'import_functions' => true],
'lowercase_cast' => true,
'method_argument_space' => ['on_multiline' => 'ensure_fully_multiline'],
'modernize_strpos' => true,
'modernize_types_casting' => true,
'multiline_whitespace_before_semicolons' => ['strategy' => 'new_line_for_chained_calls'],
'native_function_casing' => true,
'new_with_braces' => true,
'no_alias_functions' => true,
'no_blank_lines_after_phpdoc' => true,
'no_empty_phpdoc' => true,
'no_empty_statement' => true,
'no_extra_blank_lines' => true,
'no_leading_import_slash' => true,
'no_leading_namespace_whitespace' => true,
'no_multiline_whitespace_around_double_arrow' => true,
'no_null_property_initialization' => true,
'no_short_bool_cast' => true,
'no_singleline_whitespace_before_semicolons' => true,
'no_superfluous_elseif' => true,
'no_trailing_comma_in_singleline_array' => true,
'no_unneeded_control_parentheses' => true,
'no_unneeded_import_alias' => true,
'no_unused_imports' => true,
'no_useless_else' => true,
'no_whitespace_in_blank_line' => true,
'ordered_imports' => true,
'php_unit_construct' => ['assertions' => ['assertEquals', 'assertSame', 'assertNotEquals', 'assertNotSame']],
'php_unit_mock_short_will_return' => true,
'php_unit_test_case_static_method_calls' => ['call_type' => 'self'],
'phpdoc_no_access' => true,
'phpdoc_no_package' => true,
'phpdoc_order' => ['order' => ['test', 'dataProvider', 'param', 'throws', 'return']],
'phpdoc_scalar' => true,
'phpdoc_separation' => ['groups' => [['Extbase\\*']]],
'phpdoc_trim' => true,
'phpdoc_types' => true,
'phpdoc_types_order' => ['null_adjustment' => 'always_last', 'sort_algorithm' => 'none'],
'return_type_declaration' => ['space_before' => 'none'],
'single_line_comment_style' => ['comment_types' => ['hash']],
'single_quote' => true,
'single_trait_insert_per_statement' => true,
'trailing_comma_in_multiline' => ['elements' => ['arrays']],
'whitespace_after_comma_in_array' => true,
'yoda_style' => ['equal' => false, 'identical' => false, 'less_and_greater' => false],
])
->setFinder($finder)
;

View file

@ -34,24 +34,11 @@ use WerkraumMedia\ThueCat\Domain\Repository\Backend\ImportConfigurationRepositor
class ImportConfigurationCommand extends Command class ImportConfigurationCommand extends Command
{ {
/**
* @var ImportConfigurationRepository
*/
private $importConfigurationRepository;
/**
* @var Importer
*/
private $importer;
public function __construct( public function __construct(
ImportConfigurationRepository $importConfigurationRepository, private readonly ImportConfigurationRepository $importConfigurationRepository,
Importer $importer private readonly Importer $importer
) { ) {
parent::__construct(); parent::__construct();
$this->importConfigurationRepository = $importConfigurationRepository;
$this->importer = $importer;
} }
protected function configure(): void protected function configure(): void

View file

@ -23,22 +23,30 @@ declare(strict_types=1);
namespace WerkraumMedia\ThueCat\Controller\Backend; namespace WerkraumMedia\ThueCat\Controller\Backend;
use TYPO3\CMS\Backend\View\BackendTemplateView; use Psr\Http\Message\ResponseInterface;
use TYPO3\CMS\Backend\Template\ModuleTemplate;
use TYPO3\CMS\Backend\Template\ModuleTemplateFactory;
use TYPO3\CMS\Extbase\Mvc\Controller\ActionController; use TYPO3\CMS\Extbase\Mvc\Controller\ActionController;
abstract class AbstractController extends ActionController abstract class AbstractController extends ActionController
{ {
/** private ModuleTemplateFactory $moduleTemplateFactory;
* BackendTemplateContainer
*
* @var BackendTemplateView
*/
protected $view;
/** protected ModuleTemplate $moduleTemplate;
* Backend Template Container
* public function injectModuleTemplateFactory(ModuleTemplateFactory $moduleTemplateFactory): void
* @var string {
*/ $this->moduleTemplateFactory = $moduleTemplateFactory;
protected $defaultViewObjectName = BackendTemplateView::class; }
protected function initializeView(): void
{
$this->moduleTemplate = $this->moduleTemplateFactory->create($this->request);
$this->moduleTemplate->assign('settings', $this->settings);
}
protected function htmlResponse(?string $html = null): ResponseInterface
{
return parent::htmlResponse($html ?? $this->moduleTemplate->render());
}
} }

View file

@ -23,34 +23,25 @@ declare(strict_types=1);
namespace WerkraumMedia\ThueCat\Controller\Backend; namespace WerkraumMedia\ThueCat\Controller\Backend;
use Psr\Http\Message\ResponseInterface;
use WerkraumMedia\ThueCat\Domain\Repository\Backend\ImportConfigurationRepository; use WerkraumMedia\ThueCat\Domain\Repository\Backend\ImportConfigurationRepository;
use WerkraumMedia\ThueCat\Domain\Repository\Backend\OrganisationRepository; use WerkraumMedia\ThueCat\Domain\Repository\Backend\OrganisationRepository;
class ConfigurationController extends AbstractController class ConfigurationController extends AbstractController
{ {
/**
* @var OrganisationRepository
*/
private $organisationRepository;
/**
* @var ImportConfigurationRepository
*/
private $importConfigurationRepository;
public function __construct( public function __construct(
OrganisationRepository $organisationRepository, private readonly OrganisationRepository $organisationRepository,
ImportConfigurationRepository $importConfigurationRepository private readonly ImportConfigurationRepository $importConfigurationRepository
) { ) {
$this->organisationRepository = $organisationRepository;
$this->importConfigurationRepository = $importConfigurationRepository;
} }
public function indexAction(): void public function indexAction(): ResponseInterface
{ {
$this->view->assignMultiple([ $this->moduleTemplate->assignMultiple([
'importConfigurations' => $this->importConfigurationRepository->findAll(), 'importConfigurations' => $this->importConfigurationRepository->findAll(),
'organisations' => $this->organisationRepository->findAll(), 'organisations' => $this->organisationRepository->findAll(),
]); ]);
return $this->htmlResponse();
} }
} }

View file

@ -23,8 +23,9 @@ declare(strict_types=1);
namespace WerkraumMedia\ThueCat\Controller\Backend; namespace WerkraumMedia\ThueCat\Controller\Backend;
use TYPO3\CMS\Core\Messaging\AbstractMessage; use Psr\Http\Message\ResponseInterface;
use TYPO3\CMS\Extbase\Annotation as Extbase; use TYPO3\CMS\Core\Type\ContextualFeedbackSeverity;
use TYPO3\CMS\Extbase\Annotation\IgnoreValidation;
use WerkraumMedia\ThueCat\Domain\Import\Importer; use WerkraumMedia\ThueCat\Domain\Import\Importer;
use WerkraumMedia\ThueCat\Domain\Model\Backend\ImportConfiguration; use WerkraumMedia\ThueCat\Domain\Model\Backend\ImportConfiguration;
use WerkraumMedia\ThueCat\Domain\Repository\Backend\ImportLogRepository; use WerkraumMedia\ThueCat\Domain\Repository\Backend\ImportLogRepository;
@ -33,42 +34,24 @@ use WerkraumMedia\ThueCat\Typo3Wrapper\TranslationService;
class ImportController extends AbstractController class ImportController extends AbstractController
{ {
/**
* @var Importer
*/
private $importer;
/**
* @var ImportLogRepository
*/
private $repository;
/**
* @var TranslationService
*/
private $translation;
public function __construct( public function __construct(
Importer $importer, private readonly Importer $importer,
ImportLogRepository $repository, private readonly ImportLogRepository $repository,
TranslationService $translation private readonly TranslationService $translation
) { ) {
$this->importer = $importer;
$this->repository = $repository;
$this->translation = $translation;
} }
public function indexAction(): void public function indexAction(): ResponseInterface
{ {
$this->view->assignMultiple([ $this->moduleTemplate->assignMultiple([
'imports' => $this->repository->findAll(), 'imports' => $this->repository->findAll(),
]); ]);
return $this->htmlResponse();
} }
/** #[IgnoreValidation(['argumentName' => 'importConfiguration'])]
* @Extbase\IgnoreValidation("importConfiguration") public function importAction(ImportConfiguration $importConfiguration): ResponseInterface
*/
public function importAction(ImportConfiguration $importConfiguration): void
{ {
$importLog = $this->importer->importConfiguration($importConfiguration); $importLog = $this->importer->importConfiguration($importConfiguration);
@ -78,7 +61,7 @@ class ImportController extends AbstractController
$this->createImportDoneFlashMessage($importConfiguration); $this->createImportDoneFlashMessage($importConfiguration);
} }
$this->redirect('index', 'Backend\Configuration'); return $this->redirect('index', 'Backend\Configuration');
} }
private function createImportErrorFlashMessage(ImportConfiguration $importConfiguration): void private function createImportErrorFlashMessage(ImportConfiguration $importConfiguration): void
@ -93,7 +76,7 @@ class ImportController extends AbstractController
'controller.backend.import.import.error.title', 'controller.backend.import.import.error.title',
Extension::EXTENSION_NAME Extension::EXTENSION_NAME
), ),
AbstractMessage::ERROR ContextualFeedbackSeverity::ERROR
); );
} }
@ -109,7 +92,7 @@ class ImportController extends AbstractController
'controller.backend.import.import.success.title', 'controller.backend.import.import.success.title',
Extension::EXTENSION_NAME Extension::EXTENSION_NAME
), ),
AbstractMessage::OK ContextualFeedbackSeverity::OK
); );
} }
} }

View file

@ -29,7 +29,7 @@ use WerkraumMedia\ThueCat\Domain\Import\Typo3Converter\Registry;
class ConverterPass implements CompilerPassInterface class ConverterPass implements CompilerPassInterface
{ {
public const TAG = 'thuecat.typo3.converter'; final public const TAG = 'thuecat.typo3.converter';
public function process(ContainerBuilder $container): void public function process(ContainerBuilder $container): void
{ {

View file

@ -29,7 +29,7 @@ use WerkraumMedia\ThueCat\Domain\Import\EntityMapper\EntityRegistry;
class EntityPass implements CompilerPassInterface class EntityPass implements CompilerPassInterface
{ {
public const TAG = 'thuecat.entity'; final public const TAG = 'thuecat.entity';
public function process(ContainerBuilder $container): void public function process(ContainerBuilder $container): void
{ {

View file

@ -29,7 +29,7 @@ use WerkraumMedia\ThueCat\Domain\Import\UrlProvider\Registry;
class UrlProvidersPass implements CompilerPassInterface class UrlProvidersPass implements CompilerPassInterface
{ {
public const TAG = 'thuecat:urlprovider'; final public const TAG = 'thuecat:urlprovider';
public function process(ContainerBuilder $container): void public function process(ContainerBuilder $container): void
{ {

View file

@ -27,45 +27,21 @@ use WerkraumMedia\ThueCat\Domain\Import\EntityMapper\PropertyValues;
class AccessibilityCertification implements MapsToType class AccessibilityCertification implements MapsToType
{ {
/** protected string $accessibilityCertificationStatus = '';
* @var string
*/
protected $accessibilityCertificationStatus = '';
/** protected string $certificationAccessibilityDeaf = '';
* @var string
*/
protected $certificationAccessibilityDeaf = '';
/** protected string $certificationAccessibilityMental = '';
* @var string
*/
protected $certificationAccessibilityMental = '';
/** protected string $certificationAccessibilityPartiallyDeaf = '';
* @var string
*/
protected $certificationAccessibilityPartiallyDeaf = '';
/** protected string $certificationAccessibilityPartiallyVisual = '';
* @var string
*/
protected $certificationAccessibilityPartiallyVisual = '';
/** protected string $certificationAccessibilityVisual = '';
* @var string
*/
protected $certificationAccessibilityVisual = '';
/** protected string $certificationAccessibilityWalking = '';
* @var string
*/
protected $certificationAccessibilityWalking = '';
/** protected string $certificationAccessibilityWheelchair = '';
* @var string
*/
protected $certificationAccessibilityWheelchair = '';
public function getAccessibilityCertificationStatus(): string public function getAccessibilityCertificationStatus(): string
{ {
@ -109,6 +85,7 @@ class AccessibilityCertification implements MapsToType
/** /**
* @internal for mapping via Symfony component. * @internal for mapping via Symfony component.
*
* @param string|array $accessibilityCertificationStatus * @param string|array $accessibilityCertificationStatus
*/ */
public function setAccessibilityCertificationStatus($accessibilityCertificationStatus): void public function setAccessibilityCertificationStatus($accessibilityCertificationStatus): void
@ -121,6 +98,7 @@ class AccessibilityCertification implements MapsToType
/** /**
* @internal for mapping via Symfony component. * @internal for mapping via Symfony component.
*
* @param string|array $certificationAccessibilityDeaf * @param string|array $certificationAccessibilityDeaf
*/ */
public function setCertificationAccessibilityDeaf($certificationAccessibilityDeaf): void public function setCertificationAccessibilityDeaf($certificationAccessibilityDeaf): void
@ -133,6 +111,7 @@ class AccessibilityCertification implements MapsToType
/** /**
* @internal for mapping via Symfony component. * @internal for mapping via Symfony component.
*
* @param string|array $certificationAccessibilityMental * @param string|array $certificationAccessibilityMental
*/ */
public function setCertificationAccessibilityMental($certificationAccessibilityMental): void public function setCertificationAccessibilityMental($certificationAccessibilityMental): void
@ -145,6 +124,7 @@ class AccessibilityCertification implements MapsToType
/** /**
* @internal for mapping via Symfony component. * @internal for mapping via Symfony component.
*
* @param string|array $certificationAccessibilityPartiallyDeaf * @param string|array $certificationAccessibilityPartiallyDeaf
*/ */
public function setCertificationAccessibilityPartiallyDeaf($certificationAccessibilityPartiallyDeaf): void public function setCertificationAccessibilityPartiallyDeaf($certificationAccessibilityPartiallyDeaf): void
@ -157,6 +137,7 @@ class AccessibilityCertification implements MapsToType
/** /**
* @internal for mapping via Symfony component. * @internal for mapping via Symfony component.
*
* @param string|array $certificationAccessibilityPartiallyVisual * @param string|array $certificationAccessibilityPartiallyVisual
*/ */
public function setCertificationAccessibilityPartiallyVisual($certificationAccessibilityPartiallyVisual): void public function setCertificationAccessibilityPartiallyVisual($certificationAccessibilityPartiallyVisual): void
@ -169,6 +150,7 @@ class AccessibilityCertification implements MapsToType
/** /**
* @internal for mapping via Symfony component. * @internal for mapping via Symfony component.
*
* @param string|array $certificationAccessibilityVisual * @param string|array $certificationAccessibilityVisual
*/ */
public function setCertificationAccessibilityVisual($certificationAccessibilityVisual): void public function setCertificationAccessibilityVisual($certificationAccessibilityVisual): void
@ -181,6 +163,7 @@ class AccessibilityCertification implements MapsToType
/** /**
* @internal for mapping via Symfony component. * @internal for mapping via Symfony component.
*
* @param string|array $certificationAccessibilityWalking * @param string|array $certificationAccessibilityWalking
*/ */
public function setCertificationAccessibilityWalking($certificationAccessibilityWalking): void public function setCertificationAccessibilityWalking($certificationAccessibilityWalking): void
@ -193,6 +176,7 @@ class AccessibilityCertification implements MapsToType
/** /**
* @internal for mapping via Symfony component. * @internal for mapping via Symfony component.
*
* @param string|array $certificationAccessibilityWheelchair * @param string|array $certificationAccessibilityWheelchair
*/ */
public function setCertificationAccessibilityWheelchair($certificationAccessibilityWheelchair): void public function setCertificationAccessibilityWheelchair($certificationAccessibilityWheelchair): void

View file

@ -27,45 +27,21 @@ use WerkraumMedia\ThueCat\Domain\Import\EntityMapper\PropertyValues;
class AccessibilitySpecification implements MapsToType class AccessibilitySpecification implements MapsToType
{ {
/** protected AccessibilityCertification $accessibilityCertification;
* @var AccessibilityCertification
*/
protected $accessibilityCertification;
/** protected array $accessibilitySearchCriteria = [];
* @var array
*/
protected $accessibilitySearchCriteria = [];
/** protected string $shortDescriptionAccessibilityAllGenerations = '';
* @var string
*/
protected $shortDescriptionAccessibilityAllGenerations = '';
/** protected string $shortDescriptionAccessibilityAllergic = '';
* @var string
*/
protected $shortDescriptionAccessibilityAllergic = '';
/** protected string $shortDescriptionAccessibilityDeaf = '';
* @var string
*/
protected $shortDescriptionAccessibilityDeaf = '';
/** protected string $shortDescriptionAccessibilityMental = '';
* @var string
*/
protected $shortDescriptionAccessibilityMental = '';
/** protected string $shortDescriptionAccessibilityVisual = '';
* @var string
*/
protected $shortDescriptionAccessibilityVisual = '';
/** protected string $shortDescriptionAccessibilityWalking = '';
* @var string
*/
protected $shortDescriptionAccessibilityWalking = '';
public function getAccessibilityCertification(): ?AccessibilityCertification public function getAccessibilityCertification(): ?AccessibilityCertification
{ {

View file

@ -30,17 +30,14 @@ class Base extends Minimum
{ {
use ManagedBy; use ManagedBy;
/** protected ?ForeignReference $photo = null;
* @var ForeignReference
*/
protected $photo;
/** /**
* Images of this Thing. * Images of this Thing.
* *
* @var ForeignReference[] * @var ForeignReference[]
*/ */
protected $images = []; protected array $images = [];
public function getPhoto(): ?ForeignReference public function getPhoto(): ?ForeignReference
{ {
@ -65,6 +62,7 @@ class Base extends Minimum
/** /**
* @internal for mapping via Symfony component. * @internal for mapping via Symfony component.
*
* @return ForeignReference[] * @return ForeignReference[]
*/ */
public function getImage(): array public function getImage(): array

View file

@ -35,6 +35,7 @@ interface MapsToType
* - thuecat:TouristInformation * - thuecat:TouristInformation
* - thuecat:Town * - thuecat:Town
* - * -
*
* @return string[] * @return string[]
*/ */
public static function getSupportedTypes(): array; public static function getSupportedTypes(): array;

View file

@ -27,30 +27,18 @@ use WerkraumMedia\ThueCat\Domain\Import\Entity\Properties\ForeignReference;
class MediaObject extends Minimum implements MapsToType class MediaObject extends Minimum implements MapsToType
{ {
/** protected int $copyrightYear = 0;
* @var int
*/
protected $copyrightYear = 0;
/** protected string $license = '';
* @var string
*/
protected $license = '';
/** protected string $licenseAuthor = '';
* @var string
*/
protected $licenseAuthor = '';
/** /**
* @var string|ForeignReference * @var string|ForeignReference
*/ */
protected $author; protected $author;
/** protected string $type = '';
* @var string
*/
protected $type = '';
public function getCopyrightYear(): int public function getCopyrightYear(): int
{ {
@ -85,7 +73,7 @@ class MediaObject extends Minimum implements MapsToType
*/ */
public function setCopyrightYear(string $copyrightYear): void public function setCopyrightYear(string $copyrightYear): void
{ {
$this->copyrightYear = (int) $copyrightYear; $this->copyrightYear = (int)$copyrightYear;
} }
/** /**
@ -106,6 +94,7 @@ class MediaObject extends Minimum implements MapsToType
/** /**
* @internal for mapping via Symfony component. * @internal for mapping via Symfony component.
*
* @param string|ForeignReference $author * @param string|ForeignReference $author
*/ */
public function setAuthor($author): void public function setAuthor($author): void

View file

@ -29,33 +29,27 @@ abstract class Minimum
* URL to the original source at ThüCAT. * URL to the original source at ThüCAT.
* Not unique within our system. We have one entity per language, * Not unique within our system. We have one entity per language,
* while ThüCAT has a single entity containing all languages. * while ThüCAT has a single entity containing all languages.
*
* @var string
*/ */
protected $id = ''; protected string $id = '';
/** /**
* Short name of the thing. * Short name of the thing.
* Can be translated. * Can be translated.
*
* @var string
*/ */
protected $name = ''; protected string $name = '';
/** /**
* Long text describing the thing. * Long text describing the thing.
* Can be translated. * Can be translated.
*
* @var string
*/ */
protected $description = ''; protected string $description = '';
/** /**
* URL to official version of this thing outside of ThüCAT. * URL to official version of this thing outside of ThüCAT.
* *
* @var string[] * @var string[]
*/ */
protected $urls = []; protected array $urls = [];
public function getId(): string public function getId(): string
{ {
@ -108,6 +102,7 @@ abstract class Minimum
/** /**
* @internal for mapping via Symfony component. * @internal for mapping via Symfony component.
*
* @param string|array $url * @param string|array $url
*/ */
public function setUrl($url): void public function setUrl($url): void

View file

@ -25,15 +25,9 @@ namespace WerkraumMedia\ThueCat\Domain\Import\Entity;
class Person extends Base implements MapsToType class Person extends Base implements MapsToType
{ {
/** protected string $givenName = '';
* @var string
*/
protected $givenName = '';
/** protected string $familyName = '';
* @var string
*/
protected $familyName = '';
public function getGivenName(): string public function getGivenName(): string
{ {

View file

@ -23,14 +23,15 @@ declare(strict_types=1);
namespace WerkraumMedia\ThueCat\Domain\Import\Entity; namespace WerkraumMedia\ThueCat\Domain\Import\Entity;
use DateTimeImmutable;
use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Core\Utility\GeneralUtility;
use WerkraumMedia\ThueCat\Domain\Import\EntityMapper\PropertyValues;
use WerkraumMedia\ThueCat\Domain\Import\Entity\Properties\Address; use WerkraumMedia\ThueCat\Domain\Import\Entity\Properties\Address;
use WerkraumMedia\ThueCat\Domain\Import\Entity\Properties\ForeignReference; use WerkraumMedia\ThueCat\Domain\Import\Entity\Properties\ForeignReference;
use WerkraumMedia\ThueCat\Domain\Import\Entity\Properties\Geo; use WerkraumMedia\ThueCat\Domain\Import\Entity\Properties\Geo;
use WerkraumMedia\ThueCat\Domain\Import\Entity\Properties\OpeningHour; use WerkraumMedia\ThueCat\Domain\Import\Entity\Properties\OpeningHour;
use WerkraumMedia\ThueCat\Domain\Import\Entity\Shared\ContainedInPlace; use WerkraumMedia\ThueCat\Domain\Import\Entity\Shared\ContainedInPlace;
use WerkraumMedia\ThueCat\Domain\Import\Entity\Shared\Organization; use WerkraumMedia\ThueCat\Domain\Import\Entity\Shared\Organization;
use WerkraumMedia\ThueCat\Domain\Import\EntityMapper\PropertyValues;
use WerkraumMedia\ThueCat\Service\DateBasedFilter; use WerkraumMedia\ThueCat\Service\DateBasedFilter;
class Place extends Base class Place extends Base
@ -38,60 +39,48 @@ class Place extends Base
use Organization; use Organization;
use ContainedInPlace; use ContainedInPlace;
/** protected ?Address $address = null;
* @var Address
*/
protected $address;
/** protected ?Geo $geo = null;
* @var Geo
*/
protected $geo;
/** /**
* @var OpeningHour[] * @var OpeningHour[]
*/ */
protected $openingHoursSpecifications = []; protected array $openingHoursSpecifications = [];
/** /**
* @var OpeningHour[] * @var OpeningHour[]
*/ */
protected $specialOpeningHours = []; protected array $specialOpeningHours = [];
/** /**
* @var ForeignReference[] * @var ForeignReference[]
*/ */
protected $parkingFacilitiesNearBy = []; protected array $parkingFacilitiesNearBy = [];
/** /**
* @var string[] * @var string[]
*/ */
protected $sanitations = []; protected array $sanitations = [];
/** /**
* @var string[] * @var string[]
*/ */
protected $otherServices = []; protected array $otherServices = [];
/** /**
* @var string[] * @var string[]
*/ */
protected $trafficInfrastructures = []; protected array $trafficInfrastructures = [];
/** /**
* @var string[] * @var string[]
*/ */
protected $paymentsAccepted = []; protected array $paymentsAccepted = [];
/** protected string $distanceToPublicTransport = '';
* @var string
*/
protected $distanceToPublicTransport = '';
/** protected ?ForeignReference $accessibilitySpecification = null;
* @var ForeignReference
*/
protected $accessibilitySpecification;
public function getAddress(): ?Address public function getAddress(): ?Address
{ {
@ -161,10 +150,11 @@ class Place extends Base
return GeneralUtility::makeInstance(DateBasedFilter::class) return GeneralUtility::makeInstance(DateBasedFilter::class)
->filterOutPreviousDates( ->filterOutPreviousDates(
$this->openingHoursSpecifications, $this->openingHoursSpecifications,
function (OpeningHour $hour): ?\DateTimeImmutable { function (OpeningHour $hour): ?DateTimeImmutable {
return $hour->getValidThrough(); return $hour->getValidThrough();
} }
); )
;
} }
/** /**
@ -175,10 +165,11 @@ class Place extends Base
return GeneralUtility::makeInstance(DateBasedFilter::class) return GeneralUtility::makeInstance(DateBasedFilter::class)
->filterOutPreviousDates( ->filterOutPreviousDates(
$this->specialOpeningHours, $this->specialOpeningHours,
function (OpeningHour $hour): ?\DateTimeImmutable { function (OpeningHour $hour): ?DateTimeImmutable {
return $hour->getValidThrough(); return $hour->getValidThrough();
} }
); )
;
} }
/** /**
@ -252,6 +243,7 @@ class Place extends Base
/** /**
* @internal for mapping via Symfony component. * @internal for mapping via Symfony component.
*
* @param string|array $sanitation * @param string|array $sanitation
*/ */
public function setSanitation($sanitation): void public function setSanitation($sanitation): void
@ -265,6 +257,7 @@ class Place extends Base
/** /**
* @internal for mapping via Symfony component. * @internal for mapping via Symfony component.
*
* @param string|array $otherService * @param string|array $otherService
*/ */
public function setOtherService($otherService): void public function setOtherService($otherService): void
@ -278,6 +271,7 @@ class Place extends Base
/** /**
* @internal for mapping via Symfony component. * @internal for mapping via Symfony component.
*
* @param string|array $trafficInfrastructure * @param string|array $trafficInfrastructure
*/ */
public function setTrafficInfrastructure($trafficInfrastructure): void public function setTrafficInfrastructure($trafficInfrastructure): void
@ -291,6 +285,7 @@ class Place extends Base
/** /**
* @internal for mapping via Symfony component. * @internal for mapping via Symfony component.
*
* @param string|array $paymentAccepted * @param string|array $paymentAccepted
*/ */
public function setPaymentAccepted($paymentAccepted): void public function setPaymentAccepted($paymentAccepted): void

View file

@ -25,35 +25,17 @@ namespace WerkraumMedia\ThueCat\Domain\Import\Entity\Properties;
class Address class Address
{ {
/** protected string $streetAddress = '';
* @var string
*/
protected $streetAddress = '';
/** protected string $addressLocality = '';
* @var string
*/
protected $addressLocality = '';
/** protected string $postalCode = '';
* @var string
*/
protected $postalCode = '';
/** protected string $telephone = '';
* @var string
*/
protected $telephone = '';
/** protected string $faxNumber = '';
* @var string
*/
protected $faxNumber = '';
/** protected string $email = '';
* @var string
*/
protected $email = '';
public function getStreetAddress(): string public function getStreetAddress(): string
{ {

View file

@ -25,14 +25,8 @@ namespace WerkraumMedia\ThueCat\Domain\Import\Entity\Properties;
class DayOfWeek class DayOfWeek
{ {
/**
* @var string
*/
protected $dayOfWeek = '';
public function __construct( public function __construct(
string $dayOfWeek protected string $dayOfWeek
) { ) {
$this->dayOfWeek = $dayOfWeek;
} }
} }

View file

@ -33,10 +33,8 @@ class ForeignReference
* URL to the original source at ThüCAT. * URL to the original source at ThüCAT.
* Not unique within our system. We have one entity per language, * Not unique within our system. We have one entity per language,
* while ThüCAT has a single entity containing all languages. * while ThüCAT has a single entity containing all languages.
*
* @var string
*/ */
protected $id = ''; protected string $id = '';
public function getId(): string public function getId(): string
{ {

View file

@ -25,15 +25,9 @@ namespace WerkraumMedia\ThueCat\Domain\Import\Entity\Properties;
class Geo class Geo
{ {
/** protected float $longitude = 0.00;
* @var float
*/
protected $longitude = 0.00;
/** protected float $latitude = 0.00;
* @var float
*/
protected $latitude = 0.00;
public function getLongitude(): float public function getLongitude(): float
{ {
@ -50,7 +44,7 @@ class Geo
*/ */
public function setLongitude(string $longitude): void public function setLongitude(string $longitude): void
{ {
$this->longitude = (float) $longitude; $this->longitude = (float)$longitude;
} }
/** /**
@ -58,6 +52,6 @@ class Geo
*/ */
public function setLatitude(string $latitude): void public function setLatitude(string $latitude): void
{ {
$this->latitude = (float) $latitude; $this->latitude = (float)$latitude;
} }
} }

View file

@ -23,20 +23,20 @@ declare(strict_types=1);
namespace WerkraumMedia\ThueCat\Domain\Import\Entity\Properties; namespace WerkraumMedia\ThueCat\Domain\Import\Entity\Properties;
use WerkraumMedia\ThueCat\Domain\Import\EntityMapper\PropertyValues;
use WerkraumMedia\ThueCat\Domain\Import\Entity\Minimum; use WerkraumMedia\ThueCat\Domain\Import\Entity\Minimum;
use WerkraumMedia\ThueCat\Domain\Import\EntityMapper\PropertyValues;
class Offer extends Minimum class Offer extends Minimum
{ {
/** /**
* @var string[] * @var string[]
*/ */
protected $offerTypes = []; protected array $offerTypes = [];
/** /**
* @var PriceSpecification[] * @var PriceSpecification[]
*/ */
protected $prices = []; protected array $prices = [];
/** /**
* @return string[] * @return string[]
@ -48,6 +48,7 @@ class Offer extends Minimum
/** /**
* @internal for mapping via Symfony component. * @internal for mapping via Symfony component.
*
* @param string|array $offerType * @param string|array $offerType
*/ */
public function setOfferType($offerType): void public function setOfferType($offerType): void
@ -57,7 +58,7 @@ class Offer extends Minimum
} }
$this->offerTypes = array_map( $this->offerTypes = array_map(
[PropertyValues::class, 'removePrefixFromEntry'], PropertyValues::removePrefixFromEntry(...),
$offerType $offerType
); );
} }
@ -72,6 +73,7 @@ class Offer extends Minimum
/** /**
* @return PriceSpecification[] * @return PriceSpecification[]
*
* @internal for mapping via Symfony component. * @internal for mapping via Symfony component.
*/ */
public function getPriceSpecification(): array public function getPriceSpecification(): array

View file

@ -23,49 +23,39 @@ declare(strict_types=1);
namespace WerkraumMedia\ThueCat\Domain\Import\Entity\Properties; namespace WerkraumMedia\ThueCat\Domain\Import\Entity\Properties;
use DateTimeImmutable;
class OpeningHour class OpeningHour
{ {
/** protected ?DateTimeImmutable $validFrom = null;
* @var \DateTimeImmutable|null
*/
protected $validFrom = null;
/** protected ?DateTimeImmutable $validThrough = null;
* @var \DateTimeImmutable|null
*/
protected $validThrough = null;
/** protected DateTimeImmutable $opens;
* @var \DateTimeImmutable
*/
protected $opens;
/** protected DateTimeImmutable $closes;
* @var \DateTimeImmutable
*/
protected $closes;
/** /**
* @var string[] * @var string[]
*/ */
protected $daysOfWeek = []; protected array $daysOfWeek = [];
public function getValidFrom(): ?\DateTimeImmutable public function getValidFrom(): ?DateTimeImmutable
{ {
return $this->validFrom; return $this->validFrom;
} }
public function getValidThrough(): ?\DateTimeImmutable public function getValidThrough(): ?DateTimeImmutable
{ {
return $this->validThrough; return $this->validThrough;
} }
public function getOpens(): \DateTimeImmutable public function getOpens(): DateTimeImmutable
{ {
return $this->opens; return $this->opens;
} }
public function getCloses(): \DateTimeImmutable public function getCloses(): DateTimeImmutable
{ {
return $this->closes; return $this->closes;
} }
@ -81,7 +71,7 @@ class OpeningHour
/** /**
* @internal for mapping via Symfony component. * @internal for mapping via Symfony component.
*/ */
public function setValidFrom(\DateTimeImmutable $validFrom): void public function setValidFrom(DateTimeImmutable $validFrom): void
{ {
$this->validFrom = $validFrom; $this->validFrom = $validFrom;
} }
@ -89,7 +79,7 @@ class OpeningHour
/** /**
* @internal for mapping via Symfony component. * @internal for mapping via Symfony component.
*/ */
public function setValidThrough(\DateTimeImmutable $validThrough): void public function setValidThrough(DateTimeImmutable $validThrough): void
{ {
$this->validThrough = $validThrough; $this->validThrough = $validThrough;
} }
@ -97,7 +87,7 @@ class OpeningHour
/** /**
* @internal for mapping via Symfony component. * @internal for mapping via Symfony component.
*/ */
public function setOpens(\DateTimeImmutable $opens): void public function setOpens(DateTimeImmutable $opens): void
{ {
$this->opens = $opens; $this->opens = $opens;
} }
@ -105,7 +95,7 @@ class OpeningHour
/** /**
* @internal for mapping via Symfony component. * @internal for mapping via Symfony component.
*/ */
public function setCloses(\DateTimeImmutable $closes): void public function setCloses(DateTimeImmutable $closes): void
{ {
$this->closes = $closes; $this->closes = $closes;
} }

View file

@ -23,31 +23,24 @@ declare(strict_types=1);
namespace WerkraumMedia\ThueCat\Domain\Import\Entity\Properties; namespace WerkraumMedia\ThueCat\Domain\Import\Entity\Properties;
use WerkraumMedia\ThueCat\Domain\Import\EntityMapper\PropertyValues;
use WerkraumMedia\ThueCat\Domain\Import\Entity\Minimum; use WerkraumMedia\ThueCat\Domain\Import\Entity\Minimum;
use WerkraumMedia\ThueCat\Domain\Import\EntityMapper\PropertyValues;
class PriceSpecification extends Minimum class PriceSpecification extends Minimum
{ {
/** protected float $price = 0.00;
* @var float
*/
protected $price = 0.00;
/** /**
* E.g. 'EUR' * E.g. 'EUR'
* ThueCat specific format. * ThueCat specific format.
*
* @var string
*/ */
protected $currency = ''; protected string $currency = '';
/** /**
* E.g. 'PerPerson' * E.g. 'PerPerson'
* ThueCat specific property. * ThueCat specific property.
*
* @var array
*/ */
protected $calculationRules = []; protected array $calculationRules = [];
public function getPrice(): float public function getPrice(): float
{ {
@ -85,6 +78,7 @@ class PriceSpecification extends Minimum
/** /**
* @internal for mapping via Symfony component. * @internal for mapping via Symfony component.
*
* @param string|array $calculationRule * @param string|array $calculationRule
*/ */
public function setCalculationRule($calculationRule): void public function setCalculationRule($calculationRule): void

View file

@ -42,6 +42,7 @@ trait ContainedInPlace
/** /**
* @return ForeignReference[] * @return ForeignReference[]
*
* @internal for mapping via Symfony component. * @internal for mapping via Symfony component.
*/ */
public function getContainedInPlace(): array public function getContainedInPlace(): array

View file

@ -29,10 +29,8 @@ trait ManagedBy
{ {
/** /**
* The Thing responsible for the data within this Thing. * The Thing responsible for the data within this Thing.
*
* @var ForeignReference
*/ */
protected $managedBy; protected ?ForeignReference $managedBy = null;
public function getManagedBy(): ?ForeignReference public function getManagedBy(): ?ForeignReference
{ {

View file

@ -34,7 +34,7 @@ trait Organization
/** /**
* @var Offer[] * @var Offer[]
*/ */
protected $offers = []; protected array $offers = [];
/** /**
* @return Offer[] * @return Offer[]
@ -46,6 +46,7 @@ trait Organization
/** /**
* @internal for mapping via Symfony component. * @internal for mapping via Symfony component.
*
* @return Offer[] * @return Offer[]
*/ */
public function getMakesOffer(): array public function getMakesOffer(): array

View file

@ -27,55 +27,40 @@ use WerkraumMedia\ThueCat\Domain\Import\EntityMapper\PropertyValues;
class TouristAttraction extends Place implements MapsToType class TouristAttraction extends Place implements MapsToType
{ {
/** protected string $slogan = '';
* @var string
*/
protected $slogan = '';
/** protected string $startOfConstruction = '';
* @var string
*/
protected $startOfConstruction = '';
/** /**
* @var string[] * @var string[]
*/ */
protected $museumServices = []; protected array $museumServices = [];
/** /**
* @var string[] * @var string[]
*/ */
protected $architecturalStyles = []; protected array $architecturalStyles = [];
/** /**
* @var string[] * @var string[]
*/ */
protected $digitalOffers = []; protected array $digitalOffers = [];
/** /**
* @var string[] * @var string[]
*/ */
protected $photographies = []; protected array $photographies = [];
/** protected string $petsAllowed = '';
* @var string
*/
protected $petsAllowed = '';
/** protected string $isAccessibleForFree = '';
* @var string
*/
protected $isAccessibleForFree = '';
/** protected string $publicAccess = '';
* @var string
*/
protected $publicAccess = '';
/** /**
* @var string[] * @var string[]
*/ */
protected $availableLanguages = []; protected array $availableLanguages = [];
public function getSlogan(): string public function getSlogan(): string
{ {
@ -160,6 +145,7 @@ class TouristAttraction extends Place implements MapsToType
/** /**
* @internal for mapping via Symfony component. * @internal for mapping via Symfony component.
*
* @param string|array $museumService * @param string|array $museumService
*/ */
public function setMuseumService($museumService): void public function setMuseumService($museumService): void
@ -173,6 +159,7 @@ class TouristAttraction extends Place implements MapsToType
/** /**
* @internal for mapping via Symfony component. * @internal for mapping via Symfony component.
*
* @param string|array $architecturalStyle * @param string|array $architecturalStyle
*/ */
public function setArchitecturalStyle($architecturalStyle): void public function setArchitecturalStyle($architecturalStyle): void
@ -186,6 +173,7 @@ class TouristAttraction extends Place implements MapsToType
/** /**
* @internal for mapping via Symfony component. * @internal for mapping via Symfony component.
*
* @param string|array $digitalOffer * @param string|array $digitalOffer
*/ */
public function setDigitalOffer($digitalOffer): void public function setDigitalOffer($digitalOffer): void
@ -199,6 +187,7 @@ class TouristAttraction extends Place implements MapsToType
/** /**
* @internal for mapping via Symfony component. * @internal for mapping via Symfony component.
*
* @param string|array $photography * @param string|array $photography
*/ */
public function setPhotography($photography): void public function setPhotography($photography): void
@ -236,6 +225,7 @@ class TouristAttraction extends Place implements MapsToType
/** /**
* @internal for mapping via Symfony component. * @internal for mapping via Symfony component.
*
* @param string|array $availableLanguage * @param string|array $availableLanguage
*/ */
public function setAvailableLanguage($availableLanguage): void public function setAvailableLanguage($availableLanguage): void

View file

@ -30,6 +30,7 @@ use Symfony\Component\Serializer\Encoder\JsonEncoder;
use Symfony\Component\Serializer\Normalizer\DateTimeNormalizer; use Symfony\Component\Serializer\Normalizer\DateTimeNormalizer;
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer; use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
use Symfony\Component\Serializer\Serializer; use Symfony\Component\Serializer\Serializer;
use Throwable;
use WerkraumMedia\ThueCat\Domain\Import\EntityMapper\ArrayDenormalizer; use WerkraumMedia\ThueCat\Domain\Import\EntityMapper\ArrayDenormalizer;
use WerkraumMedia\ThueCat\Domain\Import\EntityMapper\CustomAnnotationExtractor; use WerkraumMedia\ThueCat\Domain\Import\EntityMapper\CustomAnnotationExtractor;
use WerkraumMedia\ThueCat\Domain\Import\EntityMapper\JsonDecode; use WerkraumMedia\ThueCat\Domain\Import\EntityMapper\JsonDecode;
@ -50,12 +51,12 @@ class EntityMapper
try { try {
return $serializer->deserialize( return $serializer->deserialize(
json_encode($jsonLD), json_encode($jsonLD, JSON_THROW_ON_ERROR),
$targetClassName, $targetClassName,
'json', 'json',
$context $context
); );
} catch (\Throwable $e) { } catch (Throwable $e) {
throw new MappingException($jsonLD, $targetClassName, $e); throw new MappingException($jsonLD, $targetClassName, $e);
} }
} }

View file

@ -23,13 +23,21 @@ declare(strict_types=1);
namespace WerkraumMedia\ThueCat\Domain\Import\EntityMapper; namespace WerkraumMedia\ThueCat\Domain\Import\EntityMapper;
use function in_array;
use InvalidArgumentException;
use LogicException; use LogicException;
use phpDocumentor\Reflection\DocBlock; use phpDocumentor\Reflection\DocBlock;
use phpDocumentor\Reflection\DocBlock\Tags\InvalidTag;
use phpDocumentor\Reflection\DocBlock\Tags\Param;
use phpDocumentor\Reflection\DocBlockFactory; use phpDocumentor\Reflection\DocBlockFactory;
use phpDocumentor\Reflection\DocBlockFactoryInterface; use phpDocumentor\Reflection\DocBlockFactoryInterface;
use phpDocumentor\Reflection\DocBlock\Tags\InvalidTag;
use phpDocumentor\Reflection\Types\Context; use phpDocumentor\Reflection\Types\Context;
use phpDocumentor\Reflection\Types\ContextFactory; use phpDocumentor\Reflection\Types\ContextFactory;
use ReflectionClass;
use ReflectionException;
use ReflectionMethod;
use ReflectionProperty;
use RuntimeException;
use Symfony\Component\PropertyInfo\Extractor\ConstructorArgumentTypeExtractorInterface; use Symfony\Component\PropertyInfo\Extractor\ConstructorArgumentTypeExtractorInterface;
use Symfony\Component\PropertyInfo\Extractor\ReflectionExtractor; use Symfony\Component\PropertyInfo\Extractor\ReflectionExtractor;
use Symfony\Component\PropertyInfo\PropertyDescriptionExtractorInterface; use Symfony\Component\PropertyInfo\PropertyDescriptionExtractorInterface;
@ -46,26 +54,26 @@ use Symfony\Component\PropertyInfo\Util\PhpDocTypeHelper;
*/ */
class CustomAnnotationExtractor implements PropertyDescriptionExtractorInterface, PropertyTypeExtractorInterface, ConstructorArgumentTypeExtractorInterface class CustomAnnotationExtractor implements PropertyDescriptionExtractorInterface, PropertyTypeExtractorInterface, ConstructorArgumentTypeExtractorInterface
{ {
public const PROPERTY = 0; final public const PROPERTY = 0;
public const ACCESSOR = 1; final public const ACCESSOR = 1;
public const MUTATOR = 2; final public const MUTATOR = 2;
/** /**
* @var array<string, array{DocBlock|null, int|null, string|null}> * @var array<string, array{DocBlock|null, int|null, string|null}>
*/ */
private $docBlocks = []; private array $docBlocks = [];
/** /**
* @var Context[] * @var Context[]
*/ */
private $contexts = []; private array $contexts = [];
private $docBlockFactory; private readonly \phpDocumentor\Reflection\DocBlockFactoryInterface $docBlockFactory;
private $contextFactory; private readonly \phpDocumentor\Reflection\Types\ContextFactory $contextFactory;
private $phpDocTypeHelper; private readonly \Symfony\Component\PropertyInfo\Util\PhpDocTypeHelper $phpDocTypeHelper;
private $mutatorPrefixes; private readonly array $mutatorPrefixes;
private $accessorPrefixes; private readonly array $accessorPrefixes;
private $arrayMutatorPrefixes; private readonly array $arrayMutatorPrefixes;
/** /**
* @param string[]|null $mutatorPrefixes * @param string[]|null $mutatorPrefixes
@ -75,7 +83,7 @@ class CustomAnnotationExtractor implements PropertyDescriptionExtractorInterface
public function __construct(DocBlockFactoryInterface $docBlockFactory = null, array $mutatorPrefixes = null, array $accessorPrefixes = null, array $arrayMutatorPrefixes = null) public function __construct(DocBlockFactoryInterface $docBlockFactory = null, array $mutatorPrefixes = null, array $accessorPrefixes = null, array $arrayMutatorPrefixes = null)
{ {
if (!class_exists(DocBlockFactory::class)) { if (!class_exists(DocBlockFactory::class)) {
throw new \LogicException(sprintf('Unable to use the "%s" class as the "phpdocumentor/reflection-docblock" package is not installed. Try running composer require "phpdocumentor/reflection-docblock".', __CLASS__)); throw new LogicException(sprintf('Unable to use the "%s" class as the "phpdocumentor/reflection-docblock" package is not installed. Try running composer require "phpdocumentor/reflection-docblock".', self::class));
} }
$this->docBlockFactory = $docBlockFactory ?: DocBlockFactory::createInstance(); $this->docBlockFactory = $docBlockFactory ?: DocBlockFactory::createInstance();
@ -129,7 +137,7 @@ class CustomAnnotationExtractor implements PropertyDescriptionExtractorInterface
$contents = $docBlock->getDescription()->render(); $contents = $docBlock->getDescription()->render();
return '' === $contents ? null : $contents; return $contents === '' ? null : $contents;
} }
/** /**
@ -161,7 +169,7 @@ class CustomAnnotationExtractor implements PropertyDescriptionExtractorInterface
$types = []; $types = [];
/** @var DocBlock\Tags\Var_|DocBlock\Tags\Return_|DocBlock\Tags\Param $tag */ /** @var DocBlock\Tags\Var_|DocBlock\Tags\Return_|DocBlock\Tags\Param $tag */
foreach ($docBlock->getTagsByName($tag) as $tag) { foreach ($docBlock->getTagsByName($tag) as $tag) {
if ($tag && !$tag instanceof InvalidTag && null !== $tag->getType()) { if ($tag && !$tag instanceof InvalidTag && $tag->getType() !== null) {
foreach ($this->phpDocTypeHelper->getTypes($tag->getType()) as $type) { foreach ($this->phpDocTypeHelper->getTypes($tag->getType()) as $type) {
switch ($type->getClassName()) { switch ($type->getClassName()) {
case 'self': case 'self':
@ -189,7 +197,7 @@ class CustomAnnotationExtractor implements PropertyDescriptionExtractorInterface
return null; return null;
} }
if (!\in_array($prefix, $this->arrayMutatorPrefixes)) { if (!in_array($prefix, $this->arrayMutatorPrefixes)) {
return $types; return $types;
} }
@ -210,12 +218,12 @@ class CustomAnnotationExtractor implements PropertyDescriptionExtractorInterface
$types = []; $types = [];
/** @var DocBlock\Tags\Var_|DocBlock\Tags\Return_|DocBlock\Tags\Param $tag */ /** @var DocBlock\Tags\Var_|DocBlock\Tags\Return_|DocBlock\Tags\Param $tag */
foreach ($docBlock->getTagsByName('param') as $tag) { foreach ($docBlock->getTagsByName('param') as $tag) {
if ($tag && null !== $tag->getType()) { if ($tag && $tag->getType() !== null) {
$types[] = $this->phpDocTypeHelper->getTypes($tag->getType()); $types[] = $this->phpDocTypeHelper->getTypes($tag->getType());
} }
} }
if (!isset($types[0]) || [] === $types[0]) { if (!isset($types[0]) || $types[0] === []) {
return null; return null;
} }
@ -225,8 +233,8 @@ class CustomAnnotationExtractor implements PropertyDescriptionExtractorInterface
private function getDocBlockFromConstructor(string $class, string $property): ?DocBlock private function getDocBlockFromConstructor(string $class, string $property): ?DocBlock
{ {
try { try {
$reflectionClass = new \ReflectionClass($class); $reflectionClass = new ReflectionClass($class);
} catch (\ReflectionException $e) { } catch (ReflectionException $e) {
return null; return null;
} }
$reflectionConstructor = $reflectionClass->getConstructor(); $reflectionConstructor = $reflectionClass->getConstructor();
@ -238,7 +246,7 @@ class CustomAnnotationExtractor implements PropertyDescriptionExtractorInterface
$docBlock = $this->docBlockFactory->create($reflectionConstructor, $this->contextFactory->createFromReflector($reflectionConstructor)); $docBlock = $this->docBlockFactory->create($reflectionConstructor, $this->contextFactory->createFromReflector($reflectionConstructor));
return $this->filterDocBlockParams($docBlock, $property); return $this->filterDocBlockParams($docBlock, $property);
} catch (\InvalidArgumentException $e) { } catch (InvalidArgumentException) {
return null; return null;
} }
} }
@ -246,11 +254,18 @@ class CustomAnnotationExtractor implements PropertyDescriptionExtractorInterface
private function filterDocBlockParams(DocBlock $docBlock, string $allowedParam): DocBlock private function filterDocBlockParams(DocBlock $docBlock, string $allowedParam): DocBlock
{ {
$tags = array_values(array_filter($docBlock->getTagsByName('param'), function ($tag) use ($allowedParam) { $tags = array_values(array_filter($docBlock->getTagsByName('param'), function ($tag) use ($allowedParam) {
return $tag instanceof DocBlock\Tags\Param && $allowedParam === $tag->getVariableName(); return $tag instanceof Param && $allowedParam === $tag->getVariableName();
})); }));
return new DocBlock($docBlock->getSummary(), $docBlock->getDescription(), $tags, $docBlock->getContext(), return new DocBlock(
$docBlock->getLocation(), $docBlock->isTemplateStart(), $docBlock->isTemplateEnd()); $docBlock->getSummary(),
$docBlock->getDescription(),
$tags,
$docBlock->getContext(),
$docBlock->getLocation(),
$docBlock->isTemplateStart(),
$docBlock->isTemplateEnd()
);
} }
/** /**
@ -290,8 +305,8 @@ class CustomAnnotationExtractor implements PropertyDescriptionExtractorInterface
{ {
// Use a ReflectionProperty instead of $class to get the parent class if applicable // Use a ReflectionProperty instead of $class to get the parent class if applicable
try { try {
$reflectionProperty = new \ReflectionProperty($class, $property); $reflectionProperty = new ReflectionProperty($class, $property);
} catch (\ReflectionException $e) { } catch (ReflectionException $e) {
return null; return null;
} }
@ -305,7 +320,7 @@ class CustomAnnotationExtractor implements PropertyDescriptionExtractorInterface
try { try {
return $this->docBlockFactory->create($reflectionProperty, $this->createFromReflector($reflector)); return $this->docBlockFactory->create($reflectionProperty, $this->createFromReflector($reflector));
} catch (\InvalidArgumentException|\RuntimeException $e) { } catch (InvalidArgumentException|RuntimeException) {
return null; return null;
} }
} }
@ -315,25 +330,25 @@ class CustomAnnotationExtractor implements PropertyDescriptionExtractorInterface
*/ */
private function getDocBlockFromMethod(string $class, string $ucFirstProperty, int $type): ?array private function getDocBlockFromMethod(string $class, string $ucFirstProperty, int $type): ?array
{ {
$prefixes = self::ACCESSOR === $type ? $this->accessorPrefixes : $this->mutatorPrefixes; $prefixes = $type === self::ACCESSOR ? $this->accessorPrefixes : $this->mutatorPrefixes;
$prefix = null; $prefix = null;
foreach ($prefixes as $prefix) { foreach ($prefixes as $prefix) {
$methodName = $prefix.$ucFirstProperty; $methodName = $prefix . $ucFirstProperty;
try { try {
$reflectionMethod = new \ReflectionMethod($class, $methodName); $reflectionMethod = new ReflectionMethod($class, $methodName);
if ($reflectionMethod->isStatic()) { if ($reflectionMethod->isStatic()) {
continue; continue;
} }
if ( if (
(self::ACCESSOR === $type && 0 === $reflectionMethod->getNumberOfRequiredParameters()) || ($type === self::ACCESSOR && $reflectionMethod->getNumberOfRequiredParameters() === 0) ||
(self::MUTATOR === $type && $reflectionMethod->getNumberOfParameters() >= 1) ($type === self::MUTATOR && $reflectionMethod->getNumberOfParameters() >= 1)
) { ) {
break; break;
} }
} catch (\ReflectionException $e) { } catch (ReflectionException) {
// Try the next prefix if the method doesn't exist // Try the next prefix if the method doesn't exist
} }
} }
@ -352,7 +367,7 @@ class CustomAnnotationExtractor implements PropertyDescriptionExtractorInterface
try { try {
return [$this->docBlockFactory->create($reflectionMethod, $this->createFromReflector($reflector)), $prefix]; return [$this->docBlockFactory->create($reflectionMethod, $this->createFromReflector($reflector)), $prefix];
} catch (\InvalidArgumentException|\RuntimeException $e) { } catch (InvalidArgumentException|RuntimeException) {
return null; return null;
} }
} }
@ -360,9 +375,9 @@ class CustomAnnotationExtractor implements PropertyDescriptionExtractorInterface
/** /**
* Prevents a lot of redundant calls to ContextFactory::createForNamespace(). * Prevents a lot of redundant calls to ContextFactory::createForNamespace().
*/ */
private function createFromReflector(\ReflectionClass $reflector): Context private function createFromReflector(ReflectionClass $reflector): Context
{ {
$cacheKey = $reflector->getNamespaceName().':'.$reflector->getFileName(); $cacheKey = $reflector->getNamespaceName() . ':' . $reflector->getFileName();
if (isset($this->contexts[$cacheKey])) { if (isset($this->contexts[$cacheKey])) {
return $this->contexts[$cacheKey]; return $this->contexts[$cacheKey];

View file

@ -23,9 +23,6 @@ declare(strict_types=1);
namespace WerkraumMedia\ThueCat\Domain\Import\EntityMapper; namespace WerkraumMedia\ThueCat\Domain\Import\EntityMapper;
use TYPO3\CMS\Core\Utility\ArrayUtility;
/** /**
* Registry with supported entities and their types. * Registry with supported entities and their types.
*/ */
@ -34,7 +31,7 @@ class EntityRegistry
/** /**
* @var array[] * @var array[]
*/ */
private $entities = []; private array $entities = [];
/** /**
* @param string[] $supportedTypes * @param string[] $supportedTypes
@ -70,10 +67,9 @@ class EntityRegistry
return ''; return '';
} }
$matches = ArrayUtility::sortArraysByKey( usort($matches, static function (array $configA, array $configB): int {
$matches, return $configA['priority'] <=> $configB['priority'];
'priority' });
);
return end($matches)['entityClassName']; return end($matches)['entityClassName'];
} }

View file

@ -23,9 +23,8 @@ declare(strict_types=1);
namespace WerkraumMedia\ThueCat\Domain\Import\EntityMapper; namespace WerkraumMedia\ThueCat\Domain\Import\EntityMapper;
use InvalidArgumentException;
use Symfony\Component\Serializer\Encoder\JsonDecode as SymfonyJsonDecode; use Symfony\Component\Serializer\Encoder\JsonDecode as SymfonyJsonDecode;
use TYPO3\CMS\Core\Utility\StringUtility;
/** /**
* Used to add further necessary normalization on decoding incoming JSON structure. * Used to add further necessary normalization on decoding incoming JSON structure.
@ -34,12 +33,12 @@ use TYPO3\CMS\Core\Utility\StringUtility;
*/ */
class JsonDecode extends SymfonyJsonDecode class JsonDecode extends SymfonyJsonDecode
{ {
public const ACTIVE_LANGUAGE = 'active_language'; final public const ACTIVE_LANGUAGE = 'active_language';
/** /**
* @var array[] * @var array[]
*/ */
private $rulesToKeepTypeInfo = [ private array $rulesToKeepTypeInfo = [
[ [
'type' => 'beginsWith', 'type' => 'beginsWith',
'comparisonValue' => 'thuecat:facilityAccessibility', 'comparisonValue' => 'thuecat:facilityAccessibility',
@ -50,14 +49,13 @@ class JsonDecode extends SymfonyJsonDecode
string $data, string $data,
string $format, string $format,
array $context = [] array $context = []
) { ): mixed {
$context[self::ASSOCIATIVE] = true; $context[self::ASSOCIATIVE] = true;
$result = parent::decode($data, $format, $context); $result = parent::decode($data, $format, $context);
$activeLanguage = $context[self::ACTIVE_LANGUAGE] ?? ''; $activeLanguage = $context[self::ACTIVE_LANGUAGE] ?? '';
if ($activeLanguage === '') { if ($activeLanguage === '') {
throw new \InvalidArgumentException('Provide active language: ' . self::ACTIVE_LANGUAGE); throw new InvalidArgumentException('Provide active language: ' . self::ACTIVE_LANGUAGE);
} }
return $this->process( return $this->process(
@ -94,11 +92,11 @@ class JsonDecode extends SymfonyJsonDecode
* *
* This decode will resolve the list to a single value based on current language settings from context. * This decode will resolve the list to a single value based on current language settings from context.
* *
* @param mixed $value *
* @return mixed * @return mixed
*/ */
private function decodeLanguageSpecificValue( private function decodeLanguageSpecificValue(
&$value, mixed &$value,
string $activeLanguage string $activeLanguage
) { ) {
if (is_array($value) === false) { if (is_array($value) === false) {
@ -155,11 +153,11 @@ class JsonDecode extends SymfonyJsonDecode
* *
* This decode will resolve single values wrapped in array with extra info. * This decode will resolve single values wrapped in array with extra info.
* *
* @param mixed $value *
* @return mixed * @return mixed
*/ */
private function decodeSingleValues( private function decodeSingleValues(
&$value mixed &$value
) { ) {
if (is_array($value) === false) { if (is_array($value) === false) {
return $value; return $value;
@ -189,11 +187,11 @@ class JsonDecode extends SymfonyJsonDecode
/** /**
* Prepare data structure for PHP \DateTimeImmutable. * Prepare data structure for PHP \DateTimeImmutable.
* *
* @param mixed $value *
* @return mixed * @return mixed
*/ */
private function decodeDateTime( private function decodeDateTime(
&$value mixed &$value
) { ) {
$supportedTypes = [ $supportedTypes = [
'schema:Time', 'schema:Time',
@ -213,22 +211,21 @@ class JsonDecode extends SymfonyJsonDecode
} }
/** /**
* @param mixed $key
* @return mixed * @return mixed
*/ */
private function mapKey($key) private function mapKey(mixed $key)
{ {
if (is_string($key) === false) { if (is_string($key) === false) {
return $key; return $key;
} }
if (StringUtility::beginsWith($key, '@')) { if (str_starts_with($key, '@')) {
return mb_substr($key, 1); return mb_substr($key, 1);
} }
if (StringUtility::beginsWith($key, 'schema:')) { if (str_starts_with($key, 'schema:')) {
return mb_substr($key, 7); return mb_substr($key, 7);
} }
if (StringUtility::beginsWith($key, 'thuecat:')) { if (str_starts_with($key, 'thuecat:')) {
return mb_substr($key, 8); return mb_substr($key, 8);
} }
@ -238,7 +235,7 @@ class JsonDecode extends SymfonyJsonDecode
private function doesRuleMatch(array $rule, string $type): bool private function doesRuleMatch(array $rule, string $type): bool
{ {
if ($rule['type'] === 'beginsWith') { if ($rule['type'] === 'beginsWith') {
return StringUtility::beginsWith($type, $rule['comparisonValue']); return str_starts_with($type, (string)$rule['comparisonValue']);
} }
return false; return false;

View file

@ -23,30 +23,21 @@ declare(strict_types=1);
namespace WerkraumMedia\ThueCat\Domain\Import\EntityMapper; namespace WerkraumMedia\ThueCat\Domain\Import\EntityMapper;
class MappingException extends \Exception use Exception;
use Throwable;
class MappingException extends Exception
{ {
/**
* @var array
*/
protected $jsonLD = [];
/**
* @var string
*/
protected $targetClassName = '';
public function __construct( public function __construct(
array $jsonLD, protected array $jsonLD,
string $targetClassName, protected string $targetClassName,
\Throwable $previous Throwable $previous
) { ) {
parent::__construct( parent::__construct(
'Could not map incoming JSON-LD to target object: ' . $previous->getMessage(), 'Could not map incoming JSON-LD to target object: ' . $previous->getMessage(),
1628157659, 1628157659,
$previous $previous
); );
$this->jsonLD = $jsonLD;
$this->targetClassName = $targetClassName;
} }
public function getUrl(): string public function getUrl(): string

View file

@ -36,7 +36,7 @@ class PropertyValues
public static function removePrefixFromEntries(array $entriesWithPrefix): array public static function removePrefixFromEntries(array $entriesWithPrefix): array
{ {
return array_map( return array_map(
[PropertyValues::class, 'removePrefixFromEntry'], PropertyValues::removePrefixFromEntry(...),
$entriesWithPrefix $entriesWithPrefix
); );
} }

View file

@ -23,6 +23,7 @@ declare(strict_types=1);
namespace WerkraumMedia\ThueCat\Domain\Import; namespace WerkraumMedia\ThueCat\Domain\Import;
use InvalidArgumentException;
use WerkraumMedia\ThueCat\Domain\Model\Backend\ImportConfiguration as Typo3ImportConfiguration; use WerkraumMedia\ThueCat\Domain\Model\Backend\ImportConfiguration as Typo3ImportConfiguration;
use WerkraumMedia\ThueCat\Domain\Model\Backend\ImportLog; use WerkraumMedia\ThueCat\Domain\Model\Backend\ImportLog;
@ -37,27 +38,21 @@ class Import
/** /**
* @var ImportLog[] * @var ImportLog[]
*/ */
private $importLogStack = []; private array $importLogStack = [];
/** /**
* @var ImportConfiguration[] * @var ImportConfiguration[]
*/ */
private $configurationStack = []; private array $configurationStack = [];
/** private ImportLog $currentImportLog;
* @var ImportLog
*/
private $currentImportLog;
/** private ImportConfiguration $currentConfiguration;
* @var ImportConfiguration
*/
private $currentConfiguration;
public function start(ImportConfiguration $configuration): void public function start(ImportConfiguration $configuration): void
{ {
if (!$configuration instanceof Typo3ImportConfiguration) { if (!$configuration instanceof Typo3ImportConfiguration) {
throw new \InvalidArgumentException('Currently only can process ImportConfiguration of TYPO3.', 1629708772); throw new InvalidArgumentException('Currently only can process ImportConfiguration of TYPO3.', 1629708772);
} }
$this->currentConfiguration = $configuration; $this->currentConfiguration = $configuration;

View file

@ -23,12 +23,13 @@ declare(strict_types=1);
namespace WerkraumMedia\ThueCat\Domain\Import; namespace WerkraumMedia\ThueCat\Domain\Import;
use TYPO3\CMS\Core\Log\LogManager; use Exception;
use TYPO3\CMS\Core\Log\Logger; use TYPO3\CMS\Core\Log\Logger;
use TYPO3\CMS\Core\Log\LogManager;
use WerkraumMedia\ThueCat\Domain\Import\Entity\MapsToType;
use WerkraumMedia\ThueCat\Domain\Import\EntityMapper\EntityRegistry; use WerkraumMedia\ThueCat\Domain\Import\EntityMapper\EntityRegistry;
use WerkraumMedia\ThueCat\Domain\Import\EntityMapper\JsonDecode; use WerkraumMedia\ThueCat\Domain\Import\EntityMapper\JsonDecode;
use WerkraumMedia\ThueCat\Domain\Import\EntityMapper\MappingException; use WerkraumMedia\ThueCat\Domain\Import\EntityMapper\MappingException;
use WerkraumMedia\ThueCat\Domain\Import\Entity\MapsToType;
use WerkraumMedia\ThueCat\Domain\Import\Importer\Converter; use WerkraumMedia\ThueCat\Domain\Import\Importer\Converter;
use WerkraumMedia\ThueCat\Domain\Import\Importer\FetchData; use WerkraumMedia\ThueCat\Domain\Import\Importer\FetchData;
use WerkraumMedia\ThueCat\Domain\Import\Importer\Languages; use WerkraumMedia\ThueCat\Domain\Import\Importer\Languages;
@ -42,76 +43,22 @@ use WerkraumMedia\ThueCat\Domain\Repository\Backend\ImportLogRepository;
class Importer class Importer
{ {
/** private readonly Logger $logger;
* @var UrlProviderRegistry
*/
private $urls;
/** private readonly Import $import;
* @var Converter
*/
private $converter;
/**
* @var EntityRegistry
*/
private $entityRegistry;
/**
* @var EntityMapper
*/
private $entityMapper;
/**
* @var Languages
*/
private $languages;
/**
* @var FetchData
*/
private $fetchData;
/**
* @var SaveData
*/
private $saveData;
/**
* @var ImportLogRepository
*/
private $importLogRepository;
/**
* @var Logger
*/
private $logger;
/**
* @var Import
*/
private $import;
public function __construct( public function __construct(
UrlProviderRegistry $urls, private readonly UrlProviderRegistry $urls,
Converter $converter, private readonly Converter $converter,
EntityRegistry $entityRegistry, private readonly EntityRegistry $entityRegistry,
EntityMapper $entityMapper, private readonly EntityMapper $entityMapper,
Languages $languages, private readonly Languages $languages,
ImportLogRepository $importLogRepository, private readonly ImportLogRepository $importLogRepository,
FetchData $fetchData, private readonly FetchData $fetchData,
SaveData $saveData, private readonly SaveData $saveData,
LogManager $logManager LogManager $logManager
) { ) {
$this->urls = $urls; $this->logger = $logManager->getLogger(self::class);
$this->converter = $converter;
$this->entityRegistry = $entityRegistry;
$this->entityMapper = $entityMapper;
$this->languages = $languages;
$this->importLogRepository = $importLogRepository;
$this->fetchData = $fetchData;
$this->saveData = $saveData;
$this->logger = $logManager->getLogger(__CLASS__);
$this->import = new Import(); $this->import = new Import();
} }
@ -139,7 +86,7 @@ class Importer
{ {
$urlProvider = $this->urls->getProviderForConfiguration($this->import->getConfiguration()); $urlProvider = $this->urls->getProviderForConfiguration($this->import->getConfiguration());
if (!$urlProvider instanceof UrlProvider) { if (!$urlProvider instanceof UrlProvider) {
throw new \Exception('No URL Provider available for given configuration.', 1629296635); throw new Exception('No URL Provider available for given configuration.', 1629296635);
} }
foreach ($urlProvider->getUrls() as $url) { foreach ($urlProvider->getUrls() as $url) {
@ -196,7 +143,7 @@ class Importer
} }
if (!$mappedEntity instanceof MapsToType) { if (!$mappedEntity instanceof MapsToType) {
$this->logger->error('Mapping did not result in an MapsToType instance.', ['class' => get_class($mappedEntity)]); $this->logger->error('Mapping did not result in an MapsToType instance.', ['class' => $mappedEntity::class]);
continue; continue;
} }
@ -218,7 +165,8 @@ class Importer
'url' => $url, 'url' => $url,
'language' => $language, 'language' => $language,
'targetEntity' => $targetEntity, 'targetEntity' => $targetEntity,
]); ]
);
continue; continue;
} }
$entities->add($convertedEntity); $entities->add($convertedEntity);

View file

@ -32,39 +32,15 @@ use WerkraumMedia\ThueCat\Domain\Import\Importer\FetchData\InvalidResponseExcept
class FetchData class FetchData
{ {
/** private string $databaseUrlPrefix = 'https://cdb.thuecat.org';
* @var RequestFactoryInterface
*/
private $requestFactory;
/** private string $urlPrefix = 'https://thuecat.org';
* @var ClientInterface
*/
private $httpClient;
/**
* @var CacheFrontendInterface
*/
private $cache;
/**
* @var string
*/
private $databaseUrlPrefix = 'https://cdb.thuecat.org';
/**
* @var string
*/
private $urlPrefix = 'https://thuecat.org';
public function __construct( public function __construct(
RequestFactoryInterface $requestFactory, private readonly RequestFactoryInterface $requestFactory,
ClientInterface $httpClient, private readonly ClientInterface $httpClient,
CacheFrontendInterface $cache private readonly CacheFrontendInterface $cache
) { ) {
$this->requestFactory = $requestFactory;
$this->httpClient = $httpClient;
$this->cache = $cache;
} }
public function updatedNodes(string $scopeId): array public function updatedNodes(string $scopeId): array
@ -94,7 +70,7 @@ class FetchData
$this->handleInvalidResponse($response, $request); $this->handleInvalidResponse($response, $request);
$jsonLD = json_decode((string) $response->getBody(), true); $jsonLD = json_decode((string)$response->getBody(), true, 512, JSON_THROW_ON_ERROR);
if (is_array($jsonLD)) { if (is_array($jsonLD)) {
$this->cache->set($cacheIdentifier, $jsonLD); $this->cache->set($cacheIdentifier, $jsonLD);
return $jsonLD; return $jsonLD;

View file

@ -23,6 +23,8 @@ declare(strict_types=1);
namespace WerkraumMedia\ThueCat\Domain\Import\Importer\FetchData; namespace WerkraumMedia\ThueCat\Domain\Import\Importer\FetchData;
class InvalidResponseException extends \RuntimeException use RuntimeException;
class InvalidResponseException extends RuntimeException
{ {
} }

View file

@ -33,26 +33,14 @@ use WerkraumMedia\ThueCat\Domain\Model\Backend\ImportLogEntry\SavingEntity;
class SaveData class SaveData
{ {
/** /**
* @var DataHandler * @var string[]
*/ */
private $dataHandler; private array $errorLog;
/**
* @var ConnectionPool
*/
private $connectionPool;
/**
* @var mixed[]
*/
private $errorLog;
public function __construct( public function __construct(
DataHandler $dataHandler, private readonly DataHandler $dataHandler,
ConnectionPool $connectionPool private readonly ConnectionPool $connectionPool
) { ) {
$this->dataHandler = $dataHandler;
$this->connectionPool = $connectionPool;
} }
public function import(EntityCollection $entityCollection, ImportLog $log): void public function import(EntityCollection $entityCollection, ImportLog $log): void
@ -78,7 +66,7 @@ class SaveData
$identifier = $this->getIdentifier($entity); $identifier = $this->getIdentifier($entity);
if (is_numeric($identifier)) { if (is_numeric($identifier)) {
$entity->setExistingTypo3Uid((int) $identifier); $entity->setExistingTypo3Uid((int)$identifier);
} }
} }
} }
@ -155,7 +143,7 @@ class SaveData
$existingUid = $this->getExistingUid($entity); $existingUid = $this->getExistingUid($entity);
if ($existingUid > 0) { if ($existingUid > 0) {
return (string) $existingUid; return (string)$existingUid;
} }
$identifier = 'NEW_' . sha1($entity->getRemoteId() . $entity->getTypo3SystemLanguageUid()); $identifier = 'NEW_' . sha1($entity->getRemoteId() . $entity->getTypo3SystemLanguageUid());
@ -176,7 +164,8 @@ class SaveData
$tableColumns = $this->connectionPool $tableColumns = $this->connectionPool
->getConnectionForTable($entity->getTypo3DatabaseTableName()) ->getConnectionForTable($entity->getTypo3DatabaseTableName())
->getSchemaManager() ->getSchemaManager()
->listTableColumns($entity->getTypo3DatabaseTableName()); ->listTableColumns($entity->getTypo3DatabaseTableName())
;
$queryBuilder = $this->connectionPool->getQueryBuilderForTable($entity->getTypo3DatabaseTableName()); $queryBuilder = $this->connectionPool->getQueryBuilderForTable($entity->getTypo3DatabaseTableName());
$queryBuilder->getRestrictions()->removeAll(); $queryBuilder->getRestrictions()->removeAll();
@ -193,9 +182,9 @@ class SaveData
)); ));
} }
$result = $queryBuilder->execute()->fetchColumn(); $result = $queryBuilder->executeQuery()->fetchOne();
if (is_numeric($result)) { if (is_numeric($result)) {
return (int) $result; return (int)$result;
} }
return 0; return 0;
@ -216,9 +205,9 @@ class SaveData
$queryBuilder->createNamedParameter(0) $queryBuilder->createNamedParameter(0)
)); ));
$result = $queryBuilder->execute()->fetchColumn(); $result = $queryBuilder->executeQuery()->fetchOne();
if (is_numeric($result)) { if (is_numeric($result)) {
return (int) $result; return (int)$result;
} }
return 0; return 0;

View file

@ -28,7 +28,7 @@ class EntityCollection
/** /**
* @var Entity[] * @var Entity[]
*/ */
private $entities = []; private array $entities = [];
public function add(Entity $entity): void public function add(Entity $entity): void
{ {
@ -61,8 +61,7 @@ class EntityCollection
{ {
return array_filter($this->entities, function (Entity $entity) { return array_filter($this->entities, function (Entity $entity) {
return $entity->isTranslation() return $entity->isTranslation()
&& $entity->exists() === false && $entity->exists() === false;
;
}); });
} }

View file

@ -25,53 +25,20 @@ namespace WerkraumMedia\ThueCat\Domain\Import\Model;
class GenericEntity implements Entity class GenericEntity implements Entity
{ {
/** private bool $created = false;
* @var int
*/ private int $typo3Uid = 0;
private $typo3StoragePid;
/** /**
* @var string * @param mixed[] $data
*/ */
private $typo3DatabaseTableName;
/**
* @var int
*/
private $typo3SystemLanguageUid;
/**
* @var bool
*/
private $created = false;
/**
* @var int
*/
private $typo3Uid = 0;
/**
* @var string
*/
private $remoteId;
/**
* @var mixed[]
*/
private $data;
public function __construct( public function __construct(
int $typo3StoragePid, private readonly int $typo3StoragePid,
string $typo3DatabaseTableName, private readonly string $typo3DatabaseTableName,
int $typo3SystemLanguageUid, private readonly int $typo3SystemLanguageUid,
string $remoteId, private readonly string $remoteId,
array $data private readonly array $data
) { ) {
$this->typo3StoragePid = $typo3StoragePid;
$this->typo3DatabaseTableName = $typo3DatabaseTableName;
$this->typo3SystemLanguageUid = $typo3SystemLanguageUid;
$this->remoteId = $remoteId;
$this->data = $data;
} }
public function getTypo3StoragePid(): int public function getTypo3StoragePid(): int

View file

@ -32,29 +32,11 @@ use TYPO3\CMS\Core\Configuration\ExtensionConfiguration;
class RequestFactory implements RequestFactoryInterface class RequestFactory implements RequestFactoryInterface
{ {
/**
* @var ExtensionConfiguration
*/
private $extensionConfiguration;
/**
* @var RequestFactoryInterface
*/
private $requestFactory;
/**
* @var UriFactoryInterface
*/
private $uriFactory;
public function __construct( public function __construct(
ExtensionConfiguration $extensionConfiguration, private readonly ExtensionConfiguration $extensionConfiguration,
RequestFactoryInterface $requestFactory, private readonly RequestFactoryInterface $requestFactory,
UriFactoryInterface $uriFactory private readonly UriFactoryInterface $uriFactory
) { ) {
$this->extensionConfiguration = $extensionConfiguration;
$this->requestFactory = $requestFactory;
$this->uriFactory = $uriFactory;
} }
/** /**
@ -63,7 +45,7 @@ class RequestFactory implements RequestFactoryInterface
public function createRequest(string $method, $uri): RequestInterface public function createRequest(string $method, $uri): RequestInterface
{ {
if (!$uri instanceof UriInterface) { if (!$uri instanceof UriInterface) {
$uri = $this->uriFactory->createUri((string) $uri); $uri = $this->uriFactory->createUri((string)$uri);
} }
$query = []; $query = [];
@ -74,7 +56,7 @@ class RequestFactory implements RequestFactoryInterface
try { try {
$query['api_key'] = $this->extensionConfiguration->get('thuecat', 'apiKey'); $query['api_key'] = $this->extensionConfiguration->get('thuecat', 'apiKey');
} catch (ExtensionConfigurationExtensionNotConfiguredException $e) { } catch (ExtensionConfigurationExtensionNotConfiguredException) {
// Nothing todo, not configured, don't add. // Nothing todo, not configured, don't add.
} }

View file

@ -23,9 +23,9 @@ declare(strict_types=1);
namespace WerkraumMedia\ThueCat\Domain\Import; namespace WerkraumMedia\ThueCat\Domain\Import;
use WerkraumMedia\ThueCat\Domain\Import\Entity\Properties\ForeignReference;
use WerkraumMedia\ThueCat\Domain\Import\EntityMapper\EntityRegistry; use WerkraumMedia\ThueCat\Domain\Import\EntityMapper\EntityRegistry;
use WerkraumMedia\ThueCat\Domain\Import\EntityMapper\JsonDecode; use WerkraumMedia\ThueCat\Domain\Import\EntityMapper\JsonDecode;
use WerkraumMedia\ThueCat\Domain\Import\Entity\Properties\ForeignReference;
use WerkraumMedia\ThueCat\Domain\Import\Importer\FetchData; use WerkraumMedia\ThueCat\Domain\Import\Importer\FetchData;
use WerkraumMedia\ThueCat\Domain\Import\Importer\FetchData\InvalidResponseException; use WerkraumMedia\ThueCat\Domain\Import\Importer\FetchData\InvalidResponseException;
@ -38,29 +38,11 @@ use WerkraumMedia\ThueCat\Domain\Import\Importer\FetchData\InvalidResponseExcept
*/ */
class ResolveForeignReference class ResolveForeignReference
{ {
/**
* @var FetchData
*/
private $fetchData;
/**
* @var EntityRegistry
*/
private $entityRegistry;
/**
* @var EntityMapper
*/
private $entityMapper;
public function __construct( public function __construct(
FetchData $fetchData, private readonly FetchData $fetchData,
EntityRegistry $entityRegistry, private readonly EntityRegistry $entityRegistry,
EntityMapper $entityMapper private readonly EntityMapper $entityMapper
) { ) {
$this->fetchData = $fetchData;
$this->entityRegistry = $entityRegistry;
$this->entityMapper = $entityMapper;
} }
public function resolve( public function resolve(
@ -69,7 +51,7 @@ class ResolveForeignReference
): ?object { ): ?object {
try { try {
$jsonLD = $this->fetchData->jsonLDFromUrl($foreignReference->getId()); $jsonLD = $this->fetchData->jsonLDFromUrl($foreignReference->getId());
} catch (InvalidResponseException $e) { } catch (InvalidResponseException) {
return null; return null;
} }
@ -94,6 +76,7 @@ class ResolveForeignReference
/** /**
* @param ForeignReference[] $foreignReferences * @param ForeignReference[] $foreignReferences
*
* @return string[] * @return string[]
*/ */
public static function convertToRemoteIds(array $foreignReferences): array public static function convertToRemoteIds(array $foreignReferences): array

View file

@ -23,6 +23,8 @@ declare(strict_types=1);
namespace WerkraumMedia\ThueCat\Domain\Import; namespace WerkraumMedia\ThueCat\Domain\Import;
use Exception;
use InvalidArgumentException;
use WerkraumMedia\ThueCat\Domain\Import\Entity\MapsToType; use WerkraumMedia\ThueCat\Domain\Import\Entity\MapsToType;
use WerkraumMedia\ThueCat\Domain\Import\Importer\Converter; use WerkraumMedia\ThueCat\Domain\Import\Importer\Converter;
use WerkraumMedia\ThueCat\Domain\Import\Model\Entity; use WerkraumMedia\ThueCat\Domain\Import\Model\Entity;
@ -32,15 +34,9 @@ use WerkraumMedia\ThueCat\Domain\Model\Backend\ImportConfiguration as Typo3Impor
class Typo3Converter implements Converter class Typo3Converter implements Converter
{ {
/**
* @var Registry
*/
private $registry;
public function __construct( public function __construct(
Registry $registry private readonly Registry $registry
) { ) {
$this->registry = $registry;
} }
public function convert( public function convert(
@ -49,13 +45,13 @@ class Typo3Converter implements Converter
string $language string $language
): ?Entity { ): ?Entity {
if (!$configuration instanceof Typo3ImportConfiguration) { if (!$configuration instanceof Typo3ImportConfiguration) {
throw new \InvalidArgumentException('Only supports TYPO3 import configuration.', 1629710386); throw new InvalidArgumentException('Only supports TYPO3 import configuration.', 1629710386);
} }
$concreteConverter = $this->registry->getConverterBasedOnType($mapped); $concreteConverter = $this->registry->getConverterBasedOnType($mapped);
if (!$concreteConverter instanceof Typo3ConcreteConverter) { if (!$concreteConverter instanceof Typo3ConcreteConverter) {
throw new \Exception( throw new Exception(
'No TYPO3 Converter registered for given Entity "' . get_class($mapped) . '".', 'No TYPO3 Converter registered for given Entity "' . $mapped::class . '".',
1628244329 1628244329
); );
} }

View file

@ -23,8 +23,9 @@ declare(strict_types=1);
namespace WerkraumMedia\ThueCat\Domain\Import\Typo3Converter; namespace WerkraumMedia\ThueCat\Domain\Import\Typo3Converter;
use TYPO3\CMS\Core\Log\LogManager; use Exception;
use TYPO3\CMS\Core\Log\Logger; use TYPO3\CMS\Core\Log\Logger;
use TYPO3\CMS\Core\Log\LogManager;
use TYPO3\CMS\Extbase\Persistence\QueryResultInterface; use TYPO3\CMS\Extbase\Persistence\QueryResultInterface;
use WerkraumMedia\ThueCat\Domain\Import\Entity\AccessibilitySpecification; use WerkraumMedia\ThueCat\Domain\Import\Entity\AccessibilitySpecification;
use WerkraumMedia\ThueCat\Domain\Import\Entity\Base; use WerkraumMedia\ThueCat\Domain\Import\Entity\Base;
@ -52,55 +53,14 @@ use WerkraumMedia\ThueCat\Domain\Repository\Backend\TownRepository;
class GeneralConverter implements Converter class GeneralConverter implements Converter
{ {
/** private readonly Logger $logger;
* @var ResolveForeignReference
*/
private $resolveForeignReference;
/** private ImportConfiguration $importConfiguration;
* @var Importer
*/
private $importer;
/**
* @var LanguageHandling
*/
private $languageHandling;
/**
* @var OrganisationRepository
*/
private $organisationRepository;
/**
* @var TownRepository
*/
private $townRepository;
/**
* @var ParkingFacilityRepository
*/
private $parkingFacilityRepository;
/**
* @var NameExtractor
*/
private $nameExtractor;
/**
* @var Logger
*/
private $logger;
/**
* @var ImportConfiguration
*/
private $importConfiguration;
/** /**
* @var string[] * @var string[]
*/ */
private $classToTableMapping = [ private array $classToTableMapping = [
TouristAttraction::class => 'tx_thuecat_tourist_attraction', TouristAttraction::class => 'tx_thuecat_tourist_attraction',
ParkingFacility::class => 'tx_thuecat_parking_facility', ParkingFacility::class => 'tx_thuecat_parking_facility',
Town::class => 'tx_thuecat_town', Town::class => 'tx_thuecat_town',
@ -110,23 +70,16 @@ class GeneralConverter implements Converter
]; ];
public function __construct( public function __construct(
ResolveForeignReference $resolveForeignReference, private readonly ResolveForeignReference $resolveForeignReference,
Importer $importer, private readonly Importer $importer,
LanguageHandling $languageHandling, private readonly LanguageHandling $languageHandling,
OrganisationRepository $organisationRepository, private readonly OrganisationRepository $organisationRepository,
TownRepository $townRepository, private readonly TownRepository $townRepository,
ParkingFacilityRepository $parkingFacilityRepository, private readonly ParkingFacilityRepository $parkingFacilityRepository,
NameExtractor $nameExtractor, private readonly NameExtractor $nameExtractor,
LogManager $logManager LogManager $logManager
) { ) {
$this->resolveForeignReference = $resolveForeignReference; $this->logger = $logManager->getLogger(self::class);
$this->importer = $importer;
$this->languageHandling = $languageHandling;
$this->organisationRepository = $organisationRepository;
$this->townRepository = $townRepository;
$this->parkingFacilityRepository = $parkingFacilityRepository;
$this->nameExtractor = $nameExtractor;
$this->logger = $logManager->getLogger(__CLASS__);
} }
public function convert( public function convert(
@ -142,7 +95,7 @@ class GeneralConverter implements Converter
$converted = new GenericEntity( $converted = new GenericEntity(
$importConfiguration->getStoragePid(), $importConfiguration->getStoragePid(),
$this->getTableNameByEntityClass(get_class($entity)), $this->getTableNameByEntityClass($entity::class),
$this->languageHandling->getLanguageUidForString( $this->languageHandling->getLanguageUidForString(
$importConfiguration->getStoragePid(), $importConfiguration->getStoragePid(),
$language $language
@ -167,12 +120,12 @@ class GeneralConverter implements Converter
ImportConfiguration $importConfiguration, ImportConfiguration $importConfiguration,
string $language string $language
): bool { ): bool {
$tableName = $this->getTableNameByEntityClass(get_class($entity)); $tableName = $this->getTableNameByEntityClass($entity::class);
if (!$entity instanceof Minimum) { if (!$entity instanceof Minimum) {
$this->logger->info('Skipped conversion of entity, got unexpected type', [ $this->logger->info('Skipped conversion of entity, got unexpected type', [
'expectedType' => Minimum::class, 'expectedType' => Minimum::class,
'actualType' => get_class($entity), 'actualType' => $entity::class,
]); ]);
return false; return false;
} }
@ -214,7 +167,7 @@ class GeneralConverter implements Converter
{ {
$tableName = $this->classToTableMapping[$className] ?? ''; $tableName = $this->classToTableMapping[$className] ?? '';
if ($tableName == '') { if ($tableName == '') {
throw new \Exception('No table name configured for class ' . $className, 1629376990); throw new Exception('No table name configured for class ' . $className, 1629376990);
} }
return $tableName; return $tableName;
@ -298,7 +251,7 @@ class GeneralConverter implements Converter
) )
); );
$town = $this->townRepository->findOneByEntity($entity); $town = $this->townRepository->findOneByEntity($entity);
return $town ? (string) $town->getUid() : ''; return $town ? (string)$town->getUid() : '';
} }
private function getParkingFacilitiesNearByUids(Base $entity): array private function getParkingFacilitiesNearByUids(Base $entity): array
@ -360,6 +313,7 @@ class GeneralConverter implements Converter
if ($result === false || $result === '[]') { if ($result === false || $result === '[]') {
return '{}'; return '{}';
} }
return $result; return $result;
} }
@ -393,7 +347,7 @@ class GeneralConverter implements Converter
} }
} }
return json_encode($data) ?: ''; return json_encode($data, JSON_THROW_ON_ERROR) ?: '';
} }
private function getSingleMedia( private function getSingleMedia(
@ -433,7 +387,7 @@ class GeneralConverter implements Converter
]); ]);
} }
return json_encode($data) ?: ''; return json_encode($data, JSON_THROW_ON_ERROR) ?: '';
} }
private function getAddress(Place $entity): string private function getAddress(Place $entity): string
@ -462,7 +416,7 @@ class GeneralConverter implements Converter
]; ];
} }
return json_encode($data) ?: ''; return json_encode($data, JSON_THROW_ON_ERROR) ?: '';
} }
private function getOffers(Place $entity): string private function getOffers(Place $entity): string
@ -473,11 +427,11 @@ class GeneralConverter implements Converter
'types' => $offer->getOfferTypes(), 'types' => $offer->getOfferTypes(),
'title' => $offer->getName(), 'title' => $offer->getName(),
'description' => $offer->getDescription(), 'description' => $offer->getDescription(),
'prices' => array_map([$this, 'getPrice'], $offer->getPrices()), 'prices' => array_map($this->getPrice(...), $offer->getPrices()),
]; ];
} }
return json_encode($data) ?: ''; return json_encode($data, JSON_THROW_ON_ERROR) ?: '';
} }
private function getPrice(PriceSpecification $priceSpecification): array private function getPrice(PriceSpecification $priceSpecification): array

View file

@ -23,6 +23,7 @@ declare(strict_types=1);
namespace WerkraumMedia\ThueCat\Domain\Import\Typo3Converter; namespace WerkraumMedia\ThueCat\Domain\Import\Typo3Converter;
use InvalidArgumentException;
use TYPO3\CMS\Core\Site\Entity\SiteLanguage; use TYPO3\CMS\Core\Site\Entity\SiteLanguage;
use TYPO3\CMS\Core\Site\SiteFinder; use TYPO3\CMS\Core\Site\SiteFinder;
use WerkraumMedia\ThueCat\Domain\Import\ImportConfiguration; use WerkraumMedia\ThueCat\Domain\Import\ImportConfiguration;
@ -30,36 +31,30 @@ use WerkraumMedia\ThueCat\Domain\Import\Importer\Languages;
class LanguageHandling implements Languages class LanguageHandling implements Languages
{ {
/**
* @var SiteFinder
*/
private $siteFinder;
public function __construct( public function __construct(
SiteFinder $siteFinder private readonly SiteFinder $siteFinder
) { ) {
$this->siteFinder = $siteFinder;
} }
public function getAvailable(ImportConfiguration $configuration): array public function getAvailable(ImportConfiguration $configuration): array
{ {
if (method_exists($configuration, 'getStoragePid') === false) { if (method_exists($configuration, 'getStoragePid') === false) {
throw new \InvalidArgumentException('Unsupported configuration, need to retrieve storage pid.', 1629710300); throw new InvalidArgumentException('Unsupported configuration, need to retrieve storage pid.', 1629710300);
} }
return array_map(function (SiteLanguage $language) { return array_map(function (SiteLanguage $language) {
return $language->getTwoLetterIsoCode(); return $language->getLocale()->getLanguageCode();
}, $this->getLanguages($configuration->getStoragePid())); }, $this->getLanguages($configuration->getStoragePid()));
} }
public function getLanguageUidForString(int $pageUid, string $isoCode): int public function getLanguageUidForString(int $pageUid, string $isoCode): int
{ {
foreach ($this->getLanguages($pageUid) as $language) { foreach ($this->getLanguages($pageUid) as $language) {
if ($language->getTwoLetterIsoCode() === $isoCode) { if ($language->getLocale()->getLanguageCode() === $isoCode) {
return $language->getLanguageId(); return $language->getLanguageId();
} }
} }
throw new \InvalidArgumentException( throw new InvalidArgumentException(
sprintf( sprintf(
'Could not find language for combination of page "%d" and iso code "%s".', 'Could not find language for combination of page "%d" and iso code "%s".',
$pageUid, $pageUid,

View file

@ -28,15 +28,9 @@ use WerkraumMedia\ThueCat\Domain\Import\ResolveForeignReference;
class NameExtractor class NameExtractor
{ {
/**
* @var ResolveForeignReference
*/
private $resolveForeignReference;
public function __construct( public function __construct(
ResolveForeignReference $resolveForeignReference private readonly ResolveForeignReference $resolveForeignReference
) { ) {
$this->resolveForeignReference = $resolveForeignReference;
} }
/** /**
@ -65,7 +59,7 @@ class NameExtractor
} }
if ($name === '' && method_exists($remote, 'getName')) { if ($name === '' && method_exists($remote, 'getName')) {
$name = trim($remote->getName()); $name = trim((string)$remote->getName());
} }
return $name; return $name;

View file

@ -37,7 +37,7 @@ class Registry
/** /**
* @var Converter[] * @var Converter[]
*/ */
private $converters = []; private array $converters = [];
public function registerConverter(Converter $converter): void public function registerConverter(Converter $converter): void
{ {

View file

@ -23,25 +23,17 @@ declare(strict_types=1);
namespace WerkraumMedia\ThueCat\Domain\Import\UrlProvider; namespace WerkraumMedia\ThueCat\Domain\Import\UrlProvider;
use InvalidArgumentException;
use WerkraumMedia\ThueCat\Domain\Import\ImportConfiguration; use WerkraumMedia\ThueCat\Domain\Import\ImportConfiguration;
use WerkraumMedia\ThueCat\Domain\Import\Importer\FetchData; use WerkraumMedia\ThueCat\Domain\Import\Importer\FetchData;
class ContainsPlaceUrlProvider implements UrlProvider class ContainsPlaceUrlProvider implements UrlProvider
{ {
/** private string $containsPlaceId = '';
* @var FetchData
*/
private $fetchData;
/**
* @var string
*/
private $containsPlaceId = '';
public function __construct( public function __construct(
FetchData $fetchData private readonly FetchData $fetchData
) { ) {
$this->fetchData = $fetchData;
} }
public function canProvideForConfiguration( public function canProvideForConfiguration(
@ -54,7 +46,7 @@ class ContainsPlaceUrlProvider implements UrlProvider
ImportConfiguration $configuration ImportConfiguration $configuration
): UrlProvider { ): UrlProvider {
if (method_exists($configuration, 'getContainsPlaceId') === false) { if (method_exists($configuration, 'getContainsPlaceId') === false) {
throw new \InvalidArgumentException('Received incompatible import configuration.', 1629709276); throw new InvalidArgumentException('Received incompatible import configuration.', 1629709276);
} }
$instance = clone $this; $instance = clone $this;
$instance->containsPlaceId = $configuration->getContainsPlaceId(); $instance->containsPlaceId = $configuration->getContainsPlaceId();

View file

@ -33,7 +33,7 @@ class Registry
/** /**
* @var UrlProvider[] * @var UrlProvider[]
*/ */
private $provider = []; private array $provider = [];
public function registerProvider(UrlProvider $provider): void public function registerProvider(UrlProvider $provider): void
{ {

View file

@ -30,7 +30,7 @@ class StaticUrlProvider implements UrlProvider
/** /**
* @var string[] * @var string[]
*/ */
private $urls = []; private array $urls = [];
public function canProvideForConfiguration( public function canProvideForConfiguration(
ImportConfiguration $configuration ImportConfiguration $configuration

View file

@ -23,25 +23,17 @@ declare(strict_types=1);
namespace WerkraumMedia\ThueCat\Domain\Import\UrlProvider; namespace WerkraumMedia\ThueCat\Domain\Import\UrlProvider;
use InvalidArgumentException;
use WerkraumMedia\ThueCat\Domain\Import\ImportConfiguration; use WerkraumMedia\ThueCat\Domain\Import\ImportConfiguration;
use WerkraumMedia\ThueCat\Domain\Import\Importer\FetchData; use WerkraumMedia\ThueCat\Domain\Import\Importer\FetchData;
class SyncScopeUrlProvider implements UrlProvider class SyncScopeUrlProvider implements UrlProvider
{ {
/** private string $syncScopeId = '';
* @var FetchData
*/
private $fetchData;
/**
* @var string
*/
private $syncScopeId = '';
public function __construct( public function __construct(
FetchData $fetchData private readonly FetchData $fetchData
) { ) {
$this->fetchData = $fetchData;
} }
public function canProvideForConfiguration( public function canProvideForConfiguration(
@ -54,7 +46,7 @@ class SyncScopeUrlProvider implements UrlProvider
ImportConfiguration $configuration ImportConfiguration $configuration
): UrlProvider { ): UrlProvider {
if (method_exists($configuration, 'getSyncScopeId') === false) { if (method_exists($configuration, 'getSyncScopeId') === false) {
throw new \InvalidArgumentException('Received incompatible import configuration.', 1629709276); throw new InvalidArgumentException('Received incompatible import configuration.', 1629709276);
} }
$instance = clone $this; $instance = clone $this;
$instance->syncScopeId = $configuration->getSyncScopeId(); $instance->syncScopeId = $configuration->getSyncScopeId();

View file

@ -23,29 +23,18 @@ declare(strict_types=1);
namespace WerkraumMedia\ThueCat\Domain\Model\Backend; namespace WerkraumMedia\ThueCat\Domain\Model\Backend;
use DateTimeImmutable;
use TYPO3\CMS\Extbase\DomainObject\AbstractEntity as Typo3AbstractEntity; use TYPO3\CMS\Extbase\DomainObject\AbstractEntity as Typo3AbstractEntity;
class AbstractEntity extends Typo3AbstractEntity class AbstractEntity extends Typo3AbstractEntity
{ {
/** protected string $remoteId = '';
* @var string
*/
protected $remoteId = '';
/** protected string $title = '';
* @var string
*/
protected $title = '';
/** protected string $description = '';
* @var string
*/
protected $description = '';
/** protected ?DateTimeImmutable $tstamp = null;
* @var \DateTimeImmutable|null
*/
protected $tstamp = null;
public function getRemoteId(): string public function getRemoteId(): string
{ {
@ -62,7 +51,7 @@ class AbstractEntity extends Typo3AbstractEntity
return $this->description; return $this->description;
} }
public function getLastImported(): ?\DateTimeImmutable public function getLastImported(): ?DateTimeImmutable
{ {
return $this->tstamp; return $this->tstamp;
} }

View file

@ -23,6 +23,8 @@ declare(strict_types=1);
namespace WerkraumMedia\ThueCat\Domain\Model\Backend; namespace WerkraumMedia\ThueCat\Domain\Model\Backend;
use DateTimeImmutable;
use Exception;
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\CMS\Extbase\DomainObject\AbstractEntity; use TYPO3\CMS\Extbase\DomainObject\AbstractEntity;
@ -33,40 +35,28 @@ use WerkraumMedia\ThueCat\Domain\Import\ResolveForeignReference;
class ImportConfiguration extends AbstractEntity implements ImportConfigurationInterface class ImportConfiguration extends AbstractEntity implements ImportConfigurationInterface
{ {
/** protected string $title = '';
* @var string
*/
protected $title = '';
/** protected string $type = '';
* @var string
*/
protected $type = '';
/** protected string $configuration = '';
* @var string
*/
protected $configuration = '';
/** protected ?DateTimeImmutable $tstamp = null;
* @var \DateTimeImmutable|null
*/
protected $tstamp = null;
/** /**
* @var ObjectStorage<ImportLog> * @var ObjectStorage<ImportLog>
*/ */
protected $logs; protected ObjectStorage $logs;
/** /**
* @var string[]|null * @var string[]|null
*/ */
protected $urls = null; protected ?array $urls = null;
/** /**
* @var string[] * @var string[]
*/ */
protected $allowedTypes = []; protected array $allowedTypes = [];
public function __construct() public function __construct()
{ {
@ -88,15 +78,15 @@ class ImportConfiguration extends AbstractEntity implements ImportConfigurationI
return 'tx_thuecat_import_configuration'; return 'tx_thuecat_import_configuration';
} }
public function getLastChanged(): ?\DateTimeImmutable public function getLastChanged(): ?DateTimeImmutable
{ {
return $this->tstamp; return $this->tstamp;
} }
public function getLastImported(): ?\DateTimeImmutable public function getLastImported(): ?DateTimeImmutable
{ {
$lastImport = null; $lastImport = null;
$positionOfLastLog = (string) (count($this->logs) - 1); $positionOfLastLog = count($this->logs) - 1;
if ($this->logs->offsetExists($positionOfLastLog)) { if ($this->logs->offsetExists($positionOfLastLog)) {
$lastImport = $this->logs->offsetGet($positionOfLastLog); $lastImport = $this->logs->offsetGet($positionOfLastLog);
} }
@ -112,7 +102,7 @@ class ImportConfiguration extends AbstractEntity implements ImportConfigurationI
$storagePid = $this->getConfigurationValueFromFlexForm('storagePid'); $storagePid = $this->getConfigurationValueFromFlexForm('storagePid');
if (is_numeric($storagePid) && $storagePid > 0) { if (is_numeric($storagePid) && $storagePid > 0) {
return intval($storagePid); return (int)$storagePid;
} }
return 0; return 0;
@ -151,7 +141,7 @@ class ImportConfiguration extends AbstractEntity implements ImportConfigurationI
{ {
$containsPlaceId = $this->getConfigurationValueFromFlexForm('containsPlaceId'); $containsPlaceId = $this->getConfigurationValueFromFlexForm('containsPlaceId');
if (!is_string($containsPlaceId)) { if (!is_string($containsPlaceId)) {
throw new \Exception('Could not fetch containsPlaceId.', 1671027015); throw new Exception('Could not fetch containsPlaceId.', 1671027015);
} }
return $containsPlaceId; return $containsPlaceId;
} }

View file

@ -23,6 +23,7 @@ declare(strict_types=1);
namespace WerkraumMedia\ThueCat\Domain\Model\Backend; namespace WerkraumMedia\ThueCat\Domain\Model\Backend;
use DateTimeImmutable;
use TYPO3\CMS\Extbase\DomainObject\AbstractEntity as Typo3AbstractEntity; use TYPO3\CMS\Extbase\DomainObject\AbstractEntity as Typo3AbstractEntity;
use TYPO3\CMS\Extbase\Persistence\ObjectStorage; use TYPO3\CMS\Extbase\Persistence\ObjectStorage;
use WerkraumMedia\ThueCat\Domain\Model\Backend\ImportLogEntry\SavingEntity; use WerkraumMedia\ThueCat\Domain\Model\Backend\ImportLogEntry\SavingEntity;
@ -32,23 +33,14 @@ class ImportLog extends Typo3AbstractEntity
/** /**
* @var ObjectStorage<ImportLogEntry> * @var ObjectStorage<ImportLogEntry>
*/ */
protected $logEntries; protected ObjectStorage $logEntries;
/** protected ?DateTimeImmutable $crdate = null;
* @var ImportConfiguration|null
*/
protected $configuration = null;
/**
* @var \DateTimeImmutable|null
*/
protected $crdate;
public function __construct( public function __construct(
?ImportConfiguration $configuration = null protected ?ImportConfiguration $configuration = null
) { ) {
$this->logEntries = new ObjectStorage(); $this->logEntries = new ObjectStorage();
$this->configuration = $configuration;
} }
public function addEntry(ImportLogEntry $entry): void public function addEntry(ImportLogEntry $entry): void
@ -78,7 +70,7 @@ class ImportLog extends Typo3AbstractEntity
return $this->logEntries; return $this->logEntries;
} }
public function getCreated(): ?\DateTimeImmutable public function getCreated(): ?DateTimeImmutable
{ {
return $this->crdate; return $this->crdate;
} }

View file

@ -23,26 +23,26 @@ declare(strict_types=1);
namespace WerkraumMedia\ThueCat\Domain\Model\Backend\ImportLogEntry; namespace WerkraumMedia\ThueCat\Domain\Model\Backend\ImportLogEntry;
use Exception;
use WerkraumMedia\ThueCat\Domain\Import\EntityMapper\MappingException; use WerkraumMedia\ThueCat\Domain\Import\EntityMapper\MappingException;
use WerkraumMedia\ThueCat\Domain\Model\Backend\ImportLogEntry; use WerkraumMedia\ThueCat\Domain\Model\Backend\ImportLogEntry;
class MappingError extends ImportLogEntry class MappingError extends ImportLogEntry
{ {
/** protected string $remoteId = '';
* @var string
*/
protected $remoteId = '';
/** /**
* Necessary for Extbase/Symfony.
*
* @var string * @var string
*/ */
protected $errors = ''; protected string $errors = '[]';
public function __construct( public function __construct(
MappingException $exception MappingException $exception
) { ) {
$this->remoteId = $exception->getUrl(); $this->remoteId = $exception->getUrl();
$this->errors = json_encode([$exception->getMessage()]) ?: ''; $this->errors = json_encode([$exception->getMessage()], JSON_THROW_ON_ERROR) ?: '';
} }
public function getRemoteId(): string public function getRemoteId(): string
@ -54,7 +54,7 @@ class MappingError extends ImportLogEntry
{ {
$errors = json_decode($this->errors, true); $errors = json_decode($this->errors, true);
if (is_array($errors) === false) { if (is_array($errors) === false) {
throw new \Exception('Could not parse errors.', 1671097690); throw new Exception('Could not parse errors.', 1671097690);
} }
return $errors; return $errors;
} }

View file

@ -23,56 +23,42 @@ declare(strict_types=1);
namespace WerkraumMedia\ThueCat\Domain\Model\Backend\ImportLogEntry; namespace WerkraumMedia\ThueCat\Domain\Model\Backend\ImportLogEntry;
use Exception;
use WerkraumMedia\ThueCat\Domain\Import\Model\Entity; use WerkraumMedia\ThueCat\Domain\Import\Model\Entity;
use WerkraumMedia\ThueCat\Domain\Model\Backend\ImportLogEntry; use WerkraumMedia\ThueCat\Domain\Model\Backend\ImportLogEntry;
class SavingEntity extends ImportLogEntry class SavingEntity extends ImportLogEntry
{ {
/** protected string $remoteId = '';
* @var string
*/
protected $remoteId = '';
/** protected bool $insertion = false;
* @var bool
*/
protected $insertion = false;
/** protected int $recordUid = 0;
* @var int
*/
protected $recordUid = 0;
/** protected int $recordPid = 0;
* @var int
*/
protected $recordPid = 0;
/** protected string $tableName = '';
* @var string
*/
protected $tableName = '';
/** protected string $errors = '';
* @var string
*/
protected $errors = '';
/** /**
* @var string[] * @var string[]
*/ */
protected $errorsAsArray = []; protected array $errorsAsArray = [];
/**
* @param string[] $errorsAsArray
*/
public function __construct( public function __construct(
Entity $entity, Entity $entity,
array $dataHandlerErrorLog array $errorsAsArray
) { ) {
$this->remoteId = $entity->getRemoteId(); $this->remoteId = $entity->getRemoteId();
$this->insertion = $entity->wasCreated(); $this->insertion = $entity->wasCreated();
$this->recordUid = $entity->getTypo3Uid(); $this->recordUid = $entity->getTypo3Uid();
$this->recordPid = $entity->getTypo3StoragePid(); $this->recordPid = $entity->getTypo3StoragePid();
$this->tableName = $entity->getTypo3DatabaseTableName(); $this->tableName = $entity->getTypo3DatabaseTableName();
$this->errorsAsArray = $dataHandlerErrorLog; $this->errorsAsArray = $errorsAsArray;
} }
public function getRemoteId(): string public function getRemoteId(): string
@ -98,9 +84,9 @@ class SavingEntity extends ImportLogEntry
public function getErrors(): array public function getErrors(): array
{ {
if ($this->errorsAsArray === [] && $this->errors !== '') { if ($this->errorsAsArray === [] && $this->errors !== '') {
$errorsAsArray = json_decode($this->errors, true); $errorsAsArray = json_decode($this->errors, true, 512, JSON_THROW_ON_ERROR);
if (is_array($errorsAsArray) === false) { if (is_array($errorsAsArray) === false) {
throw new \Exception('Could not parse errors.', 1671097690); throw new Exception('Could not parse errors.', 1671097690);
} }
$this->errorsAsArray = array_unique($errorsAsArray); $this->errorsAsArray = array_unique($errorsAsArray);
} }
@ -121,7 +107,7 @@ class SavingEntity extends ImportLogEntry
public function getInsertion(): array public function getInsertion(): array
{ {
return [ return [
'insertion' => (int) $this->wasInsertion(), 'insertion' => (int)$this->wasInsertion(),
'record_uid' => $this->getRecordUid(), 'record_uid' => $this->getRecordUid(),
'table_name' => $this->getRecordDatabaseTableName(), 'table_name' => $this->getRecordDatabaseTableName(),
]; ];

View file

@ -30,12 +30,12 @@ class Organisation extends AbstractEntity
/** /**
* @var ObjectStorage<Town> * @var ObjectStorage<Town>
*/ */
protected $managesTowns; protected ObjectStorage $managesTowns;
/** /**
* @var ObjectStorage<TouristInformation> * @var ObjectStorage<TouristInformation>
*/ */
protected $managesTouristInformation; protected ObjectStorage $managesTouristInformation;
public function getManagesTowns(): ObjectStorage public function getManagesTowns(): ObjectStorage
{ {

View file

@ -30,7 +30,7 @@ class Town extends AbstractEntity
/** /**
* @var ObjectStorage<TouristInformation> * @var ObjectStorage<TouristInformation>
*/ */
protected $touristInformation; protected ObjectStorage $touristInformation;
public function getTouristInformation(): ObjectStorage public function getTouristInformation(): ObjectStorage
{ {

View file

@ -27,19 +27,14 @@ use TYPO3\CMS\Core\Type\TypeInterface;
class AccessiblitySpecification implements TypeInterface class AccessiblitySpecification implements TypeInterface
{ {
/**
* @var string
*/
private $serialized;
/** /**
* @var mixed[] * @var mixed[]
*/ */
private $data; private array $data;
public function __construct(string $serialized) public function __construct(
{ private readonly string $serialized
$this->serialized = $serialized; ) {
$this->data = json_decode($serialized, true); $this->data = json_decode($serialized, true);
} }

View file

@ -27,20 +27,15 @@ use TYPO3\CMS\Core\Type\TypeInterface;
class Address implements TypeInterface class Address implements TypeInterface
{ {
/**
* @var string
*/
private $serialized;
/** /**
* @var mixed[] * @var mixed[]
*/ */
private $data; private array $data;
public function __construct(string $serialized) public function __construct(
{ private readonly string $serialized
$this->serialized = $serialized; ) {
$this->data = json_decode($serialized, true); $this->data = json_decode($serialized, true) ?? [];
} }
public function getStreet(): string public function getStreet(): string

View file

@ -27,20 +27,11 @@ use TYPO3\CMS\Extbase\DomainObject\AbstractEntity;
abstract class Base extends AbstractEntity abstract class Base extends AbstractEntity
{ {
/** protected string $title = '';
* @var string
*/
protected $title = '';
/** protected string $description = '';
* @var string
*/
protected $description = '';
/** protected ?Media $media = null;
* @var Media|null
*/
protected $media = null;
public function getTitle(): string public function getTitle(): string
{ {

View file

@ -28,24 +28,19 @@ use TYPO3\CMS\Core\Type\TypeInterface;
class Media implements TypeInterface class Media implements TypeInterface
{ {
/**
* @var string
*/
private $serialized;
/** /**
* @var array[] * @var array[]
*/ */
private $data; private readonly array $data;
/** /**
* @var FileReference[] * @var FileReference[]
*/ */
protected $editorialImages = []; protected array $editorialImages = [];
public function __construct(string $serialized) public function __construct(
{ private readonly string $serialized
$this->serialized = $serialized; ) {
$data = json_decode($serialized, true); $data = json_decode($serialized, true);
$this->data = $this->prepareData(is_array($data) ? $data : []); $this->data = $this->prepareData(is_array($data) ? $data : []);
} }
@ -94,6 +89,7 @@ class Media implements TypeInterface
/** /**
* @internal Only used to set the values while mapping objects. * @internal Only used to set the values while mapping objects.
*
* @see: AfterObjectThawedHandler * @see: AfterObjectThawedHandler
*/ */
public function setEditorialImages(array $images): void public function setEditorialImages(array $images): void

View file

@ -23,27 +23,23 @@ declare(strict_types=1);
namespace WerkraumMedia\ThueCat\Domain\Model\Frontend; namespace WerkraumMedia\ThueCat\Domain\Model\Frontend;
use DateTimeImmutable;
class MergedOpeningHour class MergedOpeningHour
{ {
/** /**
* @var MergedOpeningHourWeekDay[] * @var MergedOpeningHourWeekDay[]
*/ */
private $weekDays = []; private array $weekDays = [];
/** private readonly ?DateTimeImmutable $from;
* @var \DateTimeImmutable|null
*/
private $from;
/** private readonly ?DateTimeImmutable $through;
* @var \DateTimeImmutable|null
*/
private $through;
public function __construct( public function __construct(
array $weekDays, array $weekDays,
?\DateTimeImmutable $from, ?DateTimeImmutable $from,
?\DateTimeImmutable $through ?DateTimeImmutable $through
) { ) {
$this->weekDays = array_values($weekDays); $this->weekDays = array_values($weekDays);
$this->from = $from; $this->from = $from;
@ -72,12 +68,12 @@ class MergedOpeningHour
]); ]);
} }
public function getFrom(): ?\DateTimeImmutable public function getFrom(): ?DateTimeImmutable
{ {
return $this->from; return $this->from;
} }
public function getThrough(): ?\DateTimeImmutable public function getThrough(): ?DateTimeImmutable
{ {
return $this->through; return $this->through;
} }

View file

@ -27,29 +27,11 @@ use WerkraumMedia\ThueCat\Domain\TimingFormat;
class MergedOpeningHourWeekDay class MergedOpeningHourWeekDay
{ {
/**
* @var string
*/
private $opens;
/**
* @var string
*/
private $closes;
/**
* @var string
*/
private $dayOfWeek;
public function __construct( public function __construct(
string $opens, private readonly string $opens,
string $closes, private readonly string $closes,
string $dayOfWeek private readonly string $dayOfWeek
) { ) {
$this->opens = $opens;
$this->closes = $closes;
$this->dayOfWeek = $dayOfWeek;
} }
public function getOpens(): string public function getOpens(): string

View file

@ -23,17 +23,17 @@ declare(strict_types=1);
namespace WerkraumMedia\ThueCat\Domain\Model\Frontend; namespace WerkraumMedia\ThueCat\Domain\Model\Frontend;
class MergedOpeningHours implements \Iterator, \Countable use Countable;
use Iterator;
class MergedOpeningHours implements Iterator, Countable
{ {
/** /**
* @var MergedOpeningHour[] * @var MergedOpeningHour[]
*/ */
private $openingHours = []; private array $openingHours = [];
/** private int $position = 0;
* @var int
*/
private $position = 0;
/** /**
* @param MergedOpeningHour[] $openingHours * @param MergedOpeningHour[] $openingHours

View file

@ -27,45 +27,19 @@ use TYPO3\CMS\Core\Utility\ArrayUtility;
class Offer class Offer
{ {
/**
* @var string
*/
private $title;
/**
* @var string[]
*/
private $types;
/**
* @var string
*/
private $description;
/**
* @var mixed[]
*/
private $prices;
/** /**
* @param string[] $types * @param string[] $types
* @param mixed[] $prices
*/ */
private function __construct( private function __construct(
string $title, private readonly string $title,
array $types, private array $types,
string $description, private readonly string $description,
array $prices private readonly array $prices
) { ) {
$this->title = $title;
$this->types = $types;
$this->description = $description;
$this->prices = $prices;
} }
/** public static function createFromArray(array $rawData): Offer
* @return Offer
*/
public static function createFromArray(array $rawData)
{ {
$prices = []; $prices = [];
@ -95,7 +69,7 @@ class Offer
public function getType(): string public function getType(): string
{ {
$offerTypes = array_filter($this->types, function (string $type) { $offerTypes = array_filter($this->types, function (string $type) {
return strpos($type, 'Offer') !== false; return str_contains($type, 'Offer');
}); });
// Ensure clean index // Ensure clean index
$offerTypes = array_values($offerTypes); $offerTypes = array_values($offerTypes);

View file

@ -23,31 +23,25 @@ declare(strict_types=1);
namespace WerkraumMedia\ThueCat\Domain\Model\Frontend; namespace WerkraumMedia\ThueCat\Domain\Model\Frontend;
use Countable;
use Iterator;
use TYPO3\CMS\Core\Type\TypeInterface; use TYPO3\CMS\Core\Type\TypeInterface;
/** /**
* @implements \Iterator<int, Offer> * @implements Iterator<int, Offer>
*/ */
class Offers implements TypeInterface, \Iterator, \Countable class Offers implements TypeInterface, Iterator, Countable
{ {
/**
* @var string
*/
private $serialized = '';
/** /**
* @var mixed[] * @var mixed[]
*/ */
private $array = []; private array $array = [];
/** private int $position = 0;
* @var int
*/
private $position = 0;
public function __construct(string $serialized) public function __construct(
{ private readonly string $serialized
$this->serialized = $serialized; ) {
$array = json_decode($serialized, true); $array = json_decode($serialized, true);
if (is_array($array)) { if (is_array($array)) {
$array = array_map([Offer::class, 'createFromArray'], $array); $array = array_map([Offer::class, 'createFromArray'], $array);

View file

@ -23,63 +23,35 @@ declare(strict_types=1);
namespace WerkraumMedia\ThueCat\Domain\Model\Frontend; namespace WerkraumMedia\ThueCat\Domain\Model\Frontend;
use DateTimeImmutable;
use DateTimeZone;
use WerkraumMedia\ThueCat\Domain\TimingFormat; use WerkraumMedia\ThueCat\Domain\TimingFormat;
class OpeningHour class OpeningHour
{ {
/** /**
* @var string * @param mixed[] $daysOfWeek
*/ */
private $opens;
/**
* @var string
*/
private $closes;
/**
* @var mixed[]
*/
private $daysOfWeek;
/**
* @var \DateTimeImmutable|null
*/
private $from;
/**
* @var \DateTimeImmutable|null
*/
private $through;
private function __construct( private function __construct(
string $opens, private readonly string $opens,
string $closes, private readonly string $closes,
array $daysOfWeek, private array $daysOfWeek,
?\DateTimeImmutable $from, private readonly ?DateTimeImmutable $from,
?\DateTimeImmutable $through private readonly ?DateTimeImmutable $through
) { ) {
$this->opens = $opens;
$this->closes = $closes;
$this->daysOfWeek = $daysOfWeek;
$this->from = $from;
$this->through = $through;
} }
/** public static function createFromArray(array $rawData): OpeningHour
* @return OpeningHour
*/
public static function createFromArray(array $rawData)
{ {
$from = null; $from = null;
if (isset($rawData['from'])) { if (isset($rawData['from'])) {
$timeZone = new \DateTimeZone($rawData['from']['timezone'] ?? 'Europe/Berlin'); $timeZone = new DateTimeZone($rawData['from']['timezone'] ?? 'Europe/Berlin');
$from = new \DateTimeImmutable($rawData['from']['date'], $timeZone); $from = new DateTimeImmutable($rawData['from']['date'], $timeZone);
} }
$through = null; $through = null;
if (isset($rawData['through'])) { if (isset($rawData['through'])) {
$timeZone = new \DateTimeZone($rawData['through']['timezone'] ?? 'Europe/Berlin'); $timeZone = new DateTimeZone($rawData['through']['timezone'] ?? 'Europe/Berlin');
$through = new \DateTimeImmutable($rawData['through']['date'], $timeZone); $through = new DateTimeImmutable($rawData['through']['date'], $timeZone);
} }
return new self( return new self(
@ -120,12 +92,12 @@ class OpeningHour
]); ]);
} }
public function getFrom(): ?\DateTimeImmutable public function getFrom(): ?DateTimeImmutable
{ {
return $this->from; return $this->from;
} }
public function getThrough(): ?\DateTimeImmutable public function getThrough(): ?DateTimeImmutable
{ {
return $this->through; return $this->through;
} }
@ -135,10 +107,9 @@ class OpeningHour
$from = $this->getFrom(); $from = $this->getFrom();
$through = $this->getThrough(); $through = $this->getThrough();
return $from instanceof \DateTimeImmutable return $from instanceof DateTimeImmutable
&& $through instanceof \DateTimeImmutable && $through instanceof DateTimeImmutable
&& $from->format('Ymd') === $through->format('Ymd') && $from->format('Ymd') === $through->format('Ymd');
;
} }
private function sortedDaysOfWeek(array $sorting): array private function sortedDaysOfWeek(array $sorting): array

View file

@ -23,33 +23,28 @@ declare(strict_types=1);
namespace WerkraumMedia\ThueCat\Domain\Model\Frontend; namespace WerkraumMedia\ThueCat\Domain\Model\Frontend;
use Countable;
use DateTimeImmutable;
use Iterator;
use TYPO3\CMS\Core\Type\TypeInterface; use TYPO3\CMS\Core\Type\TypeInterface;
use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Core\Utility\GeneralUtility;
use WerkraumMedia\ThueCat\Service\DateBasedFilter; use WerkraumMedia\ThueCat\Service\DateBasedFilter;
/** /**
* @implements \Iterator<int, OpeningHour> * @implements Iterator<int, OpeningHour>
*/ */
class OpeningHours implements TypeInterface, \Iterator, \Countable class OpeningHours implements TypeInterface, Iterator, Countable
{ {
/**
* @var string
*/
private $serialized = '';
/** /**
* @var mixed[] * @var mixed[]
*/ */
private $array = []; private array $array = [];
/** private int $position = 0;
* @var int
*/
private $position = 0;
public function __construct(string $serialized) public function __construct(
{ private readonly string $serialized
$this->serialized = $serialized; ) {
$this->array = $this->createArray($serialized); $this->array = $this->createArray($serialized);
} }
@ -63,10 +58,11 @@ class OpeningHours implements TypeInterface, \Iterator, \Countable
$array = GeneralUtility::makeInstance(DateBasedFilter::class) $array = GeneralUtility::makeInstance(DateBasedFilter::class)
->filterOutPreviousDates( ->filterOutPreviousDates(
$array, $array,
function (OpeningHour $hour): ?\DateTimeImmutable { function (OpeningHour $hour): ?DateTimeImmutable {
return $hour->getThrough(); return $hour->getThrough();
} }
); )
;
usort($array, function (OpeningHour $hourA, OpeningHour $hourB) { usort($array, function (OpeningHour $hourA, OpeningHour $hourB) {
return $hourA->getFrom() <=> $hourB->getFrom(); return $hourA->getFrom() <=> $hourB->getFrom();

View file

@ -28,60 +28,45 @@ use TYPO3\CMS\Extbase\Persistence\ObjectStorage;
abstract class Place extends Base abstract class Place extends Base
{ {
/** protected ?Address $address = null;
* @var Address|null
*/
protected $address = null;
/** protected string $url = '';
* @var string
*/
protected $url = '';
/** protected ?OpeningHours $openingHours = null;
* @var OpeningHours|null
*/
protected $openingHours = null;
/** protected ?OpeningHours $specialOpeningHours = null;
* @var OpeningHours|null
*/
protected $specialOpeningHours = null;
/** /**
* @var ObjectStorage<ParkingFacility> * @var ObjectStorage<ParkingFacility>
*/ */
protected $parkingFacilityNearBy; protected ObjectStorage $parkingFacilityNearBy;
/** /**
* Necessary for Extbase/Symfony.
*
* @var string * @var string
*/ */
protected $sanitation = ''; protected string $sanitation = '';
protected string $otherService = '';
protected string $trafficInfrastructure = '';
/** /**
* Necessary for Extbase/Symfony.
*
* @var string * @var string
*/ */
protected $otherService = ''; protected string $paymentAccepted = '';
/** /**
* Necessary for Extbase/Symfony.
*
* @var string * @var string
*/ */
protected $trafficInfrastructure = ''; protected string $distanceToPublicTransport = '';
/** protected ?AccessiblitySpecification $accessibilitySpecification = null;
* @var string
*/
protected $paymentAccepted = '';
/**
* @var string
*/
protected $distanceToPublicTransport = '';
/**
* @var AccessiblitySpecification|null
*/
protected $accessibilitySpecification = null;
public function initializeObject(): void public function initializeObject(): void
{ {

View file

@ -27,43 +27,13 @@ use TYPO3\CMS\Core\Utility\GeneralUtility;
class Price class Price
{ {
/**
* @var string
*/
private $title;
/**
* @var string
*/
private $description;
/**
* @var float
*/
private $price;
/**
* @var string
*/
private $currency;
/**
* @var string[]
*/
private $rules;
private function __construct( private function __construct(
string $title, private readonly string $title,
string $description, private readonly string $description,
float $price, private readonly float $price,
string $currency, private readonly string $currency,
array $rules private readonly array $rules
) { ) {
$this->title = $title;
$this->description = $description;
$this->price = $price;
$this->currency = $currency;
$this->rules = $rules;
} }
/** /**

View file

@ -27,60 +27,37 @@ use TYPO3\CMS\Core\Utility\GeneralUtility;
class TouristAttraction extends Place class TouristAttraction extends Place
{ {
protected string $slogan = '';
protected ?Offers $offers = null;
protected ?Town $town = null;
protected string $startOfConstruction = '';
protected string $museumService = '';
protected string $architecturalStyle = '';
/** /**
* Necessary for Extbase/Symfony.
*
* @var string * @var string
*/ */
protected $slogan = ''; protected string $digitalOffer = '';
/**
* @var Offers|null
*/
protected $offers = null;
/**
* @var Town|null
*/
protected $town = null;
/** /**
* Necessary for Extbase/Symfony.
*
* @var string * @var string
*/ */
protected $startOfConstruction = ''; protected string $photography = '';
/** protected string $petsAllowed = '';
* @var string
*/
protected $museumService = '';
/** protected string $isAccessibleForFree = '';
* @var string
*/
protected $architecturalStyle = '';
/** protected string $publicAccess = '';
* @var string
*/
protected $digitalOffer = '';
/**
* @var string
*/
protected $photography = '';
/**
* @var string
*/
protected $petsAllowed = '';
/**
* @var string
*/
protected $isAccessibleForFree = '';
/**
* @var string
*/
protected $publicAccess = '';
public function getSlogan(): string public function getSlogan(): string
{ {

View file

@ -23,7 +23,6 @@ declare(strict_types=1);
namespace WerkraumMedia\ThueCat\Domain\Repository\Backend; namespace WerkraumMedia\ThueCat\Domain\Repository\Backend;
use TYPO3\CMS\Extbase\Object\ObjectManagerInterface;
use TYPO3\CMS\Extbase\Persistence\Generic\Typo3QuerySettings; use TYPO3\CMS\Extbase\Persistence\Generic\Typo3QuerySettings;
use TYPO3\CMS\Extbase\Persistence\Repository; use TYPO3\CMS\Extbase\Persistence\Repository;
use WerkraumMedia\ThueCat\Domain\Import\ImportConfiguration; use WerkraumMedia\ThueCat\Domain\Import\ImportConfiguration;
@ -31,10 +30,9 @@ use WerkraumMedia\ThueCat\Domain\Import\ImportConfiguration;
class ImportConfigurationRepository extends Repository class ImportConfigurationRepository extends Repository
{ {
public function __construct( public function __construct(
ObjectManagerInterface $objectManager,
Typo3QuerySettings $querySettings Typo3QuerySettings $querySettings
) { ) {
parent::__construct($objectManager); parent::__construct();
$querySettings->setRespectStoragePage(false); $querySettings->setRespectStoragePage(false);

View file

@ -24,7 +24,6 @@ declare(strict_types=1);
namespace WerkraumMedia\ThueCat\Domain\Repository\Backend; namespace WerkraumMedia\ThueCat\Domain\Repository\Backend;
use TYPO3\CMS\Core\DataHandling\DataHandler; use TYPO3\CMS\Core\DataHandling\DataHandler;
use TYPO3\CMS\Extbase\Object\ObjectManagerInterface;
use TYPO3\CMS\Extbase\Persistence\Generic\Typo3QuerySettings; use TYPO3\CMS\Extbase\Persistence\Generic\Typo3QuerySettings;
use TYPO3\CMS\Extbase\Persistence\QueryInterface; use TYPO3\CMS\Extbase\Persistence\QueryInterface;
use TYPO3\CMS\Extbase\Persistence\Repository; use TYPO3\CMS\Extbase\Persistence\Repository;
@ -32,19 +31,11 @@ use WerkraumMedia\ThueCat\Domain\Model\Backend\ImportLog;
class ImportLogRepository extends Repository class ImportLogRepository extends Repository
{ {
/**
* @var DataHandler
*/
private $dataHandler;
public function __construct( public function __construct(
ObjectManagerInterface $objectManager, private readonly DataHandler $dataHandler,
DataHandler $dataHandler,
Typo3QuerySettings $querySettings Typo3QuerySettings $querySettings
) { ) {
parent::__construct($objectManager); parent::__construct();
$this->dataHandler = $dataHandler;
$querySettings->setRespectStoragePage(false); $querySettings->setRespectStoragePage(false);
$this->setDefaultQuerySettings($querySettings); $this->setDefaultQuerySettings($querySettings);
@ -84,7 +75,7 @@ class ImportLogRepository extends Repository
'import_log' => 'NEW0', 'import_log' => 'NEW0',
'type' => $entry->getType(), 'type' => $entry->getType(),
'remote_id' => $entry->getRemoteId(), 'remote_id' => $entry->getRemoteId(),
'errors' => json_encode($entry->getErrors()), 'errors' => json_encode($entry->getErrors(), JSON_THROW_ON_ERROR),
] ]
); );
} }

View file

@ -23,7 +23,6 @@ declare(strict_types=1);
namespace WerkraumMedia\ThueCat\Domain\Repository\Backend; namespace WerkraumMedia\ThueCat\Domain\Repository\Backend;
use TYPO3\CMS\Extbase\Object\ObjectManagerInterface;
use TYPO3\CMS\Extbase\Persistence\Generic\Typo3QuerySettings; use TYPO3\CMS\Extbase\Persistence\Generic\Typo3QuerySettings;
use TYPO3\CMS\Extbase\Persistence\Repository; use TYPO3\CMS\Extbase\Persistence\Repository;
use WerkraumMedia\ThueCat\Domain\Model\Backend\Organisation; use WerkraumMedia\ThueCat\Domain\Model\Backend\Organisation;
@ -34,10 +33,9 @@ use WerkraumMedia\ThueCat\Domain\Model\Backend\Organisation;
class OrganisationRepository extends Repository class OrganisationRepository extends Repository
{ {
public function __construct( public function __construct(
ObjectManagerInterface $objectManager,
Typo3QuerySettings $querySettings Typo3QuerySettings $querySettings
) { ) {
parent::__construct($objectManager); parent::__construct();
$querySettings->setRespectStoragePage(false); $querySettings->setRespectStoragePage(false);
$this->setDefaultQuerySettings($querySettings); $this->setDefaultQuerySettings($querySettings);

View file

@ -23,7 +23,6 @@ declare(strict_types=1);
namespace WerkraumMedia\ThueCat\Domain\Repository\Backend; namespace WerkraumMedia\ThueCat\Domain\Repository\Backend;
use TYPO3\CMS\Extbase\Object\ObjectManagerInterface;
use TYPO3\CMS\Extbase\Persistence\Generic\Typo3QuerySettings; use TYPO3\CMS\Extbase\Persistence\Generic\Typo3QuerySettings;
use TYPO3\CMS\Extbase\Persistence\QueryResultInterface; use TYPO3\CMS\Extbase\Persistence\QueryResultInterface;
use TYPO3\CMS\Extbase\Persistence\Repository; use TYPO3\CMS\Extbase\Persistence\Repository;
@ -32,10 +31,9 @@ use WerkraumMedia\ThueCat\Domain\Import\Entity\Properties\ForeignReference;
class ParkingFacilityRepository extends Repository class ParkingFacilityRepository extends Repository
{ {
public function __construct( public function __construct(
ObjectManagerInterface $objectManager,
Typo3QuerySettings $querySettings Typo3QuerySettings $querySettings
) { ) {
parent::__construct($objectManager); parent::__construct();
$querySettings->setRespectStoragePage(false); $querySettings->setRespectStoragePage(false);

View file

@ -23,7 +23,6 @@ declare(strict_types=1);
namespace WerkraumMedia\ThueCat\Domain\Repository\Backend; namespace WerkraumMedia\ThueCat\Domain\Repository\Backend;
use TYPO3\CMS\Extbase\Object\ObjectManagerInterface;
use TYPO3\CMS\Extbase\Persistence\Generic\Typo3QuerySettings; use TYPO3\CMS\Extbase\Persistence\Generic\Typo3QuerySettings;
use TYPO3\CMS\Extbase\Persistence\Repository; use TYPO3\CMS\Extbase\Persistence\Repository;
use WerkraumMedia\ThueCat\Domain\Import\ResolveForeignReference; use WerkraumMedia\ThueCat\Domain\Import\ResolveForeignReference;
@ -32,10 +31,9 @@ use WerkraumMedia\ThueCat\Domain\Model\Backend\Town;
class TownRepository extends Repository class TownRepository extends Repository
{ {
public function __construct( public function __construct(
ObjectManagerInterface $objectManager,
Typo3QuerySettings $querySettings Typo3QuerySettings $querySettings
) { ) {
parent::__construct($objectManager); parent::__construct();
$querySettings->setRespectStoragePage(false); $querySettings->setRespectStoragePage(false);

View file

@ -24,80 +24,30 @@ declare(strict_types=1);
namespace WerkraumMedia\ThueCat; namespace WerkraumMedia\ThueCat;
use TYPO3\CMS\Core\Cache\Backend\TransientMemoryBackend; use TYPO3\CMS\Core\Cache\Backend\TransientMemoryBackend;
use TYPO3\CMS\Core\Imaging\IconProvider\SvgIconProvider; use TYPO3\CMS\Core\DataHandling\PageDoktypeRegistry;
use TYPO3\CMS\Core\Imaging\IconRegistry;
use TYPO3\CMS\Core\Utility\ExtensionManagementUtility; use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Extbase\Utility\ExtensionUtility;
use WerkraumMedia\ThueCat\Controller\Backend\ConfigurationController;
use WerkraumMedia\ThueCat\Controller\Backend\ImportController;
class Extension class Extension
{ {
public const EXTENSION_KEY = 'thuecat'; final public const EXTENSION_KEY = 'thuecat';
public const EXTENSION_NAME = 'Thuecat'; final public const EXTENSION_NAME = 'Thuecat';
public const TCA_SELECT_GROUP_IDENTIFIER = 'thuecat'; final public const TCA_SELECT_GROUP_IDENTIFIER = 'thuecat';
public const PAGE_DOKTYPE_TOURIST_ATTRACTION = 950; final public const PAGE_DOKTYPE_TOURIST_ATTRACTION = 950;
public static function getLanguagePath(): string public static function getLanguagePath(): string
{ {
return 'LLL:EXT:' . self::EXTENSION_KEY . '/Resources/Private/Language/'; return 'LLL:EXT:' . self::EXTENSION_KEY . '/Resources/Private/Language/';
} }
public static function registerBackendModules(): void
{
ExtensionUtility::registerModule(
self::EXTENSION_NAME,
'thuecat',
'',
'',
[],
[
'access' => 'user,group',
'icon' => self::getIconPath() . 'ModuleGroup.svg',
'labels' => self::getLanguagePath() . 'locallang_mod.xlf',
]
);
ExtensionUtility::registerModule(
self::EXTENSION_NAME,
'thuecat',
'configurations',
'',
[
ConfigurationController::class => 'index',
ImportController::class => 'import',
],
[
'access' => 'user,group',
'icon' => self::getIconPath() . 'ModuleConfigurations.svg',
'labels' => self::getLanguagePath() . 'locallang_mod_configurations.xlf',
]
);
ExtensionUtility::registerModule(
self::EXTENSION_NAME,
'thuecat',
'imports',
'',
[
ImportController::class => 'index,import',
],
[
'access' => 'user,group',
'icon' => self::getIconPath() . 'ModuleImports.svg',
'labels' => self::getLanguagePath() . 'locallang_mod_imports.xlf',
]
);
}
public static function registerConfig(): void public static function registerConfig(): void
{ {
self::addCaching(); self::addCaching();
self::addContentElements(); self::addContentElements();
self::addPageTypes(); self::addPageTypes();
self::addIcons();
} }
public static function getIconPath(): string public static function getIconPath(): string
@ -129,28 +79,20 @@ class Extension
private static function addPageTypes(): void private static function addPageTypes(): void
{ {
$registry = GeneralUtility::makeInstance(PageDoktypeRegistry::class);
$registry->add(
self::PAGE_DOKTYPE_TOURIST_ATTRACTION,
[
'type' => 'web',
'allowedTables' => '*',
]
);
ExtensionManagementUtility::addUserTSConfig( ExtensionManagementUtility::addUserTSConfig(
"@import 'EXT:" . self::EXTENSION_KEY . "/Configuration/TSconfig/User/All.tsconfig'" "@import 'EXT:" . self::EXTENSION_KEY . "/Configuration/TSconfig/User/All.tsconfig'"
); );
} }
private static function addIcons(): void
{
$iconFiles = GeneralUtility::getFilesInDir(GeneralUtility::getFileAbsFileName(self::getIconPath()));
if (is_array($iconFiles) === false) {
return;
}
$iconRegistry = GeneralUtility::makeInstance(IconRegistry::class);
foreach ($iconFiles as $iconFile) {
$iconRegistry->registerIcon(
str_replace('.svg', '', $iconFile),
SvgIconProvider::class,
['source' => self::getIconPath() . $iconFile]
);
}
}
private static function addCaching(): void private static function addCaching(): void
{ {
$cacheIdentifier = 'thuecat_fetchdata'; $cacheIdentifier = 'thuecat_fetchdata';

View file

@ -33,27 +33,12 @@ use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController;
class ResolveEntities implements DataProcessorInterface class ResolveEntities implements DataProcessorInterface
{ {
/** private readonly TypoScriptFrontendController $tsfe;
* @var ConnectionPool
*/
private $connectionPool;
/**
* @var DataMapper
*/
private $dataMapper;
/**
* @var TypoScriptFrontendController
*/
private $tsfe;
public function __construct( public function __construct(
ConnectionPool $connectionPool, private readonly ConnectionPool $connectionPool,
DataMapper $dataMapper private readonly DataMapper $dataMapper
) { ) {
$this->connectionPool = $connectionPool;
$this->dataMapper = $dataMapper;
$this->tsfe = $GLOBALS['TSFE']; $this->tsfe = $GLOBALS['TSFE'];
} }
@ -67,9 +52,9 @@ class ResolveEntities implements DataProcessorInterface
return $processedData; return $processedData;
} }
$as = (string) $cObj->stdWrapValue('as', $processorConfiguration, 'entities'); $as = (string)$cObj->stdWrapValue('as', $processorConfiguration, 'entities');
$tableName = (string) $cObj->stdWrapValue('table', $processorConfiguration, ''); $tableName = (string)$cObj->stdWrapValue('table', $processorConfiguration, '');
$uids = (string) $cObj->stdWrapValue('uids', $processorConfiguration, ''); $uids = (string)$cObj->stdWrapValue('uids', $processorConfiguration, '');
$uids = GeneralUtility::intExplode(',', $uids); $uids = GeneralUtility::intExplode(',', $uids);
if ($uids === [] || $tableName === '') { if ($uids === [] || $tableName === '') {
@ -93,14 +78,14 @@ class ResolveEntities implements DataProcessorInterface
)); ));
$rows = []; $rows = [];
foreach ($queryBuilder->execute() as $row) { foreach ($queryBuilder->executeQuery()->iterateAssociative() as $row) {
$row = $this->tsfe->sys_page->getLanguageOverlay($tableName, $row); $row = $this->tsfe->sys_page->getLanguageOverlay($tableName, $row);
if (is_array($row)) { if (is_array($row)) {
$rows[] = $row; $rows[] = $row;
} }
} }
usort($rows, function (array $rowA, array $rowB) use($uids) { usort($rows, function (array $rowA, array $rowB) use ($uids) {
return array_search($rowA['uid'], $uids) <=> array_search($rowB['uid'], $uids); return array_search($rowA['uid'], $uids) <=> array_search($rowB['uid'], $uids);
}); });

View file

@ -23,20 +23,15 @@ declare(strict_types=1);
namespace WerkraumMedia\ThueCat\Service\DateBasedFilter; namespace WerkraumMedia\ThueCat\Service\DateBasedFilter;
use DateTimeImmutable;
use TYPO3\CMS\Core\Context\Context; use TYPO3\CMS\Core\Context\Context;
use WerkraumMedia\ThueCat\Service\DateBasedFilter; use WerkraumMedia\ThueCat\Service\DateBasedFilter;
class FilterBasedOnTypo3Context implements DateBasedFilter class FilterBasedOnTypo3Context implements DateBasedFilter
{ {
/**
* @var Context
*/
private $context;
public function __construct( public function __construct(
Context $context private readonly Context $context
) { ) {
$this->context = $context;
} }
/** /**
@ -48,9 +43,9 @@ class FilterBasedOnTypo3Context implements DateBasedFilter
array $listToFilter, array $listToFilter,
callable $provideDate callable $provideDate
): array { ): array {
$referenceDate = $this->context->getPropertyFromAspect('date', 'full', new \DateTimeImmutable()); $referenceDate = $this->context->getPropertyFromAspect('date', 'full', new DateTimeImmutable());
return array_filter($listToFilter, function($elementToFilter) use ($referenceDate, $provideDate) { return array_filter($listToFilter, function ($elementToFilter) use ($referenceDate, $provideDate) {
$objectDate = $provideDate($elementToFilter); $objectDate = $provideDate($elementToFilter);
return $objectDate === null || $objectDate >= $referenceDate; return $objectDate === null || $objectDate >= $referenceDate;
}); });

View file

@ -36,22 +36,10 @@ use WerkraumMedia\ThueCat\Domain\Model\Frontend\Media;
*/ */
class AfterObjectThawedHandler class AfterObjectThawedHandler
{ {
/**
* @var FileRepository
*/
private $fileRepository;
/**
* @var DataMapFactory
*/
private $dataMapFactory;
public function __construct( public function __construct(
FileRepository $fileRepository, private readonly FileRepository $fileRepository,
DataMapFactory $dataMapFactory private readonly DataMapFactory $dataMapFactory
) { ) {
$this->fileRepository = $fileRepository;
$this->dataMapFactory = $dataMapFactory;
} }
public function __invoke(AfterObjectThawedEvent $event): void public function __invoke(AfterObjectThawedEvent $event): void
@ -89,7 +77,7 @@ class AfterObjectThawedHandler
private function getTableNameForObject(Base $object): string private function getTableNameForObject(Base $object): string
{ {
return $this->dataMapFactory return $this->dataMapFactory
->buildDataMap(get_class($object)) ->buildDataMap($object::class)
->getTableName() ->getTableName()
; ;
} }

View file

@ -25,19 +25,16 @@ namespace WerkraumMedia\ThueCat\Updates;
use TYPO3\CMS\Core\Database\ConnectionPool; use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Core\Utility\GeneralUtility;
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('thuecat_backendmoduleuserpermission_v12')]
class BackendModuleUserPermission implements UpgradeWizardInterface class BackendModuleUserPermission implements UpgradeWizardInterface
{ {
/** public function __construct(
* @var ConnectionPool private readonly ConnectionPool $connectionPool
*/ ) {
private $connectionPool;
public function __construct()
{
$this->connectionPool = GeneralUtility::makeInstance(ConnectionPool::class);
} }
public function getIdentifier(): string public function getIdentifier(): string
@ -62,8 +59,9 @@ class BackendModuleUserPermission implements UpgradeWizardInterface
$qb->count('*'); $qb->count('*');
$qb->from('be_users'); $qb->from('be_users');
$qb->where($qb->expr()->like('userMods', $qb->createNamedParameter('%site_ThuecatThuecat%'))); $qb->where($qb->expr()->like('userMods', $qb->createNamedParameter('%site_ThuecatThuecat%')));
$qb->orWhere($qb->expr()->like('userMods', $qb->createNamedParameter('%ThuecatThuecat%')));
return $qb->execute()->fetchOne() > 0; return $qb->executeQuery()->fetchOne() > 0;
} }
public function executeUpdate(): bool public function executeUpdate(): bool
@ -73,14 +71,15 @@ class BackendModuleUserPermission implements UpgradeWizardInterface
$qb->select('uid', 'userMods'); $qb->select('uid', 'userMods');
$qb->from('be_users'); $qb->from('be_users');
$qb->where($qb->expr()->like('userMods', $qb->createNamedParameter('%site_ThuecatThuecat%'))); $qb->where($qb->expr()->like('userMods', $qb->createNamedParameter('%site_ThuecatThuecat%')));
$result = $qb->execute(); $qb->orWhere($qb->expr()->like('userMods', $qb->createNamedParameter('%ThuecatThuecat%')));
$result = $qb->executeQuery()->iterateAssociative();
foreach ($result as $backendUser) { foreach ($result as $backendUser) {
$qb = $this->connectionPool->getQueryBuilderForTable('be_users'); $qb = $this->connectionPool->getQueryBuilderForTable('be_users');
$qb->update('be_users'); $qb->update('be_users');
$qb->set('userMods', $this->updateMods($backendUser['userMods'])); $qb->set('userMods', $this->updateMods($backendUser['userMods']));
$qb->where($qb->expr()->eq('uid', $qb->createNamedParameter($backendUser['uid']))); $qb->where($qb->expr()->eq('uid', $qb->createNamedParameter($backendUser['uid'])));
$qb->execute(); $qb->executeStatement();
} }
return true; return true;
@ -90,11 +89,15 @@ class BackendModuleUserPermission implements UpgradeWizardInterface
{ {
$mods = GeneralUtility::trimExplode(',', $mods, true); $mods = GeneralUtility::trimExplode(',', $mods, true);
unset($mods[array_search('site_ThuecatThuecat', $mods)]); unset(
$mods[array_search('site_ThuecatThuecat', $mods)],
$mods[array_search('ThuecatThuecat', $mods)],
$mods[array_search('ThuecatThuecat_ThuecatConfigurations', $mods)],
$mods[array_search('ThuecatThuecat_ThuecatImports', $mods)],
);
$mods[] = 'ThuecatThuecat'; $mods[] = 'thuecat_configurations';
$mods[] = 'ThuecatThuecat_ThuecatConfigurations'; $mods[] = 'thuecat_imports';
$mods[] = 'ThuecatThuecat_ThuecatImports';
return implode(',', $mods); return implode(',', $mods);
} }
@ -105,9 +108,4 @@ class BackendModuleUserPermission implements UpgradeWizardInterface
DatabaseUpdatedPrerequisite::class, DatabaseUpdatedPrerequisite::class,
]; ];
} }
public static function register(): void
{
$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install']['update'][self::class] = self::class;
}
} }

View file

@ -0,0 +1,47 @@
<?php
declare(strict_types=1);
use WerkraumMedia\ThueCat\Controller\Backend\ConfigurationController;
use WerkraumMedia\ThueCat\Controller\Backend\ImportController;
use WerkraumMedia\ThueCat\Extension;
return [
'thuecat_thuecat' => [
'icon' => Extension::getIconPath() . 'ModuleGroup.svg',
'position' => [
'after' => 'web',
'before' => 'file',
],
'labels' => 'LLL:EXT:thuecat/Resources/Private/Language/locallang_mod.xlf',
'extensionName' => 'Thuecat',
],
'thuecat_configurations' => [
'parent' => 'thuecat_thuecat',
'access' => 'user',
'icon' => Extension::getIconPath() . 'ModuleConfigurations.svg',
'labels' => 'LLL:EXT:thuecat/Resources/Private/Language/locallang_mod_configurations.xlf',
'extensionName' => 'Thuecat',
'controllerActions' => [
ConfigurationController::class => [
'index',
],
ImportController::class => [
'import',
],
],
],
'thuecat_imports' => [
'parent' => 'thuecat_thuecat',
'access' => 'user',
'icon' => Extension::getIconPath() . 'ModuleImports.svg',
'labels' => 'LLL:EXT:thuecat/Resources/Private/Language/locallang_mod_imports.xlf',
'extensionName' => 'Thuecat',
'controllerActions' => [
ImportController::class => [
'index',
'import',
],
],
],
];

View file

@ -1,47 +1,62 @@
<?php <?php
declare(strict_types=1);
use WerkraumMedia\ThueCat\Domain\Model\Backend\ImportConfiguration;
use WerkraumMedia\ThueCat\Domain\Model\Backend\ImportLog;
use WerkraumMedia\ThueCat\Domain\Model\Backend\ImportLogEntry;
use WerkraumMedia\ThueCat\Domain\Model\Backend\ImportLogEntry\MappingError;
use WerkraumMedia\ThueCat\Domain\Model\Backend\ImportLogEntry\SavingEntity;
use WerkraumMedia\ThueCat\Domain\Model\Backend\Organisation;
use WerkraumMedia\ThueCat\Domain\Model\Backend\ParkingFacility;
use WerkraumMedia\ThueCat\Domain\Model\Backend\TouristInformation;
use WerkraumMedia\ThueCat\Domain\Model\Backend\Town;
use WerkraumMedia\ThueCat\Domain\Model\Frontend\ParkingFacility as FrontendParkingFacility;
use WerkraumMedia\ThueCat\Domain\Model\Frontend\TouristAttraction as FrontendTouristAttraction;
use WerkraumMedia\ThueCat\Domain\Model\Frontend\Town as FrontendTown;
return [ return [
\WerkraumMedia\ThueCat\Domain\Model\Backend\Organisation::class => [ Organisation::class => [
'tableName' => 'tx_thuecat_organisation', 'tableName' => 'tx_thuecat_organisation',
], ],
\WerkraumMedia\ThueCat\Domain\Model\Backend\Town::class => [ Town::class => [
'tableName' => 'tx_thuecat_town', 'tableName' => 'tx_thuecat_town',
], ],
\WerkraumMedia\ThueCat\Domain\Model\Backend\TouristInformation::class => [ TouristInformation::class => [
'tableName' => 'tx_thuecat_tourist_information', 'tableName' => 'tx_thuecat_tourist_information',
], ],
WerkraumMedia\ThueCat\Domain\Model\Backend\ParkingFacility::class => [ ParkingFacility::class => [
'tableName' => 'tx_thuecat_parking_facility', 'tableName' => 'tx_thuecat_parking_facility',
], ],
\WerkraumMedia\ThueCat\Domain\Model\Backend\ImportConfiguration::class => [ ImportConfiguration::class => [
'tableName' => 'tx_thuecat_import_configuration', 'tableName' => 'tx_thuecat_import_configuration',
], ],
\WerkraumMedia\ThueCat\Domain\Model\Backend\ImportLog::class => [ ImportLog::class => [
'tableName' => 'tx_thuecat_import_log', 'tableName' => 'tx_thuecat_import_log',
], ],
\WerkraumMedia\ThueCat\Domain\Model\Backend\ImportLogEntry::class => [ ImportLogEntry::class => [
'tableName' => 'tx_thuecat_import_log_entry', 'tableName' => 'tx_thuecat_import_log_entry',
'subclasses' => [ 'subclasses' => [
'savingEntity' => \WerkraumMedia\ThueCat\Domain\Model\Backend\ImportLogEntry\SavingEntity::class, 'savingEntity' => SavingEntity::class,
'mappingError' => \WerkraumMedia\ThueCat\Domain\Model\Backend\ImportLogEntry\MappingError::class, 'mappingError' => MappingError::class,
], ],
], ],
\WerkraumMedia\ThueCat\Domain\Model\Backend\ImportLogEntry\SavingEntity::class => [ SavingEntity::class => [
'tableName' => 'tx_thuecat_import_log_entry', 'tableName' => 'tx_thuecat_import_log_entry',
'recordType' => 'savingEntity', 'recordType' => 'savingEntity',
], ],
\WerkraumMedia\ThueCat\Domain\Model\Backend\ImportLogEntry\MappingError::class => [ MappingError::class => [
'tableName' => 'tx_thuecat_import_log_entry', 'tableName' => 'tx_thuecat_import_log_entry',
'recordType' => 'mappingError', 'recordType' => 'mappingError',
], ],
\WerkraumMedia\ThueCat\Domain\Model\Frontend\TouristAttraction::class => [
FrontendTouristAttraction::class => [
'tableName' => 'tx_thuecat_tourist_attraction', 'tableName' => 'tx_thuecat_tourist_attraction',
], ],
\WerkraumMedia\ThueCat\Domain\Model\Frontend\Town::class => [ FrontendTown::class => [
'tableName' => 'tx_thuecat_town', 'tableName' => 'tx_thuecat_town',
], ],
WerkraumMedia\ThueCat\Domain\Model\Frontend\ParkingFacility::class => [ FrontendParkingFacility::class => [
'tableName' => 'tx_thuecat_parking_facility', 'tableName' => 'tx_thuecat_parking_facility',
], ],
]; ];

30
Configuration/Icons.php Normal file
View file

@ -0,0 +1,30 @@
<?php
declare(strict_types=1);
use TYPO3\CMS\Core\Imaging\IconProvider\SvgIconProvider;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use WerkraumMedia\ThueCat\Extension;
return (static function (): array {
$iconFiles = GeneralUtility::getFilesInDir(
GeneralUtility::getFileAbsFileName(
Extension::getIconPath()
)
);
if (is_array($iconFiles) === false) {
return [];
}
$icons = [];
foreach ($iconFiles as $iconFile) {
$identifier = str_replace('.svg', '', $iconFile);
$icons[$identifier] = [
'provider' => SvgIconProvider::class,
'source' => Extension::getIconPath() . $iconFile,
];
}
return $icons;
})();

View file

@ -6,17 +6,20 @@ namespace WerkraumMedia\ThueCat;
use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator; use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
use WerkraumMedia\ThueCat\DependencyInjection\ConverterPass;
use WerkraumMedia\ThueCat\DependencyInjection\EntityPass;
use WerkraumMedia\ThueCat\DependencyInjection\UrlProvidersPass;
use WerkraumMedia\ThueCat\Domain\Import\Entity\MapsToType; use WerkraumMedia\ThueCat\Domain\Import\Entity\MapsToType;
use WerkraumMedia\ThueCat\Domain\Import\Typo3Converter\Converter; use WerkraumMedia\ThueCat\Domain\Import\Typo3Converter\Converter;
use WerkraumMedia\ThueCat\Domain\Import\UrlProvider\UrlProvider; use WerkraumMedia\ThueCat\Domain\Import\UrlProvider\UrlProvider;
return function (ContainerConfigurator $container, ContainerBuilder $containerBuilder) { return function (ContainerConfigurator $container, ContainerBuilder $containerBuilder) {
$containerBuilder->registerForAutoconfiguration(UrlProvider::class)->addTag(DependencyInjection\UrlProvidersPass::TAG); $containerBuilder->registerForAutoconfiguration(UrlProvider::class)->addTag(UrlProvidersPass::TAG);
$containerBuilder->addCompilerPass(new DependencyInjection\UrlProvidersPass()); $containerBuilder->addCompilerPass(new UrlProvidersPass());
$containerBuilder->registerForAutoconfiguration(Converter::class)->addTag(DependencyInjection\ConverterPass::TAG); $containerBuilder->registerForAutoconfiguration(Converter::class)->addTag(ConverterPass::TAG);
$containerBuilder->addCompilerPass(new DependencyInjection\ConverterPass()); $containerBuilder->addCompilerPass(new ConverterPass());
$containerBuilder->registerForAutoconfiguration(MapsToType::class)->addTag(DependencyInjection\EntityPass::TAG); $containerBuilder->registerForAutoconfiguration(MapsToType::class)->addTag(EntityPass::TAG);
$containerBuilder->addCompilerPass(new DependencyInjection\EntityPass()); $containerBuilder->addCompilerPass(new EntityPass());
}; };

View file

@ -1,12 +1,18 @@
<?php <?php
declare(strict_types=1);
use TYPO3\CMS\Core\Utility\ArrayUtility;
use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
use WerkraumMedia\ThueCat\Extension;
defined('TYPO3') or die(); defined('TYPO3') or die();
(static function (string $extensionKey, string $tableName) { (static function (string $extensionKey, string $tableName) {
$languagePath = \WerkraumMedia\ThueCat\Extension::getLanguagePath() $languagePath = Extension::getLanguagePath()
. 'locallang_tca.xlf:' . $tableName; . 'locallang_tca.xlf:' . $tableName;
\TYPO3\CMS\Core\Utility\ArrayUtility::mergeRecursiveWithOverrule($GLOBALS['TCA'][$tableName], [ ArrayUtility::mergeRecursiveWithOverrule($GLOBALS['TCA'][$tableName], [
'ctrl' => [ 'ctrl' => [
'typeicon_classes' => [ 'typeicon_classes' => [
'contains-thuecat' => 'pages_module_thuecat', 'contains-thuecat' => 'pages_module_thuecat',
@ -32,23 +38,23 @@ defined('TYPO3') or die();
], ],
]); ]);
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addTcaSelectItemGroup( ExtensionManagementUtility::addTcaSelectItemGroup(
$tableName, $tableName,
'doktype', 'doktype',
\WerkraumMedia\ThueCat\Extension::TCA_SELECT_GROUP_IDENTIFIER, Extension::TCA_SELECT_GROUP_IDENTIFIER,
$languagePath . '.group' $languagePath . '.group'
); );
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addTcaSelectItem( ExtensionManagementUtility::addTcaSelectItem(
$tableName, $tableName,
'module', 'module',
[ [
0 => $languagePath . '.module.thuecat', 'label' => $languagePath . '.module.thuecat',
1 => 'thuecat', 'value' => 'thuecat',
2 => 'pages_module_thuecat', 'icon' => 'pages_module_thuecat',
] ]
); );
})( })(
\WerkraumMedia\ThueCat\Extension::EXTENSION_KEY, Extension::EXTENSION_KEY,
'pages' 'pages'
); );

View file

@ -1,12 +1,18 @@
<?php <?php
declare(strict_types=1);
use TYPO3\CMS\Core\Utility\ArrayUtility;
use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
use WerkraumMedia\ThueCat\Extension;
defined('TYPO3') or die(); defined('TYPO3') or die();
(static function (string $extensionKey, string $tableName, int $doktype, string $pageIdentifier) { (static function (string $extensionKey, string $tableName, int $doktype, string $pageIdentifier) {
$languagePath = \WerkraumMedia\ThueCat\Extension::getLanguagePath() $languagePath = Extension::getLanguagePath()
. 'locallang_tca.xlf:' . $tableName . '.' . $pageIdentifier; . 'locallang_tca.xlf:' . $tableName . '.' . $pageIdentifier;
\TYPO3\CMS\Core\Utility\ArrayUtility::mergeRecursiveWithOverrule($GLOBALS['TCA'][$tableName], [ ArrayUtility::mergeRecursiveWithOverrule($GLOBALS['TCA'][$tableName], [
'ctrl' => [ 'ctrl' => [
'typeicon_classes' => [ 'typeicon_classes' => [
$doktype => $tableName . '_' . $pageIdentifier, $doktype => $tableName . '_' . $pageIdentifier,
@ -54,19 +60,19 @@ defined('TYPO3') or die();
], ],
]); ]);
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addTcaSelectItem( ExtensionManagementUtility::addTcaSelectItem(
$tableName, $tableName,
'doktype', 'doktype',
[ [
$languagePath, 'label' => $languagePath,
$doktype, 'value' => $doktype,
\WerkraumMedia\ThueCat\Extension::getIconPath() . $tableName . '_' . $pageIdentifier . '.svg', 'icon' => Extension::getIconPath() . $tableName . '_' . $pageIdentifier . '.svg',
\WerkraumMedia\ThueCat\Extension::TCA_SELECT_GROUP_IDENTIFIER, 'group' => Extension::TCA_SELECT_GROUP_IDENTIFIER,
] ]
); );
})( })(
\WerkraumMedia\ThueCat\Extension::EXTENSION_KEY, Extension::EXTENSION_KEY,
'pages', 'pages',
\WerkraumMedia\ThueCat\Extension::PAGE_DOKTYPE_TOURIST_ATTRACTION, Extension::PAGE_DOKTYPE_TOURIST_ATTRACTION,
'tourist_attraction' 'tourist_attraction'
); );

View file

@ -1,19 +1,24 @@
<?php <?php
declare(strict_types=1);
use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
use WerkraumMedia\ThueCat\Extension;
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/ContentElements', 'Configuration/TypoScript/ContentElements',
'ThüCAT - Content Elements' 'ThüCAT - Content Elements'
); );
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addStaticFile( ExtensionManagementUtility::addStaticFile(
$extensionKey, $extensionKey,
'Configuration/TypoScript/PageTypes', 'Configuration/TypoScript/PageTypes',
'ThüCAT - Page Types' 'ThüCAT - Page Types'
); );
})( })(
\WerkraumMedia\ThueCat\Extension::EXTENSION_KEY, Extension::EXTENSION_KEY,
'sys_template' 'sys_template'
); );

View file

@ -1,18 +1,23 @@
<?php <?php
declare(strict_types=1);
use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
use WerkraumMedia\ThueCat\Extension;
defined('TYPO3') or die(); defined('TYPO3') or die();
(static function (string $extensionKey, string $tableName) { (static function (string $extensionKey, string $tableName) {
$languagePath = \WerkraumMedia\ThueCat\Extension::getLanguagePath() $languagePath = Extension::getLanguagePath()
. 'locallang_tca.xlf:' . $tableName; . 'locallang_tca.xlf:' . $tableName;
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addTcaSelectItemGroup( ExtensionManagementUtility::addTcaSelectItemGroup(
$tableName, $tableName,
'CType', 'CType',
\WerkraumMedia\ThueCat\Extension::TCA_SELECT_GROUP_IDENTIFIER, Extension::TCA_SELECT_GROUP_IDENTIFIER,
$languagePath . '.group' $languagePath . '.group'
); );
})( })(
\WerkraumMedia\ThueCat\Extension::EXTENSION_KEY, Extension::EXTENSION_KEY,
'tt_content' 'tt_content'
); );

View file

@ -1,12 +1,18 @@
<?php <?php
declare(strict_types=1);
use TYPO3\CMS\Core\Utility\ArrayUtility;
use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
use WerkraumMedia\ThueCat\Extension;
defined('TYPO3') or die(); defined('TYPO3') or die();
(static function (string $extensionKey, string $tableName, string $cType) { (static function (string $extensionKey, string $tableName, string $cType) {
$languagePath = \WerkraumMedia\ThueCat\Extension::getLanguagePath() $languagePath = Extension::getLanguagePath()
. 'locallang_tca.xlf:' . $tableName . '.' . $cType; . 'locallang_tca.xlf:' . $tableName . '.' . $cType;
\TYPO3\CMS\Core\Utility\ArrayUtility::mergeRecursiveWithOverrule($GLOBALS['TCA'][$tableName], [ ArrayUtility::mergeRecursiveWithOverrule($GLOBALS['TCA'][$tableName], [
'ctrl' => [ 'ctrl' => [
'typeicon_classes' => [ 'typeicon_classes' => [
$cType => 'tt_content_' . $cType, $cType => 'tt_content_' . $cType,
@ -48,18 +54,18 @@ defined('TYPO3') or die();
], ],
]); ]);
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addTcaSelectItem( ExtensionManagementUtility::addTcaSelectItem(
$tableName, $tableName,
'CType', 'CType',
[ [
$languagePath, 'label' => $languagePath,
$cType, 'value' => $cType,
\WerkraumMedia\ThueCat\Extension::getIconPath() . 'tt_content_' . $cType . '.svg', 'icon' => Extension::getIconPath() . 'tt_content_' . $cType . '.svg',
\WerkraumMedia\ThueCat\Extension::TCA_SELECT_GROUP_IDENTIFIER, 'group' => Extension::TCA_SELECT_GROUP_IDENTIFIER,
] ]
); );
})( })(
\WerkraumMedia\ThueCat\Extension::EXTENSION_KEY, Extension::EXTENSION_KEY,
'tt_content', 'tt_content',
'thuecat_tourist_attraction' 'thuecat_tourist_attraction'
); );

View file

@ -1,20 +1,23 @@
<?php <?php
declare(strict_types=1);
use WerkraumMedia\ThueCat\Extension;
defined('TYPO3') or die(); defined('TYPO3') or die();
return (static function (string $extensionKey, string $tableName) { return (static function (string $extensionKey, string $tableName) {
$languagePath = \WerkraumMedia\ThueCat\Extension::getLanguagePath() . 'locallang_tca.xlf:' . $tableName; $languagePath = Extension::getLanguagePath() . 'locallang_tca.xlf:' . $tableName;
$flexFormConfigurationPath = 'FILE:EXT:' . \WerkraumMedia\ThueCat\Extension::EXTENSION_KEY . '/Configuration/FlexForm/'; $flexFormConfigurationPath = 'FILE:EXT:' . Extension::EXTENSION_KEY . '/Configuration/FlexForm/';
return [ return [
'ctrl' => [ 'ctrl' => [
'label' => 'title', 'label' => 'title',
'iconfile' => \WerkraumMedia\ThueCat\Extension::getIconPath() . $tableName . '.svg', 'iconfile' => Extension::getIconPath() . $tableName . '.svg',
'type' => 'type', 'type' => 'type',
'default_sortby' => 'title', 'default_sortby' => 'title',
'tstamp' => 'tstamp', 'tstamp' => 'tstamp',
'crdate' => 'crdate', 'crdate' => 'crdate',
'cruser_id' => 'cruser_id',
'title' => $languagePath, 'title' => $languagePath,
'enablecolumns' => [ 'enablecolumns' => [
'disabled' => 'disable', 'disabled' => 'disable',
@ -28,7 +31,8 @@ return (static function (string $extensionKey, string $tableName) {
'config' => [ 'config' => [
'type' => 'input', 'type' => 'input',
'max' => 255, 'max' => 255,
'eval' => 'required,trim,unique', 'eval' => 'trim,unique',
'required' => true,
], ],
], ],
'type' => [ 'type' => [
@ -38,16 +42,16 @@ return (static function (string $extensionKey, string $tableName) {
'renderType' => 'selectSingle', 'renderType' => 'selectSingle',
'items' => [ 'items' => [
[ [
$languagePath . '.type.static', 'label' => $languagePath . '.type.static',
'static', 'value' => 'static',
], ],
[ [
$languagePath . '.type.syncScope', 'label' => $languagePath . '.type.syncScope',
'syncScope', 'value' => 'syncScope',
], ],
[ [
$languagePath . '.type.containsPlace', 'label' => $languagePath . '.type.containsPlace',
'containsPlace', 'value' => 'containsPlace',
], ],
], ],
], ],
@ -67,9 +71,8 @@ return (static function (string $extensionKey, string $tableName) {
], ],
'tstamp' => [ 'tstamp' => [
'config' => [ 'config' => [
'type' => 'input', 'type' => 'datetime',
'renderType' => 'inputDateTime', 'format' => 'datetime',
'eval' => 'datetime',
'readOnly' => true, 'readOnly' => true,
], ],
], ],
@ -89,4 +92,4 @@ return (static function (string $extensionKey, string $tableName) {
], ],
], ],
]; ];
})(\WerkraumMedia\ThueCat\Extension::EXTENSION_KEY, 'tx_thuecat_import_configuration'); })(Extension::EXTENSION_KEY, 'tx_thuecat_import_configuration');

View file

@ -1,21 +1,24 @@
<?php <?php
declare(strict_types=1);
use WerkraumMedia\ThueCat\Extension;
defined('TYPO3') or die(); defined('TYPO3') or die();
return (static function (string $extensionKey, string $tableName) { return (static function (string $extensionKey, string $tableName) {
$languagePath = \WerkraumMedia\ThueCat\Extension::getLanguagePath() . 'locallang_tca.xlf:' . $tableName; $languagePath = Extension::getLanguagePath() . 'locallang_tca.xlf:' . $tableName;
$flexFormConfigurationPath = 'FILE:EXT:' . \WerkraumMedia\ThueCat\Extension::EXTENSION_KEY . '/Configuration/FlexForm/'; $flexFormConfigurationPath = 'FILE:EXT:' . Extension::EXTENSION_KEY . '/Configuration/FlexForm/';
return [ return [
'ctrl' => [ 'ctrl' => [
'label' => 'crdate', 'label' => 'crdate',
'label_alt' => 'configuration', 'label_alt' => 'configuration',
'label_alt_force' => true, 'label_alt_force' => true,
'iconfile' => \WerkraumMedia\ThueCat\Extension::getIconPath() . $tableName . '.svg', 'iconfile' => Extension::getIconPath() . $tableName . '.svg',
'default_sortby' => 'crdate desc', 'default_sortby' => 'crdate desc',
'tstamp' => 'tstamp', 'tstamp' => 'tstamp',
'crdate' => 'crdate', 'crdate' => 'crdate',
'cruser_id' => 'cruser_id',
'title' => $languagePath, 'title' => $languagePath,
'enablecolumns' => [ 'enablecolumns' => [
'disabled' => 'disable', 'disabled' => 'disable',
@ -44,9 +47,8 @@ return (static function (string $extensionKey, string $tableName) {
'crdate' => [ 'crdate' => [
'label' => $languagePath . '.crdate', 'label' => $languagePath . '.crdate',
'config' => [ 'config' => [
'type' => 'input', 'type' => 'datetime',
'renderType' => 'inputDateTime', 'format' => 'datetime',
'eval' => 'datetime',
'readOnly' => true, 'readOnly' => true,
], ],
], ],
@ -57,4 +59,4 @@ return (static function (string $extensionKey, string $tableName) {
], ],
], ],
]; ];
})(\WerkraumMedia\ThueCat\Extension::EXTENSION_KEY, 'tx_thuecat_import_log'); })(Extension::EXTENSION_KEY, 'tx_thuecat_import_log');

View file

@ -1,22 +1,25 @@
<?php <?php
declare(strict_types=1);
use WerkraumMedia\ThueCat\Extension;
defined('TYPO3') or die(); defined('TYPO3') or die();
return (static function (string $extensionKey, string $tableName) { return (static function (string $extensionKey, string $tableName) {
$languagePath = \WerkraumMedia\ThueCat\Extension::getLanguagePath() . 'locallang_tca.xlf:' . $tableName; $languagePath = Extension::getLanguagePath() . 'locallang_tca.xlf:' . $tableName;
$flexFormConfigurationPath = 'FILE:EXT:' . \WerkraumMedia\ThueCat\Extension::EXTENSION_KEY . '/Configuration/FlexForm/'; $flexFormConfigurationPath = 'FILE:EXT:' . Extension::EXTENSION_KEY . '/Configuration/FlexForm/';
return [ return [
'ctrl' => [ 'ctrl' => [
'label' => 'type', 'label' => 'type',
'label_alt' => 'remote_id, table_name, record_uid', 'label_alt' => 'remote_id, table_name, record_uid',
'label_alt_force' => true, 'label_alt_force' => true,
'iconfile' => \WerkraumMedia\ThueCat\Extension::getIconPath() . $tableName . '.svg', 'iconfile' => Extension::getIconPath() . $tableName . '.svg',
'type' => 'type', 'type' => 'type',
'default_sortby' => 'crdate', 'default_sortby' => 'crdate',
'tstamp' => 'tstamp', 'tstamp' => 'tstamp',
'crdate' => 'crdate', 'crdate' => 'crdate',
'cruser_id' => 'cruser_id',
'title' => $languagePath, 'title' => $languagePath,
'enablecolumns' => [ 'enablecolumns' => [
'disabled' => 'disable', 'disabled' => 'disable',
@ -32,12 +35,12 @@ return (static function (string $extensionKey, string $tableName) {
'renderType' => 'selectSingle', 'renderType' => 'selectSingle',
'items' => [ 'items' => [
[ [
$languagePath . '.type.savingEntity', 'label' => $languagePath . '.type.savingEntity',
'savingEntity', 'value' => 'savingEntity',
], ],
[ [
$languagePath . '.type.mappingError', 'label' => $languagePath . '.type.mappingError',
'mappingError', 'value' => 'mappingError',
], ],
], ],
], ],
@ -56,8 +59,6 @@ return (static function (string $extensionKey, string $tableName) {
'renderType' => 'checkboxLabeledToggle', 'renderType' => 'checkboxLabeledToggle',
'items' => [ 'items' => [
[ [
0 => '',
1 => '',
'labelChecked' => $languagePath . '.insertion.yes', 'labelChecked' => $languagePath . '.insertion.yes',
'labelUnchecked' => $languagePath . '.insertion.no', 'labelUnchecked' => $languagePath . '.insertion.no',
], ],
@ -98,9 +99,8 @@ return (static function (string $extensionKey, string $tableName) {
'crdate' => [ 'crdate' => [
'label' => $languagePath . '.crdate', 'label' => $languagePath . '.crdate',
'config' => [ 'config' => [
'type' => 'input', 'type' => 'datetime',
'renderType' => 'inputDateTime', 'format' => 'datetime',
'eval' => 'datetime',
'readOnly' => true, 'readOnly' => true,
], ],
], ],
@ -120,4 +120,4 @@ return (static function (string $extensionKey, string $tableName) {
], ],
], ],
]; ];
})(\WerkraumMedia\ThueCat\Extension::EXTENSION_KEY, 'tx_thuecat_import_log_entry'); })(Extension::EXTENSION_KEY, 'tx_thuecat_import_log_entry');

View file

@ -1,18 +1,21 @@
<?php <?php
declare(strict_types=1);
use WerkraumMedia\ThueCat\Extension;
defined('TYPO3') or die(); defined('TYPO3') or die();
return (static function (string $extensionKey, string $tableName) { return (static function (string $extensionKey, string $tableName) {
$languagePath = \WerkraumMedia\ThueCat\Extension::getLanguagePath() . 'locallang_tca.xlf:' . $tableName; $languagePath = Extension::getLanguagePath() . 'locallang_tca.xlf:' . $tableName;
return [ return [
'ctrl' => [ 'ctrl' => [
'label' => 'title', 'label' => 'title',
'iconfile' => \WerkraumMedia\ThueCat\Extension::getIconPath() . $tableName . '.svg', 'iconfile' => Extension::getIconPath() . $tableName . '.svg',
'default_sortby' => 'title', 'default_sortby' => 'title',
'tstamp' => 'tstamp', 'tstamp' => 'tstamp',
'crdate' => 'crdate', 'crdate' => 'crdate',
'cruser_id' => 'cruser_id',
'title' => $languagePath, 'title' => $languagePath,
'enablecolumns' => [ 'enablecolumns' => [
'disabled' => 'disable', 'disabled' => 'disable',
@ -73,9 +76,8 @@ return (static function (string $extensionKey, string $tableName) {
'tstamp' => [ 'tstamp' => [
'label' => $languagePath . '.tstamp', 'label' => $languagePath . '.tstamp',
'config' => [ 'config' => [
'type' => 'input', 'type' => 'datetime',
'renderType' => 'inputDateTime', 'format' => 'datetime',
'eval' => 'datetime',
'readOnly' => true, 'readOnly' => true,
], ],
], ],
@ -88,4 +90,4 @@ return (static function (string $extensionKey, string $tableName) {
], ],
], ],
]; ];
})(\WerkraumMedia\ThueCat\Extension::EXTENSION_KEY, 'tx_thuecat_organisation'); })(Extension::EXTENSION_KEY, 'tx_thuecat_organisation');

View file

@ -1,18 +1,21 @@
<?php <?php
declare(strict_types=1);
use WerkraumMedia\ThueCat\Extension;
defined('TYPO3') or die(); defined('TYPO3') or die();
return (static function (string $extensionKey, string $tableName) { return (static function (string $extensionKey, string $tableName) {
$languagePath = \WerkraumMedia\ThueCat\Extension::getLanguagePath() . 'locallang_tca.xlf:' . $tableName; $languagePath = Extension::getLanguagePath() . 'locallang_tca.xlf:' . $tableName;
return [ return [
'ctrl' => [ 'ctrl' => [
'label' => 'title', 'label' => 'title',
'iconfile' => \WerkraumMedia\ThueCat\Extension::getIconPath() . $tableName . '.svg', 'iconfile' => Extension::getIconPath() . $tableName . '.svg',
'default_sortby' => 'title', 'default_sortby' => 'title',
'tstamp' => 'tstamp', 'tstamp' => 'tstamp',
'crdate' => 'crdate', 'crdate' => 'crdate',
'cruser_id' => 'cruser_id',
'title' => $languagePath, 'title' => $languagePath,
'enablecolumns' => [ 'enablecolumns' => [
'disabled' => 'disable', 'disabled' => 'disable',
@ -28,17 +31,7 @@ return (static function (string $extensionKey, string $tableName) {
'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' => 'select', 'type' => 'language',
'renderType' => 'selectSingle',
'special' => 'languages',
'items' => [
[
'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.allLanguages',
-1,
'flags-multiple',
],
],
'default' => 0,
], ],
], ],
'l18n_parent' => [ 'l18n_parent' => [
@ -47,7 +40,12 @@ return (static function (string $extensionKey, string $tableName) {
'config' => [ 'config' => [
'type' => 'select', 'type' => 'select',
'renderType' => 'selectSingle', 'renderType' => 'selectSingle',
'items' => [['', 0]], 'items' => [
[
'label' => '',
'value' => 0,
],
],
'foreign_table' => $tableName, 'foreign_table' => $tableName,
'foreign_table_where' => 'AND ' . $tableName . '.pid=###CURRENT_PID### AND ' . $tableName . '.sys_language_uid IN (-1,0)', 'foreign_table_where' => 'AND ' . $tableName . '.pid=###CURRENT_PID### AND ' . $tableName . '.sys_language_uid IN (-1,0)',
'default' => 0, 'default' => 0,
@ -66,12 +64,10 @@ return (static function (string $extensionKey, string $tableName) {
'renderType' => 'checkboxToggle', 'renderType' => 'checkboxToggle',
'items' => [ 'items' => [
[ [
0 => '', 'invertStateDisplay' => true,
1 => '', ],
'invertStateDisplay' => true ],
]
], ],
]
], ],
'title' => [ 'title' => [
@ -190,8 +186,8 @@ return (static function (string $extensionKey, string $tableName) {
'default' => '0', 'default' => '0',
'items' => [ 'items' => [
[ [
$languagePath . '.town.unkown', 'label' => $languagePath . '.town.unkown',
0, 'value' => 0,
], ],
], ],
'readOnly' => true, 'readOnly' => true,
@ -207,8 +203,8 @@ return (static function (string $extensionKey, string $tableName) {
'default' => '0', 'default' => '0',
'items' => [ 'items' => [
[ [
$languagePath . '.managed_by.unkown', 'label' => $languagePath . '.managed_by.unkown',
0, 'value' => 0,
], ],
], ],
'readOnly' => true, 'readOnly' => true,
@ -227,4 +223,4 @@ return (static function (string $extensionKey, string $tableName) {
], ],
], ],
]; ];
})(\WerkraumMedia\ThueCat\Extension::EXTENSION_KEY, 'tx_thuecat_parking_facility'); })(Extension::EXTENSION_KEY, 'tx_thuecat_parking_facility');

View file

@ -1,18 +1,21 @@
<?php <?php
declare(strict_types=1);
use WerkraumMedia\ThueCat\Extension;
defined('TYPO3') or die(); defined('TYPO3') or die();
return (static function (string $extensionKey, string $tableName) { return (static function (string $extensionKey, string $tableName) {
$languagePath = \WerkraumMedia\ThueCat\Extension::getLanguagePath() . 'locallang_tca.xlf:' . $tableName; $languagePath = Extension::getLanguagePath() . 'locallang_tca.xlf:' . $tableName;
return [ return [
'ctrl' => [ 'ctrl' => [
'label' => 'title', 'label' => 'title',
'iconfile' => \WerkraumMedia\ThueCat\Extension::getIconPath() . $tableName . '.svg', 'iconfile' => Extension::getIconPath() . $tableName . '.svg',
'default_sortby' => 'title', 'default_sortby' => 'title',
'tstamp' => 'tstamp', 'tstamp' => 'tstamp',
'crdate' => 'crdate', 'crdate' => 'crdate',
'cruser_id' => 'cruser_id',
'title' => $languagePath, 'title' => $languagePath,
'enablecolumns' => [ 'enablecolumns' => [
'disabled' => 'disable', 'disabled' => 'disable',
@ -28,17 +31,7 @@ return (static function (string $extensionKey, string $tableName) {
'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' => 'select', 'type' => 'language',
'renderType' => 'selectSingle',
'special' => 'languages',
'items' => [
[
'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.allLanguages',
-1,
'flags-multiple',
],
],
'default' => 0,
], ],
], ],
'l18n_parent' => [ 'l18n_parent' => [
@ -47,7 +40,12 @@ return (static function (string $extensionKey, string $tableName) {
'config' => [ 'config' => [
'type' => 'select', 'type' => 'select',
'renderType' => 'selectSingle', 'renderType' => 'selectSingle',
'items' => [['', 0]], 'items' => [
[
'label' => '',
'value' => 0,
],
],
'foreign_table' => $tableName, 'foreign_table' => $tableName,
'foreign_table_where' => 'AND ' . $tableName . '.pid=###CURRENT_PID### AND ' . $tableName . '.sys_language_uid IN (-1,0)', 'foreign_table_where' => 'AND ' . $tableName . '.pid=###CURRENT_PID### AND ' . $tableName . '.sys_language_uid IN (-1,0)',
'default' => 0, 'default' => 0,
@ -269,8 +267,8 @@ return (static function (string $extensionKey, string $tableName) {
'default' => '0', 'default' => '0',
'items' => [ 'items' => [
[ [
$languagePath . '.town.unkown', 'label' => $languagePath . '.town.unkown',
0, 'value' => 0,
], ],
], ],
'readOnly' => true, 'readOnly' => true,
@ -286,8 +284,8 @@ return (static function (string $extensionKey, string $tableName) {
'default' => '0', 'default' => '0',
'items' => [ 'items' => [
[ [
$languagePath . '.managed_by.unkown', 'label' => $languagePath . '.managed_by.unkown',
0, 'value' => 0,
], ],
], ],
'readOnly' => true, 'readOnly' => true,
@ -298,12 +296,11 @@ return (static function (string $extensionKey, string $tableName) {
'l10n_mode' => 'exclude', 'l10n_mode' => 'exclude',
'config' => [ 'config' => [
'type' => 'group', 'type' => 'group',
'internal_type' => 'db',
'allowed' => 'tx_thuecat_parking_facility', 'allowed' => 'tx_thuecat_parking_facility',
'foreign_table' => 'tx_thuecat_parking_facility', 'foreign_table' => 'tx_thuecat_parking_facility',
'suggestOptions' => [ 'suggestOptions' => [
'tx_thuecat_parking_facility' => [ 'tx_thuecat_parking_facility' => [
'searchCondition' => 'sys_language_uid IN (0,-1)' 'searchCondition' => 'sys_language_uid IN (0,-1)',
], ],
], ],
'readOnly' => true, 'readOnly' => true,
@ -313,11 +310,10 @@ return (static function (string $extensionKey, string $tableName) {
'editorial_images' => [ 'editorial_images' => [
'label' => $languagePath . '.editorial_images', 'label' => $languagePath . '.editorial_images',
'l10n_mode' => 'exclude', 'l10n_mode' => 'exclude',
'config' => \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::getFileFieldTCAConfig( 'config' => [
'editorial_images', 'type' => 'file',
[], 'allowed' => 'common-image-types',
$GLOBALS['TYPO3_CONF_VARS']['GFX']['imagefile_ext'] ],
),
], ],
], ],
'palettes' => [ 'palettes' => [
@ -332,4 +328,4 @@ return (static function (string $extensionKey, string $tableName) {
], ],
], ],
]; ];
})(\WerkraumMedia\ThueCat\Extension::EXTENSION_KEY, 'tx_thuecat_tourist_attraction'); })(Extension::EXTENSION_KEY, 'tx_thuecat_tourist_attraction');

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