From d39053b4987ccaab1c4382eb535da7b53e8f66a7 Mon Sep 17 00:00:00 2001 From: Daniel Siepmann Date: Thu, 30 Nov 2023 13:52:23 +0100 Subject: [PATCH] Support TYPO3 v12 and PHP 8.3 Use rector, PHPUnit, Codeception and PHPStan to find and fix issues. --- .gitattributes | 20 +- .github/workflows/ci.yaml | 62 +-- .gitignore | 1 + .php-cs-fixer.dist.php | 73 +++ .../Command/ImportConfigurationCommand.php | 17 +- .../Controller/Backend/AbstractController.php | 34 +- .../Backend/ConfigurationController.php | 23 +- .../Controller/Backend/ImportController.php | 47 +- .../Entity/AccessibilityCertification.php | 8 + Classes/Domain/Import/Entity/Base.php | 1 + Classes/Domain/Import/Entity/MapsToType.php | 1 + Classes/Domain/Import/Entity/MediaObject.php | 3 +- Classes/Domain/Import/Entity/Minimum.php | 1 + Classes/Domain/Import/Entity/Place.php | 17 +- .../Domain/Import/Entity/Properties/Geo.php | 4 +- .../Domain/Import/Entity/Properties/Offer.php | 4 +- .../Import/Entity/Properties/OpeningHour.php | 30 +- .../Entity/Properties/PriceSpecification.php | 3 +- .../Import/Entity/Shared/ContainedInPlace.php | 1 + .../Import/Entity/Shared/Organization.php | 1 + .../Import/Entity/TouristAttraction.php | 5 + Classes/Domain/Import/EntityMapper.php | 3 +- .../CustomAnnotationExtractor.php | 65 +-- .../Import/EntityMapper/EntityRegistry.php | 10 +- .../Domain/Import/EntityMapper/JsonDecode.php | 21 +- .../Import/EntityMapper/MappingException.php | 7 +- Classes/Domain/Import/Import.php | 3 +- Classes/Domain/Import/Importer.php | 74 +-- Classes/Domain/Import/Importer/FetchData.php | 26 +- .../FetchData/InvalidResponseException.php | 4 +- Classes/Domain/Import/Importer/SaveData.php | 31 +- .../Domain/Import/Model/EntityCollection.php | 3 +- Classes/Domain/Import/RequestFactory.php | 26 +- .../Domain/Import/ResolveForeignReference.php | 27 +- Classes/Domain/Import/Typo3Converter.php | 14 +- .../Typo3Converter/GeneralConverter.php | 63 +-- .../Typo3Converter/LanguageHandling.php | 17 +- .../UrlProvider/ContainsPlaceUrlProvider.php | 11 +- .../UrlProvider/SyncScopeUrlProvider.php | 11 +- .../Domain/Model/Backend/AbstractEntity.php | 7 +- .../Model/Backend/ImportConfiguration.php | 18 +- Classes/Domain/Model/Backend/ImportLog.php | 7 +- .../Backend/ImportLogEntry/MappingError.php | 3 +- .../Backend/ImportLogEntry/SavingEntity.php | 5 +- Classes/Domain/Model/Frontend/Base.php | 2 +- Classes/Domain/Model/Frontend/Media.php | 1 + .../Model/Frontend/MergedOpeningHour.php | 14 +- .../Model/Frontend/MergedOpeningHours.php | 5 +- Classes/Domain/Model/Frontend/Offer.php | 2 +- Classes/Domain/Model/Frontend/Offers.php | 4 +- Classes/Domain/Model/Frontend/OpeningHour.php | 29 +- .../Domain/Model/Frontend/OpeningHours.php | 10 +- Classes/Domain/Model/Frontend/Place.php | 8 +- .../Model/Frontend/TouristAttraction.php | 4 +- .../Backend/ImportConfigurationRepository.php | 4 +- .../Backend/ImportLogRepository.php | 13 +- .../Backend/OrganisationRepository.php | 4 +- .../Backend/ParkingFacilityRepository.php | 4 +- .../Repository/Backend/TownRepository.php | 4 +- Classes/Extension.php | 78 +--- .../DataProcessing/ResolveEntities.php | 26 +- .../FilterBasedOnTypo3Context.php | 5 +- .../Updates/BackendModuleUserPermission.php | 38 +- Configuration/Backend/Modules.php | 47 ++ Configuration/Extbase/Persistence/Classes.php | 36 +- Configuration/Icons.php | 30 ++ Configuration/Services.php | 15 +- Configuration/TCA/Overrides/pages.php | 24 +- .../Overrides/pages_tourist_attraction.php | 24 +- Configuration/TCA/Overrides/sys_template.php | 11 +- Configuration/TCA/Overrides/tt_content.php | 13 +- .../tt_content_tourist_attraction.php | 22 +- .../TCA/tx_thuecat_import_configuration.php | 33 +- Configuration/TCA/tx_thuecat_import_log.php | 18 +- .../TCA/tx_thuecat_import_log_entry.php | 28 +- Configuration/TCA/tx_thuecat_organisation.php | 16 +- .../TCA/tx_thuecat_parking_facility.php | 43 +- .../TCA/tx_thuecat_tourist_attraction.php | 47 +- .../TCA/tx_thuecat_tourist_information.php | 19 +- Configuration/TCA/tx_thuecat_town.php | 15 +- Documentation/Index.rst | 1 - Documentation/Maintenance/PHP/7.4.rst | 15 - .../Backend/Configuration/Index.html | 230 +++++----- .../Templates/Backend/Import/Index.html | 68 +-- Tests/Acceptance/Data/BasicDatabase.csv | 45 -- Tests/Acceptance/Data/BasicDatabase.php | 87 ++++ Tests/Acceptance/Support/AcceptanceTester.php | 1 + Tests/Acceptance/Support/Environment.php | 16 +- ...ortTest.php => AbstractImportTestCase.php} | 32 +- ...portWithMultipleReferencesToSameObject.php | 195 ++++++++ .../Import/ImportsContainsPlace.php | 80 ++++ ...owingRecordsInCaseOfAnMappingException.php | 119 +++++ ...ecordsInCaseOfAnMappingExceptionOldPhp.php | 119 +++++ .../Import/ImportsFreshOrganization.php | 32 ++ .../Assertions/Import/ImportsSyncScope.php | 120 +++++ ...tractionWithAccessibilitySpecification.php | 26 ++ .../ImportsTouristAttractionWithMedia.php | 22 + ...istAttractionsWithFilteredOpeningHours.php | 28 ++ ...ImportsTouristAttractionsWithRelations.php | 425 ++++++++++++++++++ ...ristAttractionsWithSpecialOpeningHours.php | 28 ++ .../ImportsTouristInformationWithRelation.php | 35 ++ .../Assertions/Import/ImportsTown.php | 24 + .../Import/ImportsTownWithRelation.php | 24 + .../Functional/Fixtures/Frontend/Content.php | 96 ++++ .../Functional/Fixtures/Frontend/Content.xml | 86 ---- .../Frontend/SecondTouristAttraction.php | 35 ++ .../Frontend/SecondTouristAttraction.xml | 31 -- .../TouristAttractionWithEditorialImages.php | 60 +++ .../TouristAttractionWithEditorialImages.xml | 58 --- .../TouristAttractionWithOfferTypes.php | 14 + .../TouristAttractionWithOfferTypes.xml | 10 - .../Frontend/TouristAttractionWithPrices.php | 14 + .../Frontend/TouristAttractionWithPrices.xml | 10 - .../Fixtures/Frontend/TouristAttractions.php | 57 +++ .../Fixtures/Frontend/TouristAttractions.xml | 49 -- ...uristAttractionsForIsAccessibleForFree.php | 62 +++ ...uristAttractionsForIsAccessibleForFree.xml | 56 --- .../Frontend/TouristAttractionsForPets.php | 60 +++ .../Frontend/TouristAttractionsForPets.xml | 54 --- .../TouristAttractionsForPublicAccess.php | 60 +++ .../TouristAttractionsForPublicAccess.xml | 54 --- .../TouristAttractionsOpeningHours.php | 14 + .../TouristAttractionsOpeningHours.xml | 10 - .../Fixtures/Import/BackendUser.php | 26 ++ ...portWithMultipleReferencesToSameObject.csv | 33 -- ...ortWithMultipleReferencesToSameObject.php} | 85 ++-- .../Fixtures/Import/ImportsContainsPlace.csv | 16 - .../Fixtures/Import/ImportsContainsPlace.php | 53 +++ .../Fixtures/Import/ImportsContainsPlace.xml | 64 --- ...owingRecordsInCaseOfAnMappingException.csv | 18 - ...wingRecordsInCaseOfAnMappingException.php} | 111 +++-- ...ecordsInCaseOfAnMappingExceptionOldPhp.csv | 18 - ...ecordsInCaseOfAnMappingExceptionOldPhp.php | 119 +++++ .../Import/ImportsFreshOrganization.csv | 9 - ...ation.xml => ImportsFreshOrganization.php} | 73 +-- .../Fixtures/Import/ImportsSyncScope.csv | 10 - .../Fixtures/Import/ImportsSyncScope.php | 66 +++ .../Fixtures/Import/ImportsSyncScope.xml | 77 ---- ...tractionWithAccessibilitySpecification.csv | 4 - ...tractionWithAccessibilitySpecification.php | 65 +++ ...tractionWithAccessibilitySpecification.xml | 76 ---- ...ristAttractionWithFilteredOpeningHours.php | 65 +++ ...ristAttractionWithFilteredOpeningHours.xml | 76 ---- .../ImportsTouristAttractionWithMedia.csv | 4 - .../ImportsTouristAttractionWithMedia.php | 65 +++ .../ImportsTouristAttractionWithMedia.xml | 76 ---- ...uristAttractionWithSpecialOpeningHours.php | 65 +++ ...uristAttractionWithSpecialOpeningHours.xml | 76 ---- ...istAttractionsWithFilteredOpeningHours.csv | 4 - ...istAttractionsWithFilteredOpeningHours.php | 28 ++ ...ImportsTouristAttractionsWithRelations.csv | 35 -- ...mportsTouristAttractionsWithRelations.php} | 111 +++-- ...ristAttractionsWithSpecialOpeningHours.csv | 4 - ...ristAttractionsWithSpecialOpeningHours.php | 28 ++ .../ImportsTouristInformationWithRelation.csv | 9 - .../ImportsTouristInformationWithRelation.php | 65 +++ .../ImportsTouristInformationWithRelation.xml | 76 ---- .../Fixtures/Import/ImportsTown.csv | 6 - .../Fixtures/Import/ImportsTown.php | 65 +++ .../Fixtures/Import/ImportsTown.xml | 76 ---- .../Import/ImportsTownWithRelation.csv | 6 - .../Import/ImportsTownWithRelation.php | 76 ++++ .../Import/ImportsTownWithRelation.xml | 87 ---- .../Import/UpdatesExistingOrganization.php | 76 ++++ .../Import/UpdatesExistingOrganization.xml | 71 --- Tests/Functional/FrontendTest.php | 148 +++--- Tests/Functional/GuzzleClientFaker.php | 4 +- .../Import/EntityMapping/BaseInfosTest.php | 35 +- .../Import/EntityMapping/JsonDecodingTest.php | 62 +-- .../Import/EntityMapping/PlaceInfosTest.php | 33 +- .../ImportConfigurationCommandTest.php | 27 +- Tests/Functional/ImportTest.php | 197 +++----- .../EntityMapper/EntityRegistryTest.php | 50 +++ Tests/Unit/Domain/Import/ImportTest.php | 44 +- .../Domain/Import/Importer/FetchDataTest.php | 49 +- .../Import/Model/EntityCollectionTest.php | 28 +- .../Domain/Import/Model/GenericEntityTest.php | 56 +-- .../Unit/Domain/Import/RequestFactoryTest.php | 29 +- .../Typo3Converter/GeneralConverterTest.php | 18 +- .../Typo3Converter/NameExtractorTest.php | 24 +- .../Import/UrlProvider/RegistryTest.php | 20 +- .../UrlProvider/StaticUrlProviderTest.php | 20 +- .../UrlProvider/SyncScopeUrlProviderTest.php | 22 +- .../Model/Backend/ImportConfigurationTest.php | 215 ++++----- .../Domain/Model/Backend/ImportLogTest.php | 26 +- .../Domain/Model/Frontend/AddressTest.php | 50 +-- .../Unit/Domain/Model/Frontend/MediaTest.php | 56 +-- .../Unit/Domain/Model/Frontend/OfferTest.php | 20 +- .../Unit/Domain/Model/Frontend/OffersTest.php | 37 +- .../Domain/Model/Frontend/OpeningHourTest.php | 28 +- .../Model/Frontend/TouristAttractionTest.php | 67 ++- Tests/Unit/ExtensionTest.php | 9 +- composer.json | 54 +-- ecs.php | 64 --- ext_emconf.php | 3 - ext_localconf.php | 16 +- ext_tables.php | 5 - phpstan-baseline.neon | 123 +---- phpstan.neon | 10 +- phpunit.xml.dist | 27 +- shell.nix | 27 ++ 201 files changed, 4383 insertions(+), 3663 deletions(-) create mode 100644 .php-cs-fixer.dist.php create mode 100644 Configuration/Backend/Modules.php create mode 100644 Configuration/Icons.php delete mode 100644 Documentation/Maintenance/PHP/7.4.rst delete mode 100644 Tests/Acceptance/Data/BasicDatabase.csv create mode 100644 Tests/Acceptance/Data/BasicDatabase.php rename Tests/Functional/{AbstractImportTest.php => AbstractImportTestCase.php} (84%) create mode 100644 Tests/Functional/Assertions/Import/ImportWithMultipleReferencesToSameObject.php create mode 100644 Tests/Functional/Assertions/Import/ImportsContainsPlace.php create mode 100644 Tests/Functional/Assertions/Import/ImportsFollowingRecordsInCaseOfAnMappingException.php create mode 100644 Tests/Functional/Assertions/Import/ImportsFollowingRecordsInCaseOfAnMappingExceptionOldPhp.php create mode 100644 Tests/Functional/Assertions/Import/ImportsFreshOrganization.php create mode 100644 Tests/Functional/Assertions/Import/ImportsSyncScope.php create mode 100644 Tests/Functional/Assertions/Import/ImportsTouristAttractionWithAccessibilitySpecification.php create mode 100644 Tests/Functional/Assertions/Import/ImportsTouristAttractionWithMedia.php create mode 100644 Tests/Functional/Assertions/Import/ImportsTouristAttractionsWithFilteredOpeningHours.php create mode 100644 Tests/Functional/Assertions/Import/ImportsTouristAttractionsWithRelations.php create mode 100644 Tests/Functional/Assertions/Import/ImportsTouristAttractionsWithSpecialOpeningHours.php create mode 100644 Tests/Functional/Assertions/Import/ImportsTouristInformationWithRelation.php create mode 100644 Tests/Functional/Assertions/Import/ImportsTown.php create mode 100644 Tests/Functional/Assertions/Import/ImportsTownWithRelation.php create mode 100644 Tests/Functional/Fixtures/Frontend/Content.php delete mode 100644 Tests/Functional/Fixtures/Frontend/Content.xml create mode 100644 Tests/Functional/Fixtures/Frontend/SecondTouristAttraction.php delete mode 100644 Tests/Functional/Fixtures/Frontend/SecondTouristAttraction.xml create mode 100644 Tests/Functional/Fixtures/Frontend/TouristAttractionWithEditorialImages.php delete mode 100644 Tests/Functional/Fixtures/Frontend/TouristAttractionWithEditorialImages.xml create mode 100644 Tests/Functional/Fixtures/Frontend/TouristAttractionWithOfferTypes.php delete mode 100644 Tests/Functional/Fixtures/Frontend/TouristAttractionWithOfferTypes.xml create mode 100644 Tests/Functional/Fixtures/Frontend/TouristAttractionWithPrices.php delete mode 100644 Tests/Functional/Fixtures/Frontend/TouristAttractionWithPrices.xml create mode 100644 Tests/Functional/Fixtures/Frontend/TouristAttractions.php delete mode 100644 Tests/Functional/Fixtures/Frontend/TouristAttractions.xml create mode 100644 Tests/Functional/Fixtures/Frontend/TouristAttractionsForIsAccessibleForFree.php delete mode 100644 Tests/Functional/Fixtures/Frontend/TouristAttractionsForIsAccessibleForFree.xml create mode 100644 Tests/Functional/Fixtures/Frontend/TouristAttractionsForPets.php delete mode 100644 Tests/Functional/Fixtures/Frontend/TouristAttractionsForPets.xml create mode 100644 Tests/Functional/Fixtures/Frontend/TouristAttractionsForPublicAccess.php delete mode 100644 Tests/Functional/Fixtures/Frontend/TouristAttractionsForPublicAccess.xml create mode 100644 Tests/Functional/Fixtures/Frontend/TouristAttractionsOpeningHours.php delete mode 100644 Tests/Functional/Fixtures/Frontend/TouristAttractionsOpeningHours.xml create mode 100644 Tests/Functional/Fixtures/Import/BackendUser.php delete mode 100644 Tests/Functional/Fixtures/Import/ImportWithMultipleReferencesToSameObject.csv rename Tests/Functional/Fixtures/Import/{ImportWithMultipleReferencesToSameObject.xml => ImportWithMultipleReferencesToSameObject.php} (57%) delete mode 100644 Tests/Functional/Fixtures/Import/ImportsContainsPlace.csv create mode 100644 Tests/Functional/Fixtures/Import/ImportsContainsPlace.php delete mode 100644 Tests/Functional/Fixtures/Import/ImportsContainsPlace.xml delete mode 100644 Tests/Functional/Fixtures/Import/ImportsFollowingRecordsInCaseOfAnMappingException.csv rename Tests/Functional/Fixtures/Import/{ImportsFollowingRecordsInCaseOfAnMappingException.xml => ImportsFollowingRecordsInCaseOfAnMappingException.php} (51%) delete mode 100644 Tests/Functional/Fixtures/Import/ImportsFollowingRecordsInCaseOfAnMappingExceptionOldPhp.csv create mode 100644 Tests/Functional/Fixtures/Import/ImportsFollowingRecordsInCaseOfAnMappingExceptionOldPhp.php delete mode 100644 Tests/Functional/Fixtures/Import/ImportsFreshOrganization.csv rename Tests/Functional/Fixtures/Import/{ImportsFreshOrganization.xml => ImportsFreshOrganization.php} (54%) delete mode 100644 Tests/Functional/Fixtures/Import/ImportsSyncScope.csv create mode 100644 Tests/Functional/Fixtures/Import/ImportsSyncScope.php delete mode 100644 Tests/Functional/Fixtures/Import/ImportsSyncScope.xml delete mode 100644 Tests/Functional/Fixtures/Import/ImportsTouristAttractionWithAccessibilitySpecification.csv create mode 100644 Tests/Functional/Fixtures/Import/ImportsTouristAttractionWithAccessibilitySpecification.php delete mode 100644 Tests/Functional/Fixtures/Import/ImportsTouristAttractionWithAccessibilitySpecification.xml create mode 100644 Tests/Functional/Fixtures/Import/ImportsTouristAttractionWithFilteredOpeningHours.php delete mode 100644 Tests/Functional/Fixtures/Import/ImportsTouristAttractionWithFilteredOpeningHours.xml delete mode 100644 Tests/Functional/Fixtures/Import/ImportsTouristAttractionWithMedia.csv create mode 100644 Tests/Functional/Fixtures/Import/ImportsTouristAttractionWithMedia.php delete mode 100644 Tests/Functional/Fixtures/Import/ImportsTouristAttractionWithMedia.xml create mode 100644 Tests/Functional/Fixtures/Import/ImportsTouristAttractionWithSpecialOpeningHours.php delete mode 100644 Tests/Functional/Fixtures/Import/ImportsTouristAttractionWithSpecialOpeningHours.xml delete mode 100644 Tests/Functional/Fixtures/Import/ImportsTouristAttractionsWithFilteredOpeningHours.csv create mode 100644 Tests/Functional/Fixtures/Import/ImportsTouristAttractionsWithFilteredOpeningHours.php delete mode 100644 Tests/Functional/Fixtures/Import/ImportsTouristAttractionsWithRelations.csv rename Tests/Functional/Fixtures/Import/{ImportsTouristAttractionsWithRelations.xml => ImportsTouristAttractionsWithRelations.php} (58%) delete mode 100644 Tests/Functional/Fixtures/Import/ImportsTouristAttractionsWithSpecialOpeningHours.csv create mode 100644 Tests/Functional/Fixtures/Import/ImportsTouristAttractionsWithSpecialOpeningHours.php delete mode 100644 Tests/Functional/Fixtures/Import/ImportsTouristInformationWithRelation.csv create mode 100644 Tests/Functional/Fixtures/Import/ImportsTouristInformationWithRelation.php delete mode 100644 Tests/Functional/Fixtures/Import/ImportsTouristInformationWithRelation.xml delete mode 100644 Tests/Functional/Fixtures/Import/ImportsTown.csv create mode 100644 Tests/Functional/Fixtures/Import/ImportsTown.php delete mode 100644 Tests/Functional/Fixtures/Import/ImportsTown.xml delete mode 100644 Tests/Functional/Fixtures/Import/ImportsTownWithRelation.csv create mode 100644 Tests/Functional/Fixtures/Import/ImportsTownWithRelation.php delete mode 100644 Tests/Functional/Fixtures/Import/ImportsTownWithRelation.xml create mode 100644 Tests/Functional/Fixtures/Import/UpdatesExistingOrganization.php delete mode 100644 Tests/Functional/Fixtures/Import/UpdatesExistingOrganization.xml create mode 100644 Tests/Unit/Domain/Import/EntityMapper/EntityRegistryTest.php delete mode 100644 ecs.php delete mode 100644 ext_tables.php diff --git a/.gitattributes b/.gitattributes index ecf7c30..578dc10 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,12 +1,10 @@ -Tests export-ignore -shell.nix export-ignore - -.github export-ignore -.gitattributes export-ignore -.gitignore export-ignore - -ecs.php export-ignore -phpstan.neon export-ignore -phpstan-baseline.neon export-ignore -phpunit.xml.dist export-ignore 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 diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 3f85f7b..2ade17b 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -15,10 +15,9 @@ jobs: strategy: matrix: php-version: - - 7.4 - - 8.0 - 8.1 - 8.2 + - 8.3 steps: - name: Checkout uses: actions/checkout@v3 @@ -41,7 +40,7 @@ jobs: - name: Install PHP uses: shivammathur/setup-php@v2 with: - php-version: "7.4" + php-version: "8.2" tools: composer:v2 - name: Install xmllint @@ -70,14 +69,14 @@ jobs: - name: Install PHP uses: shivammathur/setup-php@v2 with: - php-version: "7.4" + php-version: "8.2" tools: composer:v2 - name: Install dependencies run: composer install --prefer-dist --no-progress --no-suggest - name: Coding Guideline - run: ./vendor/bin/ecs check + run: ./vendor/bin/php-cs-fixer fix --dry-run --diff code-quality: runs-on: ubuntu-latest @@ -86,16 +85,12 @@ jobs: strategy: matrix: 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' - typo3-version: '^11.5' + typo3-version: '^12.4' - php-version: '8.2' - typo3-version: '^11.5' + typo3-version: '^12.4' + - php-version: '8.3' + typo3-version: '^12.4' steps: - uses: actions/checkout@v3 @@ -121,23 +116,14 @@ jobs: strategy: matrix: 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' - typo3-version: '^11.5' + typo3-version: '^12.4' db-version: '8' - 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' steps: - uses: actions/checkout@v3 @@ -151,10 +137,16 @@ jobs: - name: Setup MySQL uses: mirromutth/mysql-action@v1.1 with: - mysql version: '5.7' + mysql version: "${{ matrix.db-version }}" mysql database: 'typo3' 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 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 typo3DatabaseUsername="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 diff --git a/.gitignore b/.gitignore index 51313d0..bc598d6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ /.Build/ +/.phpunit.cache /composer.lock /vendor/ diff --git a/.php-cs-fixer.dist.php b/.php-cs-fixer.dist.php new file mode 100644 index 0000000..5bd6dc4 --- /dev/null +++ b/.php-cs-fixer.dist.php @@ -0,0 +1,73 @@ +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) +; diff --git a/Classes/Command/ImportConfigurationCommand.php b/Classes/Command/ImportConfigurationCommand.php index 95e4dad..c8b1630 100644 --- a/Classes/Command/ImportConfigurationCommand.php +++ b/Classes/Command/ImportConfigurationCommand.php @@ -34,24 +34,11 @@ use WerkraumMedia\ThueCat\Domain\Repository\Backend\ImportConfigurationRepositor class ImportConfigurationCommand extends Command { - /** - * @var ImportConfigurationRepository - */ - private $importConfigurationRepository; - - /** - * @var Importer - */ - private $importer; - public function __construct( - ImportConfigurationRepository $importConfigurationRepository, - Importer $importer + private readonly ImportConfigurationRepository $importConfigurationRepository, + private readonly Importer $importer ) { parent::__construct(); - - $this->importConfigurationRepository = $importConfigurationRepository; - $this->importer = $importer; } protected function configure(): void diff --git a/Classes/Controller/Backend/AbstractController.php b/Classes/Controller/Backend/AbstractController.php index 489e862..fe4ed3c 100644 --- a/Classes/Controller/Backend/AbstractController.php +++ b/Classes/Controller/Backend/AbstractController.php @@ -23,22 +23,30 @@ declare(strict_types=1); 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; abstract class AbstractController extends ActionController { - /** - * BackendTemplateContainer - * - * @var BackendTemplateView - */ - protected $view; + private ModuleTemplateFactory $moduleTemplateFactory; - /** - * Backend Template Container - * - * @var string - */ - protected $defaultViewObjectName = BackendTemplateView::class; + protected ModuleTemplate $moduleTemplate; + + public function injectModuleTemplateFactory(ModuleTemplateFactory $moduleTemplateFactory): void + { + $this->moduleTemplateFactory = $moduleTemplateFactory; + } + + 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()); + } } diff --git a/Classes/Controller/Backend/ConfigurationController.php b/Classes/Controller/Backend/ConfigurationController.php index 91e1847..18dfc38 100644 --- a/Classes/Controller/Backend/ConfigurationController.php +++ b/Classes/Controller/Backend/ConfigurationController.php @@ -23,34 +23,25 @@ declare(strict_types=1); namespace WerkraumMedia\ThueCat\Controller\Backend; +use Psr\Http\Message\ResponseInterface; use WerkraumMedia\ThueCat\Domain\Repository\Backend\ImportConfigurationRepository; use WerkraumMedia\ThueCat\Domain\Repository\Backend\OrganisationRepository; class ConfigurationController extends AbstractController { - /** - * @var OrganisationRepository - */ - private $organisationRepository; - - /** - * @var ImportConfigurationRepository - */ - private $importConfigurationRepository; - public function __construct( - OrganisationRepository $organisationRepository, - ImportConfigurationRepository $importConfigurationRepository + private readonly OrganisationRepository $organisationRepository, + 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(), 'organisations' => $this->organisationRepository->findAll(), ]); + + return $this->htmlResponse(); } } diff --git a/Classes/Controller/Backend/ImportController.php b/Classes/Controller/Backend/ImportController.php index 09f20dc..396eefb 100644 --- a/Classes/Controller/Backend/ImportController.php +++ b/Classes/Controller/Backend/ImportController.php @@ -23,8 +23,9 @@ declare(strict_types=1); namespace WerkraumMedia\ThueCat\Controller\Backend; -use TYPO3\CMS\Core\Messaging\AbstractMessage; -use TYPO3\CMS\Extbase\Annotation as Extbase; +use Psr\Http\Message\ResponseInterface; +use TYPO3\CMS\Core\Type\ContextualFeedbackSeverity; +use TYPO3\CMS\Extbase\Annotation\IgnoreValidation; use WerkraumMedia\ThueCat\Domain\Import\Importer; use WerkraumMedia\ThueCat\Domain\Model\Backend\ImportConfiguration; use WerkraumMedia\ThueCat\Domain\Repository\Backend\ImportLogRepository; @@ -33,42 +34,24 @@ use WerkraumMedia\ThueCat\Typo3Wrapper\TranslationService; class ImportController extends AbstractController { - /** - * @var Importer - */ - private $importer; - - /** - * @var ImportLogRepository - */ - private $repository; - - /** - * @var TranslationService - */ - private $translation; - public function __construct( - Importer $importer, - ImportLogRepository $repository, - TranslationService $translation + private readonly Importer $importer, + private readonly ImportLogRepository $repository, + 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(), ]); + + return $this->htmlResponse(); } - /** - * @Extbase\IgnoreValidation("importConfiguration") - */ - public function importAction(ImportConfiguration $importConfiguration): void + #[IgnoreValidation(['argumentName' => 'importConfiguration'])] + public function importAction(ImportConfiguration $importConfiguration): ResponseInterface { $importLog = $this->importer->importConfiguration($importConfiguration); @@ -78,7 +61,7 @@ class ImportController extends AbstractController $this->createImportDoneFlashMessage($importConfiguration); } - $this->redirect('index', 'Backend\Configuration'); + return $this->redirect('index', 'Backend\Configuration'); } private function createImportErrorFlashMessage(ImportConfiguration $importConfiguration): void @@ -93,7 +76,7 @@ class ImportController extends AbstractController 'controller.backend.import.import.error.title', Extension::EXTENSION_NAME ), - AbstractMessage::ERROR + ContextualFeedbackSeverity::ERROR ); } @@ -109,7 +92,7 @@ class ImportController extends AbstractController 'controller.backend.import.import.success.title', Extension::EXTENSION_NAME ), - AbstractMessage::OK + ContextualFeedbackSeverity::OK ); } } diff --git a/Classes/Domain/Import/Entity/AccessibilityCertification.php b/Classes/Domain/Import/Entity/AccessibilityCertification.php index 16f790d..986027e 100644 --- a/Classes/Domain/Import/Entity/AccessibilityCertification.php +++ b/Classes/Domain/Import/Entity/AccessibilityCertification.php @@ -109,6 +109,7 @@ class AccessibilityCertification implements MapsToType /** * @internal for mapping via Symfony component. + * * @param string|array $accessibilityCertificationStatus */ public function setAccessibilityCertificationStatus($accessibilityCertificationStatus): void @@ -121,6 +122,7 @@ class AccessibilityCertification implements MapsToType /** * @internal for mapping via Symfony component. + * * @param string|array $certificationAccessibilityDeaf */ public function setCertificationAccessibilityDeaf($certificationAccessibilityDeaf): void @@ -133,6 +135,7 @@ class AccessibilityCertification implements MapsToType /** * @internal for mapping via Symfony component. + * * @param string|array $certificationAccessibilityMental */ public function setCertificationAccessibilityMental($certificationAccessibilityMental): void @@ -145,6 +148,7 @@ class AccessibilityCertification implements MapsToType /** * @internal for mapping via Symfony component. + * * @param string|array $certificationAccessibilityPartiallyDeaf */ public function setCertificationAccessibilityPartiallyDeaf($certificationAccessibilityPartiallyDeaf): void @@ -157,6 +161,7 @@ class AccessibilityCertification implements MapsToType /** * @internal for mapping via Symfony component. + * * @param string|array $certificationAccessibilityPartiallyVisual */ public function setCertificationAccessibilityPartiallyVisual($certificationAccessibilityPartiallyVisual): void @@ -169,6 +174,7 @@ class AccessibilityCertification implements MapsToType /** * @internal for mapping via Symfony component. + * * @param string|array $certificationAccessibilityVisual */ public function setCertificationAccessibilityVisual($certificationAccessibilityVisual): void @@ -181,6 +187,7 @@ class AccessibilityCertification implements MapsToType /** * @internal for mapping via Symfony component. + * * @param string|array $certificationAccessibilityWalking */ public function setCertificationAccessibilityWalking($certificationAccessibilityWalking): void @@ -193,6 +200,7 @@ class AccessibilityCertification implements MapsToType /** * @internal for mapping via Symfony component. + * * @param string|array $certificationAccessibilityWheelchair */ public function setCertificationAccessibilityWheelchair($certificationAccessibilityWheelchair): void diff --git a/Classes/Domain/Import/Entity/Base.php b/Classes/Domain/Import/Entity/Base.php index 6bd88a4..cd79747 100644 --- a/Classes/Domain/Import/Entity/Base.php +++ b/Classes/Domain/Import/Entity/Base.php @@ -65,6 +65,7 @@ class Base extends Minimum /** * @internal for mapping via Symfony component. + * * @return ForeignReference[] */ public function getImage(): array diff --git a/Classes/Domain/Import/Entity/MapsToType.php b/Classes/Domain/Import/Entity/MapsToType.php index c65c57a..e3301fd 100644 --- a/Classes/Domain/Import/Entity/MapsToType.php +++ b/Classes/Domain/Import/Entity/MapsToType.php @@ -35,6 +35,7 @@ interface MapsToType * - thuecat:TouristInformation * - thuecat:Town * - … + * * @return string[] */ public static function getSupportedTypes(): array; diff --git a/Classes/Domain/Import/Entity/MediaObject.php b/Classes/Domain/Import/Entity/MediaObject.php index aaf6ebc..175c0e0 100644 --- a/Classes/Domain/Import/Entity/MediaObject.php +++ b/Classes/Domain/Import/Entity/MediaObject.php @@ -85,7 +85,7 @@ class MediaObject extends Minimum implements MapsToType */ public function setCopyrightYear(string $copyrightYear): void { - $this->copyrightYear = (int) $copyrightYear; + $this->copyrightYear = (int)$copyrightYear; } /** @@ -106,6 +106,7 @@ class MediaObject extends Minimum implements MapsToType /** * @internal for mapping via Symfony component. + * * @param string|ForeignReference $author */ public function setAuthor($author): void diff --git a/Classes/Domain/Import/Entity/Minimum.php b/Classes/Domain/Import/Entity/Minimum.php index 32dc453..525fe50 100644 --- a/Classes/Domain/Import/Entity/Minimum.php +++ b/Classes/Domain/Import/Entity/Minimum.php @@ -108,6 +108,7 @@ abstract class Minimum /** * @internal for mapping via Symfony component. + * * @param string|array $url */ public function setUrl($url): void diff --git a/Classes/Domain/Import/Entity/Place.php b/Classes/Domain/Import/Entity/Place.php index 208e10a..21d1623 100644 --- a/Classes/Domain/Import/Entity/Place.php +++ b/Classes/Domain/Import/Entity/Place.php @@ -23,14 +23,15 @@ declare(strict_types=1); namespace WerkraumMedia\ThueCat\Domain\Import\Entity; +use DateTimeImmutable; 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\ForeignReference; use WerkraumMedia\ThueCat\Domain\Import\Entity\Properties\Geo; use WerkraumMedia\ThueCat\Domain\Import\Entity\Properties\OpeningHour; use WerkraumMedia\ThueCat\Domain\Import\Entity\Shared\ContainedInPlace; use WerkraumMedia\ThueCat\Domain\Import\Entity\Shared\Organization; +use WerkraumMedia\ThueCat\Domain\Import\EntityMapper\PropertyValues; use WerkraumMedia\ThueCat\Service\DateBasedFilter; class Place extends Base @@ -161,10 +162,11 @@ class Place extends Base return GeneralUtility::makeInstance(DateBasedFilter::class) ->filterOutPreviousDates( $this->openingHoursSpecifications, - function (OpeningHour $hour): ?\DateTimeImmutable { + function (OpeningHour $hour): ?DateTimeImmutable { return $hour->getValidThrough(); } - ); + ) + ; } /** @@ -175,10 +177,11 @@ class Place extends Base return GeneralUtility::makeInstance(DateBasedFilter::class) ->filterOutPreviousDates( $this->specialOpeningHours, - function (OpeningHour $hour): ?\DateTimeImmutable { + function (OpeningHour $hour): ?DateTimeImmutable { return $hour->getValidThrough(); } - ); + ) + ; } /** @@ -252,6 +255,7 @@ class Place extends Base /** * @internal for mapping via Symfony component. + * * @param string|array $sanitation */ public function setSanitation($sanitation): void @@ -265,6 +269,7 @@ class Place extends Base /** * @internal for mapping via Symfony component. + * * @param string|array $otherService */ public function setOtherService($otherService): void @@ -278,6 +283,7 @@ class Place extends Base /** * @internal for mapping via Symfony component. + * * @param string|array $trafficInfrastructure */ public function setTrafficInfrastructure($trafficInfrastructure): void @@ -291,6 +297,7 @@ class Place extends Base /** * @internal for mapping via Symfony component. + * * @param string|array $paymentAccepted */ public function setPaymentAccepted($paymentAccepted): void diff --git a/Classes/Domain/Import/Entity/Properties/Geo.php b/Classes/Domain/Import/Entity/Properties/Geo.php index 275dcba..8ea1967 100644 --- a/Classes/Domain/Import/Entity/Properties/Geo.php +++ b/Classes/Domain/Import/Entity/Properties/Geo.php @@ -50,7 +50,7 @@ class Geo */ public function setLongitude(string $longitude): void { - $this->longitude = (float) $longitude; + $this->longitude = (float)$longitude; } /** @@ -58,6 +58,6 @@ class Geo */ public function setLatitude(string $latitude): void { - $this->latitude = (float) $latitude; + $this->latitude = (float)$latitude; } } diff --git a/Classes/Domain/Import/Entity/Properties/Offer.php b/Classes/Domain/Import/Entity/Properties/Offer.php index 0592126..fc5d9a1 100644 --- a/Classes/Domain/Import/Entity/Properties/Offer.php +++ b/Classes/Domain/Import/Entity/Properties/Offer.php @@ -23,8 +23,8 @@ declare(strict_types=1); 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\EntityMapper\PropertyValues; class Offer extends Minimum { @@ -48,6 +48,7 @@ class Offer extends Minimum /** * @internal for mapping via Symfony component. + * * @param string|array $offerType */ public function setOfferType($offerType): void @@ -72,6 +73,7 @@ class Offer extends Minimum /** * @return PriceSpecification[] + * * @internal for mapping via Symfony component. */ public function getPriceSpecification(): array diff --git a/Classes/Domain/Import/Entity/Properties/OpeningHour.php b/Classes/Domain/Import/Entity/Properties/OpeningHour.php index 357da02..694662f 100644 --- a/Classes/Domain/Import/Entity/Properties/OpeningHour.php +++ b/Classes/Domain/Import/Entity/Properties/OpeningHour.php @@ -23,25 +23,27 @@ declare(strict_types=1); namespace WerkraumMedia\ThueCat\Domain\Import\Entity\Properties; +use DateTimeImmutable; + class OpeningHour { /** - * @var \DateTimeImmutable|null + * @var DateTimeImmutable|null */ - protected $validFrom = null; + protected $validFrom; /** - * @var \DateTimeImmutable|null + * @var DateTimeImmutable|null */ - protected $validThrough = null; + protected $validThrough; /** - * @var \DateTimeImmutable + * @var DateTimeImmutable */ protected $opens; /** - * @var \DateTimeImmutable + * @var DateTimeImmutable */ protected $closes; @@ -50,22 +52,22 @@ class OpeningHour */ protected $daysOfWeek = []; - public function getValidFrom(): ?\DateTimeImmutable + public function getValidFrom(): ?DateTimeImmutable { return $this->validFrom; } - public function getValidThrough(): ?\DateTimeImmutable + public function getValidThrough(): ?DateTimeImmutable { return $this->validThrough; } - public function getOpens(): \DateTimeImmutable + public function getOpens(): DateTimeImmutable { return $this->opens; } - public function getCloses(): \DateTimeImmutable + public function getCloses(): DateTimeImmutable { return $this->closes; } @@ -81,7 +83,7 @@ class OpeningHour /** * @internal for mapping via Symfony component. */ - public function setValidFrom(\DateTimeImmutable $validFrom): void + public function setValidFrom(DateTimeImmutable $validFrom): void { $this->validFrom = $validFrom; } @@ -89,7 +91,7 @@ class OpeningHour /** * @internal for mapping via Symfony component. */ - public function setValidThrough(\DateTimeImmutable $validThrough): void + public function setValidThrough(DateTimeImmutable $validThrough): void { $this->validThrough = $validThrough; } @@ -97,7 +99,7 @@ class OpeningHour /** * @internal for mapping via Symfony component. */ - public function setOpens(\DateTimeImmutable $opens): void + public function setOpens(DateTimeImmutable $opens): void { $this->opens = $opens; } @@ -105,7 +107,7 @@ class OpeningHour /** * @internal for mapping via Symfony component. */ - public function setCloses(\DateTimeImmutable $closes): void + public function setCloses(DateTimeImmutable $closes): void { $this->closes = $closes; } diff --git a/Classes/Domain/Import/Entity/Properties/PriceSpecification.php b/Classes/Domain/Import/Entity/Properties/PriceSpecification.php index 6d93ee8..5991944 100644 --- a/Classes/Domain/Import/Entity/Properties/PriceSpecification.php +++ b/Classes/Domain/Import/Entity/Properties/PriceSpecification.php @@ -23,8 +23,8 @@ declare(strict_types=1); 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\EntityMapper\PropertyValues; class PriceSpecification extends Minimum { @@ -85,6 +85,7 @@ class PriceSpecification extends Minimum /** * @internal for mapping via Symfony component. + * * @param string|array $calculationRule */ public function setCalculationRule($calculationRule): void diff --git a/Classes/Domain/Import/Entity/Shared/ContainedInPlace.php b/Classes/Domain/Import/Entity/Shared/ContainedInPlace.php index 95929d1..a760589 100644 --- a/Classes/Domain/Import/Entity/Shared/ContainedInPlace.php +++ b/Classes/Domain/Import/Entity/Shared/ContainedInPlace.php @@ -42,6 +42,7 @@ trait ContainedInPlace /** * @return ForeignReference[] + * * @internal for mapping via Symfony component. */ public function getContainedInPlace(): array diff --git a/Classes/Domain/Import/Entity/Shared/Organization.php b/Classes/Domain/Import/Entity/Shared/Organization.php index bfd1710..8bfcbf3 100644 --- a/Classes/Domain/Import/Entity/Shared/Organization.php +++ b/Classes/Domain/Import/Entity/Shared/Organization.php @@ -46,6 +46,7 @@ trait Organization /** * @internal for mapping via Symfony component. + * * @return Offer[] */ public function getMakesOffer(): array diff --git a/Classes/Domain/Import/Entity/TouristAttraction.php b/Classes/Domain/Import/Entity/TouristAttraction.php index fd2579a..b8f179c 100644 --- a/Classes/Domain/Import/Entity/TouristAttraction.php +++ b/Classes/Domain/Import/Entity/TouristAttraction.php @@ -160,6 +160,7 @@ class TouristAttraction extends Place implements MapsToType /** * @internal for mapping via Symfony component. + * * @param string|array $museumService */ public function setMuseumService($museumService): void @@ -173,6 +174,7 @@ class TouristAttraction extends Place implements MapsToType /** * @internal for mapping via Symfony component. + * * @param string|array $architecturalStyle */ public function setArchitecturalStyle($architecturalStyle): void @@ -186,6 +188,7 @@ class TouristAttraction extends Place implements MapsToType /** * @internal for mapping via Symfony component. + * * @param string|array $digitalOffer */ public function setDigitalOffer($digitalOffer): void @@ -199,6 +202,7 @@ class TouristAttraction extends Place implements MapsToType /** * @internal for mapping via Symfony component. + * * @param string|array $photography */ public function setPhotography($photography): void @@ -236,6 +240,7 @@ class TouristAttraction extends Place implements MapsToType /** * @internal for mapping via Symfony component. + * * @param string|array $availableLanguage */ public function setAvailableLanguage($availableLanguage): void diff --git a/Classes/Domain/Import/EntityMapper.php b/Classes/Domain/Import/EntityMapper.php index d82fed2..f4ce833 100644 --- a/Classes/Domain/Import/EntityMapper.php +++ b/Classes/Domain/Import/EntityMapper.php @@ -30,6 +30,7 @@ use Symfony\Component\Serializer\Encoder\JsonEncoder; use Symfony\Component\Serializer\Normalizer\DateTimeNormalizer; use Symfony\Component\Serializer\Normalizer\ObjectNormalizer; use Symfony\Component\Serializer\Serializer; +use Throwable; use WerkraumMedia\ThueCat\Domain\Import\EntityMapper\ArrayDenormalizer; use WerkraumMedia\ThueCat\Domain\Import\EntityMapper\CustomAnnotationExtractor; use WerkraumMedia\ThueCat\Domain\Import\EntityMapper\JsonDecode; @@ -55,7 +56,7 @@ class EntityMapper 'json', $context ); - } catch (\Throwable $e) { + } catch (Throwable $e) { throw new MappingException($jsonLD, $targetClassName, $e); } } diff --git a/Classes/Domain/Import/EntityMapper/CustomAnnotationExtractor.php b/Classes/Domain/Import/EntityMapper/CustomAnnotationExtractor.php index 282d0ec..1842cfb 100644 --- a/Classes/Domain/Import/EntityMapper/CustomAnnotationExtractor.php +++ b/Classes/Domain/Import/EntityMapper/CustomAnnotationExtractor.php @@ -23,13 +23,21 @@ declare(strict_types=1); namespace WerkraumMedia\ThueCat\Domain\Import\EntityMapper; +use function in_array; +use InvalidArgumentException; use LogicException; use phpDocumentor\Reflection\DocBlock; +use phpDocumentor\Reflection\DocBlock\Tags\InvalidTag; +use phpDocumentor\Reflection\DocBlock\Tags\Param; use phpDocumentor\Reflection\DocBlockFactory; use phpDocumentor\Reflection\DocBlockFactoryInterface; -use phpDocumentor\Reflection\DocBlock\Tags\InvalidTag; use phpDocumentor\Reflection\Types\Context; 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\ReflectionExtractor; use Symfony\Component\PropertyInfo\PropertyDescriptionExtractorInterface; @@ -75,7 +83,7 @@ class CustomAnnotationExtractor implements PropertyDescriptionExtractorInterface public function __construct(DocBlockFactoryInterface $docBlockFactory = null, array $mutatorPrefixes = null, array $accessorPrefixes = null, array $arrayMutatorPrefixes = null) { 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".', __CLASS__)); } $this->docBlockFactory = $docBlockFactory ?: DocBlockFactory::createInstance(); @@ -129,7 +137,7 @@ class CustomAnnotationExtractor implements PropertyDescriptionExtractorInterface $contents = $docBlock->getDescription()->render(); - return '' === $contents ? null : $contents; + return $contents === '' ? null : $contents; } /** @@ -161,7 +169,7 @@ class CustomAnnotationExtractor implements PropertyDescriptionExtractorInterface $types = []; /** @var DocBlock\Tags\Var_|DocBlock\Tags\Return_|DocBlock\Tags\Param $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) { switch ($type->getClassName()) { case 'self': @@ -189,7 +197,7 @@ class CustomAnnotationExtractor implements PropertyDescriptionExtractorInterface return null; } - if (!\in_array($prefix, $this->arrayMutatorPrefixes)) { + if (!in_array($prefix, $this->arrayMutatorPrefixes)) { return $types; } @@ -210,12 +218,12 @@ class CustomAnnotationExtractor implements PropertyDescriptionExtractorInterface $types = []; /** @var DocBlock\Tags\Var_|DocBlock\Tags\Return_|DocBlock\Tags\Param $tag */ foreach ($docBlock->getTagsByName('param') as $tag) { - if ($tag && null !== $tag->getType()) { + if ($tag && $tag->getType() !== null) { $types[] = $this->phpDocTypeHelper->getTypes($tag->getType()); } } - if (!isset($types[0]) || [] === $types[0]) { + if (!isset($types[0]) || $types[0] === []) { return null; } @@ -225,8 +233,8 @@ class CustomAnnotationExtractor implements PropertyDescriptionExtractorInterface private function getDocBlockFromConstructor(string $class, string $property): ?DocBlock { try { - $reflectionClass = new \ReflectionClass($class); - } catch (\ReflectionException $e) { + $reflectionClass = new ReflectionClass($class); + } catch (ReflectionException $e) { return null; } $reflectionConstructor = $reflectionClass->getConstructor(); @@ -238,7 +246,7 @@ class CustomAnnotationExtractor implements PropertyDescriptionExtractorInterface $docBlock = $this->docBlockFactory->create($reflectionConstructor, $this->contextFactory->createFromReflector($reflectionConstructor)); return $this->filterDocBlockParams($docBlock, $property); - } catch (\InvalidArgumentException $e) { + } catch (InvalidArgumentException $e) { return null; } } @@ -246,11 +254,18 @@ class CustomAnnotationExtractor implements PropertyDescriptionExtractorInterface private function filterDocBlockParams(DocBlock $docBlock, string $allowedParam): DocBlock { $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(), - $docBlock->getLocation(), $docBlock->isTemplateStart(), $docBlock->isTemplateEnd()); + return new DocBlock( + $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 try { - $reflectionProperty = new \ReflectionProperty($class, $property); - } catch (\ReflectionException $e) { + $reflectionProperty = new ReflectionProperty($class, $property); + } catch (ReflectionException $e) { return null; } @@ -305,7 +320,7 @@ class CustomAnnotationExtractor implements PropertyDescriptionExtractorInterface try { return $this->docBlockFactory->create($reflectionProperty, $this->createFromReflector($reflector)); - } catch (\InvalidArgumentException|\RuntimeException $e) { + } catch (InvalidArgumentException|RuntimeException $e) { return null; } } @@ -315,25 +330,25 @@ class CustomAnnotationExtractor implements PropertyDescriptionExtractorInterface */ 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; foreach ($prefixes as $prefix) { - $methodName = $prefix.$ucFirstProperty; + $methodName = $prefix . $ucFirstProperty; try { - $reflectionMethod = new \ReflectionMethod($class, $methodName); + $reflectionMethod = new ReflectionMethod($class, $methodName); if ($reflectionMethod->isStatic()) { continue; } if ( - (self::ACCESSOR === $type && 0 === $reflectionMethod->getNumberOfRequiredParameters()) || - (self::MUTATOR === $type && $reflectionMethod->getNumberOfParameters() >= 1) + ($type === self::ACCESSOR && $reflectionMethod->getNumberOfRequiredParameters() === 0) || + ($type === self::MUTATOR && $reflectionMethod->getNumberOfParameters() >= 1) ) { break; } - } catch (\ReflectionException $e) { + } catch (ReflectionException $e) { // Try the next prefix if the method doesn't exist } } @@ -352,7 +367,7 @@ class CustomAnnotationExtractor implements PropertyDescriptionExtractorInterface try { return [$this->docBlockFactory->create($reflectionMethod, $this->createFromReflector($reflector)), $prefix]; - } catch (\InvalidArgumentException|\RuntimeException $e) { + } catch (InvalidArgumentException|RuntimeException $e) { return null; } } @@ -360,9 +375,9 @@ class CustomAnnotationExtractor implements PropertyDescriptionExtractorInterface /** * 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])) { return $this->contexts[$cacheKey]; diff --git a/Classes/Domain/Import/EntityMapper/EntityRegistry.php b/Classes/Domain/Import/EntityMapper/EntityRegistry.php index ad94dfb..9b05beb 100644 --- a/Classes/Domain/Import/EntityMapper/EntityRegistry.php +++ b/Classes/Domain/Import/EntityMapper/EntityRegistry.php @@ -23,9 +23,6 @@ declare(strict_types=1); namespace WerkraumMedia\ThueCat\Domain\Import\EntityMapper; -use TYPO3\CMS\Core\Utility\ArrayUtility; - - /** * Registry with supported entities and their types. */ @@ -70,10 +67,9 @@ class EntityRegistry return ''; } - $matches = ArrayUtility::sortArraysByKey( - $matches, - 'priority' - ); + usort($matches, static function (array $configA, array $configB): int { + return $configA['priority'] <=> $configB['priority']; + }); return end($matches)['entityClassName']; } diff --git a/Classes/Domain/Import/EntityMapper/JsonDecode.php b/Classes/Domain/Import/EntityMapper/JsonDecode.php index 29c53f9..25ed398 100644 --- a/Classes/Domain/Import/EntityMapper/JsonDecode.php +++ b/Classes/Domain/Import/EntityMapper/JsonDecode.php @@ -23,9 +23,9 @@ declare(strict_types=1); namespace WerkraumMedia\ThueCat\Domain\Import\EntityMapper; +use InvalidArgumentException; +use function str_starts_with; 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. @@ -50,14 +50,13 @@ class JsonDecode extends SymfonyJsonDecode string $data, string $format, array $context = [] - ) { + ): mixed { $context[self::ASSOCIATIVE] = true; $result = parent::decode($data, $format, $context); - $activeLanguage = $context[self::ACTIVE_LANGUAGE] ?? ''; if ($activeLanguage === '') { - throw new \InvalidArgumentException('Provide active language: ' . self::ACTIVE_LANGUAGE); + throw new InvalidArgumentException('Provide active language: ' . self::ACTIVE_LANGUAGE); } return $this->process( @@ -95,6 +94,7 @@ class JsonDecode extends SymfonyJsonDecode * This decode will resolve the list to a single value based on current language settings from context. * * @param mixed $value + * * @return mixed */ private function decodeLanguageSpecificValue( @@ -156,6 +156,7 @@ class JsonDecode extends SymfonyJsonDecode * This decode will resolve single values wrapped in array with extra info. * * @param mixed $value + * * @return mixed */ private function decodeSingleValues( @@ -190,6 +191,7 @@ class JsonDecode extends SymfonyJsonDecode * Prepare data structure for PHP \DateTimeImmutable. * * @param mixed $value + * * @return mixed */ private function decodeDateTime( @@ -214,6 +216,7 @@ class JsonDecode extends SymfonyJsonDecode /** * @param mixed $key + * * @return mixed */ private function mapKey($key) @@ -222,13 +225,13 @@ class JsonDecode extends SymfonyJsonDecode return $key; } - if (StringUtility::beginsWith($key, '@')) { + if (str_starts_with($key, '@')) { return mb_substr($key, 1); } - if (StringUtility::beginsWith($key, 'schema:')) { + if (str_starts_with($key, 'schema:')) { return mb_substr($key, 7); } - if (StringUtility::beginsWith($key, 'thuecat:')) { + if (str_starts_with($key, 'thuecat:')) { return mb_substr($key, 8); } @@ -238,7 +241,7 @@ class JsonDecode extends SymfonyJsonDecode private function doesRuleMatch(array $rule, string $type): bool { if ($rule['type'] === 'beginsWith') { - return StringUtility::beginsWith($type, $rule['comparisonValue']); + return str_starts_with($type, $rule['comparisonValue']); } return false; diff --git a/Classes/Domain/Import/EntityMapper/MappingException.php b/Classes/Domain/Import/EntityMapper/MappingException.php index 035860a..3c0b885 100644 --- a/Classes/Domain/Import/EntityMapper/MappingException.php +++ b/Classes/Domain/Import/EntityMapper/MappingException.php @@ -23,7 +23,10 @@ declare(strict_types=1); namespace WerkraumMedia\ThueCat\Domain\Import\EntityMapper; -class MappingException extends \Exception +use Exception; +use Throwable; + +class MappingException extends Exception { /** * @var array @@ -38,7 +41,7 @@ class MappingException extends \Exception public function __construct( array $jsonLD, string $targetClassName, - \Throwable $previous + Throwable $previous ) { parent::__construct( 'Could not map incoming JSON-LD to target object: ' . $previous->getMessage(), diff --git a/Classes/Domain/Import/Import.php b/Classes/Domain/Import/Import.php index 1311897..e3fb040 100644 --- a/Classes/Domain/Import/Import.php +++ b/Classes/Domain/Import/Import.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace WerkraumMedia\ThueCat\Domain\Import; +use InvalidArgumentException; use WerkraumMedia\ThueCat\Domain\Model\Backend\ImportConfiguration as Typo3ImportConfiguration; use WerkraumMedia\ThueCat\Domain\Model\Backend\ImportLog; @@ -57,7 +58,7 @@ class Import public function start(ImportConfiguration $configuration): void { 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; diff --git a/Classes/Domain/Import/Importer.php b/Classes/Domain/Import/Importer.php index e67f056..c85d8ec 100644 --- a/Classes/Domain/Import/Importer.php +++ b/Classes/Domain/Import/Importer.php @@ -23,12 +23,13 @@ declare(strict_types=1); namespace WerkraumMedia\ThueCat\Domain\Import; -use TYPO3\CMS\Core\Log\LogManager; +use Exception; 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\JsonDecode; 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\FetchData; use WerkraumMedia\ThueCat\Domain\Import\Importer\Languages; @@ -42,46 +43,6 @@ use WerkraumMedia\ThueCat\Domain\Repository\Backend\ImportLogRepository; class Importer { - /** - * @var UrlProviderRegistry - */ - private $urls; - - /** - * @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 */ @@ -93,24 +54,16 @@ class Importer private $import; public function __construct( - UrlProviderRegistry $urls, - Converter $converter, - EntityRegistry $entityRegistry, - EntityMapper $entityMapper, - Languages $languages, - ImportLogRepository $importLogRepository, - FetchData $fetchData, - SaveData $saveData, + private readonly UrlProviderRegistry $urls, + private readonly Converter $converter, + private readonly EntityRegistry $entityRegistry, + private readonly EntityMapper $entityMapper, + private readonly Languages $languages, + private readonly ImportLogRepository $importLogRepository, + private readonly FetchData $fetchData, + private readonly SaveData $saveData, LogManager $logManager ) { - $this->urls = $urls; - $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(); } @@ -139,7 +92,7 @@ class Importer { $urlProvider = $this->urls->getProviderForConfiguration($this->import->getConfiguration()); 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) { @@ -218,7 +171,8 @@ class Importer 'url' => $url, 'language' => $language, 'targetEntity' => $targetEntity, - ]); + ] + ); continue; } $entities->add($convertedEntity); diff --git a/Classes/Domain/Import/Importer/FetchData.php b/Classes/Domain/Import/Importer/FetchData.php index 5d5b2a0..a29e62a 100644 --- a/Classes/Domain/Import/Importer/FetchData.php +++ b/Classes/Domain/Import/Importer/FetchData.php @@ -32,21 +32,6 @@ use WerkraumMedia\ThueCat\Domain\Import\Importer\FetchData\InvalidResponseExcept class FetchData { - /** - * @var RequestFactoryInterface - */ - private $requestFactory; - - /** - * @var ClientInterface - */ - private $httpClient; - - /** - * @var CacheFrontendInterface - */ - private $cache; - /** * @var string */ @@ -58,13 +43,10 @@ class FetchData private $urlPrefix = 'https://thuecat.org'; public function __construct( - RequestFactoryInterface $requestFactory, - ClientInterface $httpClient, - CacheFrontendInterface $cache + private readonly RequestFactoryInterface $requestFactory, + private readonly ClientInterface $httpClient, + private readonly CacheFrontendInterface $cache ) { - $this->requestFactory = $requestFactory; - $this->httpClient = $httpClient; - $this->cache = $cache; } public function updatedNodes(string $scopeId): array @@ -94,7 +76,7 @@ class FetchData $this->handleInvalidResponse($response, $request); - $jsonLD = json_decode((string) $response->getBody(), true); + $jsonLD = json_decode((string)$response->getBody(), true); if (is_array($jsonLD)) { $this->cache->set($cacheIdentifier, $jsonLD); return $jsonLD; diff --git a/Classes/Domain/Import/Importer/FetchData/InvalidResponseException.php b/Classes/Domain/Import/Importer/FetchData/InvalidResponseException.php index 4568a56..b51528c 100644 --- a/Classes/Domain/Import/Importer/FetchData/InvalidResponseException.php +++ b/Classes/Domain/Import/Importer/FetchData/InvalidResponseException.php @@ -23,6 +23,8 @@ declare(strict_types=1); namespace WerkraumMedia\ThueCat\Domain\Import\Importer\FetchData; -class InvalidResponseException extends \RuntimeException +use RuntimeException; + +class InvalidResponseException extends RuntimeException { } diff --git a/Classes/Domain/Import/Importer/SaveData.php b/Classes/Domain/Import/Importer/SaveData.php index ac12613..8a3847e 100644 --- a/Classes/Domain/Import/Importer/SaveData.php +++ b/Classes/Domain/Import/Importer/SaveData.php @@ -32,27 +32,15 @@ use WerkraumMedia\ThueCat\Domain\Model\Backend\ImportLogEntry\SavingEntity; class SaveData { - /** - * @var DataHandler - */ - private $dataHandler; - - /** - * @var ConnectionPool - */ - private $connectionPool; - /** * @var mixed[] */ private $errorLog; public function __construct( - DataHandler $dataHandler, - ConnectionPool $connectionPool + private readonly DataHandler $dataHandler, + private readonly ConnectionPool $connectionPool ) { - $this->dataHandler = $dataHandler; - $this->connectionPool = $connectionPool; } public function import(EntityCollection $entityCollection, ImportLog $log): void @@ -78,7 +66,7 @@ class SaveData $identifier = $this->getIdentifier($entity); if (is_numeric($identifier)) { - $entity->setExistingTypo3Uid((int) $identifier); + $entity->setExistingTypo3Uid((int)$identifier); } } } @@ -155,7 +143,7 @@ class SaveData $existingUid = $this->getExistingUid($entity); if ($existingUid > 0) { - return (string) $existingUid; + return (string)$existingUid; } $identifier = 'NEW_' . sha1($entity->getRemoteId() . $entity->getTypo3SystemLanguageUid()); @@ -176,7 +164,8 @@ class SaveData $tableColumns = $this->connectionPool ->getConnectionForTable($entity->getTypo3DatabaseTableName()) ->getSchemaManager() - ->listTableColumns($entity->getTypo3DatabaseTableName()); + ->listTableColumns($entity->getTypo3DatabaseTableName()) + ; $queryBuilder = $this->connectionPool->getQueryBuilderForTable($entity->getTypo3DatabaseTableName()); $queryBuilder->getRestrictions()->removeAll(); @@ -193,9 +182,9 @@ class SaveData )); } - $result = $queryBuilder->execute()->fetchColumn(); + $result = $queryBuilder->executeQuery()->fetchOne(); if (is_numeric($result)) { - return (int) $result; + return (int)$result; } return 0; @@ -216,9 +205,9 @@ class SaveData $queryBuilder->createNamedParameter(0) )); - $result = $queryBuilder->execute()->fetchColumn(); + $result = $queryBuilder->executeQuery()->fetchOne(); if (is_numeric($result)) { - return (int) $result; + return (int)$result; } return 0; diff --git a/Classes/Domain/Import/Model/EntityCollection.php b/Classes/Domain/Import/Model/EntityCollection.php index f383c72..08e75f4 100644 --- a/Classes/Domain/Import/Model/EntityCollection.php +++ b/Classes/Domain/Import/Model/EntityCollection.php @@ -61,8 +61,7 @@ class EntityCollection { return array_filter($this->entities, function (Entity $entity) { return $entity->isTranslation() - && $entity->exists() === false - ; + && $entity->exists() === false; }); } diff --git a/Classes/Domain/Import/RequestFactory.php b/Classes/Domain/Import/RequestFactory.php index 2e9302d..2b02fc0 100644 --- a/Classes/Domain/Import/RequestFactory.php +++ b/Classes/Domain/Import/RequestFactory.php @@ -32,29 +32,11 @@ use TYPO3\CMS\Core\Configuration\ExtensionConfiguration; class RequestFactory implements RequestFactoryInterface { - /** - * @var ExtensionConfiguration - */ - private $extensionConfiguration; - - /** - * @var RequestFactoryInterface - */ - private $requestFactory; - - /** - * @var UriFactoryInterface - */ - private $uriFactory; - public function __construct( - ExtensionConfiguration $extensionConfiguration, - RequestFactoryInterface $requestFactory, - UriFactoryInterface $uriFactory + private readonly ExtensionConfiguration $extensionConfiguration, + private readonly RequestFactoryInterface $requestFactory, + 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 { if (!$uri instanceof UriInterface) { - $uri = $this->uriFactory->createUri((string) $uri); + $uri = $this->uriFactory->createUri((string)$uri); } $query = []; diff --git a/Classes/Domain/Import/ResolveForeignReference.php b/Classes/Domain/Import/ResolveForeignReference.php index cbd7b91..449dca2 100644 --- a/Classes/Domain/Import/ResolveForeignReference.php +++ b/Classes/Domain/Import/ResolveForeignReference.php @@ -23,9 +23,9 @@ declare(strict_types=1); 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\JsonDecode; -use WerkraumMedia\ThueCat\Domain\Import\Entity\Properties\ForeignReference; use WerkraumMedia\ThueCat\Domain\Import\Importer\FetchData; use WerkraumMedia\ThueCat\Domain\Import\Importer\FetchData\InvalidResponseException; @@ -38,29 +38,11 @@ use WerkraumMedia\ThueCat\Domain\Import\Importer\FetchData\InvalidResponseExcept */ class ResolveForeignReference { - /** - * @var FetchData - */ - private $fetchData; - - /** - * @var EntityRegistry - */ - private $entityRegistry; - - /** - * @var EntityMapper - */ - private $entityMapper; - public function __construct( - FetchData $fetchData, - EntityRegistry $entityRegistry, - EntityMapper $entityMapper + private readonly FetchData $fetchData, + private readonly EntityRegistry $entityRegistry, + private readonly EntityMapper $entityMapper ) { - $this->fetchData = $fetchData; - $this->entityRegistry = $entityRegistry; - $this->entityMapper = $entityMapper; } public function resolve( @@ -94,6 +76,7 @@ class ResolveForeignReference /** * @param ForeignReference[] $foreignReferences + * * @return string[] */ public static function convertToRemoteIds(array $foreignReferences): array diff --git a/Classes/Domain/Import/Typo3Converter.php b/Classes/Domain/Import/Typo3Converter.php index d5719f3..38f2779 100644 --- a/Classes/Domain/Import/Typo3Converter.php +++ b/Classes/Domain/Import/Typo3Converter.php @@ -23,6 +23,8 @@ declare(strict_types=1); namespace WerkraumMedia\ThueCat\Domain\Import; +use Exception; +use InvalidArgumentException; use WerkraumMedia\ThueCat\Domain\Import\Entity\MapsToType; use WerkraumMedia\ThueCat\Domain\Import\Importer\Converter; use WerkraumMedia\ThueCat\Domain\Import\Model\Entity; @@ -32,15 +34,9 @@ use WerkraumMedia\ThueCat\Domain\Model\Backend\ImportConfiguration as Typo3Impor class Typo3Converter implements Converter { - /** - * @var Registry - */ - private $registry; - public function __construct( - Registry $registry + private readonly Registry $registry ) { - $this->registry = $registry; } public function convert( @@ -49,12 +45,12 @@ class Typo3Converter implements Converter string $language ): ?Entity { 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); if (!$concreteConverter instanceof Typo3ConcreteConverter) { - throw new \Exception( + throw new Exception( 'No TYPO3 Converter registered for given Entity "' . get_class($mapped) . '".', 1628244329 ); diff --git a/Classes/Domain/Import/Typo3Converter/GeneralConverter.php b/Classes/Domain/Import/Typo3Converter/GeneralConverter.php index 40613cb..3f9e594 100644 --- a/Classes/Domain/Import/Typo3Converter/GeneralConverter.php +++ b/Classes/Domain/Import/Typo3Converter/GeneralConverter.php @@ -23,8 +23,9 @@ declare(strict_types=1); 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\LogManager; use TYPO3\CMS\Extbase\Persistence\QueryResultInterface; use WerkraumMedia\ThueCat\Domain\Import\Entity\AccessibilitySpecification; use WerkraumMedia\ThueCat\Domain\Import\Entity\Base; @@ -52,41 +53,6 @@ use WerkraumMedia\ThueCat\Domain\Repository\Backend\TownRepository; class GeneralConverter implements Converter { - /** - * @var ResolveForeignReference - */ - private $resolveForeignReference; - - /** - * @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 */ @@ -110,22 +76,15 @@ class GeneralConverter implements Converter ]; public function __construct( - ResolveForeignReference $resolveForeignReference, - Importer $importer, - LanguageHandling $languageHandling, - OrganisationRepository $organisationRepository, - TownRepository $townRepository, - ParkingFacilityRepository $parkingFacilityRepository, - NameExtractor $nameExtractor, + private readonly ResolveForeignReference $resolveForeignReference, + private readonly Importer $importer, + private readonly LanguageHandling $languageHandling, + private readonly OrganisationRepository $organisationRepository, + private readonly TownRepository $townRepository, + private readonly ParkingFacilityRepository $parkingFacilityRepository, + private readonly NameExtractor $nameExtractor, LogManager $logManager ) { - $this->resolveForeignReference = $resolveForeignReference; - $this->importer = $importer; - $this->languageHandling = $languageHandling; - $this->organisationRepository = $organisationRepository; - $this->townRepository = $townRepository; - $this->parkingFacilityRepository = $parkingFacilityRepository; - $this->nameExtractor = $nameExtractor; $this->logger = $logManager->getLogger(__CLASS__); } @@ -214,7 +173,7 @@ class GeneralConverter implements Converter { $tableName = $this->classToTableMapping[$className] ?? ''; 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; @@ -298,7 +257,7 @@ class GeneralConverter implements Converter ) ); $town = $this->townRepository->findOneByEntity($entity); - return $town ? (string) $town->getUid() : ''; + return $town ? (string)$town->getUid() : ''; } private function getParkingFacilitiesNearByUids(Base $entity): array diff --git a/Classes/Domain/Import/Typo3Converter/LanguageHandling.php b/Classes/Domain/Import/Typo3Converter/LanguageHandling.php index 9b024d6..d80afbb 100644 --- a/Classes/Domain/Import/Typo3Converter/LanguageHandling.php +++ b/Classes/Domain/Import/Typo3Converter/LanguageHandling.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace WerkraumMedia\ThueCat\Domain\Import\Typo3Converter; +use InvalidArgumentException; use TYPO3\CMS\Core\Site\Entity\SiteLanguage; use TYPO3\CMS\Core\Site\SiteFinder; use WerkraumMedia\ThueCat\Domain\Import\ImportConfiguration; @@ -30,36 +31,30 @@ use WerkraumMedia\ThueCat\Domain\Import\Importer\Languages; class LanguageHandling implements Languages { - /** - * @var SiteFinder - */ - private $siteFinder; - public function __construct( - SiteFinder $siteFinder + private readonly SiteFinder $siteFinder ) { - $this->siteFinder = $siteFinder; } public function getAvailable(ImportConfiguration $configuration): array { 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 $language->getTwoLetterIsoCode(); + return $language->getLocale()->getLanguageCode(); }, $this->getLanguages($configuration->getStoragePid())); } public function getLanguageUidForString(int $pageUid, string $isoCode): int { foreach ($this->getLanguages($pageUid) as $language) { - if ($language->getTwoLetterIsoCode() === $isoCode) { + if ($language->getLocale()->getLanguageCode() === $isoCode) { return $language->getLanguageId(); } } - throw new \InvalidArgumentException( + throw new InvalidArgumentException( sprintf( 'Could not find language for combination of page "%d" and iso code "%s".', $pageUid, diff --git a/Classes/Domain/Import/UrlProvider/ContainsPlaceUrlProvider.php b/Classes/Domain/Import/UrlProvider/ContainsPlaceUrlProvider.php index 8f0c752..be91be1 100644 --- a/Classes/Domain/Import/UrlProvider/ContainsPlaceUrlProvider.php +++ b/Classes/Domain/Import/UrlProvider/ContainsPlaceUrlProvider.php @@ -23,25 +23,20 @@ declare(strict_types=1); namespace WerkraumMedia\ThueCat\Domain\Import\UrlProvider; +use InvalidArgumentException; use WerkraumMedia\ThueCat\Domain\Import\ImportConfiguration; use WerkraumMedia\ThueCat\Domain\Import\Importer\FetchData; class ContainsPlaceUrlProvider implements UrlProvider { - /** - * @var FetchData - */ - private $fetchData; - /** * @var string */ private $containsPlaceId = ''; public function __construct( - FetchData $fetchData + private readonly FetchData $fetchData ) { - $this->fetchData = $fetchData; } public function canProvideForConfiguration( @@ -54,7 +49,7 @@ class ContainsPlaceUrlProvider implements UrlProvider ImportConfiguration $configuration ): UrlProvider { 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->containsPlaceId = $configuration->getContainsPlaceId(); diff --git a/Classes/Domain/Import/UrlProvider/SyncScopeUrlProvider.php b/Classes/Domain/Import/UrlProvider/SyncScopeUrlProvider.php index 6afa5e4..90f598a 100644 --- a/Classes/Domain/Import/UrlProvider/SyncScopeUrlProvider.php +++ b/Classes/Domain/Import/UrlProvider/SyncScopeUrlProvider.php @@ -23,25 +23,20 @@ declare(strict_types=1); namespace WerkraumMedia\ThueCat\Domain\Import\UrlProvider; +use InvalidArgumentException; use WerkraumMedia\ThueCat\Domain\Import\ImportConfiguration; use WerkraumMedia\ThueCat\Domain\Import\Importer\FetchData; class SyncScopeUrlProvider implements UrlProvider { - /** - * @var FetchData - */ - private $fetchData; - /** * @var string */ private $syncScopeId = ''; public function __construct( - FetchData $fetchData + private readonly FetchData $fetchData ) { - $this->fetchData = $fetchData; } public function canProvideForConfiguration( @@ -54,7 +49,7 @@ class SyncScopeUrlProvider implements UrlProvider ImportConfiguration $configuration ): UrlProvider { 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->syncScopeId = $configuration->getSyncScopeId(); diff --git a/Classes/Domain/Model/Backend/AbstractEntity.php b/Classes/Domain/Model/Backend/AbstractEntity.php index c5c677b..005ead4 100644 --- a/Classes/Domain/Model/Backend/AbstractEntity.php +++ b/Classes/Domain/Model/Backend/AbstractEntity.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace WerkraumMedia\ThueCat\Domain\Model\Backend; +use DateTimeImmutable; use TYPO3\CMS\Extbase\DomainObject\AbstractEntity as Typo3AbstractEntity; class AbstractEntity extends Typo3AbstractEntity @@ -43,9 +44,9 @@ class AbstractEntity extends Typo3AbstractEntity protected $description = ''; /** - * @var \DateTimeImmutable|null + * @var DateTimeImmutable|null */ - protected $tstamp = null; + protected $tstamp; public function getRemoteId(): string { @@ -62,7 +63,7 @@ class AbstractEntity extends Typo3AbstractEntity return $this->description; } - public function getLastImported(): ?\DateTimeImmutable + public function getLastImported(): ?DateTimeImmutable { return $this->tstamp; } diff --git a/Classes/Domain/Model/Backend/ImportConfiguration.php b/Classes/Domain/Model/Backend/ImportConfiguration.php index 86113b9..311d98e 100644 --- a/Classes/Domain/Model/Backend/ImportConfiguration.php +++ b/Classes/Domain/Model/Backend/ImportConfiguration.php @@ -23,6 +23,8 @@ declare(strict_types=1); namespace WerkraumMedia\ThueCat\Domain\Model\Backend; +use DateTimeImmutable; +use Exception; use TYPO3\CMS\Core\Utility\ArrayUtility; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Extbase\DomainObject\AbstractEntity; @@ -49,9 +51,9 @@ class ImportConfiguration extends AbstractEntity implements ImportConfigurationI protected $configuration = ''; /** - * @var \DateTimeImmutable|null + * @var DateTimeImmutable|null */ - protected $tstamp = null; + protected $tstamp; /** * @var ObjectStorage @@ -61,7 +63,7 @@ class ImportConfiguration extends AbstractEntity implements ImportConfigurationI /** * @var string[]|null */ - protected $urls = null; + protected $urls; /** * @var string[] @@ -88,15 +90,15 @@ class ImportConfiguration extends AbstractEntity implements ImportConfigurationI return 'tx_thuecat_import_configuration'; } - public function getLastChanged(): ?\DateTimeImmutable + public function getLastChanged(): ?DateTimeImmutable { return $this->tstamp; } - public function getLastImported(): ?\DateTimeImmutable + public function getLastImported(): ?DateTimeImmutable { $lastImport = null; - $positionOfLastLog = (string) (count($this->logs) - 1); + $positionOfLastLog = (count($this->logs) - 1); if ($this->logs->offsetExists($positionOfLastLog)) { $lastImport = $this->logs->offsetGet($positionOfLastLog); } @@ -112,7 +114,7 @@ class ImportConfiguration extends AbstractEntity implements ImportConfigurationI $storagePid = $this->getConfigurationValueFromFlexForm('storagePid'); if (is_numeric($storagePid) && $storagePid > 0) { - return intval($storagePid); + return (int)$storagePid; } return 0; @@ -151,7 +153,7 @@ class ImportConfiguration extends AbstractEntity implements ImportConfigurationI { $containsPlaceId = $this->getConfigurationValueFromFlexForm('containsPlaceId'); if (!is_string($containsPlaceId)) { - throw new \Exception('Could not fetch containsPlaceId.', 1671027015); + throw new Exception('Could not fetch containsPlaceId.', 1671027015); } return $containsPlaceId; } diff --git a/Classes/Domain/Model/Backend/ImportLog.php b/Classes/Domain/Model/Backend/ImportLog.php index ca094b8..e33d65d 100644 --- a/Classes/Domain/Model/Backend/ImportLog.php +++ b/Classes/Domain/Model/Backend/ImportLog.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace WerkraumMedia\ThueCat\Domain\Model\Backend; +use DateTimeImmutable; use TYPO3\CMS\Extbase\DomainObject\AbstractEntity as Typo3AbstractEntity; use TYPO3\CMS\Extbase\Persistence\ObjectStorage; use WerkraumMedia\ThueCat\Domain\Model\Backend\ImportLogEntry\SavingEntity; @@ -37,10 +38,10 @@ class ImportLog extends Typo3AbstractEntity /** * @var ImportConfiguration|null */ - protected $configuration = null; + protected $configuration; /** - * @var \DateTimeImmutable|null + * @var DateTimeImmutable|null */ protected $crdate; @@ -78,7 +79,7 @@ class ImportLog extends Typo3AbstractEntity return $this->logEntries; } - public function getCreated(): ?\DateTimeImmutable + public function getCreated(): ?DateTimeImmutable { return $this->crdate; } diff --git a/Classes/Domain/Model/Backend/ImportLogEntry/MappingError.php b/Classes/Domain/Model/Backend/ImportLogEntry/MappingError.php index 12db1d3..5eb8b2d 100644 --- a/Classes/Domain/Model/Backend/ImportLogEntry/MappingError.php +++ b/Classes/Domain/Model/Backend/ImportLogEntry/MappingError.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace WerkraumMedia\ThueCat\Domain\Model\Backend\ImportLogEntry; +use Exception; use WerkraumMedia\ThueCat\Domain\Import\EntityMapper\MappingException; use WerkraumMedia\ThueCat\Domain\Model\Backend\ImportLogEntry; @@ -54,7 +55,7 @@ class MappingError extends ImportLogEntry { $errors = json_decode($this->errors, true); if (is_array($errors) === false) { - throw new \Exception('Could not parse errors.', 1671097690); + throw new Exception('Could not parse errors.', 1671097690); } return $errors; } diff --git a/Classes/Domain/Model/Backend/ImportLogEntry/SavingEntity.php b/Classes/Domain/Model/Backend/ImportLogEntry/SavingEntity.php index 4b61597..fd10a23 100644 --- a/Classes/Domain/Model/Backend/ImportLogEntry/SavingEntity.php +++ b/Classes/Domain/Model/Backend/ImportLogEntry/SavingEntity.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace WerkraumMedia\ThueCat\Domain\Model\Backend\ImportLogEntry; +use Exception; use WerkraumMedia\ThueCat\Domain\Import\Model\Entity; use WerkraumMedia\ThueCat\Domain\Model\Backend\ImportLogEntry; @@ -100,7 +101,7 @@ class SavingEntity extends ImportLogEntry if ($this->errorsAsArray === [] && $this->errors !== '') { $errorsAsArray = json_decode($this->errors, true); 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); } @@ -121,7 +122,7 @@ class SavingEntity extends ImportLogEntry public function getInsertion(): array { return [ - 'insertion' => (int) $this->wasInsertion(), + 'insertion' => (int)$this->wasInsertion(), 'record_uid' => $this->getRecordUid(), 'table_name' => $this->getRecordDatabaseTableName(), ]; diff --git a/Classes/Domain/Model/Frontend/Base.php b/Classes/Domain/Model/Frontend/Base.php index 985c415..80d3f0f 100644 --- a/Classes/Domain/Model/Frontend/Base.php +++ b/Classes/Domain/Model/Frontend/Base.php @@ -40,7 +40,7 @@ abstract class Base extends AbstractEntity /** * @var Media|null */ - protected $media = null; + protected $media; public function getTitle(): string { diff --git a/Classes/Domain/Model/Frontend/Media.php b/Classes/Domain/Model/Frontend/Media.php index 028e6c2..f535984 100644 --- a/Classes/Domain/Model/Frontend/Media.php +++ b/Classes/Domain/Model/Frontend/Media.php @@ -94,6 +94,7 @@ class Media implements TypeInterface /** * @internal Only used to set the values while mapping objects. + * * @see: AfterObjectThawedHandler */ public function setEditorialImages(array $images): void diff --git a/Classes/Domain/Model/Frontend/MergedOpeningHour.php b/Classes/Domain/Model/Frontend/MergedOpeningHour.php index 6ab9171..ca9b1cd 100644 --- a/Classes/Domain/Model/Frontend/MergedOpeningHour.php +++ b/Classes/Domain/Model/Frontend/MergedOpeningHour.php @@ -23,6 +23,8 @@ declare(strict_types=1); namespace WerkraumMedia\ThueCat\Domain\Model\Frontend; +use DateTimeImmutable; + class MergedOpeningHour { /** @@ -31,19 +33,19 @@ class MergedOpeningHour private $weekDays = []; /** - * @var \DateTimeImmutable|null + * @var DateTimeImmutable|null */ private $from; /** - * @var \DateTimeImmutable|null + * @var DateTimeImmutable|null */ private $through; public function __construct( array $weekDays, - ?\DateTimeImmutable $from, - ?\DateTimeImmutable $through + ?DateTimeImmutable $from, + ?DateTimeImmutable $through ) { $this->weekDays = array_values($weekDays); $this->from = $from; @@ -72,12 +74,12 @@ class MergedOpeningHour ]); } - public function getFrom(): ?\DateTimeImmutable + public function getFrom(): ?DateTimeImmutable { return $this->from; } - public function getThrough(): ?\DateTimeImmutable + public function getThrough(): ?DateTimeImmutable { return $this->through; } diff --git a/Classes/Domain/Model/Frontend/MergedOpeningHours.php b/Classes/Domain/Model/Frontend/MergedOpeningHours.php index b93fff4..4fa199f 100644 --- a/Classes/Domain/Model/Frontend/MergedOpeningHours.php +++ b/Classes/Domain/Model/Frontend/MergedOpeningHours.php @@ -23,7 +23,10 @@ declare(strict_types=1); namespace WerkraumMedia\ThueCat\Domain\Model\Frontend; -class MergedOpeningHours implements \Iterator, \Countable +use Countable; +use Iterator; + +class MergedOpeningHours implements Iterator, Countable { /** * @var MergedOpeningHour[] diff --git a/Classes/Domain/Model/Frontend/Offer.php b/Classes/Domain/Model/Frontend/Offer.php index 73a42b1..66b0831 100644 --- a/Classes/Domain/Model/Frontend/Offer.php +++ b/Classes/Domain/Model/Frontend/Offer.php @@ -95,7 +95,7 @@ class Offer public function getType(): string { $offerTypes = array_filter($this->types, function (string $type) { - return strpos($type, 'Offer') !== false; + return str_contains($type, 'Offer'); }); // Ensure clean index $offerTypes = array_values($offerTypes); diff --git a/Classes/Domain/Model/Frontend/Offers.php b/Classes/Domain/Model/Frontend/Offers.php index 9821edf..b9c157e 100644 --- a/Classes/Domain/Model/Frontend/Offers.php +++ b/Classes/Domain/Model/Frontend/Offers.php @@ -23,12 +23,14 @@ declare(strict_types=1); namespace WerkraumMedia\ThueCat\Domain\Model\Frontend; +use Countable; +use Iterator; use TYPO3\CMS\Core\Type\TypeInterface; /** * @implements \Iterator */ -class Offers implements TypeInterface, \Iterator, \Countable +class Offers implements TypeInterface, Iterator, Countable { /** * @var string diff --git a/Classes/Domain/Model/Frontend/OpeningHour.php b/Classes/Domain/Model/Frontend/OpeningHour.php index 5b03f32..31c4f37 100644 --- a/Classes/Domain/Model/Frontend/OpeningHour.php +++ b/Classes/Domain/Model/Frontend/OpeningHour.php @@ -23,6 +23,8 @@ declare(strict_types=1); namespace WerkraumMedia\ThueCat\Domain\Model\Frontend; +use DateTimeImmutable; +use DateTimeZone; use WerkraumMedia\ThueCat\Domain\TimingFormat; class OpeningHour @@ -43,12 +45,12 @@ class OpeningHour private $daysOfWeek; /** - * @var \DateTimeImmutable|null + * @var DateTimeImmutable|null */ private $from; /** - * @var \DateTimeImmutable|null + * @var DateTimeImmutable|null */ private $through; @@ -56,8 +58,8 @@ class OpeningHour string $opens, string $closes, array $daysOfWeek, - ?\DateTimeImmutable $from, - ?\DateTimeImmutable $through + ?DateTimeImmutable $from, + ?DateTimeImmutable $through ) { $this->opens = $opens; $this->closes = $closes; @@ -73,13 +75,13 @@ class OpeningHour { $from = null; if (isset($rawData['from'])) { - $timeZone = new \DateTimeZone($rawData['from']['timezone'] ?? 'Europe/Berlin'); - $from = new \DateTimeImmutable($rawData['from']['date'], $timeZone); + $timeZone = new DateTimeZone($rawData['from']['timezone'] ?? 'Europe/Berlin'); + $from = new DateTimeImmutable($rawData['from']['date'], $timeZone); } $through = null; if (isset($rawData['through'])) { - $timeZone = new \DateTimeZone($rawData['through']['timezone'] ?? 'Europe/Berlin'); - $through = new \DateTimeImmutable($rawData['through']['date'], $timeZone); + $timeZone = new DateTimeZone($rawData['through']['timezone'] ?? 'Europe/Berlin'); + $through = new DateTimeImmutable($rawData['through']['date'], $timeZone); } return new self( @@ -120,12 +122,12 @@ class OpeningHour ]); } - public function getFrom(): ?\DateTimeImmutable + public function getFrom(): ?DateTimeImmutable { return $this->from; } - public function getThrough(): ?\DateTimeImmutable + public function getThrough(): ?DateTimeImmutable { return $this->through; } @@ -135,10 +137,9 @@ class OpeningHour $from = $this->getFrom(); $through = $this->getThrough(); - return $from instanceof \DateTimeImmutable - && $through instanceof \DateTimeImmutable - && $from->format('Ymd') === $through->format('Ymd') - ; + return $from instanceof DateTimeImmutable + && $through instanceof DateTimeImmutable + && $from->format('Ymd') === $through->format('Ymd'); } private function sortedDaysOfWeek(array $sorting): array diff --git a/Classes/Domain/Model/Frontend/OpeningHours.php b/Classes/Domain/Model/Frontend/OpeningHours.php index ed51800..0bdf285 100644 --- a/Classes/Domain/Model/Frontend/OpeningHours.php +++ b/Classes/Domain/Model/Frontend/OpeningHours.php @@ -23,6 +23,9 @@ declare(strict_types=1); namespace WerkraumMedia\ThueCat\Domain\Model\Frontend; +use Countable; +use DateTimeImmutable; +use Iterator; use TYPO3\CMS\Core\Type\TypeInterface; use TYPO3\CMS\Core\Utility\GeneralUtility; use WerkraumMedia\ThueCat\Service\DateBasedFilter; @@ -30,7 +33,7 @@ use WerkraumMedia\ThueCat\Service\DateBasedFilter; /** * @implements \Iterator */ -class OpeningHours implements TypeInterface, \Iterator, \Countable +class OpeningHours implements TypeInterface, Iterator, Countable { /** * @var string @@ -63,10 +66,11 @@ class OpeningHours implements TypeInterface, \Iterator, \Countable $array = GeneralUtility::makeInstance(DateBasedFilter::class) ->filterOutPreviousDates( $array, - function (OpeningHour $hour): ?\DateTimeImmutable { + function (OpeningHour $hour): ?DateTimeImmutable { return $hour->getThrough(); } - ); + ) + ; usort($array, function (OpeningHour $hourA, OpeningHour $hourB) { return $hourA->getFrom() <=> $hourB->getFrom(); diff --git a/Classes/Domain/Model/Frontend/Place.php b/Classes/Domain/Model/Frontend/Place.php index 46a0f22..721678e 100644 --- a/Classes/Domain/Model/Frontend/Place.php +++ b/Classes/Domain/Model/Frontend/Place.php @@ -31,7 +31,7 @@ abstract class Place extends Base /** * @var Address|null */ - protected $address = null; + protected $address; /** * @var string @@ -41,12 +41,12 @@ abstract class Place extends Base /** * @var OpeningHours|null */ - protected $openingHours = null; + protected $openingHours; /** * @var OpeningHours|null */ - protected $specialOpeningHours = null; + protected $specialOpeningHours; /** * @var ObjectStorage @@ -81,7 +81,7 @@ abstract class Place extends Base /** * @var AccessiblitySpecification|null */ - protected $accessibilitySpecification = null; + protected $accessibilitySpecification; public function initializeObject(): void { diff --git a/Classes/Domain/Model/Frontend/TouristAttraction.php b/Classes/Domain/Model/Frontend/TouristAttraction.php index 1f3f169..393ba37 100644 --- a/Classes/Domain/Model/Frontend/TouristAttraction.php +++ b/Classes/Domain/Model/Frontend/TouristAttraction.php @@ -35,12 +35,12 @@ class TouristAttraction extends Place /** * @var Offers|null */ - protected $offers = null; + protected $offers; /** * @var Town|null */ - protected $town = null; + protected $town; /** * @var string diff --git a/Classes/Domain/Repository/Backend/ImportConfigurationRepository.php b/Classes/Domain/Repository/Backend/ImportConfigurationRepository.php index f19354b..34a2b4f 100644 --- a/Classes/Domain/Repository/Backend/ImportConfigurationRepository.php +++ b/Classes/Domain/Repository/Backend/ImportConfigurationRepository.php @@ -23,7 +23,6 @@ declare(strict_types=1); namespace WerkraumMedia\ThueCat\Domain\Repository\Backend; -use TYPO3\CMS\Extbase\Object\ObjectManagerInterface; use TYPO3\CMS\Extbase\Persistence\Generic\Typo3QuerySettings; use TYPO3\CMS\Extbase\Persistence\Repository; use WerkraumMedia\ThueCat\Domain\Import\ImportConfiguration; @@ -31,10 +30,9 @@ use WerkraumMedia\ThueCat\Domain\Import\ImportConfiguration; class ImportConfigurationRepository extends Repository { public function __construct( - ObjectManagerInterface $objectManager, Typo3QuerySettings $querySettings ) { - parent::__construct($objectManager); + parent::__construct(); $querySettings->setRespectStoragePage(false); diff --git a/Classes/Domain/Repository/Backend/ImportLogRepository.php b/Classes/Domain/Repository/Backend/ImportLogRepository.php index a4fa8e9..0df30bd 100644 --- a/Classes/Domain/Repository/Backend/ImportLogRepository.php +++ b/Classes/Domain/Repository/Backend/ImportLogRepository.php @@ -24,7 +24,6 @@ declare(strict_types=1); namespace WerkraumMedia\ThueCat\Domain\Repository\Backend; use TYPO3\CMS\Core\DataHandling\DataHandler; -use TYPO3\CMS\Extbase\Object\ObjectManagerInterface; use TYPO3\CMS\Extbase\Persistence\Generic\Typo3QuerySettings; use TYPO3\CMS\Extbase\Persistence\QueryInterface; use TYPO3\CMS\Extbase\Persistence\Repository; @@ -32,19 +31,11 @@ use WerkraumMedia\ThueCat\Domain\Model\Backend\ImportLog; class ImportLogRepository extends Repository { - /** - * @var DataHandler - */ - private $dataHandler; - public function __construct( - ObjectManagerInterface $objectManager, - DataHandler $dataHandler, + private readonly DataHandler $dataHandler, Typo3QuerySettings $querySettings ) { - parent::__construct($objectManager); - - $this->dataHandler = $dataHandler; + parent::__construct(); $querySettings->setRespectStoragePage(false); $this->setDefaultQuerySettings($querySettings); diff --git a/Classes/Domain/Repository/Backend/OrganisationRepository.php b/Classes/Domain/Repository/Backend/OrganisationRepository.php index 29c21d3..446cb6c 100644 --- a/Classes/Domain/Repository/Backend/OrganisationRepository.php +++ b/Classes/Domain/Repository/Backend/OrganisationRepository.php @@ -23,7 +23,6 @@ declare(strict_types=1); namespace WerkraumMedia\ThueCat\Domain\Repository\Backend; -use TYPO3\CMS\Extbase\Object\ObjectManagerInterface; use TYPO3\CMS\Extbase\Persistence\Generic\Typo3QuerySettings; use TYPO3\CMS\Extbase\Persistence\Repository; use WerkraumMedia\ThueCat\Domain\Model\Backend\Organisation; @@ -34,10 +33,9 @@ use WerkraumMedia\ThueCat\Domain\Model\Backend\Organisation; class OrganisationRepository extends Repository { public function __construct( - ObjectManagerInterface $objectManager, Typo3QuerySettings $querySettings ) { - parent::__construct($objectManager); + parent::__construct(); $querySettings->setRespectStoragePage(false); $this->setDefaultQuerySettings($querySettings); diff --git a/Classes/Domain/Repository/Backend/ParkingFacilityRepository.php b/Classes/Domain/Repository/Backend/ParkingFacilityRepository.php index 45e9d23..1037b50 100644 --- a/Classes/Domain/Repository/Backend/ParkingFacilityRepository.php +++ b/Classes/Domain/Repository/Backend/ParkingFacilityRepository.php @@ -23,7 +23,6 @@ declare(strict_types=1); namespace WerkraumMedia\ThueCat\Domain\Repository\Backend; -use TYPO3\CMS\Extbase\Object\ObjectManagerInterface; use TYPO3\CMS\Extbase\Persistence\Generic\Typo3QuerySettings; use TYPO3\CMS\Extbase\Persistence\QueryResultInterface; use TYPO3\CMS\Extbase\Persistence\Repository; @@ -32,10 +31,9 @@ use WerkraumMedia\ThueCat\Domain\Import\Entity\Properties\ForeignReference; class ParkingFacilityRepository extends Repository { public function __construct( - ObjectManagerInterface $objectManager, Typo3QuerySettings $querySettings ) { - parent::__construct($objectManager); + parent::__construct(); $querySettings->setRespectStoragePage(false); diff --git a/Classes/Domain/Repository/Backend/TownRepository.php b/Classes/Domain/Repository/Backend/TownRepository.php index 7c47517..52e0d1f 100644 --- a/Classes/Domain/Repository/Backend/TownRepository.php +++ b/Classes/Domain/Repository/Backend/TownRepository.php @@ -23,7 +23,6 @@ declare(strict_types=1); namespace WerkraumMedia\ThueCat\Domain\Repository\Backend; -use TYPO3\CMS\Extbase\Object\ObjectManagerInterface; use TYPO3\CMS\Extbase\Persistence\Generic\Typo3QuerySettings; use TYPO3\CMS\Extbase\Persistence\Repository; use WerkraumMedia\ThueCat\Domain\Import\ResolveForeignReference; @@ -32,10 +31,9 @@ use WerkraumMedia\ThueCat\Domain\Model\Backend\Town; class TownRepository extends Repository { public function __construct( - ObjectManagerInterface $objectManager, Typo3QuerySettings $querySettings ) { - parent::__construct($objectManager); + parent::__construct(); $querySettings->setRespectStoragePage(false); diff --git a/Classes/Extension.php b/Classes/Extension.php index 382011d..e2a0029 100644 --- a/Classes/Extension.php +++ b/Classes/Extension.php @@ -24,13 +24,9 @@ declare(strict_types=1); namespace WerkraumMedia\ThueCat; use TYPO3\CMS\Core\Cache\Backend\TransientMemoryBackend; -use TYPO3\CMS\Core\Imaging\IconProvider\SvgIconProvider; -use TYPO3\CMS\Core\Imaging\IconRegistry; +use TYPO3\CMS\Core\DataHandling\PageDoktypeRegistry; use TYPO3\CMS\Core\Utility\ExtensionManagementUtility; 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 { @@ -47,57 +43,11 @@ class Extension 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 { self::addCaching(); self::addContentElements(); self::addPageTypes(); - self::addIcons(); } public static function getIconPath(): string @@ -129,28 +79,20 @@ class Extension private static function addPageTypes(): void { + $registry = GeneralUtility::makeInstance(PageDoktypeRegistry::class); + $registry->add( + self::PAGE_DOKTYPE_TOURIST_ATTRACTION, + [ + 'type' => 'web', + 'allowedTables' => '*', + ] + ); + ExtensionManagementUtility::addUserTSConfig( "@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 { $cacheIdentifier = 'thuecat_fetchdata'; diff --git a/Classes/Frontend/DataProcessing/ResolveEntities.php b/Classes/Frontend/DataProcessing/ResolveEntities.php index 2ae37d0..ebd28e1 100644 --- a/Classes/Frontend/DataProcessing/ResolveEntities.php +++ b/Classes/Frontend/DataProcessing/ResolveEntities.php @@ -33,27 +33,15 @@ use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController; class ResolveEntities implements DataProcessorInterface { - /** - * @var ConnectionPool - */ - private $connectionPool; - - /** - * @var DataMapper - */ - private $dataMapper; - /** * @var TypoScriptFrontendController */ private $tsfe; public function __construct( - ConnectionPool $connectionPool, - DataMapper $dataMapper + private readonly ConnectionPool $connectionPool, + private readonly DataMapper $dataMapper ) { - $this->connectionPool = $connectionPool; - $this->dataMapper = $dataMapper; $this->tsfe = $GLOBALS['TSFE']; } @@ -67,9 +55,9 @@ class ResolveEntities implements DataProcessorInterface return $processedData; } - $as = (string) $cObj->stdWrapValue('as', $processorConfiguration, 'entities'); - $tableName = (string) $cObj->stdWrapValue('table', $processorConfiguration, ''); - $uids = (string) $cObj->stdWrapValue('uids', $processorConfiguration, ''); + $as = (string)$cObj->stdWrapValue('as', $processorConfiguration, 'entities'); + $tableName = (string)$cObj->stdWrapValue('table', $processorConfiguration, ''); + $uids = (string)$cObj->stdWrapValue('uids', $processorConfiguration, ''); $uids = GeneralUtility::intExplode(',', $uids); if ($uids === [] || $tableName === '') { @@ -93,14 +81,14 @@ class ResolveEntities implements DataProcessorInterface )); $rows = []; - foreach ($queryBuilder->execute() as $row) { + foreach ($queryBuilder->executeQuery()->iterateAssociative() as $row) { $row = $this->tsfe->sys_page->getLanguageOverlay($tableName, $row); if (is_array($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); }); diff --git a/Classes/Service/DateBasedFilter/FilterBasedOnTypo3Context.php b/Classes/Service/DateBasedFilter/FilterBasedOnTypo3Context.php index 1671cb7..1b3538c 100644 --- a/Classes/Service/DateBasedFilter/FilterBasedOnTypo3Context.php +++ b/Classes/Service/DateBasedFilter/FilterBasedOnTypo3Context.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace WerkraumMedia\ThueCat\Service\DateBasedFilter; +use DateTimeImmutable; use TYPO3\CMS\Core\Context\Context; use WerkraumMedia\ThueCat\Service\DateBasedFilter; @@ -48,9 +49,9 @@ class FilterBasedOnTypo3Context implements DateBasedFilter array $listToFilter, callable $provideDate ): 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); return $objectDate === null || $objectDate >= $referenceDate; }); diff --git a/Classes/Updates/BackendModuleUserPermission.php b/Classes/Updates/BackendModuleUserPermission.php index e4cfca2..ff19e1c 100644 --- a/Classes/Updates/BackendModuleUserPermission.php +++ b/Classes/Updates/BackendModuleUserPermission.php @@ -25,19 +25,16 @@ namespace WerkraumMedia\ThueCat\Updates; use TYPO3\CMS\Core\Database\ConnectionPool; use TYPO3\CMS\Core\Utility\GeneralUtility; +use TYPO3\CMS\Install\Attribute\UpgradeWizard; use TYPO3\CMS\Install\Updates\DatabaseUpdatedPrerequisite; use TYPO3\CMS\Install\Updates\UpgradeWizardInterface; +#[UpgradeWizard('thuecat_backendmoduleuserpermission_v12')] class BackendModuleUserPermission implements UpgradeWizardInterface { - /** - * @var ConnectionPool - */ - private $connectionPool; - - public function __construct() - { - $this->connectionPool = GeneralUtility::makeInstance(ConnectionPool::class); + public function __construct( + private readonly ConnectionPool $connectionPool + ) { } public function getIdentifier(): string @@ -62,8 +59,9 @@ class BackendModuleUserPermission implements UpgradeWizardInterface $qb->count('*'); $qb->from('be_users'); $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 @@ -73,14 +71,15 @@ class BackendModuleUserPermission implements UpgradeWizardInterface $qb->select('uid', 'userMods'); $qb->from('be_users'); $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) { $qb = $this->connectionPool->getQueryBuilderForTable('be_users'); $qb->update('be_users'); $qb->set('userMods', $this->updateMods($backendUser['userMods'])); $qb->where($qb->expr()->eq('uid', $qb->createNamedParameter($backendUser['uid']))); - $qb->execute(); + $qb->executeStatement(); } return true; @@ -90,11 +89,15 @@ class BackendModuleUserPermission implements UpgradeWizardInterface { $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[] = 'ThuecatThuecat_ThuecatConfigurations'; - $mods[] = 'ThuecatThuecat_ThuecatImports'; + $mods[] = 'thuecat_configurations'; + $mods[] = 'thuecat_imports'; return implode(',', $mods); } @@ -105,9 +108,4 @@ class BackendModuleUserPermission implements UpgradeWizardInterface DatabaseUpdatedPrerequisite::class, ]; } - - public static function register(): void - { - $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install']['update'][self::class] = self::class; - } } diff --git a/Configuration/Backend/Modules.php b/Configuration/Backend/Modules.php new file mode 100644 index 0000000..05be5d2 --- /dev/null +++ b/Configuration/Backend/Modules.php @@ -0,0 +1,47 @@ + [ + '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', + ], + ], + ], +]; diff --git a/Configuration/Extbase/Persistence/Classes.php b/Configuration/Extbase/Persistence/Classes.php index 33481e4..049f860 100644 --- a/Configuration/Extbase/Persistence/Classes.php +++ b/Configuration/Extbase/Persistence/Classes.php @@ -1,41 +1,53 @@ [ + Organisation::class => [ 'tableName' => 'tx_thuecat_organisation', ], - \WerkraumMedia\ThueCat\Domain\Model\Backend\Town::class => [ + Town::class => [ 'tableName' => 'tx_thuecat_town', ], - \WerkraumMedia\ThueCat\Domain\Model\Backend\TouristInformation::class => [ + TouristInformation::class => [ 'tableName' => 'tx_thuecat_tourist_information', ], - WerkraumMedia\ThueCat\Domain\Model\Backend\ParkingFacility::class => [ + ParkingFacility::class => [ 'tableName' => 'tx_thuecat_parking_facility', ], - \WerkraumMedia\ThueCat\Domain\Model\Backend\ImportConfiguration::class => [ + ImportConfiguration::class => [ 'tableName' => 'tx_thuecat_import_configuration', ], - \WerkraumMedia\ThueCat\Domain\Model\Backend\ImportLog::class => [ + ImportLog::class => [ 'tableName' => 'tx_thuecat_import_log', ], - \WerkraumMedia\ThueCat\Domain\Model\Backend\ImportLogEntry::class => [ + ImportLogEntry::class => [ 'tableName' => 'tx_thuecat_import_log_entry', 'subclasses' => [ - 'savingEntity' => \WerkraumMedia\ThueCat\Domain\Model\Backend\ImportLogEntry\SavingEntity::class, - 'mappingError' => \WerkraumMedia\ThueCat\Domain\Model\Backend\ImportLogEntry\MappingError::class, + 'savingEntity' => SavingEntity::class, + 'mappingError' => MappingError::class, ], ], - \WerkraumMedia\ThueCat\Domain\Model\Backend\ImportLogEntry\SavingEntity::class => [ + SavingEntity::class => [ 'tableName' => 'tx_thuecat_import_log_entry', 'recordType' => 'savingEntity', ], - \WerkraumMedia\ThueCat\Domain\Model\Backend\ImportLogEntry\MappingError::class => [ + MappingError::class => [ 'tableName' => 'tx_thuecat_import_log_entry', 'recordType' => 'mappingError', ], - \WerkraumMedia\ThueCat\Domain\Model\Frontend\TouristAttraction::class => [ + TouristAttraction::class => [ 'tableName' => 'tx_thuecat_tourist_attraction', ], \WerkraumMedia\ThueCat\Domain\Model\Frontend\Town::class => [ diff --git a/Configuration/Icons.php b/Configuration/Icons.php new file mode 100644 index 0000000..cbc9b7a --- /dev/null +++ b/Configuration/Icons.php @@ -0,0 +1,30 @@ + SvgIconProvider::class, + 'source' => Extension::getIconPath() . $iconFile, + ]; + } + + return $icons; +})(); diff --git a/Configuration/Services.php b/Configuration/Services.php index 7087a5e..c1819f5 100644 --- a/Configuration/Services.php +++ b/Configuration/Services.php @@ -6,17 +6,20 @@ namespace WerkraumMedia\ThueCat; use Symfony\Component\DependencyInjection\ContainerBuilder; 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\Typo3Converter\Converter; use WerkraumMedia\ThueCat\Domain\Import\UrlProvider\UrlProvider; return function (ContainerConfigurator $container, ContainerBuilder $containerBuilder) { - $containerBuilder->registerForAutoconfiguration(UrlProvider::class)->addTag(DependencyInjection\UrlProvidersPass::TAG); - $containerBuilder->addCompilerPass(new DependencyInjection\UrlProvidersPass()); + $containerBuilder->registerForAutoconfiguration(UrlProvider::class)->addTag(UrlProvidersPass::TAG); + $containerBuilder->addCompilerPass(new UrlProvidersPass()); - $containerBuilder->registerForAutoconfiguration(Converter::class)->addTag(DependencyInjection\ConverterPass::TAG); - $containerBuilder->addCompilerPass(new DependencyInjection\ConverterPass()); + $containerBuilder->registerForAutoconfiguration(Converter::class)->addTag(ConverterPass::TAG); + $containerBuilder->addCompilerPass(new ConverterPass()); - $containerBuilder->registerForAutoconfiguration(MapsToType::class)->addTag(DependencyInjection\EntityPass::TAG); - $containerBuilder->addCompilerPass(new DependencyInjection\EntityPass()); + $containerBuilder->registerForAutoconfiguration(MapsToType::class)->addTag(EntityPass::TAG); + $containerBuilder->addCompilerPass(new EntityPass()); }; diff --git a/Configuration/TCA/Overrides/pages.php b/Configuration/TCA/Overrides/pages.php index 1eb4e24..87b1026 100644 --- a/Configuration/TCA/Overrides/pages.php +++ b/Configuration/TCA/Overrides/pages.php @@ -1,12 +1,18 @@ [ 'typeicon_classes' => [ 'contains-thuecat' => 'pages_module_thuecat', @@ -32,23 +38,23 @@ defined('TYPO3') or die(); ], ]); - \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addTcaSelectItemGroup( + ExtensionManagementUtility::addTcaSelectItemGroup( $tableName, 'doktype', - \WerkraumMedia\ThueCat\Extension::TCA_SELECT_GROUP_IDENTIFIER, + Extension::TCA_SELECT_GROUP_IDENTIFIER, $languagePath . '.group' ); - \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addTcaSelectItem( + ExtensionManagementUtility::addTcaSelectItem( $tableName, 'module', [ - 0 => $languagePath . '.module.thuecat', - 1 => 'thuecat', - 2 => 'pages_module_thuecat', + 'label' => $languagePath . '.module.thuecat', + 'value' => 'thuecat', + 'icon' => 'pages_module_thuecat', ] ); })( - \WerkraumMedia\ThueCat\Extension::EXTENSION_KEY, + Extension::EXTENSION_KEY, 'pages' ); diff --git a/Configuration/TCA/Overrides/pages_tourist_attraction.php b/Configuration/TCA/Overrides/pages_tourist_attraction.php index 576604e..fecca3a 100644 --- a/Configuration/TCA/Overrides/pages_tourist_attraction.php +++ b/Configuration/TCA/Overrides/pages_tourist_attraction.php @@ -1,12 +1,18 @@ [ 'typeicon_classes' => [ $doktype => $tableName . '_' . $pageIdentifier, @@ -54,19 +60,19 @@ defined('TYPO3') or die(); ], ]); - \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addTcaSelectItem( + ExtensionManagementUtility::addTcaSelectItem( $tableName, 'doktype', [ - $languagePath, - $doktype, - \WerkraumMedia\ThueCat\Extension::getIconPath() . $tableName . '_' . $pageIdentifier . '.svg', - \WerkraumMedia\ThueCat\Extension::TCA_SELECT_GROUP_IDENTIFIER, + 'label' => $languagePath, + 'value' => $doktype, + 'icon' => Extension::getIconPath() . $tableName . '_' . $pageIdentifier . '.svg', + 'group' => Extension::TCA_SELECT_GROUP_IDENTIFIER, ] ); })( - \WerkraumMedia\ThueCat\Extension::EXTENSION_KEY, + Extension::EXTENSION_KEY, 'pages', - \WerkraumMedia\ThueCat\Extension::PAGE_DOKTYPE_TOURIST_ATTRACTION, + Extension::PAGE_DOKTYPE_TOURIST_ATTRACTION, 'tourist_attraction' ); diff --git a/Configuration/TCA/Overrides/sys_template.php b/Configuration/TCA/Overrides/sys_template.php index 379ee9f..9f6c0c7 100644 --- a/Configuration/TCA/Overrides/sys_template.php +++ b/Configuration/TCA/Overrides/sys_template.php @@ -1,19 +1,24 @@ [ 'typeicon_classes' => [ $cType => 'tt_content_' . $cType, @@ -48,18 +54,18 @@ defined('TYPO3') or die(); ], ]); - \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addTcaSelectItem( + ExtensionManagementUtility::addTcaSelectItem( $tableName, 'CType', [ - $languagePath, - $cType, - \WerkraumMedia\ThueCat\Extension::getIconPath() . 'tt_content_' . $cType . '.svg', - \WerkraumMedia\ThueCat\Extension::TCA_SELECT_GROUP_IDENTIFIER, + 'label' => $languagePath, + 'value' => $cType, + 'icon' => Extension::getIconPath() . 'tt_content_' . $cType . '.svg', + 'group' => Extension::TCA_SELECT_GROUP_IDENTIFIER, ] ); })( - \WerkraumMedia\ThueCat\Extension::EXTENSION_KEY, + Extension::EXTENSION_KEY, 'tt_content', 'thuecat_tourist_attraction' ); diff --git a/Configuration/TCA/tx_thuecat_import_configuration.php b/Configuration/TCA/tx_thuecat_import_configuration.php index 1ef5ccd..b86db90 100644 --- a/Configuration/TCA/tx_thuecat_import_configuration.php +++ b/Configuration/TCA/tx_thuecat_import_configuration.php @@ -1,20 +1,23 @@ [ 'label' => 'title', - 'iconfile' => \WerkraumMedia\ThueCat\Extension::getIconPath() . $tableName . '.svg', + 'iconfile' => Extension::getIconPath() . $tableName . '.svg', 'type' => 'type', 'default_sortby' => 'title', 'tstamp' => 'tstamp', 'crdate' => 'crdate', - 'cruser_id' => 'cruser_id', 'title' => $languagePath, 'enablecolumns' => [ 'disabled' => 'disable', @@ -28,7 +31,8 @@ return (static function (string $extensionKey, string $tableName) { 'config' => [ 'type' => 'input', 'max' => 255, - 'eval' => 'required,trim,unique', + 'eval' => 'trim,unique', + 'required' => true, ], ], 'type' => [ @@ -38,16 +42,16 @@ return (static function (string $extensionKey, string $tableName) { 'renderType' => 'selectSingle', 'items' => [ [ - $languagePath . '.type.static', - 'static', + 'label' => $languagePath . '.type.static', + 'value' => 'static', ], [ - $languagePath . '.type.syncScope', - 'syncScope', + 'label' => $languagePath . '.type.syncScope', + 'value' => 'syncScope', ], [ - $languagePath . '.type.containsPlace', - 'containsPlace', + 'label' => $languagePath . '.type.containsPlace', + 'value' => 'containsPlace', ], ], ], @@ -67,9 +71,8 @@ return (static function (string $extensionKey, string $tableName) { ], 'tstamp' => [ 'config' => [ - 'type' => 'input', - 'renderType' => 'inputDateTime', - 'eval' => 'datetime', + 'type' => 'datetime', + 'format' => 'datetime', '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'); diff --git a/Configuration/TCA/tx_thuecat_import_log.php b/Configuration/TCA/tx_thuecat_import_log.php index c679555..6104523 100644 --- a/Configuration/TCA/tx_thuecat_import_log.php +++ b/Configuration/TCA/tx_thuecat_import_log.php @@ -1,21 +1,24 @@ [ 'label' => 'crdate', 'label_alt' => 'configuration', 'label_alt_force' => true, - 'iconfile' => \WerkraumMedia\ThueCat\Extension::getIconPath() . $tableName . '.svg', + 'iconfile' => Extension::getIconPath() . $tableName . '.svg', 'default_sortby' => 'crdate desc', 'tstamp' => 'tstamp', 'crdate' => 'crdate', - 'cruser_id' => 'cruser_id', 'title' => $languagePath, 'enablecolumns' => [ 'disabled' => 'disable', @@ -44,9 +47,8 @@ return (static function (string $extensionKey, string $tableName) { 'crdate' => [ 'label' => $languagePath . '.crdate', 'config' => [ - 'type' => 'input', - 'renderType' => 'inputDateTime', - 'eval' => 'datetime', + 'type' => 'datetime', + 'format' => 'datetime', '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'); diff --git a/Configuration/TCA/tx_thuecat_import_log_entry.php b/Configuration/TCA/tx_thuecat_import_log_entry.php index 3edf288..3adfe0b 100644 --- a/Configuration/TCA/tx_thuecat_import_log_entry.php +++ b/Configuration/TCA/tx_thuecat_import_log_entry.php @@ -1,22 +1,25 @@ [ 'label' => 'type', 'label_alt' => 'remote_id, table_name, record_uid', 'label_alt_force' => true, - 'iconfile' => \WerkraumMedia\ThueCat\Extension::getIconPath() . $tableName . '.svg', + 'iconfile' => Extension::getIconPath() . $tableName . '.svg', 'type' => 'type', 'default_sortby' => 'crdate', 'tstamp' => 'tstamp', 'crdate' => 'crdate', - 'cruser_id' => 'cruser_id', 'title' => $languagePath, 'enablecolumns' => [ 'disabled' => 'disable', @@ -32,12 +35,12 @@ return (static function (string $extensionKey, string $tableName) { 'renderType' => 'selectSingle', 'items' => [ [ - $languagePath . '.type.savingEntity', - 'savingEntity', + 'label' => $languagePath . '.type.savingEntity', + 'value' => 'savingEntity', ], [ - $languagePath . '.type.mappingError', - 'mappingError', + 'label' => $languagePath . '.type.mappingError', + 'value' => 'mappingError', ], ], ], @@ -56,7 +59,7 @@ return (static function (string $extensionKey, string $tableName) { 'renderType' => 'checkboxLabeledToggle', 'items' => [ [ - 0 => '', + 'label' => '', 1 => '', 'labelChecked' => $languagePath . '.insertion.yes', 'labelUnchecked' => $languagePath . '.insertion.no', @@ -98,9 +101,8 @@ return (static function (string $extensionKey, string $tableName) { 'crdate' => [ 'label' => $languagePath . '.crdate', 'config' => [ - 'type' => 'input', - 'renderType' => 'inputDateTime', - 'eval' => 'datetime', + 'type' => 'datetime', + 'format' => 'datetime', 'readOnly' => true, ], ], @@ -120,4 +122,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'); diff --git a/Configuration/TCA/tx_thuecat_organisation.php b/Configuration/TCA/tx_thuecat_organisation.php index 0d37b72..a5840af 100644 --- a/Configuration/TCA/tx_thuecat_organisation.php +++ b/Configuration/TCA/tx_thuecat_organisation.php @@ -1,18 +1,21 @@ [ 'label' => 'title', - 'iconfile' => \WerkraumMedia\ThueCat\Extension::getIconPath() . $tableName . '.svg', + 'iconfile' => Extension::getIconPath() . $tableName . '.svg', 'default_sortby' => 'title', 'tstamp' => 'tstamp', 'crdate' => 'crdate', - 'cruser_id' => 'cruser_id', 'title' => $languagePath, 'enablecolumns' => [ 'disabled' => 'disable', @@ -73,9 +76,8 @@ return (static function (string $extensionKey, string $tableName) { 'tstamp' => [ 'label' => $languagePath . '.tstamp', 'config' => [ - 'type' => 'input', - 'renderType' => 'inputDateTime', - 'eval' => 'datetime', + 'type' => 'datetime', + 'format' => 'datetime', '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'); diff --git a/Configuration/TCA/tx_thuecat_parking_facility.php b/Configuration/TCA/tx_thuecat_parking_facility.php index 1d1e5bf..73c0351 100644 --- a/Configuration/TCA/tx_thuecat_parking_facility.php +++ b/Configuration/TCA/tx_thuecat_parking_facility.php @@ -1,18 +1,21 @@ [ 'label' => 'title', - 'iconfile' => \WerkraumMedia\ThueCat\Extension::getIconPath() . $tableName . '.svg', + 'iconfile' => Extension::getIconPath() . $tableName . '.svg', 'default_sortby' => 'title', 'tstamp' => 'tstamp', 'crdate' => 'crdate', - 'cruser_id' => 'cruser_id', 'title' => $languagePath, 'enablecolumns' => [ 'disabled' => 'disable', @@ -27,19 +30,7 @@ return (static function (string $extensionKey, string $tableName) { 'sys_language_uid' => [ 'exclude' => true, 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.language', - 'config' => [ - 'type' => 'select', - 'renderType' => 'selectSingle', - 'special' => 'languages', - 'items' => [ - [ - 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.allLanguages', - -1, - 'flags-multiple', - ], - ], - 'default' => 0, - ], + 'config' => ['type' => 'language'], ], 'l18n_parent' => [ 'displayCond' => 'FIELD:sys_language_uid:>:0', @@ -47,7 +38,7 @@ return (static function (string $extensionKey, string $tableName) { 'config' => [ 'type' => 'select', 'renderType' => 'selectSingle', - 'items' => [['', 0]], + 'items' => [['label' => '', 'value' => 0]], 'foreign_table' => $tableName, 'foreign_table_where' => 'AND ' . $tableName . '.pid=###CURRENT_PID### AND ' . $tableName . '.sys_language_uid IN (-1,0)', 'default' => 0, @@ -66,12 +57,12 @@ return (static function (string $extensionKey, string $tableName) { 'renderType' => 'checkboxToggle', 'items' => [ [ - 0 => '', + 'label' => '', 1 => '', - 'invertStateDisplay' => true - ] + 'invertStateDisplay' => true, + ], ], - ] + ], ], 'title' => [ @@ -190,8 +181,8 @@ return (static function (string $extensionKey, string $tableName) { 'default' => '0', 'items' => [ [ - $languagePath . '.town.unkown', - 0, + 'label' => $languagePath . '.town.unkown', + 'value' => 0, ], ], 'readOnly' => true, @@ -207,8 +198,8 @@ return (static function (string $extensionKey, string $tableName) { 'default' => '0', 'items' => [ [ - $languagePath . '.managed_by.unkown', - 0, + 'label' => $languagePath . '.managed_by.unkown', + 'value' => 0, ], ], 'readOnly' => true, @@ -227,4 +218,4 @@ return (static function (string $extensionKey, string $tableName) { ], ], ]; -})(\WerkraumMedia\ThueCat\Extension::EXTENSION_KEY, 'tx_thuecat_parking_facility'); +})(Extension::EXTENSION_KEY, 'tx_thuecat_parking_facility'); diff --git a/Configuration/TCA/tx_thuecat_tourist_attraction.php b/Configuration/TCA/tx_thuecat_tourist_attraction.php index 5c6a48f..1cae9a1 100644 --- a/Configuration/TCA/tx_thuecat_tourist_attraction.php +++ b/Configuration/TCA/tx_thuecat_tourist_attraction.php @@ -1,18 +1,21 @@ [ 'label' => 'title', - 'iconfile' => \WerkraumMedia\ThueCat\Extension::getIconPath() . $tableName . '.svg', + 'iconfile' => Extension::getIconPath() . $tableName . '.svg', 'default_sortby' => 'title', 'tstamp' => 'tstamp', 'crdate' => 'crdate', - 'cruser_id' => 'cruser_id', 'title' => $languagePath, 'enablecolumns' => [ 'disabled' => 'disable', @@ -27,19 +30,7 @@ return (static function (string $extensionKey, string $tableName) { 'sys_language_uid' => [ 'exclude' => true, 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.language', - 'config' => [ - 'type' => 'select', - 'renderType' => 'selectSingle', - 'special' => 'languages', - 'items' => [ - [ - 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.allLanguages', - -1, - 'flags-multiple', - ], - ], - 'default' => 0, - ], + 'config' => ['type' => 'language'], ], 'l18n_parent' => [ 'displayCond' => 'FIELD:sys_language_uid:>:0', @@ -47,7 +38,7 @@ return (static function (string $extensionKey, string $tableName) { 'config' => [ 'type' => 'select', 'renderType' => 'selectSingle', - 'items' => [['', 0]], + 'items' => [['label' => '', 'value' => 0]], 'foreign_table' => $tableName, 'foreign_table_where' => 'AND ' . $tableName . '.pid=###CURRENT_PID### AND ' . $tableName . '.sys_language_uid IN (-1,0)', 'default' => 0, @@ -269,8 +260,8 @@ return (static function (string $extensionKey, string $tableName) { 'default' => '0', 'items' => [ [ - $languagePath . '.town.unkown', - 0, + 'label' => $languagePath . '.town.unkown', + 'value' => 0, ], ], 'readOnly' => true, @@ -286,8 +277,8 @@ return (static function (string $extensionKey, string $tableName) { 'default' => '0', 'items' => [ [ - $languagePath . '.managed_by.unkown', - 0, + 'label' => $languagePath . '.managed_by.unkown', + 'value' => 0, ], ], 'readOnly' => true, @@ -298,12 +289,11 @@ return (static function (string $extensionKey, string $tableName) { 'l10n_mode' => 'exclude', 'config' => [ 'type' => 'group', - 'internal_type' => 'db', 'allowed' => 'tx_thuecat_parking_facility', 'foreign_table' => 'tx_thuecat_parking_facility', 'suggestOptions' => [ 'tx_thuecat_parking_facility' => [ - 'searchCondition' => 'sys_language_uid IN (0,-1)' + 'searchCondition' => 'sys_language_uid IN (0,-1)', ], ], 'readOnly' => true, @@ -313,11 +303,10 @@ return (static function (string $extensionKey, string $tableName) { 'editorial_images' => [ 'label' => $languagePath . '.editorial_images', 'l10n_mode' => 'exclude', - 'config' => \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::getFileFieldTCAConfig( - 'editorial_images', - [], - $GLOBALS['TYPO3_CONF_VARS']['GFX']['imagefile_ext'] - ), + 'config' => [ + 'type' => 'file', + 'allowed' => 'common-image-types', + ], ], ], 'palettes' => [ @@ -332,4 +321,4 @@ return (static function (string $extensionKey, string $tableName) { ], ], ]; -})(\WerkraumMedia\ThueCat\Extension::EXTENSION_KEY, 'tx_thuecat_tourist_attraction'); +})(Extension::EXTENSION_KEY, 'tx_thuecat_tourist_attraction'); diff --git a/Configuration/TCA/tx_thuecat_tourist_information.php b/Configuration/TCA/tx_thuecat_tourist_information.php index 4b0afbf..e8e041f 100644 --- a/Configuration/TCA/tx_thuecat_tourist_information.php +++ b/Configuration/TCA/tx_thuecat_tourist_information.php @@ -1,18 +1,21 @@ [ 'label' => 'title', - 'iconfile' => \WerkraumMedia\ThueCat\Extension::getIconPath() . $tableName . '.svg', + 'iconfile' => Extension::getIconPath() . $tableName . '.svg', 'default_sortby' => 'title', 'tstamp' => 'tstamp', 'crdate' => 'crdate', - 'cruser_id' => 'cruser_id', 'title' => $languagePath, 'enablecolumns' => [ 'disabled' => 'disable', @@ -52,8 +55,8 @@ return (static function (string $extensionKey, string $tableName) { 'default' => '0', 'items' => [ [ - $languagePath . '.town.unkown', - 0, + 'label' => $languagePath . '.town.unkown', + 'value' => 0, ], ], 'readOnly' => true, @@ -68,8 +71,8 @@ return (static function (string $extensionKey, string $tableName) { 'default' => '0', 'items' => [ [ - $languagePath . '.managed_by.unkown', - 0, + 'label' => $languagePath . '.managed_by.unkown', + 'value' => 0, ], ], 'readOnly' => true, @@ -82,4 +85,4 @@ return (static function (string $extensionKey, string $tableName) { ], ], ]; -})(\WerkraumMedia\ThueCat\Extension::EXTENSION_KEY, 'tx_thuecat_tourist_information'); +})(Extension::EXTENSION_KEY, 'tx_thuecat_tourist_information'); diff --git a/Configuration/TCA/tx_thuecat_town.php b/Configuration/TCA/tx_thuecat_town.php index 7cfe603..9eb4d8e 100644 --- a/Configuration/TCA/tx_thuecat_town.php +++ b/Configuration/TCA/tx_thuecat_town.php @@ -1,18 +1,21 @@ [ 'label' => 'title', - 'iconfile' => \WerkraumMedia\ThueCat\Extension::getIconPath() . $tableName . '.svg', + 'iconfile' => Extension::getIconPath() . $tableName . '.svg', 'default_sortby' => 'title', 'tstamp' => 'tstamp', 'crdate' => 'crdate', - 'cruser_id' => 'cruser_id', 'title' => $languagePath, 'enablecolumns' => [ 'disabled' => 'disable', @@ -51,8 +54,8 @@ return (static function (string $extensionKey, string $tableName) { 'foreign_table' => 'tx_thuecat_organisation', 'items' => [ [ - $languagePath . '.managed_by.unkown', - 0, + 'label' => $languagePath . '.managed_by.unkown', + 'value' => 0, ], ], 'readOnly' => true, @@ -74,4 +77,4 @@ return (static function (string $extensionKey, string $tableName) { ], ], ]; -})(\WerkraumMedia\ThueCat\Extension::EXTENSION_KEY, 'tx_thuecat_town'); +})(Extension::EXTENSION_KEY, 'tx_thuecat_town'); diff --git a/Documentation/Index.rst b/Documentation/Index.rst index 4a5ef2a..59bc1fa 100644 --- a/Documentation/Index.rst +++ b/Documentation/Index.rst @@ -20,5 +20,4 @@ Table of Contents Configuration Integration Changelog - Maintenance Sitemap diff --git a/Documentation/Maintenance/PHP/7.4.rst b/Documentation/Maintenance/PHP/7.4.rst deleted file mode 100644 index 2aba0df..0000000 --- a/Documentation/Maintenance/PHP/7.4.rst +++ /dev/null @@ -1,15 +0,0 @@ -PHP 7.4 -======= - -Changes that should happen once we drop PHP 7.4. - -Remove ``symfony/polyfill-php80`` dependency --------------------------------------------- - -We use PHP 8.0 functions within our code base (to not add legacy code and deprecations). - -One example is :file:`Classes/Domain/Import/Import.php` where we use ``str_ends_with()``. -We therefore added ``symfony/polyfill-php80`` as composer package to already make use of those functions. - -We can drop that package once we are at least on PHP 8.0. - diff --git a/Resources/Private/Templates/Backend/Configuration/Index.html b/Resources/Private/Templates/Backend/Configuration/Index.html index e88e28e..160692e 100644 --- a/Resources/Private/Templates/Backend/Configuration/Index.html +++ b/Resources/Private/Templates/Backend/Configuration/Index.html @@ -3,130 +3,138 @@ xmlns:f="http://typo3.org/ns/TYPO3/CMS/Backend/ViewHelpers" data-namespace-typo3-fluid="true"> -

{f:translate(id: 'module.overview.headline')}

+ {f:layout(name: 'Module')} - + +

{f:translate(id: 'module.overview.headline')}

-

- {f:translate(id: 'module.importConfigurations.headline')} - - {f:icon(identifier: 'actions-document-add')} - -

- - - {f:render(section: 'ImportConfigurations', arguments: {importConfigurations: importConfigurations})} - - - + +

+ {f:translate(id: 'module.importConfigurations.headline')} + - {f:translate( - id: 'module.importConfigurations.missing.text', - arguments: { - 0: "{f:uri.newRecord(table: 'tx_thuecat_import_configuration', pid: settings.newRecordPid.tx_thuecat_import_configuration)}" - } - ) -> f:format.raw()} - - - + {f:icon(identifier: 'actions-document-add')} + +

+ + + {f:render(section: 'ImportConfigurations', arguments: {importConfigurations: importConfigurations})} + + + + {f:translate( + id: 'module.importConfigurations.missing.text', + arguments: { + 0: "{f:uri.newRecord(table: 'tx_thuecat_import_configuration', pid: settings.newRecordPid.tx_thuecat_import_configuration)}" + } + ) -> f:format.raw()} + + + -

{f:translate(id: 'module.organisations.headline')}

- - - {f:render(section: 'Organisations', arguments: {organisations: organisations})} - - - {f:translate(id: 'module.organisations.missing.text')} - - +

{f:translate(id: 'module.organisations.headline')}

+ + + {f:render(section: 'Organisations', arguments: {organisations: organisations})} + + + {f:translate(id: 'module.organisations.missing.text')} + + +
- - - - - - - - - - - +
+
{f:translate(id: 'module.importConfigurations.title')}{f:translate(id: 'module.importConfigurations.lastChanged')}{f:translate(id: 'module.importConfigurations.lastImported')}{f:translate(id: 'module.actions')}
+ - - - - + + + + - - -
{importConfiguration.title}{importConfiguration.lastChanged -> f:format.date(format: 'd.m.Y H:i')} - - - {importConfiguration.lastImported -> f:format.date(format: 'd.m.Y H:i')} - - - {f:translate(id: 'module.importConfigurations.lastImported.never')} - - - - - {f:icon(identifier: 'actions-document-edit')} - - - {f:icon(identifier: 'actions-download')} - - {f:translate(id: 'module.importConfigurations.title')}{f:translate(id: 'module.importConfigurations.lastChanged')}{f:translate(id: 'module.importConfigurations.lastImported')}{f:translate(id: 'module.actions')}
+ + + + + {importConfiguration.title} + {importConfiguration.lastChanged -> f:format.date(format: 'd.m.Y H:i')} + + + + {importConfiguration.lastImported -> f:format.date(format: 'd.m.Y H:i')} + + + {f:translate(id: 'module.importConfigurations.lastImported.never')} + + + + + + {f:icon(identifier: 'actions-document-edit')} + + + {f:icon(identifier: 'actions-download')} + + + + + + +
- - - - - - - - - - - +
+
{f:translate(id: 'module.organisation.title')}{f:translate(id: 'module.organisation.towns')}{f:translate(id: 'module.organisation.lastImported')}{f:translate(id: 'module.actions')}
+ - - - - + + + + - - -
{organisation.title} - {f:render(section: 'Towns', arguments: {towns: organisation.managesTowns})} - {organisation.lastImported -> f:format.date(format: 'd.m.Y H:i')} - - {f:icon(identifier: 'actions-document-edit')} - - {f:translate(id: 'module.organisation.title')}{f:translate(id: 'module.organisation.towns')}{f:translate(id: 'module.organisation.lastImported')}{f:translate(id: 'module.actions')}
+ + + + + {organisation.title} + + {f:render(section: 'Towns', arguments: {towns: organisation.managesTowns})} + + {organisation.lastImported -> f:format.date(format: 'd.m.Y H:i')} + + + {f:icon(identifier: 'actions-document-edit')} + + + + + + +
diff --git a/Resources/Private/Templates/Backend/Import/Index.html b/Resources/Private/Templates/Backend/Import/Index.html index 29dfb60..14e1214 100644 --- a/Resources/Private/Templates/Backend/Import/Index.html +++ b/Resources/Private/Templates/Backend/Import/Index.html @@ -1,41 +1,47 @@ -

{f:translate(id: 'module.imports.headline')}

+ {f:layout(name: 'Module')} - + +

{f:translate(id: 'module.imports.headline')}

- - - {f:render(section: 'Imports', arguments: {imports: imports})} - - - - {f:translate(id: 'module.imports.missing.text')} - - - + + + + + {f:render(section: 'Imports', arguments: {imports: imports})} + + + + {f:translate(id: 'module.imports.missing.text')} + + + +
- - - - - - - - - - - - - {f:render(section: 'Import', arguments: {import: import})} - - -
{f:translate(id: 'module.imports.th.created')}{f:translate(id: 'module.imports.th.configuration')}{f:translate(id: 'module.imports.th.amountOfRecords')}{f:translate(id: 'module.imports.th.summary')}{f:translate(id: 'module.imports.th.errors')}
+
+ + + + + + + + + + + + + {f:render(section: 'Import', arguments: {import: import})} + + +
{f:translate(id: 'module.imports.th.created')}{f:translate(id: 'module.imports.th.configuration')}{f:translate(id: 'module.imports.th.amountOfRecords')}{f:translate(id: 'module.imports.th.summary')}{f:translate(id: 'module.imports.th.errors')}
+
diff --git a/Tests/Acceptance/Data/BasicDatabase.csv b/Tests/Acceptance/Data/BasicDatabase.csv deleted file mode 100644 index d99b3ad..0000000 --- a/Tests/Acceptance/Data/BasicDatabase.csv +++ /dev/null @@ -1,45 +0,0 @@ -pages -,uid,pid,doktype,slug,title -,1,0,4,/,Rootpage -,2,1,255,/storage,Storage -tx_thuecat_import_configuration -,uid,pid,title,type,configuration -,1,2,"Example Configuration",static," - - - - - 2 - - - - - - - - https://thuecat.org/resources/644315157726-jmww - - - - 0 - - - - - - https://thuecat.org/resources/072778761562-kwah - - - - 0 - - - - - - -", -"be_users" -,"uid","pid","tstamp","username","password","admin","disable","starttime","endtime","options","crdate","workspace_perms","deleted","TSconfig","lastlogin","workspace_id","db_mountpoints","usergroup","realName" -# password is "password" -,1,0,1366642540,"admin","$1$tCrlLajZ$C0sikFQQ3SWaFAZ1Me0Z/1",1,0,0,0,0,1366642540,1,0,,1371033743,0,0,0,"Klaus Admin" diff --git a/Tests/Acceptance/Data/BasicDatabase.php b/Tests/Acceptance/Data/BasicDatabase.php new file mode 100644 index 0000000..88e9cae --- /dev/null +++ b/Tests/Acceptance/Data/BasicDatabase.php @@ -0,0 +1,87 @@ + [ + 0 => [ + 'uid' => '1', + 'pid' => '0', + 'tstamp' => '1366642540', + 'username' => 'admin', + 'password' => '$1$tCrlLajZ$C0sikFQQ3SWaFAZ1Me0Z/1', + 'admin' => '1', + 'disable' => '0', + 'starttime' => '0', + 'endtime' => '0', + 'options' => '0', + 'crdate' => '1366642540', + 'workspace_perms' => '1', + 'deleted' => '0', + 'TSconfig' => null, + 'lastlogin' => '1371033743', + 'workspace_id' => '0', + ], + ], + 'pages' => [ + 0 => [ + 'uid' => '1', + 'pid' => '0', + 'doktype' => PageRepository::DOKTYPE_DEFAULT, + 'slug' => '/', + 'title' => 'Rootpage', + ], + 1 => [ + 'uid' => '2', + 'pid' => '1', + 'doktype' => PageRepository::DOKTYPE_SYSFOLDER, + 'slug' => '/storage', + 'title' => 'Storage', + ], + ], + 'tx_thuecat_import_configuration' => [ + 0 => [ + 'uid' => '1', + 'pid' => '2', + 'title' => 'Example Configuration', + 'type' => 'static', + 'configuration' => ' + + + + + 2 + + + + + + + + https://thuecat.org/resources/644315157726-jmww + + + + 0 + + + + + + https://thuecat.org/resources/072778761562-kwah + + + + 0 + + + + + + + ', + ], + ], +]; diff --git a/Tests/Acceptance/Support/AcceptanceTester.php b/Tests/Acceptance/Support/AcceptanceTester.php index 8ac78d2..5ebb41e 100644 --- a/Tests/Acceptance/Support/AcceptanceTester.php +++ b/Tests/Acceptance/Support/AcceptanceTester.php @@ -29,6 +29,7 @@ use WerkraumMedia\ThueCat\Tests\Acceptance\Support\_generated\AcceptanceTesterAc /** * Inherited Methods + * * @method void wantToTest($text) * @method void wantTo($text) * @method void execute($callable) diff --git a/Tests/Acceptance/Support/Environment.php b/Tests/Acceptance/Support/Environment.php index 59433ba..6487710 100644 --- a/Tests/Acceptance/Support/Environment.php +++ b/Tests/Acceptance/Support/Environment.php @@ -23,6 +23,8 @@ declare(strict_types=1); namespace WerkraumMedia\ThueCat\Tests\Acceptance\Support; +use Codappix\Typo3PhpDatasets\TestingFramework; +use Codeception\Event\SuiteEvent; use TYPO3\TestingFramework\Core\Acceptance\Extension\BackendEnvironment; /** @@ -30,6 +32,8 @@ use TYPO3\TestingFramework\Core\Acceptance\Extension\BackendEnvironment; */ class Environment extends BackendEnvironment { + use TestingFramework; + protected $localConfig = [ 'coreExtensionsToLoad' => [ 'install', @@ -40,13 +44,17 @@ class Environment extends BackendEnvironment 'fluid', ], 'testExtensionsToLoad' => [ - 'typo3conf/ext/thuecat', - ], - 'csvDatabaseFixtures' => [ - __DIR__ . '/../Data/BasicDatabase.csv', + 'werkraummedia/thuecat', ], 'pathsToLinkInTestInstance' => [ '/../../../../../../Tests/Acceptance/Data/Sites/' => 'typo3conf/sites', ], ]; + + public function bootstrapTypo3Environment(SuiteEvent $suiteEvent) + { + parent::bootstrapTypo3Environment($suiteEvent); + + $this->importPHPDataSet(__DIR__ . '/../Data/BasicDatabase.php'); + } } diff --git a/Tests/Functional/AbstractImportTest.php b/Tests/Functional/AbstractImportTestCase.php similarity index 84% rename from Tests/Functional/AbstractImportTest.php rename to Tests/Functional/AbstractImportTestCase.php index 31d8075..428b87e 100644 --- a/Tests/Functional/AbstractImportTest.php +++ b/Tests/Functional/AbstractImportTestCase.php @@ -23,14 +23,17 @@ declare(strict_types=1); namespace WerkraumMedia\ThueCat\Tests\Functional; -use TYPO3\CMS\Core\Localization\LanguageService; -use TYPO3\TestingFramework\Core\Functional\FunctionalTestCase; +use Codappix\Typo3PhpDatasets\TestingFramework; +use TYPO3\CMS\Core\Localization\LanguageServiceFactory; -abstract class AbstractImportTest extends FunctionalTestCase +abstract class AbstractImportTestCase extends \TYPO3\TestingFramework\Core\Functional\FunctionalTestCase { + use TestingFramework; + /** * Whether to expect errors to be logged. * Will check for no errors if set to false. + * * @var bool */ protected $expectErrors = false; @@ -43,15 +46,12 @@ abstract class AbstractImportTest extends FunctionalTestCase 'extbase', 'frontend', ]); - $this->testExtensionsToLoad = array_merge($this->testExtensionsToLoad, [ - 'typo3conf/ext/thuecat/', + 'werkraummedia/thuecat/', ]); - $this->pathsToLinkInTestInstance = array_merge($this->pathsToLinkInTestInstance, [ 'typo3conf/ext/thuecat/Tests/Functional/Fixtures/Import/Sites/' => 'typo3conf/sites', ]); - $this->configurationToUseInTestInstance = array_merge($this->configurationToUseInTestInstance, [ 'LOG' => [ 'WerkraumMedia' => [ @@ -72,12 +72,11 @@ abstract class AbstractImportTest extends FunctionalTestCase ]); parent::setUp(); + GuzzleClientFaker::registerClient(); - - $this->setUpBackendUserFromFixture(1); - - $GLOBALS['LANG'] = $this->getContainer()->get(LanguageService::class); - + $this->importPHPDataSet(__DIR__ . '/Fixtures/Import/BackendUser.php'); + $this->setUpBackendUser(1); + $GLOBALS['LANG'] = $this->getContainer()->get(LanguageServiceFactory::class)->create('en_US'); foreach ($this->getLogFiles() as $logFile) { file_put_contents($logFile, ''); } @@ -88,13 +87,8 @@ abstract class AbstractImportTest extends FunctionalTestCase if ($this->expectErrors === true) { return; } - foreach ($this->getLogFiles() as $file) { - $this->assertSame( - '', - file_get_contents($file), - 'The TYPO3 log file "' . $file . '" contained content while expecting to be empty.' - ); + self::assertSame('', file_get_contents($file), 'The TYPO3 log file "' . $file . '" contained content while expecting to be empty.'); } } @@ -103,10 +97,8 @@ abstract class AbstractImportTest extends FunctionalTestCase $this->expectErrors = false; unset($GLOBALS['LANG']); GuzzleClientFaker::tearDown(); - parent::tearDown(); } - /** * @return string[] */ diff --git a/Tests/Functional/Assertions/Import/ImportWithMultipleReferencesToSameObject.php b/Tests/Functional/Assertions/Import/ImportWithMultipleReferencesToSameObject.php new file mode 100644 index 0000000..b72404b --- /dev/null +++ b/Tests/Functional/Assertions/Import/ImportWithMultipleReferencesToSameObject.php @@ -0,0 +1,195 @@ + [ + 0 => [ + 'uid' => '1', + 'pid' => '0', + 'configuration' => '1', + ], + ], + 'tx_thuecat_import_log_entry' => [ + 0 => [ + 'uid' => '1', + 'pid' => '0', + 'import_log' => '1', + 'record_uid' => '1', + 'table_name' => 'tx_thuecat_organisation', + 'insertion' => '1', + 'errors' => '[]', + ], + 1 => [ + 'uid' => '2', + 'pid' => '0', + 'import_log' => '1', + 'record_uid' => '1', + 'table_name' => 'tx_thuecat_town', + 'insertion' => '1', + 'errors' => '[]', + ], + 2 => [ + 'uid' => '3', + 'pid' => '0', + 'import_log' => '1', + 'record_uid' => '1', + 'table_name' => 'tx_thuecat_parking_facility', + 'insertion' => '1', + 'errors' => '[]', + ], + 3 => [ + 'uid' => '4', + 'pid' => '0', + 'import_log' => '1', + 'record_uid' => '2', + 'table_name' => 'tx_thuecat_parking_facility', + 'insertion' => '0', + 'errors' => '[]', + ], + 4 => [ + 'uid' => '5', + 'pid' => '0', + 'import_log' => '1', + 'record_uid' => '3', + 'table_name' => 'tx_thuecat_parking_facility', + 'insertion' => '0', + 'errors' => '[]', + ], + 5 => [ + 'uid' => '6', + 'pid' => '0', + 'import_log' => '1', + 'record_uid' => '1', + 'table_name' => 'tx_thuecat_tourist_attraction', + 'insertion' => '1', + 'errors' => '[]', + ], + 6 => [ + 'uid' => '7', + 'pid' => '0', + 'import_log' => '1', + 'record_uid' => '2', + 'table_name' => 'tx_thuecat_tourist_attraction', + 'insertion' => '0', + 'errors' => '[]', + ], + 7 => [ + 'uid' => '8', + 'pid' => '0', + 'import_log' => '1', + 'record_uid' => '3', + 'table_name' => 'tx_thuecat_tourist_attraction', + 'insertion' => '1', + 'errors' => '[]', + ], + 8 => [ + 'uid' => '9', + 'pid' => '0', + 'import_log' => '1', + 'record_uid' => '4', + 'table_name' => 'tx_thuecat_tourist_attraction', + 'insertion' => '0', + 'errors' => '[]', + ], + 9 => [ + 'uid' => '10', + 'pid' => '0', + 'import_log' => '1', + 'record_uid' => '5', + 'table_name' => 'tx_thuecat_tourist_attraction', + 'insertion' => '0', + 'errors' => '[]', + ], + ], + 'tx_thuecat_organisation' => [ + 0 => [ + 'uid' => '1', + 'pid' => '10', + 'remote_id' => 'https://thuecat.org/resources/018132452787-ngbe', + 'title' => 'Erfurt Tourismus und Marketing GmbH', + ], + ], + 'tx_thuecat_town' => [ + 0 => [ + 'uid' => '1', + 'pid' => '10', + 'remote_id' => 'https://thuecat.org/resources/043064193523-jcyt', + 'title' => 'Erfurt', + 'managed_by' => '1', + ], + ], + 'tx_thuecat_parking_facility' => [ + 0 => [ + 'uid' => '1', + 'pid' => '10', + 'sys_language_uid' => '0', + 'remote_id' => 'https://thuecat.org/resources/396420044896-drzt', + 'title' => 'Parkhaus Domplatz', + 'managed_by' => '1', + ], + 1 => [ + 'uid' => '2', + 'pid' => '10', + 'sys_language_uid' => '1', + 'remote_id' => 'https://thuecat.org/resources/396420044896-drzt', + 'title' => 'Car park Domplatz', + 'managed_by' => '1', + ], + 2 => [ + 'uid' => '3', + 'pid' => '10', + 'sys_language_uid' => '2', + 'remote_id' => 'https://thuecat.org/resources/396420044896-drzt', + 'title' => 'Parking Domplatz', + 'managed_by' => '1', + ], + ], + 'tx_thuecat_tourist_attraction' => [ + 0 => [ + 'uid' => '1', + 'pid' => '10', + 'sys_language_uid' => '0', + 'remote_id' => 'https://thuecat.org/resources/835224016581-dara', + 'title' => 'Dom St. Marien', + 'managed_by' => '1', + 'town' => '1', + ], + 1 => [ + 'uid' => '2', + 'pid' => '10', + 'sys_language_uid' => '1', + 'remote_id' => 'https://thuecat.org/resources/835224016581-dara', + 'title' => 'Cathedral of St. Mary', + 'managed_by' => '1', + 'town' => '1', + ], + 2 => [ + 'uid' => '3', + 'pid' => '10', + 'sys_language_uid' => '0', + 'remote_id' => 'https://thuecat.org/resources/165868194223-zmqf', + 'title' => 'Alte Synagoge', + 'managed_by' => '1', + 'town' => '1', + ], + 3 => [ + 'uid' => '4', + 'pid' => '10', + 'sys_language_uid' => '1', + 'remote_id' => 'https://thuecat.org/resources/165868194223-zmqf', + 'title' => 'Old Synagogue', + 'managed_by' => '1', + 'town' => '1', + ], + 4 => [ + 'uid' => '5', + 'pid' => '10', + 'sys_language_uid' => '2', + 'remote_id' => 'https://thuecat.org/resources/165868194223-zmqf', + 'title' => 'La vieille synagogue', + 'managed_by' => '1', + 'town' => '1', + ], + ], +]; diff --git a/Tests/Functional/Assertions/Import/ImportsContainsPlace.php b/Tests/Functional/Assertions/Import/ImportsContainsPlace.php new file mode 100644 index 0000000..fa570d3 --- /dev/null +++ b/Tests/Functional/Assertions/Import/ImportsContainsPlace.php @@ -0,0 +1,80 @@ + [ + 0 => [ + 'uid' => '1', + 'pid' => '10', + 'sys_language_uid' => '0', + 'remote_id' => 'https://thuecat.org/resources/835224016581-dara', + 'title' => 'Dom St. Marien', + ], + 1 => [ + 'uid' => '2', + 'pid' => '10', + 'sys_language_uid' => '1', + 'remote_id' => 'https://thuecat.org/resources/835224016581-dara', + 'title' => 'Cathedral of St. Mary', + ], + 2 => [ + 'uid' => '3', + 'pid' => '10', + 'sys_language_uid' => '0', + 'remote_id' => 'https://thuecat.org/resources/165868194223-zmqf', + 'title' => 'Alte Synagoge', + ], + 3 => [ + 'uid' => '4', + 'pid' => '10', + 'sys_language_uid' => '1', + 'remote_id' => 'https://thuecat.org/resources/165868194223-zmqf', + 'title' => 'Old Synagogue', + ], + 4 => [ + 'uid' => '5', + 'pid' => '10', + 'sys_language_uid' => '2', + 'remote_id' => 'https://thuecat.org/resources/165868194223-zmqf', + 'title' => 'La vieille synagogue', + ], + 5 => [ + 'uid' => '6', + 'pid' => '10', + 'sys_language_uid' => '0', + 'remote_id' => 'https://thuecat.org/resources/215230952334-yyno', + 'title' => 'Krämerbrücke', + ], + 6 => [ + 'uid' => '7', + 'pid' => '10', + 'sys_language_uid' => '1', + 'remote_id' => 'https://thuecat.org/resources/215230952334-yyno', + 'title' => 'Merchants\' Bridge', + ], + 7 => [ + 'uid' => '8', + 'pid' => '10', + 'sys_language_uid' => '2', + 'remote_id' => 'https://thuecat.org/resources/215230952334-yyno', + 'title' => 'Pont de l\'épicier', + ], + ], + 'tx_thuecat_organisation' => [ + 0 => [ + 'uid' => '1', + 'pid' => '10', + 'remote_id' => 'https://thuecat.org/resources/018132452787-ngbe', + 'title' => 'Erfurt Tourismus und Marketing GmbH', + ], + ], + 'tx_thuecat_town' => [ + 0 => [ + 'uid' => '1', + 'pid' => '10', + 'remote_id' => 'https://thuecat.org/resources/043064193523-jcyt', + 'title' => 'Erfurt', + ], + ], +]; diff --git a/Tests/Functional/Assertions/Import/ImportsFollowingRecordsInCaseOfAnMappingException.php b/Tests/Functional/Assertions/Import/ImportsFollowingRecordsInCaseOfAnMappingException.php new file mode 100644 index 0000000..a122900 --- /dev/null +++ b/Tests/Functional/Assertions/Import/ImportsFollowingRecordsInCaseOfAnMappingException.php @@ -0,0 +1,119 @@ + [ + 0 => [ + 'uid' => '1', + 'pid' => '10', + 'sys_language_uid' => '0', + 'remote_id' => 'https://thuecat.org/resources/165868194223-zmqf', + 'title' => 'Alte Synagoge', + ], + 1 => [ + 'uid' => '2', + 'pid' => '10', + 'sys_language_uid' => '1', + 'remote_id' => 'https://thuecat.org/resources/165868194223-zmqf', + 'title' => 'Old Synagogue', + ], + 2 => [ + 'uid' => '3', + 'pid' => '10', + 'sys_language_uid' => '2', + 'remote_id' => 'https://thuecat.org/resources/165868194223-zmqf', + 'title' => 'La vieille synagogue', + ], + ], + 'tx_thuecat_import_log' => [ + 0 => [ + 'uid' => '1', + 'pid' => '0', + 'configuration' => '1', + 'log_entries' => '0', + ], + ], + 'tx_thuecat_import_log_entry' => [ + 0 => [ + 'uid' => '1', + 'pid' => '0', + 'type' => 'mappingError', + 'import_log' => '1', + 'record_uid' => '0', + 'table_name' => '', + 'insertion' => '0', + 'errors' => '["Could not map incoming JSON-LD to target object: Failed to parse time string (18:00: 00) at position 5 (:): Unexpected character"]', + ], + 1 => [ + 'uid' => '2', + 'pid' => '0', + 'type' => 'mappingError', + 'import_log' => '1', + 'record_uid' => '0', + 'table_name' => '', + 'insertion' => '0', + 'errors' => '["Could not map incoming JSON-LD to target object: Failed to parse time string (18:00: 00) at position 5 (:): Unexpected character"]', + ], + 2 => [ + 'uid' => '3', + 'pid' => '0', + 'type' => 'mappingError', + 'import_log' => '1', + 'record_uid' => '0', + 'table_name' => '', + 'insertion' => '0', + 'errors' => '["Could not map incoming JSON-LD to target object: Failed to parse time string (18:00: 00) at position 5 (:): Unexpected character"]', + ], + 3 => [ + 'uid' => '4', + 'pid' => '0', + 'type' => 'savingEntity', + 'import_log' => '1', + 'record_uid' => '1', + 'table_name' => 'tx_thuecat_organisation', + 'insertion' => '1', + 'errors' => '[]', + ], + 4 => [ + 'uid' => '5', + 'pid' => '0', + 'type' => 'savingEntity', + 'import_log' => '1', + 'record_uid' => '1', + 'table_name' => 'tx_thuecat_town', + 'insertion' => '0', + 'errors' => '[]', + ], + 5 => [ + 'uid' => '6', + 'pid' => '0', + 'type' => 'savingEntity', + 'import_log' => '1', + 'record_uid' => '1', + 'table_name' => 'tx_thuecat_tourist_attraction', + 'insertion' => '1', + 'errors' => '[]', + ], + 6 => [ + 'uid' => '7', + 'pid' => '0', + 'type' => 'savingEntity', + 'import_log' => '1', + 'record_uid' => '2', + 'table_name' => 'tx_thuecat_tourist_attraction', + 'insertion' => '0', + 'errors' => '[]', + ], + 7 => [ + 'uid' => '8', + 'pid' => '0', + 'type' => 'savingEntity', + 'import_log' => '1', + 'record_uid' => '3', + 'table_name' => 'tx_thuecat_tourist_attraction', + 'insertion' => '0', + 'errors' => '[]', + ], + ], +]; diff --git a/Tests/Functional/Assertions/Import/ImportsFollowingRecordsInCaseOfAnMappingExceptionOldPhp.php b/Tests/Functional/Assertions/Import/ImportsFollowingRecordsInCaseOfAnMappingExceptionOldPhp.php new file mode 100644 index 0000000..d4a2fc1 --- /dev/null +++ b/Tests/Functional/Assertions/Import/ImportsFollowingRecordsInCaseOfAnMappingExceptionOldPhp.php @@ -0,0 +1,119 @@ + [ + 0 => [ + 'uid' => '1', + 'pid' => '10', + 'sys_language_uid' => '0', + 'remote_id' => 'https://thuecat.org/resources/165868194223-zmqf', + 'title' => 'Alte Synagoge', + ], + 1 => [ + 'uid' => '2', + 'pid' => '10', + 'sys_language_uid' => '1', + 'remote_id' => 'https://thuecat.org/resources/165868194223-zmqf', + 'title' => 'Old Synagogue', + ], + 2 => [ + 'uid' => '3', + 'pid' => '10', + 'sys_language_uid' => '2', + 'remote_id' => 'https://thuecat.org/resources/165868194223-zmqf', + 'title' => 'La vieille synagogue', + ], + ], + 'tx_thuecat_import_log' => [ + 0 => [ + 'uid' => '1', + 'pid' => '0', + 'configuration' => '1', + 'log_entries' => '0', + ], + ], + 'tx_thuecat_import_log_entry' => [ + 0 => [ + 'uid' => '1', + 'pid' => '0', + 'type' => 'mappingError', + 'import_log' => '1', + 'record_uid' => '0', + 'table_name' => '', + 'insertion' => '0', + 'errors' => '["Could not map incoming JSON-LD to target object: DateTimeImmutable::__construct(): Failed to parse time string (18:00: 00) at position 5 (:): Unexpected character"]', + ], + 1 => [ + 'uid' => '2', + 'pid' => '0', + 'type' => 'mappingError', + 'import_log' => '1', + 'record_uid' => '0', + 'table_name' => '', + 'insertion' => '0', + 'errors' => '["Could not map incoming JSON-LD to target object: DateTimeImmutable::__construct(): Failed to parse time string (18:00: 00) at position 5 (:): Unexpected character"]', + ], + 2 => [ + 'uid' => '3', + 'pid' => '0', + 'type' => 'mappingError', + 'import_log' => '1', + 'record_uid' => '0', + 'table_name' => '', + 'insertion' => '0', + 'errors' => '["Could not map incoming JSON-LD to target object: DateTimeImmutable::__construct(): Failed to parse time string (18:00: 00) at position 5 (:): Unexpected character"]', + ], + 3 => [ + 'uid' => '4', + 'pid' => '0', + 'type' => 'savingEntity', + 'import_log' => '1', + 'record_uid' => '1', + 'table_name' => 'tx_thuecat_organisation', + 'insertion' => '1', + 'errors' => '[]', + ], + 4 => [ + 'uid' => '5', + 'pid' => '0', + 'type' => 'savingEntity', + 'import_log' => '1', + 'record_uid' => '1', + 'table_name' => 'tx_thuecat_town', + 'insertion' => '0', + 'errors' => '[]', + ], + 5 => [ + 'uid' => '6', + 'pid' => '0', + 'type' => 'savingEntity', + 'import_log' => '1', + 'record_uid' => '1', + 'table_name' => 'tx_thuecat_tourist_attraction', + 'insertion' => '1', + 'errors' => '[]', + ], + 6 => [ + 'uid' => '7', + 'pid' => '0', + 'type' => 'savingEntity', + 'import_log' => '1', + 'record_uid' => '2', + 'table_name' => 'tx_thuecat_tourist_attraction', + 'insertion' => '0', + 'errors' => '[]', + ], + 7 => [ + 'uid' => '8', + 'pid' => '0', + 'type' => 'savingEntity', + 'import_log' => '1', + 'record_uid' => '3', + 'table_name' => 'tx_thuecat_tourist_attraction', + 'insertion' => '0', + 'errors' => '[]', + ], + ], +]; diff --git a/Tests/Functional/Assertions/Import/ImportsFreshOrganization.php b/Tests/Functional/Assertions/Import/ImportsFreshOrganization.php new file mode 100644 index 0000000..f8aa424 --- /dev/null +++ b/Tests/Functional/Assertions/Import/ImportsFreshOrganization.php @@ -0,0 +1,32 @@ + [ + 0 => [ + 'uid' => '1', + 'pid' => '11', + 'remote_id' => 'https://thuecat.org/resources/018132452787-ngbe', + 'title' => 'Erfurt Tourismus und Marketing GmbH', + ], + ], + 'tx_thuecat_import_log' => [ + 0 => [ + 'uid' => '1', + 'pid' => '0', + 'configuration' => '1', + ], + ], + 'tx_thuecat_import_log_entry' => [ + 0 => [ + 'uid' => '1', + 'pid' => '0', + 'import_log' => '1', + 'record_uid' => '1', + 'table_name' => 'tx_thuecat_organisation', + 'insertion' => '1', + 'errors' => '[]', + ], + ], +]; diff --git a/Tests/Functional/Assertions/Import/ImportsSyncScope.php b/Tests/Functional/Assertions/Import/ImportsSyncScope.php new file mode 100644 index 0000000..68c14ee --- /dev/null +++ b/Tests/Functional/Assertions/Import/ImportsSyncScope.php @@ -0,0 +1,120 @@ + [ + 0 => [ + 'uid' => '1', + 'pid' => '10', + 'sys_language_uid' => '0', + 'l18n_parent' => '0', + 'l10n_source' => '0', + 'l10n_state' => null, + 'remote_id' => 'https://thuecat.org/resources/835224016581-dara', + 'title' => 'Dom St. Marien', + 'managed_by' => '1', + 'town' => '1', + 'address' => '{"street":"Domstufen 1","zip":"99084","city":"Erfurt","email":"dominformation@domberg-erfurt.de","phone":"+49 361 6461265","fax":"","geo":{"latitude":50.975955358589545,"longitude":11.023667024961856}}', + 'offers' => '[]', + ], + 1 => [ + 'uid' => '2', + 'pid' => '10', + 'sys_language_uid' => '1', + 'l18n_parent' => '1', + 'l10n_source' => '1', + 'l10n_state' => null, + 'remote_id' => 'https://thuecat.org/resources/835224016581-dara', + 'title' => 'Cathedral of St. Mary', + 'managed_by' => '1', + 'town' => '1', + 'address' => '{"street":"Domstufen 1","zip":"99084","city":"Erfurt","email":"dominformation@domberg-erfurt.de","phone":"+49 361 6461265","fax":"","geo":{"latitude":50.975955358589545,"longitude":11.023667024961856}}', + 'offers' => '[]', + ], + 2 => [ + 'uid' => '3', + 'pid' => '10', + 'sys_language_uid' => '0', + 'l18n_parent' => '0', + 'l10n_source' => '0', + 'l10n_state' => null, + 'remote_id' => 'https://thuecat.org/resources/165868194223-zmqf', + 'title' => 'Alte Synagoge', + 'managed_by' => '1', + 'town' => '1', + 'address' => '{"street":"Waagegasse 8","zip":"99084","city":"Erfurt","email":"altesynagoge@erfurt.de","phone":"+49 361 6551520","fax":"+49 361 6551669","geo":{"latitude":50.978765,"longitude":11.029133}}', + 'offers' => '[{"types":["GuidedTourOffer"],"title":"F\\u00fchrungen","description":"Immer samstags, um 11:15 Uhr findet eine \\u00f6ffentliche F\\u00fchrung durch das Museum statt. Dauer etwa 90 Minuten","prices":[{"title":"Erwachsene","description":"","price":8,"currency":"EUR","rule":"PerPerson"},{"title":"Erm\\u00e4\\u00dfigt","description":"als erm\\u00e4\\u00dfigt gelten schulpflichtige Kinder, Auszubildende, Studierende, Rentner\\/-innen, Menschen mit Behinderungen, Inhaber Sozialausweis der Landeshauptstadt Erfurt","price":5,"currency":"EUR","rule":"PerPerson"}]},{"types":["EntryOffer"],"title":"Eintritt","description":"Schulklassen und Kitagruppen im Rahmen des Unterrichts: Eintritt frei\\nAn jedem ersten Dienstag im Monat: Eintritt frei","prices":[{"title":"Erm\\u00e4\\u00dfigt","description":"als erm\\u00e4\\u00dfigt gelten schulpflichtige Kinder, Auszubildende, Studierende, Rentner\\/-innen, Menschen mit Behinderungen, Inhaber Sozialausweis der Landeshauptstadt Erfurt","price":5,"currency":"EUR","rule":"PerPerson"},{"title":"Familienkarte","description":"","price":17,"currency":"EUR","rule":"PerGroup"},{"title":"ErfurtCard","description":"","price":14.9,"currency":"EUR","rule":"PerPackage"},{"title":"Erwachsene","description":"","price":8,"currency":"EUR","rule":"PerPerson"}]}]', + ], + 3 => [ + 'uid' => '4', + 'pid' => '10', + 'sys_language_uid' => '1', + 'l18n_parent' => '3', + 'l10n_source' => '3', + 'l10n_state' => null, + 'remote_id' => 'https://thuecat.org/resources/165868194223-zmqf', + 'title' => 'Old Synagogue', + 'managed_by' => '1', + 'town' => '1', + 'address' => '{"street":"Waagegasse 8","zip":"99084","city":"Erfurt","email":"altesynagoge@erfurt.de","phone":"+49 361 6551520","fax":"+49 361 6551669","geo":{"latitude":50.978765,"longitude":11.029133}}', + 'offers' => '[{"types":["GuidedTourOffer"],"title":"","description":"","prices":[{"title":"","description":"","price":8,"currency":"EUR","rule":"PerPerson"},{"title":"","description":"","price":5,"currency":"EUR","rule":"PerPerson"}]},{"types":["EntryOffer"],"title":"","description":"","prices":[{"title":"","description":"","price":5,"currency":"EUR","rule":"PerPerson"},{"title":"","description":"","price":17,"currency":"EUR","rule":"PerGroup"},{"title":"","description":"","price":14.9,"currency":"EUR","rule":"PerPackage"},{"title":"","description":"","price":8,"currency":"EUR","rule":"PerPerson"}]}]', + ], + 4 => [ + 'uid' => '5', + 'pid' => '10', + 'sys_language_uid' => '2', + 'l18n_parent' => '3', + 'l10n_source' => '3', + 'l10n_state' => null, + 'remote_id' => 'https://thuecat.org/resources/165868194223-zmqf', + 'title' => 'La vieille synagogue', + 'managed_by' => '1', + 'town' => '1', + 'address' => '{"street":"Waagegasse 8","zip":"99084","city":"Erfurt","email":"altesynagoge@erfurt.de","phone":"+49 361 6551520","fax":"+49 361 6551669","geo":{"latitude":50.978765,"longitude":11.029133}}', + 'offers' => '[{"types":["GuidedTourOffer"],"title":"","description":"","prices":[{"title":"","description":"","price":8,"currency":"EUR","rule":"PerPerson"},{"title":"","description":"","price":5,"currency":"EUR","rule":"PerPerson"}]},{"types":["EntryOffer"],"title":"","description":"","prices":[{"title":"","description":"","price":5,"currency":"EUR","rule":"PerPerson"},{"title":"","description":"","price":17,"currency":"EUR","rule":"PerGroup"},{"title":"","description":"","price":14.9,"currency":"EUR","rule":"PerPackage"},{"title":"","description":"","price":8,"currency":"EUR","rule":"PerPerson"}]}]', + ], + 5 => [ + 'uid' => '6', + 'pid' => '10', + 'sys_language_uid' => '0', + 'l18n_parent' => '0', + 'l10n_source' => '0', + 'l10n_state' => null, + 'remote_id' => 'https://thuecat.org/resources/215230952334-yyno', + 'title' => 'Krämerbrücke', + 'managed_by' => '1', + 'town' => '1', + 'address' => '{"street":"Benediktsplatz 1","zip":"99084","city":"Erfurt","email":"service@erfurt-tourismus.de","phone":"+49 361 66 400","fax":"","geo":{"latitude":50.978772,"longitude":11.031622}}', + 'offers' => '[]', + ], + 6 => [ + 'uid' => '7', + 'pid' => '10', + 'sys_language_uid' => '1', + 'l18n_parent' => '6', + 'l10n_source' => '6', + 'l10n_state' => null, + 'remote_id' => 'https://thuecat.org/resources/215230952334-yyno', + 'title' => 'Merchants\' Bridge', + 'managed_by' => '1', + 'town' => '1', + 'address' => '{"street":"Benediktsplatz 1","zip":"99084","city":"Erfurt","email":"service@erfurt-tourismus.de","phone":"+49 361 66 400","fax":"","geo":{"latitude":50.978772,"longitude":11.031622}}', + 'offers' => '[]', + ], + 7 => [ + 'uid' => '8', + 'pid' => '10', + 'sys_language_uid' => '2', + 'l18n_parent' => '6', + 'l10n_source' => '6', + 'l10n_state' => null, + 'remote_id' => 'https://thuecat.org/resources/215230952334-yyno', + 'title' => 'Pont de l\'épicier', + 'managed_by' => '1', + 'town' => '1', + 'address' => '{"street":"Benediktsplatz 1","zip":"99084","city":"Erfurt","email":"service@erfurt-tourismus.de","phone":"+49 361 66 400","fax":"","geo":{"latitude":50.978772,"longitude":11.031622}}', + 'offers' => '[]', + ], + ], +]; diff --git a/Tests/Functional/Assertions/Import/ImportsTouristAttractionWithAccessibilitySpecification.php b/Tests/Functional/Assertions/Import/ImportsTouristAttractionWithAccessibilitySpecification.php new file mode 100644 index 0000000..6ba52a8 --- /dev/null +++ b/Tests/Functional/Assertions/Import/ImportsTouristAttractionWithAccessibilitySpecification.php @@ -0,0 +1,26 @@ + [ + 0 => [ + 'uid' => '1', + 'pid' => '10', + 'sys_language_uid' => '0', + 'l18n_parent' => '0', + 'l10n_source' => '0', + 'remote_id' => 'https://thuecat.org/resources/attraction-with-accessibility-specification', + 'title' => 'Attraktion mit accessibility specification', + ], + 1 => [ + 'uid' => '2', + 'pid' => '10', + 'sys_language_uid' => '1', + 'l18n_parent' => '1', + 'l10n_source' => '1', + 'remote_id' => 'https://thuecat.org/resources/attraction-with-accessibility-specification', + 'title' => 'Attraction with accessibility specification', + ], + ], +]; diff --git a/Tests/Functional/Assertions/Import/ImportsTouristAttractionWithMedia.php b/Tests/Functional/Assertions/Import/ImportsTouristAttractionWithMedia.php new file mode 100644 index 0000000..14a4a9a --- /dev/null +++ b/Tests/Functional/Assertions/Import/ImportsTouristAttractionWithMedia.php @@ -0,0 +1,22 @@ + [ + 0 => [ + 'uid' => '1', + 'pid' => '10', + 'remote_id' => 'https://thuecat.org/resources/attraction-with-media', + 'title' => 'Attraktion mit Bildern', + 'media' => '[{"mainImage":false,"type":"image","title":"Bild mit externem Autor","description":"","url":"https:\\/\\/cms.thuecat.org\\/o\\/adaptive-media\\/image\\/5099196\\/Preview-1280x0\\/image","author":"GivenName FamilyName","copyrightYear":0,"license":{"type":"","author":""}},{"mainImage":false,"type":"image","title":"Bild mit author","description":"","url":"https:\\/\\/cms.thuecat.org\\/o\\/adaptive-media\\/image\\/5099196\\/Preview-1280x0\\/image","author":"Full Name","copyrightYear":0,"license":{"type":"https:\\/\\/creativecommons.org\\/licenses\\/by\\/4.0\\/","author":""}},{"mainImage":false,"type":"image","title":"Bild mit license author","description":"","url":"https:\\/\\/cms.thuecat.org\\/o\\/adaptive-media\\/image\\/5099196\\/Preview-1280x0\\/image","author":"","copyrightYear":0,"license":{"type":"https:\\/\\/creativecommons.org\\/licenses\\/by\\/4.0\\/","author":"Autor aus Lizenz"}},{"mainImage":false,"type":"image","title":"Bild mit author und license author","description":"","url":"https:\\/\\/cms.thuecat.org\\/o\\/adaptive-media\\/image\\/5099196\\/Preview-1280x0\\/image","author":"Full Name","copyrightYear":0,"license":{"type":"https:\\/\\/creativecommons.org\\/licenses\\/by\\/4.0\\/","author":"Autor aus Lizenz"}}]', + ], + 1 => [ + 'uid' => '2', + 'pid' => '10', + 'remote_id' => 'https://thuecat.org/resources/attraction-with-media', + 'title' => 'Attraction with media', + 'media' => '[{"mainImage":false,"type":"image","title":"Bild mit externem Autor","description":"","url":"https:\\/\\/cms.thuecat.org\\/o\\/adaptive-media\\/image\\/5099196\\/Preview-1280x0\\/image","author":"GivenName FamilyName","copyrightYear":0,"license":{"type":"","author":""}},{"mainImage":false,"type":"image","title":"Bild mit author","description":"","url":"https:\\/\\/cms.thuecat.org\\/o\\/adaptive-media\\/image\\/5099196\\/Preview-1280x0\\/image","author":"Full Name","copyrightYear":0,"license":{"type":"https:\\/\\/creativecommons.org\\/licenses\\/by\\/4.0\\/","author":""}},{"mainImage":false,"type":"image","title":"Bild mit license author","description":"","url":"https:\\/\\/cms.thuecat.org\\/o\\/adaptive-media\\/image\\/5099196\\/Preview-1280x0\\/image","author":"","copyrightYear":0,"license":{"type":"https:\\/\\/creativecommons.org\\/licenses\\/by\\/4.0\\/","author":"Autor aus Lizenz"}},{"mainImage":false,"type":"image","title":"Bild mit author und license author","description":"","url":"https:\\/\\/cms.thuecat.org\\/o\\/adaptive-media\\/image\\/5099196\\/Preview-1280x0\\/image","author":"Full Name","copyrightYear":0,"license":{"type":"https:\\/\\/creativecommons.org\\/licenses\\/by\\/4.0\\/","author":"Autor aus Lizenz"}}]', + ], + ], +]; diff --git a/Tests/Functional/Assertions/Import/ImportsTouristAttractionsWithFilteredOpeningHours.php b/Tests/Functional/Assertions/Import/ImportsTouristAttractionsWithFilteredOpeningHours.php new file mode 100644 index 0000000..62d8aa2 --- /dev/null +++ b/Tests/Functional/Assertions/Import/ImportsTouristAttractionsWithFilteredOpeningHours.php @@ -0,0 +1,28 @@ + [ + 0 => [ + 'uid' => '1', + 'pid' => '10', + 'sys_language_uid' => '0', + 'l18n_parent' => '0', + 'l10n_source' => '0', + 'remote_id' => 'https://thuecat.org/resources/835224016581-dara', + 'title' => 'Dom St. Marien', + 'opening_hours' => '[{"opens":"13:00:00","closes":"17:00:00","from":{"date":"2050-11-01 00:00:00.000000","timezone_type":3,"timezone":"UTC"},"through":{"date":"2050-04-30 00:00:00.000000","timezone_type":3,"timezone":"UTC"},"daysOfWeek":["Sunday"]}]', + ], + 1 => [ + 'uid' => '2', + 'pid' => '10', + 'sys_language_uid' => '1', + 'l18n_parent' => '1', + 'l10n_source' => '1', + 'remote_id' => 'https://thuecat.org/resources/835224016581-dara', + 'title' => 'Cathedral of St. Mary', + 'opening_hours' => '[{"opens":"13:00:00","closes":"17:00:00","from":{"date":"2050-11-01 00:00:00.000000","timezone_type":3,"timezone":"UTC"},"through":{"date":"2050-04-30 00:00:00.000000","timezone_type":3,"timezone":"UTC"},"daysOfWeek":["Sunday"]}]', + ], + ], +]; diff --git a/Tests/Functional/Assertions/Import/ImportsTouristAttractionsWithRelations.php b/Tests/Functional/Assertions/Import/ImportsTouristAttractionsWithRelations.php new file mode 100644 index 0000000..aa987af --- /dev/null +++ b/Tests/Functional/Assertions/Import/ImportsTouristAttractionsWithRelations.php @@ -0,0 +1,425 @@ + [ + 0 => [ + 'uid' => '1', + 'pid' => '10', + 'sys_language_uid' => '0', + 'l18n_parent' => '0', + 'l10n_source' => '0', + 'l10n_state' => null, + 'remote_id' => 'https://thuecat.org/resources/835224016581-dara', + 'title' => 'Dom St. Marien', + 'description' => 'Über eine 70-stufige Freitreppe gelangt man vom Domplatz auf den Domberg mit seinen beiden ehemaligen Stiftskirchen. Der Dom, mit hochgotischem Chor, romanischem Turmbereich und spätgotischer Westhalle, ist Nachfolger des 724 von Rom veranlassten Sakralbaus. Er war die Hauptkirche des 742 von Bischof Bonifatius gegründeten Bistums Erfurt und während des Mittelalters bis in das frühe 19. Jahrhundert Sitz des Collegiatstifts St. Marien. 1507 erhielt Martin Luther hier die Priesterweihe. +Der ursprünglich romanische Kirchenbau wurde in der Zeit der Gotik entscheidend umgebaut. Besonders sehenswert sind die gotischen Chorfenster, das umfängliche Chorgestühl (14. Jhd.) sowie die romanischen Skulpturen einer thronenden Madonna und eines monumentalen Kerzenträgers im Innenraum. Berühmt ist er auch wegen der „Gloriosa“, der mit 2,56 m Durchmesser größten freischwingenden mittelalterlichen Glocke der Welt. +Das Ensemble von Dom und Severikirche bildet eine imposante Kulisse für die jährlich im Sommer stattfindenden DomStufen-Festspiele.', + 'managed_by' => '1', + 'town' => '1', + 'address' => '{"street":"Domstufen 1","zip":"99084","city":"Erfurt","email":"dominformation@domberg-erfurt.de","phone":"+49 361 6461265","fax":"","geo":{"latitude":50.975955358589545,"longitude":11.023667024961856}}', + 'offers' => '[]', + 'media' => '[{"mainImage":true,"type":"image","title":"Erfurt-Dom und Severikirche-beleuchtet.jpg","description":"","url":"https:\\/\\/cms.thuecat.org\\/o\\/adaptive-media\\/image\\/5159216\\/Preview-1280x0\\/image","author":"","copyrightYear":2016,"license":{"type":"https:\\/\\/creativecommons.org\\/licenses\\/by\\/4.0\\/","author":""}},{"mainImage":false,"type":"image","title":"Erfurt-Dom-und-Severikirche.jpg","description":"Sicht auf Dom St. Marien, St. Severikirche sowie die davor liegenden Klostergeb\\u00e4ude und einem Ausschnitt des Biergartens umgeben von einem d\\u00e4mmerungsverf\\u00e4rten Himmel","url":"https:\\/\\/cms.thuecat.org\\/o\\/adaptive-media\\/image\\/5159186\\/Preview-1280x0\\/image","author":"","copyrightYear":2020,"license":{"type":"https:\\/\\/creativecommons.org\\/licenses\\/by\\/4.0\\/","author":""}}]', + 'slogan' => '', + 'start_of_construction' => '', + 'sanitation' => 'Toilets,DisabledToilets', + 'other_service' => 'SeatingPossibilitiesRestArea,SouvenirShop', + 'museum_service' => '', + 'architectural_style' => 'GothicArt', + 'traffic_infrastructure' => 'BicycleLockersEnumMem,BusParkCoachParkEnumMem', + 'payment_accepted' => '', + 'digital_offer' => 'AugmentedReality', + 'photography' => 'Fotogenehmigung für innen', + 'pets_allowed' => 'false', + 'is_accessible_for_free' => 'true', + 'public_access' => 'true', + 'available_languages' => 'German,English', + 'distance_to_public_transport' => '350:MTR:Streetcar:CityBus', + 'parking_facility_near_by' => '1', + 'accessibility_specification' => '{}', + 'url' => 'http://www.dom-erfurt.de', + ], + 1 => [ + 'uid' => '2', + 'pid' => '10', + 'sys_language_uid' => '1', + 'l18n_parent' => '1', + 'l10n_source' => '1', + 'l10n_state' => null, + 'remote_id' => 'https://thuecat.org/resources/835224016581-dara', + 'title' => 'Cathedral of St. Mary', + 'description' => 'The late Gothic cathedral with its high-Gothic choir and Romanesque tower replaced the church built on this site for Bishop Boniface in 742. The central tower houses the "Gloriosa", the world’s largest medieval free-swinging bell.', + 'managed_by' => '1', + 'town' => '1', + 'address' => '{"street":"Domstufen 1","zip":"99084","city":"Erfurt","email":"dominformation@domberg-erfurt.de","phone":"+49 361 6461265","fax":"","geo":{"latitude":50.975955358589545,"longitude":11.023667024961856}}', + 'offers' => '[]', + 'media' => '[{"mainImage":true,"type":"image","title":"Erfurt-Dom und Severikirche-beleuchtet.jpg","description":"","url":"https:\\/\\/cms.thuecat.org\\/o\\/adaptive-media\\/image\\/5159216\\/Preview-1280x0\\/image","author":"","copyrightYear":2016,"license":{"type":"https:\\/\\/creativecommons.org\\/licenses\\/by\\/4.0\\/","author":""}},{"mainImage":false,"type":"image","title":"Erfurt-Dom-und-Severikirche.jpg","description":"Sicht auf Dom St. Marien, St. Severikirche sowie die davor liegenden Klostergeb\\u00e4ude und einem Ausschnitt des Biergartens umgeben von einem d\\u00e4mmerungsverf\\u00e4rten Himmel","url":"https:\\/\\/cms.thuecat.org\\/o\\/adaptive-media\\/image\\/5159186\\/Preview-1280x0\\/image","author":"","copyrightYear":2020,"license":{"type":"https:\\/\\/creativecommons.org\\/licenses\\/by\\/4.0\\/","author":""}}]', + 'slogan' => '', + 'start_of_construction' => '', + 'sanitation' => 'Toilets,DisabledToilets', + 'other_service' => 'SeatingPossibilitiesRestArea,SouvenirShop', + 'museum_service' => '', + 'architectural_style' => 'GothicArt', + 'traffic_infrastructure' => 'BicycleLockersEnumMem,BusParkCoachParkEnumMem', + 'payment_accepted' => '', + 'digital_offer' => 'AugmentedReality', + 'photography' => '', + 'pets_allowed' => 'false', + 'is_accessible_for_free' => 'true', + 'public_access' => 'true', + 'available_languages' => 'German,English', + 'distance_to_public_transport' => '350:MTR:Streetcar:CityBus', + 'parking_facility_near_by' => '1', + 'accessibility_specification' => '{}', + 'url' => 'http://www.dom-erfurt.de', + ], + 2 => [ + 'uid' => '3', + 'pid' => '10', + 'sys_language_uid' => '0', + 'l18n_parent' => '0', + 'l10n_source' => '0', + 'l10n_state' => null, + 'remote_id' => 'https://thuecat.org/resources/165868194223-zmqf', + 'title' => 'Alte Synagoge', + 'description' => 'Beispiel Beschreibung', + 'managed_by' => '1', + 'town' => '1', + 'address' => '{"street":"Waagegasse 8","zip":"99084","city":"Erfurt","email":"altesynagoge@erfurt.de","phone":"+49 361 6551520","fax":"+49 361 6551669","geo":{"latitude":50.978765,"longitude":11.029133}}', + 'offers' => '[{"types":["GuidedTourOffer"],"title":"F\\u00fchrungen","description":"Immer samstags, um 11:15 Uhr findet eine \\u00f6ffentliche F\\u00fchrung durch das Museum statt. Dauer etwa 90 Minuten","prices":[{"title":"Erwachsene","description":"","price":8,"currency":"EUR","rule":"PerPerson"},{"title":"Erm\\u00e4\\u00dfigt","description":"als erm\\u00e4\\u00dfigt gelten schulpflichtige Kinder, Auszubildende, Studierende, Rentner\\/-innen, Menschen mit Behinderungen, Inhaber Sozialausweis der Landeshauptstadt Erfurt","price":5,"currency":"EUR","rule":"PerPerson"}]},{"types":["EntryOffer"],"title":"Eintritt","description":"Schulklassen und Kitagruppen im Rahmen des Unterrichts: Eintritt frei\\nAn jedem ersten Dienstag im Monat: Eintritt frei","prices":[{"title":"Erm\\u00e4\\u00dfigt","description":"als erm\\u00e4\\u00dfigt gelten schulpflichtige Kinder, Auszubildende, Studierende, Rentner\\/-innen, Menschen mit Behinderungen, Inhaber Sozialausweis der Landeshauptstadt Erfurt","price":5,"currency":"EUR","rule":"PerPerson"},{"title":"Familienkarte","description":"","price":17,"currency":"EUR","rule":"PerGroup"},{"title":"ErfurtCard","description":"","price":14.9,"currency":"EUR","rule":"PerPackage"},{"title":"Erwachsene","description":"","price":8,"currency":"EUR","rule":"PerPerson"}]}]', + 'media' => '[{"mainImage":true,"type":"image","title":"Erfurt-Alte Synagoge","description":"Frontaler Blick auf die Hausfront\\/Hausfassade im Innenhof mit Zugang \\u00fcber die Waagegasse","url":"https:\\/\\/cms.thuecat.org\\/o\\/adaptive-media\\/image\\/5099196\\/Preview-1280x0\\/image","author":"","copyrightYear":2009,"license":{"type":"https:\\/\\/creativecommons.org\\/licenses\\/by\\/4.0\\/","author":"F:\\\\Bilddatenbank\\\\Museen und Ausstellungen\\\\Alte Synagoge"}}]', + 'slogan' => 'Highlight', + 'start_of_construction' => '11. Jh.', + 'sanitation' => 'Toilets,DisabledToilets,NappyChangingArea,FamilyAndChildFriendly', + 'other_service' => 'SeatingPossibilitiesRestArea,LockBoxes,SouvenirShop,BaggageStorage', + 'museum_service' => 'MuseumShop', + 'architectural_style' => 'GothicArt', + 'traffic_infrastructure' => 'ZeroSpecialTrafficInfrastructure', + 'payment_accepted' => 'CashPayment,EC', + 'digital_offer' => 'AudioGuide,VideoGuide', + 'photography' => 'ZeroPhotography', + 'pets_allowed' => 'Tiere sind im Gebäude nicht gestattet, ausgenommen sind Blinden- und Blindenbegleithunde.', + 'is_accessible_for_free' => 'false', + 'public_access' => 'true', + 'available_languages' => 'German,English,French', + 'distance_to_public_transport' => '200:MTR:CityBus', + 'parking_facility_near_by' => '', + 'accessibility_specification' => '{"accessibilityCertificationStatus":"AccessibilityChecked","certificationAccessibilityDeaf":"None","certificationAccessibilityMental":"None","certificationAccessibilityPartiallyDeaf":"None","certificationAccessibilityPartiallyVisual":"Info","certificationAccessibilityVisual":"None","certificationAccessibilityWalking":"Info","certificationAccessibilityWheelchair":"Info","accessibilitySearchCriteria":{"facilityAccessibilityWalking":["AllRoomsStepFreeAccess","HingedGrabRailToilet","LateralAccessibleToilet","StepFreeAccess","ToiletsPeopleWithDisabilities","NinetyCMWidthPassageWays","SpecialOffersWalkingImpairment","SpecialOffersWheelchairUsers"],"facilityAccessibilityVisual":["AssistanceDogsWelcome","VisuallyContrastingStepEdges","OffersInPictoralLanguage","SpecialOffersBlindPeople","SpecialOffersVisualImpairment","TactileOffers"],"facilityAccessibilityDeaf":["AudioInductionLoop","SpecialOffersHearingImpairment"],"facilityAccessibilityMental":["InformationWithPictogramsOrPictures"]},"shortDescriptionAccessibilityDeaf":"Deutsche Beschreibung von shortDescriptionAccessibilityDeaf","shortDescriptionAccessibilityMental":"Deutsche Beschreibung von shortDescriptionAccessibilityMental","shortDescriptionAccessibilityVisual":"Deutsche Beschreibung von shortDescriptionAccessibilityVisual","shortDescriptionAccessibilityWalking":"Deutsche Beschreibung von shortDescriptionAccessibilityWalking"}', + 'url' => 'http://www.alte-synagoge.erfurt.de', + ], + 3 => [ + 'uid' => '4', + 'pid' => '10', + 'sys_language_uid' => '1', + 'l18n_parent' => '3', + 'l10n_source' => '3', + 'l10n_state' => null, + 'remote_id' => 'https://thuecat.org/resources/165868194223-zmqf', + 'title' => 'Old Synagogue', + 'description' => 'The Old Synagogue is one of very few preserved medieval synagogues in Europe. Thanks to the extensive preservation of the original structure, it has a special place in the history of art and architecture and is among the most impressive and highly rated architectural monuments in Erfurt and Thuringia. The synagogue was constructed during the Middle Ages on the "via regia", one of the major European trade routes, at the heart of the historical old quarter very close to the Merchants Bridge and the town hall. Many parts of the structure still remain today, including all four thick outer walls, the Roman­esque gemel window, the Gothic rose window and the entrance to the synagogue room.', + 'managed_by' => '1', + 'town' => '1', + 'address' => '{"street":"Waagegasse 8","zip":"99084","city":"Erfurt","email":"altesynagoge@erfurt.de","phone":"+49 361 6551520","fax":"+49 361 6551669","geo":{"latitude":50.978765,"longitude":11.029133}}', + 'offers' => '[{"types":["GuidedTourOffer"],"title":"","description":"","prices":[{"title":"","description":"","price":8,"currency":"EUR","rule":"PerPerson"},{"title":"","description":"","price":5,"currency":"EUR","rule":"PerPerson"}]},{"types":["EntryOffer"],"title":"","description":"","prices":[{"title":"","description":"","price":5,"currency":"EUR","rule":"PerPerson"},{"title":"","description":"","price":17,"currency":"EUR","rule":"PerGroup"},{"title":"","description":"","price":14.9,"currency":"EUR","rule":"PerPackage"},{"title":"","description":"","price":8,"currency":"EUR","rule":"PerPerson"}]}]', + 'media' => '[{"mainImage":true,"type":"image","title":"Erfurt-Alte Synagoge","description":"Frontaler Blick auf die Hausfront\\/Hausfassade im Innenhof mit Zugang \\u00fcber die Waagegasse","url":"https:\\/\\/cms.thuecat.org\\/o\\/adaptive-media\\/image\\/5099196\\/Preview-1280x0\\/image","author":"","copyrightYear":2009,"license":{"type":"https:\\/\\/creativecommons.org\\/licenses\\/by\\/4.0\\/","author":"F:\\\\Bilddatenbank\\\\Museen und Ausstellungen\\\\Alte Synagoge"}}]', + 'slogan' => 'Highlight', + 'start_of_construction' => '11th century', + 'sanitation' => 'Toilets,DisabledToilets,NappyChangingArea,FamilyAndChildFriendly', + 'other_service' => 'SeatingPossibilitiesRestArea,LockBoxes,SouvenirShop,BaggageStorage', + 'museum_service' => 'MuseumShop', + 'architectural_style' => 'GothicArt', + 'traffic_infrastructure' => 'ZeroSpecialTrafficInfrastructure', + 'payment_accepted' => 'CashPayment,EC', + 'digital_offer' => 'AudioGuide,VideoGuide', + 'photography' => 'ZeroPhotography', + 'pets_allowed' => '', + 'is_accessible_for_free' => 'false', + 'public_access' => 'true', + 'available_languages' => 'German,English,French', + 'distance_to_public_transport' => '200:MTR:CityBus', + 'parking_facility_near_by' => '', + 'accessibility_specification' => '{"accessibilityCertificationStatus":"AccessibilityChecked","certificationAccessibilityDeaf":"None","certificationAccessibilityMental":"None","certificationAccessibilityPartiallyDeaf":"None","certificationAccessibilityPartiallyVisual":"Info","certificationAccessibilityVisual":"None","certificationAccessibilityWalking":"Info","certificationAccessibilityWheelchair":"Info","accessibilitySearchCriteria":{"facilityAccessibilityWalking":["AllRoomsStepFreeAccess","HingedGrabRailToilet","LateralAccessibleToilet","StepFreeAccess","ToiletsPeopleWithDisabilities","NinetyCMWidthPassageWays","SpecialOffersWalkingImpairment","SpecialOffersWheelchairUsers"],"facilityAccessibilityVisual":["AssistanceDogsWelcome","VisuallyContrastingStepEdges","OffersInPictoralLanguage","SpecialOffersBlindPeople","SpecialOffersVisualImpairment","TactileOffers"],"facilityAccessibilityDeaf":["AudioInductionLoop","SpecialOffersHearingImpairment"],"facilityAccessibilityMental":["InformationWithPictogramsOrPictures"]},"shortDescriptionAccessibilityDeaf":"English description of shortDescriptionAccessibilityDeaf","shortDescriptionAccessibilityMental":"English description of shortDescriptionAccessibilityMental","shortDescriptionAccessibilityVisual":"English description of shortDescriptionAccessibilityVisual","shortDescriptionAccessibilityWalking":"English description of shortDescriptionAccessibilityWalking"}', + 'url' => 'http://www.alte-synagoge.erfurt.de', + ], + 4 => [ + 'uid' => '5', + 'pid' => '10', + 'sys_language_uid' => '2', + 'l18n_parent' => '3', + 'l10n_source' => '3', + 'l10n_state' => null, + 'remote_id' => 'https://thuecat.org/resources/165868194223-zmqf', + 'title' => 'La vieille synagogue', + 'description' => 'La vieille synagogue (datant des années 1100) est la synagogue la plus vieille d’Europe totalement conservée, dans laquelle est exposé un trésor datant des 13/14èmes siècles avec une alliance juive unique et des écritures hébraïques (datant des 12ème, 13ème et 14èmes siècles). Après la redécouverte du Mikwé, Erfurt abrite des témoins uniques et fascinants d’une communauté juive médiévale.', + 'managed_by' => '1', + 'town' => '1', + 'address' => '{"street":"Waagegasse 8","zip":"99084","city":"Erfurt","email":"altesynagoge@erfurt.de","phone":"+49 361 6551520","fax":"+49 361 6551669","geo":{"latitude":50.978765,"longitude":11.029133}}', + 'offers' => '[{"types":["GuidedTourOffer"],"title":"","description":"","prices":[{"title":"","description":"","price":8,"currency":"EUR","rule":"PerPerson"},{"title":"","description":"","price":5,"currency":"EUR","rule":"PerPerson"}]},{"types":["EntryOffer"],"title":"","description":"","prices":[{"title":"","description":"","price":5,"currency":"EUR","rule":"PerPerson"},{"title":"","description":"","price":17,"currency":"EUR","rule":"PerGroup"},{"title":"","description":"","price":14.9,"currency":"EUR","rule":"PerPackage"},{"title":"","description":"","price":8,"currency":"EUR","rule":"PerPerson"}]}]', + 'media' => '[{"mainImage":true,"type":"image","title":"Erfurt-Alte Synagoge","description":"Frontaler Blick auf die Hausfront\\/Hausfassade im Innenhof mit Zugang \\u00fcber die Waagegasse","url":"https:\\/\\/cms.thuecat.org\\/o\\/adaptive-media\\/image\\/5099196\\/Preview-1280x0\\/image","author":"","copyrightYear":2009,"license":{"type":"https:\\/\\/creativecommons.org\\/licenses\\/by\\/4.0\\/","author":"F:\\\\Bilddatenbank\\\\Museen und Ausstellungen\\\\Alte Synagoge"}}]', + 'slogan' => 'Highlight', + 'start_of_construction' => '', + 'sanitation' => 'Toilets,DisabledToilets,NappyChangingArea,FamilyAndChildFriendly', + 'other_service' => 'SeatingPossibilitiesRestArea,LockBoxes,SouvenirShop,BaggageStorage', + 'museum_service' => 'MuseumShop', + 'architectural_style' => 'GothicArt', + 'traffic_infrastructure' => 'ZeroSpecialTrafficInfrastructure', + 'payment_accepted' => 'CashPayment,EC', + 'digital_offer' => 'AudioGuide,VideoGuide', + 'photography' => 'ZeroPhotography', + 'pets_allowed' => '', + 'is_accessible_for_free' => 'false', + 'public_access' => 'true', + 'available_languages' => 'German,English,French', + 'distance_to_public_transport' => '200:MTR:CityBus', + 'parking_facility_near_by' => '', + 'accessibility_specification' => '{"accessibilityCertificationStatus":"AccessibilityChecked","certificationAccessibilityDeaf":"None","certificationAccessibilityMental":"None","certificationAccessibilityPartiallyDeaf":"None","certificationAccessibilityPartiallyVisual":"Info","certificationAccessibilityVisual":"None","certificationAccessibilityWalking":"Info","certificationAccessibilityWheelchair":"Info","accessibilitySearchCriteria":{"facilityAccessibilityWalking":["AllRoomsStepFreeAccess","HingedGrabRailToilet","LateralAccessibleToilet","StepFreeAccess","ToiletsPeopleWithDisabilities","NinetyCMWidthPassageWays","SpecialOffersWalkingImpairment","SpecialOffersWheelchairUsers"],"facilityAccessibilityVisual":["AssistanceDogsWelcome","VisuallyContrastingStepEdges","OffersInPictoralLanguage","SpecialOffersBlindPeople","SpecialOffersVisualImpairment","TactileOffers"],"facilityAccessibilityDeaf":["AudioInductionLoop","SpecialOffersHearingImpairment"],"facilityAccessibilityMental":["InformationWithPictogramsOrPictures"]}}', + 'url' => 'http://www.alte-synagoge.erfurt.de', + ], + 5 => [ + 'uid' => '6', + 'pid' => '10', + 'sys_language_uid' => '0', + 'l18n_parent' => '0', + 'l10n_source' => '0', + 'l10n_state' => null, + 'remote_id' => 'https://thuecat.org/resources/215230952334-yyno', + 'title' => 'Krämerbrücke', + 'description' => 'Ein bekanntes Wahrzeichen Erfurts ist die Krämerbrücke, die längste bebaute und bewohnte Brücke Europas.Die Krämerbrücke wurde zu Beginn aus Holz und 1325 aus Stein erbaut. Zunächst war die 120 m lange Brücke mit 62 schmalen Häusern bebaut. Später wurden einige der Häuser auf nun mehr 32 zusammengefasst. An beiden Enden der Brücke standen zwei Brückenkopfkirchen. Heute existiert nur noch eine der beiden, die östlich gelegene Ägidienkirche.Auf der Krämerbrücke kann man in Galerien und Boutiquen sehr schön bummeln gehen. Man kann Thüringer Handwerksmeistern bei ihrer Arbeit über die Schulter schauen. Keramik, Porzellan und Holzschnitzereien, Blaudruck und Lauschaer Glas sind beliebte Souvenirs. Cafès, Weinhändler und Feinkostgeschäfte mit Thüringer Spezialitäten laden zum Verweilen ein.', + 'managed_by' => '1', + 'town' => '1', + 'address' => '{"street":"Benediktsplatz 1","zip":"99084","city":"Erfurt","email":"service@erfurt-tourismus.de","phone":"+49 361 66 400","fax":"","geo":{"latitude":50.978772,"longitude":11.031622}}', + 'offers' => '[]', + 'media' => '[{"mainImage":true,"type":"image","title":"Erfurt-Kraemerbruecke-11.jpg","description":"Kr\\u00e4merbr\\u00fccke in Erfurt","url":"https:\\/\\/cms.thuecat.org\\/o\\/adaptive-media\\/image\\/134362\\/Preview-1280x0\\/image","author":"Florian Trykowski","copyrightYear":2019,"license":{"type":"https:\\/\\/creativecommons.org\\/publicdomain\\/zero\\/1.0\\/deed.de","author":"https:\\/\\/home.ttgnet.de\\/ttg\\/projekte\\/10006\\/90136\\/Projektdokumente\\/Vergabe%20Rahmenvertrag%20Fotoproduktion"}},{"mainImage":false,"type":"image","title":"Erfurt-Kraemerbruecke.jpg","description":"Kr\\u00e4merbr\\u00fccke in Erfurt","url":"https:\\/\\/cms.thuecat.org\\/o\\/adaptive-media\\/image\\/134288\\/Preview-1280x0\\/image","author":"Florian Trykowski","copyrightYear":2019,"license":{"type":"https:\\/\\/creativecommons.org\\/publicdomain\\/zero\\/1.0\\/deed.de","author":"https:\\/\\/home.ttgnet.de\\/ttg\\/projekte\\/10006\\/90136\\/Projektdokumente\\/Vergabe%20Rahmenvertrag%20Fotoproduktion"}},{"mainImage":false,"type":"image","title":"Erfurt-Kraemerbruecke-13.jpg","description":"Ansicht der Kr\\u00e4merbr\\u00fccke, Erfurt","url":"https:\\/\\/cms.thuecat.org\\/o\\/adaptive-media\\/image\\/652340\\/Preview-1280x0\\/image","author":"Florian Trykowski","copyrightYear":2019,"license":{"type":"https:\\/\\/creativecommons.org\\/publicdomain\\/zero\\/1.0\\/deed.de","author":"https:\\/\\/home.ttgnet.de\\/ttg\\/projekte\\/10006\\/90136\\/Projektdokumente\\/Vergabe%20Rahmenvertrag%20Fotoproduktion"}}]', + 'slogan' => '', + 'start_of_construction' => '', + 'sanitation' => 'ZeroSanitation', + 'other_service' => 'Playground,SeatingPossibilitiesRestArea,SouvenirShop,PlayCornerOrPlayArea', + 'museum_service' => '', + 'architectural_style' => 'ZeroInformationArchitecturalStyle', + 'traffic_infrastructure' => 'BicycleLockersEnumMem', + 'payment_accepted' => '', + 'digital_offer' => 'ZeroDigitalOffer', + 'photography' => 'TakingPicturesPermitted', + 'pets_allowed' => 'true', + 'is_accessible_for_free' => 'true', + 'public_access' => 'true', + 'available_languages' => 'German,English,French', + 'distance_to_public_transport' => '250:MTR', + 'parking_facility_near_by' => '1,4', + 'accessibility_specification' => '{}', + 'url' => 'https://www.erfurt-tourismus.de/sehenswertes/kraemerbruecke', + ], + 6 => [ + 'uid' => '7', + 'pid' => '10', + 'sys_language_uid' => '1', + 'l18n_parent' => '6', + 'l10n_source' => '6', + 'l10n_state' => null, + 'remote_id' => 'https://thuecat.org/resources/215230952334-yyno', + 'title' => 'Merchants\' Bridge', + 'description' => 'Another Erfurt landmark is the Merchants\' Bridge (Krämerbrücke), the longest series of inhabited buildings on any bridge in Europe. The Merchants\' Bridge is Erfurts most interesting secular construction, initially in wood but rebuilt in stone in 1325. There were originally 62 narrow buildings along its 120-metre length, but subsequent redevelopment left just 32 buildings. Of what was once a pair of bridgehead churches, only the Church of St. Aegidius remains at the eastern end of the bridge today. The Merchants\' Bridge is lined with galleries, cafés and boutiques offering traditional crafts, Thuringian blue printed fabrics, hand-painted ceramics, handblown glassware, jewellery, wood carvings, antiques and delicious Thuringian specialities - perfect for browsing.', + 'managed_by' => '1', + 'town' => '1', + 'address' => '{"street":"Benediktsplatz 1","zip":"99084","city":"Erfurt","email":"service@erfurt-tourismus.de","phone":"+49 361 66 400","fax":"","geo":{"latitude":50.978772,"longitude":11.031622}}', + 'offers' => '[]', + 'media' => '[{"mainImage":true,"type":"image","title":"Erfurt-Kraemerbruecke-11.jpg","description":"Kr\\u00e4merbr\\u00fccke in Erfurt","url":"https:\\/\\/cms.thuecat.org\\/o\\/adaptive-media\\/image\\/134362\\/Preview-1280x0\\/image","author":"Florian Trykowski","copyrightYear":2019,"license":{"type":"https:\\/\\/creativecommons.org\\/publicdomain\\/zero\\/1.0\\/deed.de","author":"https:\\/\\/home.ttgnet.de\\/ttg\\/projekte\\/10006\\/90136\\/Projektdokumente\\/Vergabe%20Rahmenvertrag%20Fotoproduktion"}},{"mainImage":false,"type":"image","title":"Erfurt-Kraemerbruecke.jpg","description":"Kr\\u00e4merbr\\u00fccke in Erfurt","url":"https:\\/\\/cms.thuecat.org\\/o\\/adaptive-media\\/image\\/134288\\/Preview-1280x0\\/image","author":"Florian Trykowski","copyrightYear":2019,"license":{"type":"https:\\/\\/creativecommons.org\\/publicdomain\\/zero\\/1.0\\/deed.de","author":"https:\\/\\/home.ttgnet.de\\/ttg\\/projekte\\/10006\\/90136\\/Projektdokumente\\/Vergabe%20Rahmenvertrag%20Fotoproduktion"}},{"mainImage":false,"type":"image","title":"Erfurt-Kraemerbruecke-13.jpg","description":"Ansicht der Kr\\u00e4merbr\\u00fccke, Erfurt","url":"https:\\/\\/cms.thuecat.org\\/o\\/adaptive-media\\/image\\/652340\\/Preview-1280x0\\/image","author":"Florian Trykowski","copyrightYear":2019,"license":{"type":"https:\\/\\/creativecommons.org\\/publicdomain\\/zero\\/1.0\\/deed.de","author":"https:\\/\\/home.ttgnet.de\\/ttg\\/projekte\\/10006\\/90136\\/Projektdokumente\\/Vergabe%20Rahmenvertrag%20Fotoproduktion"}}]', + 'slogan' => '', + 'start_of_construction' => '', + 'sanitation' => 'ZeroSanitation', + 'other_service' => 'Playground,SeatingPossibilitiesRestArea,SouvenirShop,PlayCornerOrPlayArea', + 'museum_service' => '', + 'architectural_style' => 'ZeroInformationArchitecturalStyle', + 'traffic_infrastructure' => 'BicycleLockersEnumMem', + 'payment_accepted' => '', + 'digital_offer' => 'ZeroDigitalOffer', + 'photography' => 'TakingPicturesPermitted', + 'pets_allowed' => 'true', + 'is_accessible_for_free' => 'true', + 'public_access' => 'true', + 'available_languages' => 'German,English,French', + 'distance_to_public_transport' => '250:MTR', + 'parking_facility_near_by' => '1,4', + 'accessibility_specification' => '{}', + 'url' => 'https://www.erfurt-tourismus.de/sehenswertes/kraemerbruecke', + ], + 7 => [ + 'uid' => '8', + 'pid' => '10', + 'sys_language_uid' => '2', + 'l18n_parent' => '6', + 'l10n_source' => '6', + 'l10n_state' => null, + 'remote_id' => 'https://thuecat.org/resources/215230952334-yyno', + 'title' => 'Pont de l\'épicier', + 'description' => 'Le pont de l’épicier est un des symboles de la ville d’Erfurt, le plus grand pont habité en continu d’Europe. A l’origine, le pont de l’épicier faisait 120 m de long et comptait 62 maisons étroites, qui furent plus tard regroupées en 32 maisons. Sur le pont de l’épicier se trouvent des galeries et des petites échoppes proposant des étoffes à motifs bleu indigo de Thuringe, des céramiques peintes main, du verre de Lauscha, des bijoux et des sculptures en bois.', + 'managed_by' => '1', + 'town' => '1', + 'address' => '{"street":"Benediktsplatz 1","zip":"99084","city":"Erfurt","email":"service@erfurt-tourismus.de","phone":"+49 361 66 400","fax":"","geo":{"latitude":50.978772,"longitude":11.031622}}', + 'offers' => '[]', + 'media' => '[{"mainImage":true,"type":"image","title":"Erfurt-Kraemerbruecke-11.jpg","description":"Kr\\u00e4merbr\\u00fccke in Erfurt","url":"https:\\/\\/cms.thuecat.org\\/o\\/adaptive-media\\/image\\/134362\\/Preview-1280x0\\/image","author":"Florian Trykowski","copyrightYear":2019,"license":{"type":"https:\\/\\/creativecommons.org\\/publicdomain\\/zero\\/1.0\\/deed.de","author":"https:\\/\\/home.ttgnet.de\\/ttg\\/projekte\\/10006\\/90136\\/Projektdokumente\\/Vergabe%20Rahmenvertrag%20Fotoproduktion"}},{"mainImage":false,"type":"image","title":"Erfurt-Kraemerbruecke.jpg","description":"Kr\\u00e4merbr\\u00fccke in Erfurt","url":"https:\\/\\/cms.thuecat.org\\/o\\/adaptive-media\\/image\\/134288\\/Preview-1280x0\\/image","author":"Florian Trykowski","copyrightYear":2019,"license":{"type":"https:\\/\\/creativecommons.org\\/publicdomain\\/zero\\/1.0\\/deed.de","author":"https:\\/\\/home.ttgnet.de\\/ttg\\/projekte\\/10006\\/90136\\/Projektdokumente\\/Vergabe%20Rahmenvertrag%20Fotoproduktion"}},{"mainImage":false,"type":"image","title":"Erfurt-Kraemerbruecke-13.jpg","description":"Ansicht der Kr\\u00e4merbr\\u00fccke, Erfurt","url":"https:\\/\\/cms.thuecat.org\\/o\\/adaptive-media\\/image\\/652340\\/Preview-1280x0\\/image","author":"Florian Trykowski","copyrightYear":2019,"license":{"type":"https:\\/\\/creativecommons.org\\/publicdomain\\/zero\\/1.0\\/deed.de","author":"https:\\/\\/home.ttgnet.de\\/ttg\\/projekte\\/10006\\/90136\\/Projektdokumente\\/Vergabe%20Rahmenvertrag%20Fotoproduktion"}}]', + 'slogan' => '', + 'start_of_construction' => '', + 'sanitation' => 'ZeroSanitation', + 'other_service' => 'Playground,SeatingPossibilitiesRestArea,SouvenirShop,PlayCornerOrPlayArea', + 'museum_service' => '', + 'architectural_style' => 'ZeroInformationArchitecturalStyle', + 'traffic_infrastructure' => 'BicycleLockersEnumMem', + 'payment_accepted' => '', + 'digital_offer' => 'ZeroDigitalOffer', + 'photography' => 'TakingPicturesPermitted', + 'pets_allowed' => 'true', + 'is_accessible_for_free' => 'true', + 'public_access' => 'true', + 'available_languages' => 'German,English,French', + 'distance_to_public_transport' => '250:MTR', + 'parking_facility_near_by' => '1,4', + 'accessibility_specification' => '{}', + 'url' => 'https://www.erfurt-tourismus.de/sehenswertes/kraemerbruecke', + ], + ], + 'tx_thuecat_parking_facility' => [ + 0 => [ + 'uid' => '1', + 'pid' => '10', + 'sys_language_uid' => '0', + 'l18n_parent' => '0', + 'l10n_source' => '0', + 'l10n_state' => null, + 'remote_id' => 'https://thuecat.org/resources/396420044896-drzt', + 'title' => 'Parkhaus Domplatz', + 'description' => 'Das Parkhaus Domplatz befindet sich unmittelbar unterhalb der Zitadelle Petersberg am nördlichen Rand des Domplatzes. Durch die zentrale Lage ist es ein idealer Ausgangspunkt für Stadtbummel und Erkundungen des Zentrums, des Petersbergs und des Andreasviertels.', + 'managed_by' => '1', + 'address' => '{"street":"Bechtheimer Str. 1","zip":"99084","city":"Erfurt","email":"info@stadtwerke-erfurt.de","phone":"+49 361 5640","fax":"","geo":{"latitude":50.977648905044,"longitude":11.022127985954299}}', + 'offers' => '[{"types":["ParkingFee"],"title":"","description":"","prices":[{"title":"","description":"","price":35,"currency":"EUR","rule":"PerCar"}]},{"types":["ParkingFee"],"title":"","description":"","prices":[{"title":"","description":"","price":1.5,"currency":"EUR","rule":"PerCar"}]},{"types":["ParkingFee"],"title":"","description":"","prices":[{"title":"","description":"","price":10,"currency":"EUR","rule":"PerCar"}]},{"types":["ParkingFee"],"title":"","description":"","prices":[{"title":"","description":"","price":50,"currency":"EUR","rule":"PerCar"}]}]', + 'media' => '[{"mainImage":true,"type":"image","title":"Erfurt-Parkhaus-Domplatz.jpg","description":"","url":"https:\\/\\/cms.thuecat.org\\/o\\/adaptive-media\\/image\\/6486108\\/Preview-1280x0\\/image","author":"Florian Trykowski","copyrightYear":2021,"license":{"type":"https:\\/\\/creativecommons.org\\/licenses\\/by\\/4.0\\/","author":""}}]', + 'sanitation' => 'ZeroSanitation', + 'other_service' => 'ZeroOtherServiceEnumMem', + 'traffic_infrastructure' => 'ElectricVehicleCarChargingStationEnumMem', + 'payment_accepted' => '', + 'distance_to_public_transport' => '240:MTR:CityBus', + ], + 1 => [ + 'uid' => '2', + 'pid' => '10', + 'sys_language_uid' => '1', + 'l18n_parent' => '1', + 'l10n_source' => '1', + 'l10n_state' => null, + 'remote_id' => 'https://thuecat.org/resources/396420044896-drzt', + 'title' => 'Car park Domplatz', + 'description' => 'The Domplatz multi-storey car park is located directly below the Petersberg Citadel on the northern edge of the Domplatz. Its central location makes it an ideal starting point for strolling through the city and exploring the centre, the Petersberg and the Andreasviertel.', + 'managed_by' => '1', + 'address' => '{"street":"Bechtheimer Str. 1","zip":"99084","city":"Erfurt","email":"info@stadtwerke-erfurt.de","phone":"+49 361 5640","fax":"","geo":{"latitude":50.977648905044,"longitude":11.022127985954299}}', + 'offers' => '[{"types":["ParkingFee"],"title":"","description":"","prices":[{"title":"","description":"","price":35,"currency":"EUR","rule":"PerCar"}]},{"types":["ParkingFee"],"title":"","description":"","prices":[{"title":"","description":"","price":1.5,"currency":"EUR","rule":"PerCar"}]},{"types":["ParkingFee"],"title":"","description":"","prices":[{"title":"","description":"","price":10,"currency":"EUR","rule":"PerCar"}]},{"types":["ParkingFee"],"title":"","description":"","prices":[{"title":"","description":"","price":50,"currency":"EUR","rule":"PerCar"}]}]', + 'media' => '[{"mainImage":true,"type":"image","title":"Erfurt-Parkhaus-Domplatz.jpg","description":"","url":"https:\\/\\/cms.thuecat.org\\/o\\/adaptive-media\\/image\\/6486108\\/Preview-1280x0\\/image","author":"Florian Trykowski","copyrightYear":2021,"license":{"type":"https:\\/\\/creativecommons.org\\/licenses\\/by\\/4.0\\/","author":""}}]', + 'sanitation' => 'ZeroSanitation', + 'other_service' => 'ZeroOtherServiceEnumMem', + 'traffic_infrastructure' => 'ElectricVehicleCarChargingStationEnumMem', + 'payment_accepted' => '', + 'distance_to_public_transport' => '240:MTR:CityBus', + ], + 2 => [ + 'uid' => '3', + 'pid' => '10', + 'sys_language_uid' => '2', + 'l18n_parent' => '1', + 'l10n_source' => '1', + 'l10n_state' => null, + 'remote_id' => 'https://thuecat.org/resources/396420044896-drzt', + 'title' => 'Parking Domplatz', + 'description' => 'Le parking à étages de la Domplatz est situé juste en dessous de la citadelle de Petersberg, sur le bord nord de la Domplatz. Son emplacement central en fait un point de départ idéal pour se promener dans la ville et explorer le centre, le Petersberg et l\'Andreasviertel.', + 'managed_by' => '1', + 'address' => '{"street":"Bechtheimer Str. 1","zip":"99084","city":"Erfurt","email":"info@stadtwerke-erfurt.de","phone":"+49 361 5640","fax":"","geo":{"latitude":50.977648905044,"longitude":11.022127985954299}}', + 'offers' => '[{"types":["ParkingFee"],"title":"","description":"","prices":[{"title":"","description":"","price":35,"currency":"EUR","rule":"PerCar"}]},{"types":["ParkingFee"],"title":"","description":"","prices":[{"title":"","description":"","price":1.5,"currency":"EUR","rule":"PerCar"}]},{"types":["ParkingFee"],"title":"","description":"","prices":[{"title":"","description":"","price":10,"currency":"EUR","rule":"PerCar"}]},{"types":["ParkingFee"],"title":"","description":"","prices":[{"title":"","description":"","price":50,"currency":"EUR","rule":"PerCar"}]}]', + 'media' => '[{"mainImage":true,"type":"image","title":"Erfurt-Parkhaus-Domplatz.jpg","description":"","url":"https:\\/\\/cms.thuecat.org\\/o\\/adaptive-media\\/image\\/6486108\\/Preview-1280x0\\/image","author":"Florian Trykowski","copyrightYear":2021,"license":{"type":"https:\\/\\/creativecommons.org\\/licenses\\/by\\/4.0\\/","author":""}}]', + 'sanitation' => 'ZeroSanitation', + 'other_service' => 'ZeroOtherServiceEnumMem', + 'traffic_infrastructure' => 'ElectricVehicleCarChargingStationEnumMem', + 'payment_accepted' => '', + 'distance_to_public_transport' => '240:MTR:CityBus', + ], + 3 => [ + 'uid' => '4', + 'pid' => '10', + 'sys_language_uid' => '0', + 'l18n_parent' => '0', + 'l10n_source' => '0', + 'l10n_state' => null, + 'remote_id' => 'https://thuecat.org/resources/440055527204-ocar', + 'title' => 'Q-Park Anger 1 Parkhaus', + 'description' => 'Der Q-Park liegt direkt hinter dem Kaufhaus Anger 1 im Erfurter Stadtzentrum und ist über Juri-Gagarin-Ring/Meyfartstraße zu erreichen. Durch die direkte Anbindung an den Stadtring, ist das Parkhaus gut von außerhalb über Schnellstraßen und Autobahnen zu erreichen und befindet sich gleichzeitig im unmittelbaren modernen Zentrum Erfurts.', + 'managed_by' => '1', + 'address' => '{"street":"Anger 1","zip":"99084","city":"Erfurt","email":"servicecenter@q-park.de","phone":"+49 218 18190290","fax":"","geo":{"latitude":50.977999330565794,"longitude":11.037503264052475}}', + 'offers' => '[{"types":["ParkingFee"],"title":"","description":"","prices":[{"title":"","description":"","price":2.2,"currency":"EUR","rule":"PerCar"}]},{"types":["ParkingFee"],"title":"","description":"","prices":[{"title":"","description":"","price":1,"currency":"EUR","rule":"PerCar"}]},{"types":["ParkingFee"],"title":"","description":"","prices":[{"title":"","description":"","price":13,"currency":"EUR","rule":"PerCar"}]}]', + 'media' => '[{"mainImage":true,"type":"image","title":"Q-Park-Parkhaus-Anger1-Juri-Gagarin-Ring.JPG","description":"Stra\\u00dfenansicht des Parkhauses Q-Park am Kaufhaus Anger 1, schr\\u00e4g \\u00fcber den Juri-Gagarin-Ring","url":"https:\\/\\/cms.thuecat.org\\/o\\/adaptive-media\\/image\\/5197164\\/Preview-1280x0\\/image","author":"Florian Trykowski","copyrightYear":2020,"license":{"type":"https:\\/\\/creativecommons.org\\/licenses\\/by\\/4.0\\/","author":""}}]', + 'sanitation' => 'Toilets', + 'other_service' => 'ZeroOtherServiceEnumMem', + 'traffic_infrastructure' => '', + 'payment_accepted' => '', + 'distance_to_public_transport' => '120:MTR', + ], + 4 => [ + 'uid' => '5', + 'pid' => '10', + 'sys_language_uid' => '1', + 'l18n_parent' => '4', + 'l10n_source' => '4', + 'l10n_state' => null, + 'remote_id' => 'https://thuecat.org/resources/440055527204-ocar', + 'title' => 'Q-Park Anger 1 multi-storey car park', + 'description' => 'The Q-Park is located directly behind the department store Anger 1 in Erfurt\'s city centre and can be reached via Juri-Gagarin-Ring/Meyfartstraße.', + 'managed_by' => '1', + 'address' => '{"street":"Anger 1","zip":"99084","city":"Erfurt","email":"servicecenter@q-park.de","phone":"+49 218 18190290","fax":"","geo":{"latitude":50.977999330565794,"longitude":11.037503264052475}}', + 'offers' => '[{"types":["ParkingFee"],"title":"","description":"","prices":[{"title":"","description":"","price":2.2,"currency":"EUR","rule":"PerCar"}]},{"types":["ParkingFee"],"title":"","description":"","prices":[{"title":"","description":"","price":1,"currency":"EUR","rule":"PerCar"}]},{"types":["ParkingFee"],"title":"","description":"","prices":[{"title":"","description":"","price":13,"currency":"EUR","rule":"PerCar"}]}]', + 'media' => '[{"mainImage":true,"type":"image","title":"Q-Park-Parkhaus-Anger1-Juri-Gagarin-Ring.JPG","description":"Stra\\u00dfenansicht des Parkhauses Q-Park am Kaufhaus Anger 1, schr\\u00e4g \\u00fcber den Juri-Gagarin-Ring","url":"https:\\/\\/cms.thuecat.org\\/o\\/adaptive-media\\/image\\/5197164\\/Preview-1280x0\\/image","author":"Florian Trykowski","copyrightYear":2020,"license":{"type":"https:\\/\\/creativecommons.org\\/licenses\\/by\\/4.0\\/","author":""}}]', + 'sanitation' => 'Toilets', + 'other_service' => 'ZeroOtherServiceEnumMem', + 'traffic_infrastructure' => '', + 'payment_accepted' => '', + 'distance_to_public_transport' => '120:MTR', + ], + 5 => [ + 'uid' => '6', + 'pid' => '10', + 'sys_language_uid' => '2', + 'l18n_parent' => '4', + 'l10n_source' => '4', + 'l10n_state' => null, + 'remote_id' => 'https://thuecat.org/resources/440055527204-ocar', + 'title' => 'Q-Park Anger 1 parking à étages', + 'description' => 'Le Q-Park est situé directement derrière le grand magasin Anger 1 dans le centre-ville d\'Erfurt et peut être atteint par la Juri-Gagarin-Ring/Meyfartstraße.', + 'managed_by' => '1', + 'address' => '{"street":"Anger 1","zip":"99084","city":"Erfurt","email":"servicecenter@q-park.de","phone":"+49 218 18190290","fax":"","geo":{"latitude":50.977999330565794,"longitude":11.037503264052475}}', + 'offers' => '[{"types":["ParkingFee"],"title":"","description":"","prices":[{"title":"","description":"","price":2.2,"currency":"EUR","rule":"PerCar"}]},{"types":["ParkingFee"],"title":"","description":"","prices":[{"title":"","description":"","price":1,"currency":"EUR","rule":"PerCar"}]},{"types":["ParkingFee"],"title":"","description":"","prices":[{"title":"","description":"","price":13,"currency":"EUR","rule":"PerCar"}]}]', + 'media' => '[{"mainImage":true,"type":"image","title":"Q-Park-Parkhaus-Anger1-Juri-Gagarin-Ring.JPG","description":"Stra\\u00dfenansicht des Parkhauses Q-Park am Kaufhaus Anger 1, schr\\u00e4g \\u00fcber den Juri-Gagarin-Ring","url":"https:\\/\\/cms.thuecat.org\\/o\\/adaptive-media\\/image\\/5197164\\/Preview-1280x0\\/image","author":"Florian Trykowski","copyrightYear":2020,"license":{"type":"https:\\/\\/creativecommons.org\\/licenses\\/by\\/4.0\\/","author":""}}]', + 'sanitation' => 'Toilets', + 'other_service' => 'ZeroOtherServiceEnumMem', + 'traffic_infrastructure' => '', + 'payment_accepted' => '', + 'distance_to_public_transport' => '120:MTR', + ], + ], + 'tx_thuecat_organisation' => [ + 0 => [ + 'uid' => '1', + 'pid' => '10', + 'remote_id' => 'https://thuecat.org/resources/018132452787-ngbe', + 'title' => 'Erfurt Tourismus und Marketing GmbH', + 'description' => 'Die Erfurt Tourismus & Marketing GmbH (ETMG) wurde 1997 als offizielle Organisation zur Tourismusförderung in der Landeshauptstadt Erfurt gegründet und nahm am 01.01.1998 die Geschäftstätigkeit auf. + +Zu den Aufgaben zählen die kommunale Tourismusförderung als wesentliches Instrument der Wirtschafts- und Stadtentwicklung der Landeshauptstadt Erfurt, die Positionierung der Stadt Erfurt auf dem nationalen und internationalen Tourismusmarkt als dynamische und sympathische Landeshauptstadt, attraktives Städtereiseziel und Tagungsstandort, die Vervollkommnung des touristischen Serviceangebotes entsprechend den Bedürfnissen der individuellen Gäste und der Tourismuswirtschaft und das Betreiben der Erfurt Tourist Information. + +Im Januar 2009 wurde das Marketing für die Landeshauptstadt Erfurt an die ETMG übertragen und neu geordnet. Die Hauptaufgaben im Stadtmarketing liegen darin, die Wahrnehmung der Stadt in folgenden Bereichen zu verstärken: traditionsreicher und innovativer Wirtschaftsstandort, lebendiger und kreativer Wissenschaftsstandort, attraktiver Wohnstandort mit Flair und Sportstandort mit exzellenten Bedingungen für Nachwuchs- und Spitzensportler. + +Gesellschafter: Stadt Erfurt + +Geschäftsführerin: Frau Dr. Carmen Hildebrandt + +Aufsichtsratsvorsitzender: Herr Dominik Kordon + +Mitarbeiter: ca. 30 Angestellte, 4 Auszubildende', + ], + ], +]; diff --git a/Tests/Functional/Assertions/Import/ImportsTouristAttractionsWithSpecialOpeningHours.php b/Tests/Functional/Assertions/Import/ImportsTouristAttractionsWithSpecialOpeningHours.php new file mode 100644 index 0000000..3be421f --- /dev/null +++ b/Tests/Functional/Assertions/Import/ImportsTouristAttractionsWithSpecialOpeningHours.php @@ -0,0 +1,28 @@ + [ + 0 => [ + 'uid' => '1', + 'pid' => '10', + 'sys_language_uid' => '0', + 'l18n_parent' => '0', + 'l10n_source' => '0', + 'remote_id' => 'https://thuecat.org/resources/835224016581-dara', + 'title' => 'Dom St. Marien', + 'special_opening_hours' => '[{"opens":"10:00:00","closes":"14:00:00","from":{"date":"2050-12-31 00:00:00.000000","timezone_type":3,"timezone":"UTC"},"through":{"date":"2050-12-31 00:00:00.000000","timezone_type":3,"timezone":"UTC"},"daysOfWeek":["Saturday"]}]', + ], + 1 => [ + 'uid' => '2', + 'pid' => '10', + 'sys_language_uid' => '1', + 'l18n_parent' => '1', + 'l10n_source' => '1', + 'remote_id' => 'https://thuecat.org/resources/835224016581-dara', + 'title' => 'Cathedral of St. Mary', + 'special_opening_hours' => '[{"opens":"10:00:00","closes":"14:00:00","from":{"date":"2050-12-31 00:00:00.000000","timezone_type":3,"timezone":"UTC"},"through":{"date":"2050-12-31 00:00:00.000000","timezone_type":3,"timezone":"UTC"},"daysOfWeek":["Saturday"]}]', + ], + ], +]; diff --git a/Tests/Functional/Assertions/Import/ImportsTouristInformationWithRelation.php b/Tests/Functional/Assertions/Import/ImportsTouristInformationWithRelation.php new file mode 100644 index 0000000..ed38a72 --- /dev/null +++ b/Tests/Functional/Assertions/Import/ImportsTouristInformationWithRelation.php @@ -0,0 +1,35 @@ + [ + 0 => [ + 'uid' => '1', + 'pid' => '10', + 'remote_id' => 'https://thuecat.org/resources/333039283321-xxwg', + 'title' => 'Erfurt Tourist Information', + 'description' => 'Direkt an der Krämerbrücke liegt die Erfurter Tourist Information. Nach einer Modernisierung im Frühjahr 2017 erstrahlt diese in neuem Glanz und ist auch technisch auf dem neuesten Stand. Hier erhalten Sie Stadtpläne, Broschüren zu Erfurt und originelle Souvenirs. Zudem bietet die Tourist Information vielfältige Stadtführungen und Rundfahrten mit Straßenbahn oder Bus sowie kompetente Beratung zu Hotels, Pensionen und Privatunterkünften.', + 'managed_by' => '1', + 'town' => '1', + ], + ], + 'tx_thuecat_town' => [ + 0 => [ + 'uid' => '1', + 'pid' => '10', + 'remote_id' => 'https://thuecat.org/resources/043064193523-jcyt', + 'title' => 'Erfurt', + 'description' => 'Krämerbrücke, Dom, Alte Synagoge – die Thüringer Landeshauptstadt Erfurt hat viele Kulturschätze. Und ein wunderbar junges, studentisches Flair.Eine gute Mischung für alle, die beim Schlendern und Bummeln gerne Städte entdecken: Denn in Erfurt findet man einen wunderbaren mittelalterlichen Stadtkern – mit vielen netten Läden, Cafès und Restaurants. Urlauber wie Einheimische bummeln durch die Gassen der Altstadt, aus allen Ecken wispern Geschichte und alte Geschichten. Stolze historische Bügerhäuser bilden eine der schönsten Altstädte Europas, mittendrin das neugotische Rathaus aus den 1870er-Jahren am Fischmarkt, die spitztürmige St. Severikirche und der mächtige Dom, 1117 erstmals urkundlich erwähnt – auf seiner schier endlosen, kaskadenförmigen Freitreppe chillen Jung und Alt gern in der Abendsonne. Ehe sie weiter ziehen zum Tagesausklang in eine der coolen Kneipen und Bars (Tipp: Oma Lilo oder Cafè Hilgenfeld), in die Wein-Destille am benachbarten Petersberg oder in eins der lässigen Restaurants (Tipp: Mathilda oder Ballenberger), wo zum freundlichen Miteinander eine frische und moderne Küche serviert wird.In Erfurt pulsiert das Leben, lassen Sie sich einfach treiben. Von Ihrer Neugierde ...', + 'managed_by' => '1', + ], + ], + 'tx_thuecat_organisation' => [ + 0 => [ + 'uid' => '1', + 'pid' => '10', + 'remote_id' => 'https://thuecat.org/resources/018132452787-ngbe', + 'title' => 'Erfurt Tourismus und Marketing GmbH', + ], + ], +]; diff --git a/Tests/Functional/Assertions/Import/ImportsTown.php b/Tests/Functional/Assertions/Import/ImportsTown.php new file mode 100644 index 0000000..1e422c1 --- /dev/null +++ b/Tests/Functional/Assertions/Import/ImportsTown.php @@ -0,0 +1,24 @@ + [ + 0 => [ + 'uid' => '1', + 'pid' => '10', + 'remote_id' => 'https://thuecat.org/resources/043064193523-jcyt', + 'title' => 'Erfurt', + 'description' => 'Krämerbrücke, Dom, Alte Synagoge – die Thüringer Landeshauptstadt Erfurt hat viele Kulturschätze. Und ein wunderbar junges, studentisches Flair.Eine gute Mischung für alle, die beim Schlendern und Bummeln gerne Städte entdecken: Denn in Erfurt findet man einen wunderbaren mittelalterlichen Stadtkern – mit vielen netten Läden, Cafès und Restaurants. Urlauber wie Einheimische bummeln durch die Gassen der Altstadt, aus allen Ecken wispern Geschichte und alte Geschichten. Stolze historische Bügerhäuser bilden eine der schönsten Altstädte Europas, mittendrin das neugotische Rathaus aus den 1870er-Jahren am Fischmarkt, die spitztürmige St. Severikirche und der mächtige Dom, 1117 erstmals urkundlich erwähnt – auf seiner schier endlosen, kaskadenförmigen Freitreppe chillen Jung und Alt gern in der Abendsonne. Ehe sie weiter ziehen zum Tagesausklang in eine der coolen Kneipen und Bars (Tipp: Oma Lilo oder Cafè Hilgenfeld), in die Wein-Destille am benachbarten Petersberg oder in eins der lässigen Restaurants (Tipp: Mathilda oder Ballenberger), wo zum freundlichen Miteinander eine frische und moderne Küche serviert wird.In Erfurt pulsiert das Leben, lassen Sie sich einfach treiben. Von Ihrer Neugierde ...', + 'managed_by' => '1', + ], + ], + 'tx_thuecat_organisation' => [ + 0 => [ + 'uid' => '1', + 'pid' => '10', + 'remote_id' => 'https://thuecat.org/resources/018132452787-ngbe', + 'title' => 'Erfurt Tourismus und Marketing GmbH', + ], + ], +]; diff --git a/Tests/Functional/Assertions/Import/ImportsTownWithRelation.php b/Tests/Functional/Assertions/Import/ImportsTownWithRelation.php new file mode 100644 index 0000000..1e422c1 --- /dev/null +++ b/Tests/Functional/Assertions/Import/ImportsTownWithRelation.php @@ -0,0 +1,24 @@ + [ + 0 => [ + 'uid' => '1', + 'pid' => '10', + 'remote_id' => 'https://thuecat.org/resources/043064193523-jcyt', + 'title' => 'Erfurt', + 'description' => 'Krämerbrücke, Dom, Alte Synagoge – die Thüringer Landeshauptstadt Erfurt hat viele Kulturschätze. Und ein wunderbar junges, studentisches Flair.Eine gute Mischung für alle, die beim Schlendern und Bummeln gerne Städte entdecken: Denn in Erfurt findet man einen wunderbaren mittelalterlichen Stadtkern – mit vielen netten Läden, Cafès und Restaurants. Urlauber wie Einheimische bummeln durch die Gassen der Altstadt, aus allen Ecken wispern Geschichte und alte Geschichten. Stolze historische Bügerhäuser bilden eine der schönsten Altstädte Europas, mittendrin das neugotische Rathaus aus den 1870er-Jahren am Fischmarkt, die spitztürmige St. Severikirche und der mächtige Dom, 1117 erstmals urkundlich erwähnt – auf seiner schier endlosen, kaskadenförmigen Freitreppe chillen Jung und Alt gern in der Abendsonne. Ehe sie weiter ziehen zum Tagesausklang in eine der coolen Kneipen und Bars (Tipp: Oma Lilo oder Cafè Hilgenfeld), in die Wein-Destille am benachbarten Petersberg oder in eins der lässigen Restaurants (Tipp: Mathilda oder Ballenberger), wo zum freundlichen Miteinander eine frische und moderne Küche serviert wird.In Erfurt pulsiert das Leben, lassen Sie sich einfach treiben. Von Ihrer Neugierde ...', + 'managed_by' => '1', + ], + ], + 'tx_thuecat_organisation' => [ + 0 => [ + 'uid' => '1', + 'pid' => '10', + 'remote_id' => 'https://thuecat.org/resources/018132452787-ngbe', + 'title' => 'Erfurt Tourismus und Marketing GmbH', + ], + ], +]; diff --git a/Tests/Functional/Fixtures/Frontend/Content.php b/Tests/Functional/Fixtures/Frontend/Content.php new file mode 100644 index 0000000..719137f --- /dev/null +++ b/Tests/Functional/Fixtures/Frontend/Content.php @@ -0,0 +1,96 @@ + [ + 0 => [ + 'uid' => '1', + 'pid' => '0', + 'title' => 'Root', + 'doktype' => PageRepository::DOKTYPE_DEFAULT, + 'slug' => '/', + 'sorting' => '128', + 'deleted' => '0', + ], + 1 => [ + 'uid' => '2', + 'pid' => '1', + 'title' => 'Tourist Attraction', + 'doktype' => PageRepository::DOKTYPE_DEFAULT, + 'slug' => '/example-attraction/', + 'sorting' => '128', + 'deleted' => '0', + ], + 2 => [ + 'uid' => '3', + 'pid' => '1', + 'title' => 'Storage', + 'doktype' => PageRepository::DOKTYPE_SYSFOLDER, + 'sorting' => '128', + 'deleted' => '0', + ], + 3 => [ + 'uid' => '4', + 'pid' => '1', + 'title' => 'Tourist Attraction false', + 'slug' => '/example-attraction-false/', + 'sorting' => '128', + 'deleted' => '0', + ], + 4 => [ + 'uid' => '5', + 'pid' => '1', + 'title' => 'Tourist Attraction true', + 'slug' => '/example-attraction-true/', + 'sorting' => '128', + 'deleted' => '0', + ], + ], + 'tt_content' => [ + 0 => [ + 'uid' => '2', + 'pid' => '2', + 'hidden' => '0', + 'sorting' => '1', + 'CType' => 'thuecat_tourist_attraction', + 'header' => 'Show Example Tourist Attraction', + 'deleted' => '0', + 'starttime' => '0', + 'endtime' => '0', + 'colPos' => '0', + 'sys_language_uid' => '0', + 'records' => '1', + ], + 1 => [ + 'uid' => '3', + 'pid' => '4', + 'hidden' => '0', + 'sorting' => '1', + 'CType' => 'thuecat_tourist_attraction', + 'header' => 'Show Example Tourist Attraction with false', + 'deleted' => '0', + 'starttime' => '0', + 'endtime' => '0', + 'colPos' => '0', + 'sys_language_uid' => '0', + 'records' => '2', + ], + 2 => [ + 'uid' => '4', + 'pid' => '5', + 'hidden' => '0', + 'sorting' => '1', + 'CType' => 'thuecat_tourist_attraction', + 'header' => 'Show Example Tourist Attraction with true', + 'deleted' => '0', + 'starttime' => '0', + 'endtime' => '0', + 'colPos' => '0', + 'sys_language_uid' => '0', + 'records' => '3', + ], + ], +]; diff --git a/Tests/Functional/Fixtures/Frontend/Content.xml b/Tests/Functional/Fixtures/Frontend/Content.xml deleted file mode 100644 index e04ae05..0000000 --- a/Tests/Functional/Fixtures/Frontend/Content.xml +++ /dev/null @@ -1,86 +0,0 @@ - - - - 1 - 0 - Root - / - 128 - 0 - - - 2 - 1 - Tourist Attraction - /example-attraction/ - 128 - 0 - - - 3 - 1 - Storage - 254 - 128 - 0 - - - 4 - 1 - Tourist Attraction false - /example-attraction-false/ - 128 - 0 - - - 5 - 1 - Tourist Attraction true - /example-attraction-true/ - 128 - 0 - - - 2 - 2 - 0 - 1 - thuecat_tourist_attraction -
Show Example Tourist Attraction
- 0 - 0 - 0 - 0 - 0 - 1 -
- - 3 - 4 - 0 - 1 - thuecat_tourist_attraction -
Show Example Tourist Attraction with false
- 0 - 0 - 0 - 0 - 0 - 2 -
- - 4 - 5 - 0 - 1 - thuecat_tourist_attraction -
Show Example Tourist Attraction with true
- 0 - 0 - 0 - 0 - 0 - 3 -
-
- diff --git a/Tests/Functional/Fixtures/Frontend/SecondTouristAttraction.php b/Tests/Functional/Fixtures/Frontend/SecondTouristAttraction.php new file mode 100644 index 0000000..9b4dedb --- /dev/null +++ b/Tests/Functional/Fixtures/Frontend/SecondTouristAttraction.php @@ -0,0 +1,35 @@ + [ + 0 => [ + 'uid' => '2', + 'pid' => '3', + 'title' => 'Eine weitere Attraktion', + 'description' => 'Die Beschreibung der Attraktion', + 'town' => '1', + 'media' => '[{"mainImage":true,"type":"image","title":"Erfurt-Dom und Severikirche-beleuchtet.jpg","description":"","url":"https:\\/\\/cms.thuecat.org\\/o\\/adaptive-media\\/image\\/5159216\\/Preview-1280x0\\/image","copyrightYear":2016,"author":"Image Author","license":{"type":"https:\\/\\/creativecommons.org\\/licenses\\/by\\/4.0\\/","author":""}},{"mainImage":false,"type":"image","title":"Erfurt-Dom-und-Severikirche.jpg","description":"Sicht auf Dom St. Marien, St. Severikirche sowie die davor liegenden Klostergeb\\u00e4ude und einem Ausschnitt des Biergartens umgeben von einem d\\u00e4mmerungsverf\\u00e4rten Himmel","url":"https:\\/\\/cms.thuecat.org\\/o\\/adaptive-media\\/image\\/5159186\\/Preview-1280x0\\/image","copyrightYear":2020,"license":{"type":"https:\\/\\/creativecommons.org\\/licenses\\/by\\/4.0\\/","author":""}},{"mainImage":false,"type":"image","title":"Erfurt-Dom und Severikirche-beleuchtet.jpg","description":"","url":"https:\\/\\/cms.thuecat.org\\/o\\/adaptive-media\\/image\\/5159216\\/Preview-1280x0\\/image","copyrightYear":2016,"license":{"type":"https:\\/\\/creativecommons.org\\/licenses\\/by\\/4.0\\/","author":""}}]', + 'opening_hours' => '[{"opens":"09:30:00","closes":"18:00:00","from":{"date":"2021-05-01 00:00:00.000000","timezone_type":3,"timezone":"UTC"},"through":{"date":"2021-10-31 00:00:00.000000","timezone_type":3,"timezone":"UTC"},"daysOfWeek":["Saturday","Friday","Thursday","Tuesday","Monday","Wednesday"]},{"opens":"13:00:00","closes":"18:00:00","from":{"date":"2021-05-01 00:00:00.000000","timezone_type":3,"timezone":"UTC"},"through":{"date":"2021-10-31 00:00:00.000000","timezone_type":3,"timezone":"UTC"},"daysOfWeek":["Sunday"]},{"opens":"09:30:00","closes":"17:00:00","from":{"date":"2021-11-01 00:00:00.000000","timezone_type":3,"timezone":"UTC"},"through":{"date":"2022-04-30 00:00:00.000000","timezone_type":3,"timezone":"UTC"},"daysOfWeek":["Saturday","Friday","Thursday","Tuesday","Monday","Wednesday"]},{"opens":"13:00:00","closes":"17:00:00","from":{"date":"2021-11-01 00:00:00.000000","timezone_type":3,"timezone":"UTC"},"through":{"date":"2022-04-30 00:00:00.000000","timezone_type":3,"timezone":"UTC"},"daysOfWeek":["Sunday","PublicHolidays"]}]', + 'address' => '{"street":"Beispielstraße 1a","zip":"99084","city":"Beispielstadt","email":"example@example.com","phone":"(0)30 23125 000","fax":"","geo":{"latitude":50.975955358589545,"longitude":11.023667024961856}}', + 'url' => 'https://example.com/attraction', + 'offers' => '[{"type":"GuidedTourOffer","title":"F\\u00fchrungen","description":"Immer samstags, um 11:15 Uhr findet eine \\u00f6ffentliche F\\u00fchrung durch das Museum statt. Dauer etwa 90 Minuten","prices":[{"title":"Erwachsene","description":"","price":8,"currency":"EUR","rule":"PerPerson"},{"title":"Erm\\u00e4\\u00dfigt","description":"als erm\\u00e4\\u00dfigt gelten schulpflichtige Kinder, Auszubildende, Studierende, Rentner\\/-innen, Menschen mit Behinderungen, Inhaber Sozialausweis der Landeshauptstadt Erfurt","price":5,"currency":"EUR","rule":"PerPerson"}]},{"type":"EntryOffer","title":"Eintritt","description":"Schulklassen und Kitagruppen im Rahmen des Unterrichts: Eintritt frei\\nAn jedem ersten Dienstag im Monat: Eintritt frei","prices":[{"title":"Erm\\u00e4\\u00dfigt","description":"als erm\\u00e4\\u00dfigt gelten schulpflichtige Kinder, Auszubildende, Studierende, Rentner\\/-innen, Menschen mit Behinderungen, Inhaber Sozialausweis der Landeshauptstadt Erfurt","price":5,"currency":"EUR","rule":"PerPerson"},{"title":"Familienkarte","description":"","price":17,"currency":"EUR","rule":"PerGroup"},{"title":"ErfurtCard","description":"","price":14.9,"currency":"EUR","rule":"PerPackage"},{"title":"Erwachsene","description":"","price":8,"currency":"EUR","rule":"PerPerson"}]}]', + 'slogan' => 'Highlight', + 'start_of_construction' => '11. Jh', + 'sanitation' => 'Toilets,DisabledToilets,NappyChangingArea,FamilyAndChildFriendly', + 'other_service' => 'Playground,SeatingPossibilitiesRestArea,SouvenirShop,PlayCornerOrPlayArea', + 'museum_service' => 'MuseumShop,PedagogicalOffer,ZeroInformationMuseumService', + 'architectural_style' => 'ArchitectureOfHomelandSecurity,ArtDeco,ArtNouveau,Baroque,BauhausStyle,Brutalism,Classicism,Constructivism,CriticalRegionalism,Deconstructivism,Expressionism,Functionalism,GothicArt,GothicRevival,HighTechArchitecture,Historicism,InternationalStyle,Minimalism,Modernism,Neoclassicism,Neorenaissance,NewBuilding,NewObjectivity,OrganicConstruction,PostWarModernism,PostmodernAge,Rationalism,Renaissance,Rococo,RomanesquePeriod,ZeroInformationArchitecturalStyle', + 'traffic_infrastructure' => 'BicycleLockersEnumMem,BicycleStandsEnumMem,BicycleStandsBicycleLockersEnumMem,BusParkCoachParkEnumMem,EbikeChargingStationEnumMem,ElectricVehicleCarChargingStationEnumMem,ZeroSpecialTrafficInfrastructure', + 'payment_accepted' => 'AliPay,AmericanExpress,ApplePay,CashPayment,EC,InstantBankTransfer,Invoice,MasterCard,PayPal,Visa', + 'digital_offer' => 'AppForMobileDevices,AudioGuide,AugmentedReality,VideoGuide,VirtuellReality,ZeroDigitalOffer', + 'photography' => 'PhotoLicenceFeeRequired,TakingPicturesPermitted,ZeroPhotography,some free text value for photography', + 'pets_allowed' => 'Tiere sind im Gebäude nicht gestattet, ausgenommen sind Blinden- und Blindenbegleithunde.', + 'available_languages' => 'German,English,French', + 'distance_to_public_transport' => '250:MTR', + 'parking_facility_near_by' => '1,2', + 'accessibility_specification' => '{"accessibilityCertificationStatus":"AccessibilityChecked","accessibilitySearchCriteria":{"facilityAccessibilityDeaf":["AudioInductionLoop","FlashingSignalCallWaitingDoor","SpecialOffersDeafPeople","SpecialOffersHearingImpairment","VisualConfirmationDistressCallElevator"],"facilityAccessibilityMental":["ColoredOrPictorialGuidanceSystem","InformationInEasyLanguage","InformationWithPictogramsOrPictures"],"facilityAccessibilityVisual":["AssistanceDogsWelcome","GuidanceSystemWithFloorIndicators","InformationBrailleOrPrismaticFont","OffersInPictoralLanguage","SpecialOffersBlindPeople","SpecialOffersVisualImpairment","TactileOffers","VisuallyContrastingStepEdges"],"facilityAccessibilityWalking":["AllRoomsStepFreeAccess","EightyCMWidthPassageWays","EntryAidSwimmingPool","GrabRailInShower","HandrailsOnBothSidesOfAllStaircases","HingedGrabRailToilet","LateralAccessibleToilet","MinumumManoeuvringSpaceShower","NinetyCMWidthPassageWays","NursingBed","ParkingPeopleWithDisabilities","SeventyCMWidthPassageWays","ShowerSeat","SpecialOffersWalkingImpairment","SpecialOffersWheelchairUsers","StepFreeAccess","StepFreeShower","ToiletsPeopleWithDisabilities"]},"certificationAccessibilityDeaf":"Full","certificationAccessibilityMental":"None","certificationAccessibilityPartiallyDeaf":"None","certificationAccessibilityPartiallyVisual":"Info","certificationAccessibilityVisual":"None","certificationAccessibilityWalking":"Info","certificationAccessibilityWheelchair":"Info","shortDescriptionAccessibilityAllGenerations":"Deutsche Beschreibung von shortDescriptionAccessibilityAllGenerations","shortDescriptionAccessibilityAllergic":"Deutsche Beschreibung von shortDescriptionAccessibilityAllergic","shortDescriptionAccessibilityDeaf":"Deutsche Beschreibung von shortDescriptionAccessibilityDeaf","shortDescriptionAccessibilityMental":"Deutsche Beschreibung von shortDescriptionAccessibilityMental","shortDescriptionAccessibilityVisual":"Deutsche Beschreibung von shortDescriptionAccessibilityVisual","shortDescriptionAccessibilityWalking":"Deutsche Beschreibung von shortDescriptionAccessibilityWalking"}', + ], + ], +]; diff --git a/Tests/Functional/Fixtures/Frontend/SecondTouristAttraction.xml b/Tests/Functional/Fixtures/Frontend/SecondTouristAttraction.xml deleted file mode 100644 index 8ec52b8..0000000 --- a/Tests/Functional/Fixtures/Frontend/SecondTouristAttraction.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - 2 - 3 - Eine weitere Attraktion - Die Beschreibung der Attraktion - 1 - [{"mainImage":true,"type":"image","title":"Erfurt-Dom und Severikirche-beleuchtet.jpg","description":"","url":"https:\/\/cms.thuecat.org\/o\/adaptive-media\/image\/5159216\/Preview-1280x0\/image","copyrightYear":2016,"author":"Image Author","license":{"type":"https:\/\/creativecommons.org\/licenses\/by\/4.0\/","author":""}},{"mainImage":false,"type":"image","title":"Erfurt-Dom-und-Severikirche.jpg","description":"Sicht auf Dom St. Marien, St. Severikirche sowie die davor liegenden Klostergeb\u00e4ude und einem Ausschnitt des Biergartens umgeben von einem d\u00e4mmerungsverf\u00e4rten Himmel","url":"https:\/\/cms.thuecat.org\/o\/adaptive-media\/image\/5159186\/Preview-1280x0\/image","copyrightYear":2020,"license":{"type":"https:\/\/creativecommons.org\/licenses\/by\/4.0\/","author":""}},{"mainImage":false,"type":"image","title":"Erfurt-Dom und Severikirche-beleuchtet.jpg","description":"","url":"https:\/\/cms.thuecat.org\/o\/adaptive-media\/image\/5159216\/Preview-1280x0\/image","copyrightYear":2016,"license":{"type":"https:\/\/creativecommons.org\/licenses\/by\/4.0\/","author":""}}] - [{"opens":"09:30:00","closes":"18:00:00","from":{"date":"2021-05-01 00:00:00.000000","timezone_type":3,"timezone":"UTC"},"through":{"date":"2021-10-31 00:00:00.000000","timezone_type":3,"timezone":"UTC"},"daysOfWeek":["Saturday","Friday","Thursday","Tuesday","Monday","Wednesday"]},{"opens":"13:00:00","closes":"18:00:00","from":{"date":"2021-05-01 00:00:00.000000","timezone_type":3,"timezone":"UTC"},"through":{"date":"2021-10-31 00:00:00.000000","timezone_type":3,"timezone":"UTC"},"daysOfWeek":["Sunday"]},{"opens":"09:30:00","closes":"17:00:00","from":{"date":"2021-11-01 00:00:00.000000","timezone_type":3,"timezone":"UTC"},"through":{"date":"2022-04-30 00:00:00.000000","timezone_type":3,"timezone":"UTC"},"daysOfWeek":["Saturday","Friday","Thursday","Tuesday","Monday","Wednesday"]},{"opens":"13:00:00","closes":"17:00:00","from":{"date":"2021-11-01 00:00:00.000000","timezone_type":3,"timezone":"UTC"},"through":{"date":"2022-04-30 00:00:00.000000","timezone_type":3,"timezone":"UTC"},"daysOfWeek":["Sunday","PublicHolidays"]}] -
{"street":"Beispielstraße 1a","zip":"99084","city":"Beispielstadt","email":"example@example.com","phone":"(0)30 23125 000","fax":"","geo":{"latitude":50.975955358589545,"longitude":11.023667024961856}}
- https://example.com/attraction - [{"type":"GuidedTourOffer","title":"F\u00fchrungen","description":"Immer samstags, um 11:15 Uhr findet eine \u00f6ffentliche F\u00fchrung durch das Museum statt. Dauer etwa 90 Minuten","prices":[{"title":"Erwachsene","description":"","price":8,"currency":"EUR","rule":"PerPerson"},{"title":"Erm\u00e4\u00dfigt","description":"als erm\u00e4\u00dfigt gelten schulpflichtige Kinder, Auszubildende, Studierende, Rentner\/-innen, Menschen mit Behinderungen, Inhaber Sozialausweis der Landeshauptstadt Erfurt","price":5,"currency":"EUR","rule":"PerPerson"}]},{"type":"EntryOffer","title":"Eintritt","description":"Schulklassen und Kitagruppen im Rahmen des Unterrichts: Eintritt frei\nAn jedem ersten Dienstag im Monat: Eintritt frei","prices":[{"title":"Erm\u00e4\u00dfigt","description":"als erm\u00e4\u00dfigt gelten schulpflichtige Kinder, Auszubildende, Studierende, Rentner\/-innen, Menschen mit Behinderungen, Inhaber Sozialausweis der Landeshauptstadt Erfurt","price":5,"currency":"EUR","rule":"PerPerson"},{"title":"Familienkarte","description":"","price":17,"currency":"EUR","rule":"PerGroup"},{"title":"ErfurtCard","description":"","price":14.9,"currency":"EUR","rule":"PerPackage"},{"title":"Erwachsene","description":"","price":8,"currency":"EUR","rule":"PerPerson"}]}] - Highlight - 11. Jh - Toilets,DisabledToilets,NappyChangingArea,FamilyAndChildFriendly - Playground,SeatingPossibilitiesRestArea,SouvenirShop,PlayCornerOrPlayArea - MuseumShop,PedagogicalOffer,ZeroInformationMuseumService - ArchitectureOfHomelandSecurity,ArtDeco,ArtNouveau,Baroque,BauhausStyle,Brutalism,Classicism,Constructivism,CriticalRegionalism,Deconstructivism,Expressionism,Functionalism,GothicArt,GothicRevival,HighTechArchitecture,Historicism,InternationalStyle,Minimalism,Modernism,Neoclassicism,Neorenaissance,NewBuilding,NewObjectivity,OrganicConstruction,PostWarModernism,PostmodernAge,Rationalism,Renaissance,Rococo,RomanesquePeriod,ZeroInformationArchitecturalStyle - BicycleLockersEnumMem,BicycleStandsEnumMem,BicycleStandsBicycleLockersEnumMem,BusParkCoachParkEnumMem,EbikeChargingStationEnumMem,ElectricVehicleCarChargingStationEnumMem,ZeroSpecialTrafficInfrastructure - AliPay,AmericanExpress,ApplePay,CashPayment,EC,InstantBankTransfer,Invoice,MasterCard,PayPal,Visa - AppForMobileDevices,AudioGuide,AugmentedReality,VideoGuide,VirtuellReality,ZeroDigitalOffer - PhotoLicenceFeeRequired,TakingPicturesPermitted,ZeroPhotography,some free text value for photography - Tiere sind im Gebäude nicht gestattet, ausgenommen sind Blinden- und Blindenbegleithunde. - German,English,French - 250:MTR - 1,2 - {"accessibilityCertificationStatus":"AccessibilityChecked","accessibilitySearchCriteria":{"facilityAccessibilityDeaf":["AudioInductionLoop","FlashingSignalCallWaitingDoor","SpecialOffersDeafPeople","SpecialOffersHearingImpairment","VisualConfirmationDistressCallElevator"],"facilityAccessibilityMental":["ColoredOrPictorialGuidanceSystem","InformationInEasyLanguage","InformationWithPictogramsOrPictures"],"facilityAccessibilityVisual":["AssistanceDogsWelcome","GuidanceSystemWithFloorIndicators","InformationBrailleOrPrismaticFont","OffersInPictoralLanguage","SpecialOffersBlindPeople","SpecialOffersVisualImpairment","TactileOffers","VisuallyContrastingStepEdges"],"facilityAccessibilityWalking":["AllRoomsStepFreeAccess","EightyCMWidthPassageWays","EntryAidSwimmingPool","GrabRailInShower","HandrailsOnBothSidesOfAllStaircases","HingedGrabRailToilet","LateralAccessibleToilet","MinumumManoeuvringSpaceShower","NinetyCMWidthPassageWays","NursingBed","ParkingPeopleWithDisabilities","SeventyCMWidthPassageWays","ShowerSeat","SpecialOffersWalkingImpairment","SpecialOffersWheelchairUsers","StepFreeAccess","StepFreeShower","ToiletsPeopleWithDisabilities"]},"certificationAccessibilityDeaf":"Full","certificationAccessibilityMental":"None","certificationAccessibilityPartiallyDeaf":"None","certificationAccessibilityPartiallyVisual":"Info","certificationAccessibilityVisual":"None","certificationAccessibilityWalking":"Info","certificationAccessibilityWheelchair":"Info","shortDescriptionAccessibilityAllGenerations":"Deutsche Beschreibung von shortDescriptionAccessibilityAllGenerations","shortDescriptionAccessibilityAllergic":"Deutsche Beschreibung von shortDescriptionAccessibilityAllergic","shortDescriptionAccessibilityDeaf":"Deutsche Beschreibung von shortDescriptionAccessibilityDeaf","shortDescriptionAccessibilityMental":"Deutsche Beschreibung von shortDescriptionAccessibilityMental","shortDescriptionAccessibilityVisual":"Deutsche Beschreibung von shortDescriptionAccessibilityVisual","shortDescriptionAccessibilityWalking":"Deutsche Beschreibung von shortDescriptionAccessibilityWalking"} -
-
- diff --git a/Tests/Functional/Fixtures/Frontend/TouristAttractionWithEditorialImages.php b/Tests/Functional/Fixtures/Frontend/TouristAttractionWithEditorialImages.php new file mode 100644 index 0000000..4e3bb12 --- /dev/null +++ b/Tests/Functional/Fixtures/Frontend/TouristAttractionWithEditorialImages.php @@ -0,0 +1,60 @@ + [ + 0 => [ + 'uid' => '1', + 'pid' => '3', + 'title' => 'Attraktion mit redaktionellen Bildern', + 'editorial_images' => '2', + ], + ], + 'sys_file_reference' => [ + 0 => [ + 'uid' => '1', + 'uid_local' => '1', + 'uid_foreign' => '1', + 'tablenames' => 'tx_thuecat_tourist_attraction', + 'fieldname' => 'editorial_images', + 'sorting_foreign' => '1', + ], + 1 => [ + 'uid' => '2', + 'uid_local' => '2', + 'uid_foreign' => '1', + 'tablenames' => 'tx_thuecat_tourist_attraction', + 'fieldname' => 'editorial_images', + 'sorting_foreign' => '2', + ], + ], + 'sys_file' => [ + 0 => [ + 'uid' => '1', + 'type' => '2', + 'storage' => '1', + 'identifier' => '/tourismus/images/inhalte/sehenswertes/parks_gaerten/hirschgarten/2998_Spielplaetze_Hirschgarten.jpg', + 'extension' => 'jpg', + 'mime_type' => 'image/jpeg', + 'name' => '2998_Spielplaetze_Hirschgarten.jpg', + 'sha1' => '61079cbeb5d13c21d20dbbcc2e28e9c8fa04b3b4', + 'size' => '7329219', + 'identifier_hash' => '69066cc9c3b5ff135a7daa36059b18c75b3d9a23', + 'folder_hash' => '4dd66a1c0a2a0ab89a22bfe734df75d9750d28f2', + ], + 1 => [ + 'uid' => '2', + 'type' => '2', + 'storage' => '1', + 'identifier' => '/tourismus/images/inhalte/sehenswertes/sehenswuerdigkeiten/Petersberg/20_Erfurt-Schriftzug_Petersberg_2021__c_Stadtverwaltung_Erfurt_CC-BY-NC-SA.JPG', + 'extension' => 'JPG', + 'mime_type' => 'image/jpeg', + 'name' => '20_Erfurt-Schriftzug_Petersberg_2021__c_Stadtverwaltung_Erfurt_CC-BY-NC-SA.JPG', + 'sha1' => 'f4c45d3c738d29162759ecd7d2dbc9af2a8f515f', + 'size' => '2807135', + 'identifier_hash' => '384f006a1452e901badb0db799fa7ff364e88a5e', + 'folder_hash' => '01086eae3464ef516edc0756ba3e12e35e09c33d', + ], + ], +]; diff --git a/Tests/Functional/Fixtures/Frontend/TouristAttractionWithEditorialImages.xml b/Tests/Functional/Fixtures/Frontend/TouristAttractionWithEditorialImages.xml deleted file mode 100644 index d7de1d0..0000000 --- a/Tests/Functional/Fixtures/Frontend/TouristAttractionWithEditorialImages.xml +++ /dev/null @@ -1,58 +0,0 @@ - - - - 1 - 3 - Attraktion mit redaktionellen Bildern - 2 - - - - 1 - 1 - 1 - tx_thuecat_tourist_attraction - editorial_images - 1 - sys_file - - - - 2 - 2 - 1 - tx_thuecat_tourist_attraction - editorial_images - 2 - sys_file - - - - 1 - 2 - 1 - /tourismus/images/inhalte/sehenswertes/parks_gaerten/hirschgarten/2998_Spielplaetze_Hirschgarten.jpg - jpg - image/jpeg - 2998_Spielplaetze_Hirschgarten.jpg - 61079cbeb5d13c21d20dbbcc2e28e9c8fa04b3b4 - 7329219 - 69066cc9c3b5ff135a7daa36059b18c75b3d9a23 - 4dd66a1c0a2a0ab89a22bfe734df75d9750d28f2 - - - - 2 - 2 - 1 - /tourismus/images/inhalte/sehenswertes/sehenswuerdigkeiten/Petersberg/20_Erfurt-Schriftzug_Petersberg_2021__c_Stadtverwaltung_Erfurt_CC-BY-NC-SA.JPG - JPG - image/jpeg - 20_Erfurt-Schriftzug_Petersberg_2021__c_Stadtverwaltung_Erfurt_CC-BY-NC-SA.JPG - f4c45d3c738d29162759ecd7d2dbc9af2a8f515f - 2807135 - 384f006a1452e901badb0db799fa7ff364e88a5e - 01086eae3464ef516edc0756ba3e12e35e09c33d - - - diff --git a/Tests/Functional/Fixtures/Frontend/TouristAttractionWithOfferTypes.php b/Tests/Functional/Fixtures/Frontend/TouristAttractionWithOfferTypes.php new file mode 100644 index 0000000..6800373 --- /dev/null +++ b/Tests/Functional/Fixtures/Frontend/TouristAttractionWithOfferTypes.php @@ -0,0 +1,14 @@ + [ + 0 => [ + 'uid' => '1', + 'pid' => '3', + 'title' => 'Attraktion mit Angebotstypen', + 'offers' => '[{"description":"","prices":[{"currency":"EUR","description":"","price":8,"rule":"PerGroup","title":"Schulklassen"}],"title":"Führungen","type":"GuidedTourOffer"},{"description":"","prices":[{"currency":"EUR","description":"","price":8,"rule":"PerGroup","title":"Schulklassen"}],"title":"Verkostung","type":"Tasting"},{"description":"","prices":[{"currency":"EUR","description":"","price":8,"rule":"PerGroup","title":"Schulklassen"}],"title":"Eintritt 1","type":"EntryOffer"},{"description":"","prices":[{"currency":"EUR","description":"","price":8,"rule":"PerGroup","title":"Schulklassen"}],"title":"Eintritt 2","type":"EntryOffer"},{"description":"","prices":[{"currency":"EUR","description":"","price":8,"rule":"PerGroup","title":"Schulklassen"}],"title":"Parkgebühr","type":"ParkingFee"}]', + ], + ], +]; diff --git a/Tests/Functional/Fixtures/Frontend/TouristAttractionWithOfferTypes.xml b/Tests/Functional/Fixtures/Frontend/TouristAttractionWithOfferTypes.xml deleted file mode 100644 index 26422a2..0000000 --- a/Tests/Functional/Fixtures/Frontend/TouristAttractionWithOfferTypes.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - 1 - 3 - Attraktion mit Angebotstypen - [{"description":"","prices":[{"currency":"EUR","description":"","price":8,"rule":"PerGroup","title":"Schulklassen"}],"title":"Führungen","type":"GuidedTourOffer"},{"description":"","prices":[{"currency":"EUR","description":"","price":8,"rule":"PerGroup","title":"Schulklassen"}],"title":"Verkostung","type":"Tasting"},{"description":"","prices":[{"currency":"EUR","description":"","price":8,"rule":"PerGroup","title":"Schulklassen"}],"title":"Eintritt 1","type":"EntryOffer"},{"description":"","prices":[{"currency":"EUR","description":"","price":8,"rule":"PerGroup","title":"Schulklassen"}],"title":"Eintritt 2","type":"EntryOffer"},{"description":"","prices":[{"currency":"EUR","description":"","price":8,"rule":"PerGroup","title":"Schulklassen"}],"title":"Parkgebühr","type":"ParkingFee"}] - - - diff --git a/Tests/Functional/Fixtures/Frontend/TouristAttractionWithPrices.php b/Tests/Functional/Fixtures/Frontend/TouristAttractionWithPrices.php new file mode 100644 index 0000000..0019477 --- /dev/null +++ b/Tests/Functional/Fixtures/Frontend/TouristAttractionWithPrices.php @@ -0,0 +1,14 @@ + [ + 0 => [ + 'uid' => '1', + 'pid' => '3', + 'title' => 'Attraktion mit Preisen', + 'offers' => '[{"prices":[{"currency":"EUR","description":"","price":8,"rule":"PerGroup","title":"Schulklassen"},{"currency":"EUR","description":"","price":8,"rule":"PerPerson","title":"Erwachsene"},{"currency":"EUR","description":"","price":5,"rule":"PerPerson","title":"Familienkarte B"},{"currency":"EUR","description":"","price":5,"rule":"PerPerson","title":"Familienkarte A"}],"description":"","title":"Führungen","type":"GuidedTourOffer"}]', + ], + ], +]; diff --git a/Tests/Functional/Fixtures/Frontend/TouristAttractionWithPrices.xml b/Tests/Functional/Fixtures/Frontend/TouristAttractionWithPrices.xml deleted file mode 100644 index 964911c..0000000 --- a/Tests/Functional/Fixtures/Frontend/TouristAttractionWithPrices.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - 1 - 3 - Attraktion mit Preisen - [{"prices":[{"currency":"EUR","description":"","price":8,"rule":"PerGroup","title":"Schulklassen"},{"currency":"EUR","description":"","price":8,"rule":"PerPerson","title":"Erwachsene"},{"currency":"EUR","description":"","price":5,"rule":"PerPerson","title":"Familienkarte B"},{"currency":"EUR","description":"","price":5,"rule":"PerPerson","title":"Familienkarte A"}],"description":"","title":"Führungen","type":"GuidedTourOffer"}] - - - diff --git a/Tests/Functional/Fixtures/Frontend/TouristAttractions.php b/Tests/Functional/Fixtures/Frontend/TouristAttractions.php new file mode 100644 index 0000000..586d425 --- /dev/null +++ b/Tests/Functional/Fixtures/Frontend/TouristAttractions.php @@ -0,0 +1,57 @@ + [ + 0 => [ + 'uid' => '1', + 'pid' => '3', + 'title' => 'Erste Attraktion', + 'description' => 'Die Beschreibung der Attraktion', + 'town' => '1', + 'media' => '[{"mainImage":true,"type":"image","title":"Erfurt-Dom und Severikirche-beleuchtet.jpg","description":"","url":"https:\\/\\/cms.thuecat.org\\/o\\/adaptive-media\\/image\\/5159216\\/Preview-1280x0\\/image","copyrightYear":2016,"author":"Image Author","license":{"type":"https:\\/\\/creativecommons.org\\/licenses\\/by\\/4.0\\/","author":""}},{"mainImage":false,"type":"image","title":"Erfurt-Dom-und-Severikirche.jpg","description":"Sicht auf Dom St. Marien, St. Severikirche sowie die davor liegenden Klostergeb\\u00e4ude und einem Ausschnitt des Biergartens umgeben von einem d\\u00e4mmerungsverf\\u00e4rten Himmel","url":"https:\\/\\/cms.thuecat.org\\/o\\/adaptive-media\\/image\\/5159186\\/Preview-1280x0\\/image","copyrightYear":2020,"license":{"type":"https:\\/\\/creativecommons.org\\/licenses\\/by\\/4.0\\/","author":""}},{"mainImage":false,"type":"image","title":"Erfurt-Dom und Severikirche-beleuchtet.jpg","description":"","url":"https:\\/\\/cms.thuecat.org\\/o\\/adaptive-media\\/image\\/5159216\\/Preview-1280x0\\/image","copyrightYear":2016,"license":{"type":"https:\\/\\/creativecommons.org\\/licenses\\/by\\/4.0\\/","author":""}}]', + 'opening_hours' => '[{"opens":"09:30:00","closes":"18:00:00","from":{"date":"2021-05-01 00:00:00.000000","timezone_type":3,"timezone":"UTC"},"through":{"date":"2021-10-31 00:00:00.000000","timezone_type":3,"timezone":"UTC"},"daysOfWeek":["Saturday","Friday","Thursday","Tuesday","Monday","Wednesday"]},{"opens":"13:00:00","closes":"18:00:00","from":{"date":"2021-05-01 00:00:00.000000","timezone_type":3,"timezone":"UTC"},"through":{"date":"2021-10-31 00:00:00.000000","timezone_type":3,"timezone":"UTC"},"daysOfWeek":["Sunday"]},{"opens":"09:30:00","closes":"17:00:00","from":{"date":"2021-11-01 00:00:00.000000","timezone_type":3,"timezone":"UTC"},"through":{"date":"2022-04-30 00:00:00.000000","timezone_type":3,"timezone":"UTC"},"daysOfWeek":["Saturday","Friday","Thursday","Tuesday","Monday","Wednesday"]},{"opens":"13:00:00","closes":"17:00:00","from":{"date":"2021-11-01 00:00:00.000000","timezone_type":3,"timezone":"UTC"},"through":{"date":"2022-04-30 00:00:00.000000","timezone_type":3,"timezone":"UTC"},"daysOfWeek":["Sunday","PublicHolidays"]}]', + 'address' => '{"street":"Beispielstraße 1a","zip":"99084","city":"Beispielstadt","email":"example@example.com","phone":"(0)30 23125 000","fax":"","geo":{"latitude":50.975955358589545,"longitude":11.023667024961856}}', + 'url' => 'https://example.com/attraction', + 'offers' => '[{"type":"GuidedTourOffer","title":"F\\u00fchrungen","description":"Immer samstags, um 11:15 Uhr findet eine \\u00f6ffentliche F\\u00fchrung durch das Museum statt. Dauer etwa 90 Minuten","prices":[{"title":"Erwachsene","description":"","price":8,"currency":"EUR","rule":"PerPerson"},{"title":"Erm\\u00e4\\u00dfigt","description":"als erm\\u00e4\\u00dfigt gelten schulpflichtige Kinder, Auszubildende, Studierende, Rentner\\/-innen, Menschen mit Behinderungen, Inhaber Sozialausweis der Landeshauptstadt Erfurt","price":5,"currency":"EUR","rule":"PerPerson"}]},{"type":"EntryOffer","title":"Eintritt","description":"Schulklassen und Kitagruppen im Rahmen des Unterrichts: Eintritt frei\\nAn jedem ersten Dienstag im Monat: Eintritt frei","prices":[{"title":"Erm\\u00e4\\u00dfigt","description":"als erm\\u00e4\\u00dfigt gelten schulpflichtige Kinder, Auszubildende, Studierende, Rentner\\/-innen, Menschen mit Behinderungen, Inhaber Sozialausweis der Landeshauptstadt Erfurt","price":5,"currency":"EUR","rule":"PerPerson"},{"title":"Familienkarte","description":"","price":17,"currency":"EUR","rule":"PerGroup"},{"title":"ErfurtCard","description":"","price":14.9,"currency":"EUR","rule":"PerPackage"},{"title":"Erwachsene","description":"","price":8,"currency":"EUR","rule":"PerPerson"}]}]', + 'slogan' => 'Highlight', + 'start_of_construction' => '11. Jh', + 'sanitation' => 'Toilets,DisabledToilets,NappyChangingArea,FamilyAndChildFriendly', + 'other_service' => 'Playground,SeatingPossibilitiesRestArea,SouvenirShop,PlayCornerOrPlayArea', + 'museum_service' => 'MuseumShop,PedagogicalOffer,ZeroInformationMuseumService', + 'architectural_style' => 'ArchitectureOfHomelandSecurity,ArtDeco,ArtNouveau,Baroque,BauhausStyle,Brutalism,Classicism,Constructivism,CriticalRegionalism,Deconstructivism,Expressionism,Functionalism,GothicArt,GothicRevival,HighTechArchitecture,Historicism,InternationalStyle,Minimalism,Modernism,Neoclassicism,Neorenaissance,NewBuilding,NewObjectivity,OrganicConstruction,PostWarModernism,PostmodernAge,Rationalism,Renaissance,Rococo,RomanesquePeriod,ZeroInformationArchitecturalStyle', + 'traffic_infrastructure' => 'BicycleLockersEnumMem,BicycleStandsEnumMem,BicycleStandsBicycleLockersEnumMem,BusParkCoachParkEnumMem,EbikeChargingStationEnumMem,ElectricVehicleCarChargingStationEnumMem,ZeroSpecialTrafficInfrastructure', + 'payment_accepted' => 'AliPay,AmericanExpress,ApplePay,CashPayment,EC,InstantBankTransfer,Invoice,MasterCard,PayPal,Visa', + 'digital_offer' => 'AppForMobileDevices,AudioGuide,AugmentedReality,VideoGuide,VirtuellReality,ZeroDigitalOffer', + 'photography' => 'PhotoLicenceFeeRequired,TakingPicturesPermitted,ZeroPhotography,some free text value for photography', + 'pets_allowed' => 'Tiere sind im Gebäude nicht gestattet, ausgenommen sind Blinden- und Blindenbegleithunde.', + 'available_languages' => 'German,English,French', + 'distance_to_public_transport' => '250:MTR', + 'parking_facility_near_by' => '1,2', + 'accessibility_specification' => '{"accessibilityCertificationStatus":"AccessibilityChecked","accessibilitySearchCriteria":{"facilityAccessibilityDeaf":["AudioInductionLoop","FlashingSignalCallWaitingDoor","SpecialOffersDeafPeople","SpecialOffersHearingImpairment","VisualConfirmationDistressCallElevator"],"facilityAccessibilityMental":["ColoredOrPictorialGuidanceSystem","InformationInEasyLanguage","InformationWithPictogramsOrPictures"],"facilityAccessibilityVisual":["AssistanceDogsWelcome","GuidanceSystemWithFloorIndicators","InformationBrailleOrPrismaticFont","OffersInPictoralLanguage","SpecialOffersBlindPeople","SpecialOffersVisualImpairment","TactileOffers","VisuallyContrastingStepEdges"],"facilityAccessibilityWalking":["AllRoomsStepFreeAccess","EightyCMWidthPassageWays","EntryAidSwimmingPool","GrabRailInShower","HandrailsOnBothSidesOfAllStaircases","HingedGrabRailToilet","LateralAccessibleToilet","MinumumManoeuvringSpaceShower","NinetyCMWidthPassageWays","NursingBed","ParkingPeopleWithDisabilities","SeventyCMWidthPassageWays","ShowerSeat","SpecialOffersWalkingImpairment","SpecialOffersWheelchairUsers","StepFreeAccess","StepFreeShower","ToiletsPeopleWithDisabilities"]},"certificationAccessibilityDeaf":"Full","certificationAccessibilityMental":"None","certificationAccessibilityPartiallyDeaf":"None","certificationAccessibilityPartiallyVisual":"Info","certificationAccessibilityVisual":"None","certificationAccessibilityWalking":"Info","certificationAccessibilityWheelchair":"Info","shortDescriptionAccessibilityAllGenerations":"Deutsche Beschreibung von shortDescriptionAccessibilityAllGenerations","shortDescriptionAccessibilityAllergic":"Deutsche Beschreibung von shortDescriptionAccessibilityAllergic","shortDescriptionAccessibilityDeaf":"Deutsche Beschreibung von shortDescriptionAccessibilityDeaf","shortDescriptionAccessibilityMental":"Deutsche Beschreibung von shortDescriptionAccessibilityMental","shortDescriptionAccessibilityVisual":"Deutsche Beschreibung von shortDescriptionAccessibilityVisual","shortDescriptionAccessibilityWalking":"Deutsche Beschreibung von shortDescriptionAccessibilityWalking"}', + ], + ], + 'tx_thuecat_town' => [ + 0 => [ + 'uid' => '1', + 'pid' => '3', + 'title' => 'Beispielstadt', + 'description' => 'Die Beschreibung der Stadt', + ], + ], + 'tx_thuecat_parking_facility' => [ + 0 => [ + 'uid' => '1', + 'pid' => '3', + 'title' => 'Parkhaus Domplatz', + 'address' => '{"street":"Bechtheimer Str. 1","zip":"99084","city":"Erfurt","email":"info@stadtwerke-erfurt.de","phone":"+49 361 5640","fax":"","geo":{"latitude":50.977648905044,"longitude":11.022127985954299}}', + ], + 1 => [ + 'uid' => '2', + 'pid' => '3', + 'title' => 'Q-Park Anger 1 Parkhaus', + 'address' => '{"street":"Anger 1","zip":"99084","city":"Erfurt","email":"servicecenter@q-park.de","phone":"+49 218 18190290","fax":"","geo":{"latitude":50.977999330565794,"longitude":11.037503264052475}}', + ], + ], +]; diff --git a/Tests/Functional/Fixtures/Frontend/TouristAttractions.xml b/Tests/Functional/Fixtures/Frontend/TouristAttractions.xml deleted file mode 100644 index 6708c57..0000000 --- a/Tests/Functional/Fixtures/Frontend/TouristAttractions.xml +++ /dev/null @@ -1,49 +0,0 @@ - - - - 1 - 3 - Erste Attraktion - Die Beschreibung der Attraktion - 1 - [{"mainImage":true,"type":"image","title":"Erfurt-Dom und Severikirche-beleuchtet.jpg","description":"","url":"https:\/\/cms.thuecat.org\/o\/adaptive-media\/image\/5159216\/Preview-1280x0\/image","copyrightYear":2016,"author":"Image Author","license":{"type":"https:\/\/creativecommons.org\/licenses\/by\/4.0\/","author":""}},{"mainImage":false,"type":"image","title":"Erfurt-Dom-und-Severikirche.jpg","description":"Sicht auf Dom St. Marien, St. Severikirche sowie die davor liegenden Klostergeb\u00e4ude und einem Ausschnitt des Biergartens umgeben von einem d\u00e4mmerungsverf\u00e4rten Himmel","url":"https:\/\/cms.thuecat.org\/o\/adaptive-media\/image\/5159186\/Preview-1280x0\/image","copyrightYear":2020,"license":{"type":"https:\/\/creativecommons.org\/licenses\/by\/4.0\/","author":""}},{"mainImage":false,"type":"image","title":"Erfurt-Dom und Severikirche-beleuchtet.jpg","description":"","url":"https:\/\/cms.thuecat.org\/o\/adaptive-media\/image\/5159216\/Preview-1280x0\/image","copyrightYear":2016,"license":{"type":"https:\/\/creativecommons.org\/licenses\/by\/4.0\/","author":""}}] - [{"opens":"09:30:00","closes":"18:00:00","from":{"date":"2021-05-01 00:00:00.000000","timezone_type":3,"timezone":"UTC"},"through":{"date":"2021-10-31 00:00:00.000000","timezone_type":3,"timezone":"UTC"},"daysOfWeek":["Saturday","Friday","Thursday","Tuesday","Monday","Wednesday"]},{"opens":"13:00:00","closes":"18:00:00","from":{"date":"2021-05-01 00:00:00.000000","timezone_type":3,"timezone":"UTC"},"through":{"date":"2021-10-31 00:00:00.000000","timezone_type":3,"timezone":"UTC"},"daysOfWeek":["Sunday"]},{"opens":"09:30:00","closes":"17:00:00","from":{"date":"2021-11-01 00:00:00.000000","timezone_type":3,"timezone":"UTC"},"through":{"date":"2022-04-30 00:00:00.000000","timezone_type":3,"timezone":"UTC"},"daysOfWeek":["Saturday","Friday","Thursday","Tuesday","Monday","Wednesday"]},{"opens":"13:00:00","closes":"17:00:00","from":{"date":"2021-11-01 00:00:00.000000","timezone_type":3,"timezone":"UTC"},"through":{"date":"2022-04-30 00:00:00.000000","timezone_type":3,"timezone":"UTC"},"daysOfWeek":["Sunday","PublicHolidays"]}] -
{"street":"Beispielstraße 1a","zip":"99084","city":"Beispielstadt","email":"example@example.com","phone":"(0)30 23125 000","fax":"","geo":{"latitude":50.975955358589545,"longitude":11.023667024961856}}
- https://example.com/attraction - [{"type":"GuidedTourOffer","title":"F\u00fchrungen","description":"Immer samstags, um 11:15 Uhr findet eine \u00f6ffentliche F\u00fchrung durch das Museum statt. Dauer etwa 90 Minuten","prices":[{"title":"Erwachsene","description":"","price":8,"currency":"EUR","rule":"PerPerson"},{"title":"Erm\u00e4\u00dfigt","description":"als erm\u00e4\u00dfigt gelten schulpflichtige Kinder, Auszubildende, Studierende, Rentner\/-innen, Menschen mit Behinderungen, Inhaber Sozialausweis der Landeshauptstadt Erfurt","price":5,"currency":"EUR","rule":"PerPerson"}]},{"type":"EntryOffer","title":"Eintritt","description":"Schulklassen und Kitagruppen im Rahmen des Unterrichts: Eintritt frei\nAn jedem ersten Dienstag im Monat: Eintritt frei","prices":[{"title":"Erm\u00e4\u00dfigt","description":"als erm\u00e4\u00dfigt gelten schulpflichtige Kinder, Auszubildende, Studierende, Rentner\/-innen, Menschen mit Behinderungen, Inhaber Sozialausweis der Landeshauptstadt Erfurt","price":5,"currency":"EUR","rule":"PerPerson"},{"title":"Familienkarte","description":"","price":17,"currency":"EUR","rule":"PerGroup"},{"title":"ErfurtCard","description":"","price":14.9,"currency":"EUR","rule":"PerPackage"},{"title":"Erwachsene","description":"","price":8,"currency":"EUR","rule":"PerPerson"}]}] - Highlight - 11. Jh - Toilets,DisabledToilets,NappyChangingArea,FamilyAndChildFriendly - Playground,SeatingPossibilitiesRestArea,SouvenirShop,PlayCornerOrPlayArea - MuseumShop,PedagogicalOffer,ZeroInformationMuseumService - ArchitectureOfHomelandSecurity,ArtDeco,ArtNouveau,Baroque,BauhausStyle,Brutalism,Classicism,Constructivism,CriticalRegionalism,Deconstructivism,Expressionism,Functionalism,GothicArt,GothicRevival,HighTechArchitecture,Historicism,InternationalStyle,Minimalism,Modernism,Neoclassicism,Neorenaissance,NewBuilding,NewObjectivity,OrganicConstruction,PostWarModernism,PostmodernAge,Rationalism,Renaissance,Rococo,RomanesquePeriod,ZeroInformationArchitecturalStyle - BicycleLockersEnumMem,BicycleStandsEnumMem,BicycleStandsBicycleLockersEnumMem,BusParkCoachParkEnumMem,EbikeChargingStationEnumMem,ElectricVehicleCarChargingStationEnumMem,ZeroSpecialTrafficInfrastructure - AliPay,AmericanExpress,ApplePay,CashPayment,EC,InstantBankTransfer,Invoice,MasterCard,PayPal,Visa - AppForMobileDevices,AudioGuide,AugmentedReality,VideoGuide,VirtuellReality,ZeroDigitalOffer - PhotoLicenceFeeRequired,TakingPicturesPermitted,ZeroPhotography,some free text value for photography - Tiere sind im Gebäude nicht gestattet, ausgenommen sind Blinden- und Blindenbegleithunde. - German,English,French - 250:MTR - 1,2 - {"accessibilityCertificationStatus":"AccessibilityChecked","accessibilitySearchCriteria":{"facilityAccessibilityDeaf":["AudioInductionLoop","FlashingSignalCallWaitingDoor","SpecialOffersDeafPeople","SpecialOffersHearingImpairment","VisualConfirmationDistressCallElevator"],"facilityAccessibilityMental":["ColoredOrPictorialGuidanceSystem","InformationInEasyLanguage","InformationWithPictogramsOrPictures"],"facilityAccessibilityVisual":["AssistanceDogsWelcome","GuidanceSystemWithFloorIndicators","InformationBrailleOrPrismaticFont","OffersInPictoralLanguage","SpecialOffersBlindPeople","SpecialOffersVisualImpairment","TactileOffers","VisuallyContrastingStepEdges"],"facilityAccessibilityWalking":["AllRoomsStepFreeAccess","EightyCMWidthPassageWays","EntryAidSwimmingPool","GrabRailInShower","HandrailsOnBothSidesOfAllStaircases","HingedGrabRailToilet","LateralAccessibleToilet","MinumumManoeuvringSpaceShower","NinetyCMWidthPassageWays","NursingBed","ParkingPeopleWithDisabilities","SeventyCMWidthPassageWays","ShowerSeat","SpecialOffersWalkingImpairment","SpecialOffersWheelchairUsers","StepFreeAccess","StepFreeShower","ToiletsPeopleWithDisabilities"]},"certificationAccessibilityDeaf":"Full","certificationAccessibilityMental":"None","certificationAccessibilityPartiallyDeaf":"None","certificationAccessibilityPartiallyVisual":"Info","certificationAccessibilityVisual":"None","certificationAccessibilityWalking":"Info","certificationAccessibilityWheelchair":"Info","shortDescriptionAccessibilityAllGenerations":"Deutsche Beschreibung von shortDescriptionAccessibilityAllGenerations","shortDescriptionAccessibilityAllergic":"Deutsche Beschreibung von shortDescriptionAccessibilityAllergic","shortDescriptionAccessibilityDeaf":"Deutsche Beschreibung von shortDescriptionAccessibilityDeaf","shortDescriptionAccessibilityMental":"Deutsche Beschreibung von shortDescriptionAccessibilityMental","shortDescriptionAccessibilityVisual":"Deutsche Beschreibung von shortDescriptionAccessibilityVisual","shortDescriptionAccessibilityWalking":"Deutsche Beschreibung von shortDescriptionAccessibilityWalking"} -
- - 1 - 3 - Beispielstadt - Die Beschreibung der Stadt - - - 1 - 3 - Parkhaus Domplatz -
{"street":"Bechtheimer Str. 1","zip":"99084","city":"Erfurt","email":"info@stadtwerke-erfurt.de","phone":"+49 361 5640","fax":"","geo":{"latitude":50.977648905044,"longitude":11.022127985954299}}
-
- - 2 - 3 - Q-Park Anger 1 Parkhaus -
{"street":"Anger 1","zip":"99084","city":"Erfurt","email":"servicecenter@q-park.de","phone":"+49 218 18190290","fax":"","geo":{"latitude":50.977999330565794,"longitude":11.037503264052475}}
-
-
- diff --git a/Tests/Functional/Fixtures/Frontend/TouristAttractionsForIsAccessibleForFree.php b/Tests/Functional/Fixtures/Frontend/TouristAttractionsForIsAccessibleForFree.php new file mode 100644 index 0000000..31a6a05 --- /dev/null +++ b/Tests/Functional/Fixtures/Frontend/TouristAttractionsForIsAccessibleForFree.php @@ -0,0 +1,62 @@ + [ + 0 => [ + 'uid' => '2', + 'pid' => '3', + 'title' => 'Attraktion mit false', + 'description' => '', + 'town' => '0', + 'media' => '', + 'opening_hours' => '', + 'address' => '', + 'offers' => '', + 'slogan' => '', + 'start_of_construction' => '', + 'sanitation' => '', + 'other_service' => '', + 'museum_service' => '', + 'architectural_style' => '', + 'traffic_infrastructure' => '', + 'payment_accepted' => '', + 'digital_offer' => '', + 'photography' => '', + 'pets_allowed' => '', + 'is_accessible_for_free' => 'false', + ], + 1 => [ + 'uid' => '3', + 'pid' => '3', + 'title' => 'Attraktion mit true', + 'description' => '', + 'town' => '0', + 'media' => '', + 'opening_hours' => '', + 'address' => '', + 'offers' => '', + 'slogan' => '', + 'start_of_construction' => '', + 'sanitation' => '', + 'other_service' => '', + 'museum_service' => '', + 'architectural_style' => '', + 'traffic_infrastructure' => '', + 'payment_accepted' => '', + 'digital_offer' => '', + 'photography' => '', + 'pets_allowed' => '', + 'is_accessible_for_free' => 'true', + ], + ], + 'tx_thuecat_town' => [ + 0 => [ + 'uid' => '1', + 'pid' => '3', + 'title' => 'Beispielstadt', + 'description' => 'Die Beschreibung der Stadt', + ], + ], +]; diff --git a/Tests/Functional/Fixtures/Frontend/TouristAttractionsForIsAccessibleForFree.xml b/Tests/Functional/Fixtures/Frontend/TouristAttractionsForIsAccessibleForFree.xml deleted file mode 100644 index ad4a306..0000000 --- a/Tests/Functional/Fixtures/Frontend/TouristAttractionsForIsAccessibleForFree.xml +++ /dev/null @@ -1,56 +0,0 @@ - - - - 2 - 3 - Attraktion mit false - - 0 - - -
- - - - - - - - - - - - - false -
- - 3 - 3 - Attraktion mit true - - 0 - - -
- - - - - - - - - - - - - true -
- - 1 - 3 - Beispielstadt - Die Beschreibung der Stadt - -
- diff --git a/Tests/Functional/Fixtures/Frontend/TouristAttractionsForPets.php b/Tests/Functional/Fixtures/Frontend/TouristAttractionsForPets.php new file mode 100644 index 0000000..0def6ba --- /dev/null +++ b/Tests/Functional/Fixtures/Frontend/TouristAttractionsForPets.php @@ -0,0 +1,60 @@ + [ + 0 => [ + 'uid' => '2', + 'pid' => '3', + 'title' => 'Attraktion mit pets_allowed = false', + 'description' => '', + 'town' => '0', + 'media' => '', + 'opening_hours' => '', + 'address' => '', + 'offers' => '', + 'slogan' => '', + 'start_of_construction' => '', + 'sanitation' => '', + 'other_service' => '', + 'museum_service' => '', + 'architectural_style' => '', + 'traffic_infrastructure' => '', + 'payment_accepted' => '', + 'digital_offer' => '', + 'photography' => '', + 'pets_allowed' => 'false', + ], + 1 => [ + 'uid' => '3', + 'pid' => '3', + 'title' => 'Attraktion mit pets_allowed = true', + 'description' => '', + 'town' => '0', + 'media' => '', + 'opening_hours' => '', + 'address' => '', + 'offers' => '', + 'slogan' => '', + 'start_of_construction' => '', + 'sanitation' => '', + 'other_service' => '', + 'museum_service' => '', + 'architectural_style' => '', + 'traffic_infrastructure' => '', + 'payment_accepted' => '', + 'digital_offer' => '', + 'photography' => '', + 'pets_allowed' => 'true', + ], + ], + 'tx_thuecat_town' => [ + 0 => [ + 'uid' => '1', + 'pid' => '3', + 'title' => 'Beispielstadt', + 'description' => 'Die Beschreibung der Stadt', + ], + ], +]; diff --git a/Tests/Functional/Fixtures/Frontend/TouristAttractionsForPets.xml b/Tests/Functional/Fixtures/Frontend/TouristAttractionsForPets.xml deleted file mode 100644 index bb86587..0000000 --- a/Tests/Functional/Fixtures/Frontend/TouristAttractionsForPets.xml +++ /dev/null @@ -1,54 +0,0 @@ - - - - 2 - 3 - Attraktion mit pets_allowed = false - - 0 - - -
- - - - - - - - - - - - false -
- - 3 - 3 - Attraktion mit pets_allowed = true - - 0 - - -
- - - - - - - - - - - - true -
- - 1 - 3 - Beispielstadt - Die Beschreibung der Stadt - -
- diff --git a/Tests/Functional/Fixtures/Frontend/TouristAttractionsForPublicAccess.php b/Tests/Functional/Fixtures/Frontend/TouristAttractionsForPublicAccess.php new file mode 100644 index 0000000..d9495cc --- /dev/null +++ b/Tests/Functional/Fixtures/Frontend/TouristAttractionsForPublicAccess.php @@ -0,0 +1,60 @@ + [ + 0 => [ + 'uid' => '2', + 'pid' => '3', + 'title' => 'Attraktion mit public_access = false', + 'description' => '', + 'town' => '0', + 'media' => '', + 'opening_hours' => '', + 'address' => '', + 'offers' => '', + 'slogan' => '', + 'start_of_construction' => '', + 'sanitation' => '', + 'other_service' => '', + 'museum_service' => '', + 'architectural_style' => '', + 'traffic_infrastructure' => '', + 'payment_accepted' => '', + 'digital_offer' => '', + 'photography' => '', + 'public_access' => 'false', + ], + 1 => [ + 'uid' => '3', + 'pid' => '3', + 'title' => 'Attraktion mit public_access = true', + 'description' => '', + 'town' => '0', + 'media' => '', + 'opening_hours' => '', + 'address' => '', + 'offers' => '', + 'slogan' => '', + 'start_of_construction' => '', + 'sanitation' => '', + 'other_service' => '', + 'museum_service' => '', + 'architectural_style' => '', + 'traffic_infrastructure' => '', + 'payment_accepted' => '', + 'digital_offer' => '', + 'photography' => '', + 'public_access' => 'true', + ], + ], + 'tx_thuecat_town' => [ + 0 => [ + 'uid' => '1', + 'pid' => '3', + 'title' => 'Beispielstadt', + 'description' => 'Die Beschreibung der Stadt', + ], + ], +]; diff --git a/Tests/Functional/Fixtures/Frontend/TouristAttractionsForPublicAccess.xml b/Tests/Functional/Fixtures/Frontend/TouristAttractionsForPublicAccess.xml deleted file mode 100644 index 5604dd9..0000000 --- a/Tests/Functional/Fixtures/Frontend/TouristAttractionsForPublicAccess.xml +++ /dev/null @@ -1,54 +0,0 @@ - - - - 2 - 3 - Attraktion mit public_access = false - - 0 - - -
- - - - - - - - - - - - false -
- - 3 - 3 - Attraktion mit public_access = true - - 0 - - -
- - - - - - - - - - - - true -
- - 1 - 3 - Beispielstadt - Die Beschreibung der Stadt - -
- diff --git a/Tests/Functional/Fixtures/Frontend/TouristAttractionsOpeningHours.php b/Tests/Functional/Fixtures/Frontend/TouristAttractionsOpeningHours.php new file mode 100644 index 0000000..dcab1b9 --- /dev/null +++ b/Tests/Functional/Fixtures/Frontend/TouristAttractionsOpeningHours.php @@ -0,0 +1,14 @@ + [ + 0 => [ + 'uid' => '1', + 'pid' => '3', + 'title' => 'Erste Attraktion', + 'description' => 'Die Beschreibung der Attraktion', + ], + ], +]; diff --git a/Tests/Functional/Fixtures/Frontend/TouristAttractionsOpeningHours.xml b/Tests/Functional/Fixtures/Frontend/TouristAttractionsOpeningHours.xml deleted file mode 100644 index d2c3857..0000000 --- a/Tests/Functional/Fixtures/Frontend/TouristAttractionsOpeningHours.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - 1 - 3 - Erste Attraktion - Die Beschreibung der Attraktion - - - diff --git a/Tests/Functional/Fixtures/Import/BackendUser.php b/Tests/Functional/Fixtures/Import/BackendUser.php new file mode 100644 index 0000000..0f878d0 --- /dev/null +++ b/Tests/Functional/Fixtures/Import/BackendUser.php @@ -0,0 +1,26 @@ + [ + 0 => [ + 'uid' => '1', + 'pid' => '0', + 'tstamp' => '1366642540', + 'username' => 'admin', + 'password' => '$1$tCrlLajZ$C0sikFQQ3SWaFAZ1Me0Z/1', + 'admin' => '1', + 'disable' => '0', + 'starttime' => '0', + 'endtime' => '0', + 'options' => '0', + 'crdate' => '1366642540', + 'workspace_perms' => '1', + 'deleted' => '0', + 'TSconfig' => null, + 'lastlogin' => '1371033743', + 'workspace_id' => '0', + ], + ], +]; diff --git a/Tests/Functional/Fixtures/Import/ImportWithMultipleReferencesToSameObject.csv b/Tests/Functional/Fixtures/Import/ImportWithMultipleReferencesToSameObject.csv deleted file mode 100644 index 868d981..0000000 --- a/Tests/Functional/Fixtures/Import/ImportWithMultipleReferencesToSameObject.csv +++ /dev/null @@ -1,33 +0,0 @@ -"tx_thuecat_import_log",,,,,,, -,"uid","pid","configuration",,,, -,1,0,1,,,, -"tx_thuecat_import_log_entry",,,,,,, -,"uid","pid","import_log","record_uid","table_name","insertion","errors" -,1,0,1,1,"tx_thuecat_organisation",1,"[]" -,2,0,1,1,"tx_thuecat_town",1,"[]" -,3,0,1,1,"tx_thuecat_parking_facility",1,"[]" -,4,0,1,2,"tx_thuecat_parking_facility",0,"[]" -,5,0,1,3,"tx_thuecat_parking_facility",0,"[]" -,6,0,1,1,"tx_thuecat_tourist_attraction",1,"[]" -,7,0,1,2,"tx_thuecat_tourist_attraction",0,"[]" -,8,0,1,3,"tx_thuecat_tourist_attraction",1,"[]" -,9,0,1,4,"tx_thuecat_tourist_attraction",0,"[]" -,10,0,1,5,"tx_thuecat_tourist_attraction",0,"[]" -"tx_thuecat_organisation",,,,,,, -,"uid","pid","remote_id","title",,, -,1,10,"https://thuecat.org/resources/018132452787-ngbe","Erfurt Tourismus und Marketing GmbH",,, -"tx_thuecat_town",,,,,,, -,"uid","pid","remote_id","title","managed_by",, -,1,10,"https://thuecat.org/resources/043064193523-jcyt","Erfurt",1,, -"tx_thuecat_parking_facility",,,,,,, -,"uid","pid","sys_language_uid","remote_id","title","managed_by", -,1,10,0,"https://thuecat.org/resources/396420044896-drzt","Parkhaus Domplatz",1, -,2,10,1,"https://thuecat.org/resources/396420044896-drzt","Car park Domplatz",1, -,3,10,2,"https://thuecat.org/resources/396420044896-drzt","Parking Domplatz",1, -"tx_thuecat_tourist_attraction",,,,,,, -,"uid","pid","sys_language_uid","remote_id","title","managed_by","town" -,1,10,0,"https://thuecat.org/resources/835224016581-dara","Dom St. Marien",1,1 -,2,10,1,"https://thuecat.org/resources/835224016581-dara","Cathedral of St. Mary",1,1 -,3,10,0,"https://thuecat.org/resources/165868194223-zmqf","Alte Synagoge",1,1 -,4,10,1,"https://thuecat.org/resources/165868194223-zmqf","Old Synagogue",1,1 -,5,10,2,"https://thuecat.org/resources/165868194223-zmqf","La vieille synagogue",1,1 diff --git a/Tests/Functional/Fixtures/Import/ImportWithMultipleReferencesToSameObject.xml b/Tests/Functional/Fixtures/Import/ImportWithMultipleReferencesToSameObject.php similarity index 57% rename from Tests/Functional/Fixtures/Import/ImportWithMultipleReferencesToSameObject.xml rename to Tests/Functional/Fixtures/Import/ImportWithMultipleReferencesToSameObject.php index 3d5e735..4a18bb2 100644 --- a/Tests/Functional/Fixtures/Import/ImportWithMultipleReferencesToSameObject.xml +++ b/Tests/Functional/Fixtures/Import/ImportWithMultipleReferencesToSameObject.php @@ -1,51 +1,39 @@ - - - - 1 - 0 - 1613400587 - 1613400558 - 1 - 4 - Rootpage - 1 - - - 10 - 1 - 1613400587 - 1613400558 - 1 - 254 - Storage folder - + - 1 - 0 - English - en-us-gb - en - +declare(strict_types=1); - - 2 - 0 - French - fr - fr - +use TYPO3\CMS\Core\Domain\Repository\PageRepository; - - 1 - 0 - 1613400587 - 1613400558 - 1 - 0 - Attractions within Town Erfurt - static - +return [ + 'pages' => [ + 0 => [ + 'uid' => '1', + 'pid' => '0', + 'tstamp' => '1613400587', + 'crdate' => '1613400558', + 'doktype' => PageRepository::DOKTYPE_DEFAULT, + 'title' => 'Rootpage', + 'is_siteroot' => '1', + ], + 1 => [ + 'uid' => '10', + 'pid' => '1', + 'tstamp' => '1613400587', + 'crdate' => '1613400558', + 'doktype' => PageRepository::DOKTYPE_SYSFOLDER, + 'title' => 'Storage folder', + ], + ], + 'tx_thuecat_import_configuration' => [ + 0 => [ + 'uid' => '1', + 'pid' => '0', + 'tstamp' => '1613400587', + 'crdate' => '1613400558', + 'disable' => '0', + 'title' => 'Attractions within Town Erfurt', + 'type' => 'static', + 'configuration' => ' @@ -80,6 +68,7 @@ - ]]> - - + ', + ], + ], +]; diff --git a/Tests/Functional/Fixtures/Import/ImportsContainsPlace.csv b/Tests/Functional/Fixtures/Import/ImportsContainsPlace.csv deleted file mode 100644 index 4d34c99..0000000 --- a/Tests/Functional/Fixtures/Import/ImportsContainsPlace.csv +++ /dev/null @@ -1,16 +0,0 @@ -"tx_thuecat_tourist_attraction",,,,, -,"uid","pid","sys_language_uid","remote_id","title" -,1,10,0,"https://thuecat.org/resources/835224016581-dara","Dom St. Marien" -,2,10,1,"https://thuecat.org/resources/835224016581-dara","Cathedral of St. Mary" -,3,10,0,"https://thuecat.org/resources/165868194223-zmqf","Alte Synagoge" -,4,10,1,"https://thuecat.org/resources/165868194223-zmqf","Old Synagogue" -,5,10,2,"https://thuecat.org/resources/165868194223-zmqf","La vieille synagogue" -,6,10,0,"https://thuecat.org/resources/215230952334-yyno","Krämerbrücke" -,7,10,1,"https://thuecat.org/resources/215230952334-yyno","Merchants' Bridge" -,8,10,2,"https://thuecat.org/resources/215230952334-yyno","Pont de l'épicier" -"tx_thuecat_organisation",,,,, -,"uid","pid","remote_id","title", -,1,10,"https://thuecat.org/resources/018132452787-ngbe","Erfurt Tourismus und Marketing GmbH", -"tx_thuecat_town",,,,, -,"uid","pid","remote_id","title", -,1,10,"https://thuecat.org/resources/043064193523-jcyt","Erfurt", diff --git a/Tests/Functional/Fixtures/Import/ImportsContainsPlace.php b/Tests/Functional/Fixtures/Import/ImportsContainsPlace.php new file mode 100644 index 0000000..76b4405 --- /dev/null +++ b/Tests/Functional/Fixtures/Import/ImportsContainsPlace.php @@ -0,0 +1,53 @@ + [ + 0 => [ + 'uid' => '1', + 'pid' => '0', + 'tstamp' => '1613400587', + 'crdate' => '1613400558', + 'doktype' => PageRepository::DOKTYPE_DEFAULT, + 'title' => 'Rootpage', + 'is_siteroot' => '1', + ], + 1 => [ + 'uid' => '10', + 'pid' => '1', + 'tstamp' => '1613400587', + 'crdate' => '1613400558', + 'doktype' => PageRepository::DOKTYPE_SYSFOLDER, + 'title' => 'Storage folder', + ], + ], + 'tx_thuecat_import_configuration' => [ + 0 => [ + 'uid' => '1', + 'pid' => '0', + 'tstamp' => '1613400587', + 'crdate' => '1613400558', + 'disable' => '0', + 'title' => 'Contains Place', + 'type' => 'containsPlace', + 'configuration' => ' + + + + + + 10 + + + 043064193523-contains + + + + + ', + ], + ], +]; diff --git a/Tests/Functional/Fixtures/Import/ImportsContainsPlace.xml b/Tests/Functional/Fixtures/Import/ImportsContainsPlace.xml deleted file mode 100644 index e756748..0000000 --- a/Tests/Functional/Fixtures/Import/ImportsContainsPlace.xml +++ /dev/null @@ -1,64 +0,0 @@ - - - - 1 - 0 - 1613400587 - 1613400558 - 1 - 4 - Rootpage - 1 - - - 10 - 1 - 1613400587 - 1613400558 - 1 - 254 - Storage folder - - - - 1 - 0 - English - en-us-gb - en - - - - 2 - 0 - French - fr - fr - - - - 1 - 0 - 1613400587 - 1613400558 - 1 - 0 - Contains Place - containsPlace - - - - - - - 10 - - - 043064193523-contains - - - - - ]]> - - diff --git a/Tests/Functional/Fixtures/Import/ImportsFollowingRecordsInCaseOfAnMappingException.csv b/Tests/Functional/Fixtures/Import/ImportsFollowingRecordsInCaseOfAnMappingException.csv deleted file mode 100644 index b8d795c..0000000 --- a/Tests/Functional/Fixtures/Import/ImportsFollowingRecordsInCaseOfAnMappingException.csv +++ /dev/null @@ -1,18 +0,0 @@ -"tx_thuecat_tourist_attraction",,,,,,,, -,"uid","pid","sys_language_uid","remote_id","title",,, -,1,10,0,"https://thuecat.org/resources/165868194223-zmqf","Alte Synagoge",,, -,2,10,1,"https://thuecat.org/resources/165868194223-zmqf","Old Synagogue",,, -,3,10,2,"https://thuecat.org/resources/165868194223-zmqf","La vieille synagogue",,, -"tx_thuecat_import_log",,,,,,,, -,"uid","pid","configuration","log_entries",,,, -,1,0,1,0,,,, -"tx_thuecat_import_log_entry",,,,,,,, -,"uid","pid","type","import_log","record_uid","table_name","insertion","errors" -,1,0,"mappingError",1,0,,0,"[""Could not map incoming JSON-LD to target object: Failed to parse time string (18:00: 00) at position 5 (:): Unexpected character""]" -,2,0,"mappingError",1,0,,0,"[""Could not map incoming JSON-LD to target object: Failed to parse time string (18:00: 00) at position 5 (:): Unexpected character""]" -,3,0,"mappingError",1,0,,0,"[""Could not map incoming JSON-LD to target object: Failed to parse time string (18:00: 00) at position 5 (:): Unexpected character""]" -,4,0,"savingEntity",1,1,"tx_thuecat_organisation",1,"[]" -,5,0,"savingEntity",1,1,"tx_thuecat_town",0,"[]" -,6,0,"savingEntity",1,1,"tx_thuecat_tourist_attraction",1,"[]" -,7,0,"savingEntity",1,2,"tx_thuecat_tourist_attraction",0,"[]" -,8,0,"savingEntity",1,3,"tx_thuecat_tourist_attraction",0,"[]" diff --git a/Tests/Functional/Fixtures/Import/ImportsFollowingRecordsInCaseOfAnMappingException.xml b/Tests/Functional/Fixtures/Import/ImportsFollowingRecordsInCaseOfAnMappingException.php similarity index 51% rename from Tests/Functional/Fixtures/Import/ImportsFollowingRecordsInCaseOfAnMappingException.xml rename to Tests/Functional/Fixtures/Import/ImportsFollowingRecordsInCaseOfAnMappingException.php index c78bae8..4c382b5 100644 --- a/Tests/Functional/Fixtures/Import/ImportsFollowingRecordsInCaseOfAnMappingException.xml +++ b/Tests/Functional/Fixtures/Import/ImportsFollowingRecordsInCaseOfAnMappingException.php @@ -1,51 +1,39 @@ - - - - 1 - 0 - 1613400587 - 1613400558 - 1 - 4 - Rootpage - 1 - - - 10 - 1 - 1613400587 - 1613400558 - 1 - 254 - Storage folder - + - 1 - 0 - English - en-us-gb - en - +declare(strict_types=1); - - 2 - 0 - French - fr - fr - +use TYPO3\CMS\Core\Domain\Repository\PageRepository; - - 1 - 0 - 1613400587 - 1613400558 - 1 - 0 - Import With Exceptions - static - +return [ + 'pages' => [ + 0 => [ + 'uid' => '1', + 'pid' => '0', + 'tstamp' => '1613400587', + 'crdate' => '1613400558', + 'doktype' => PageRepository::DOKTYPE_DEFAULT, + 'title' => 'Rootpage', + 'is_siteroot' => '1', + ], + 1 => [ + 'uid' => '10', + 'pid' => '1', + 'tstamp' => '1613400587', + 'crdate' => '1613400558', + 'doktype' => PageRepository::DOKTYPE_SYSFOLDER, + 'title' => 'Storage folder', + ], + ], + 'tx_thuecat_import_configuration' => [ + 0 => [ + 'uid' => '1', + 'pid' => '0', + 'tstamp' => '1613400587', + 'crdate' => '1613400558', + 'disable' => '0', + 'title' => 'Import With Exceptions', + 'type' => 'static', + 'configuration' => ' @@ -81,19 +69,20 @@ - ]]> - - - - 1 - 10 - 1613401129 - 1613401129 - 1 - 0 - https://thuecat.org/resources/043064193523-jcyt - 1 - 0 - Erfurt - - + ', + ], + ], + 'tx_thuecat_town' => [ + 0 => [ + 'uid' => '1', + 'pid' => '10', + 'tstamp' => '1613401129', + 'crdate' => '1613401129', + 'disable' => '0', + 'remote_id' => 'https://thuecat.org/resources/043064193523-jcyt', + 'managed_by' => '1', + 'tourist_information' => '0', + 'title' => 'Erfurt', + ], + ], +]; diff --git a/Tests/Functional/Fixtures/Import/ImportsFollowingRecordsInCaseOfAnMappingExceptionOldPhp.csv b/Tests/Functional/Fixtures/Import/ImportsFollowingRecordsInCaseOfAnMappingExceptionOldPhp.csv deleted file mode 100644 index 3de3703..0000000 --- a/Tests/Functional/Fixtures/Import/ImportsFollowingRecordsInCaseOfAnMappingExceptionOldPhp.csv +++ /dev/null @@ -1,18 +0,0 @@ -"tx_thuecat_tourist_attraction",,,,,,,, -,"uid","pid","sys_language_uid","remote_id","title",,, -,1,10,0,"https://thuecat.org/resources/165868194223-zmqf","Alte Synagoge",,, -,2,10,1,"https://thuecat.org/resources/165868194223-zmqf","Old Synagogue",,, -,3,10,2,"https://thuecat.org/resources/165868194223-zmqf","La vieille synagogue",,, -"tx_thuecat_import_log",,,,,,,, -,"uid","pid","configuration","log_entries",,,, -,1,0,1,0,,,, -"tx_thuecat_import_log_entry",,,,,,,, -,"uid","pid","type","import_log","record_uid","table_name","insertion","errors" -,1,0,"mappingError",1,0,,0,"[""Could not map incoming JSON-LD to target object: DateTimeImmutable::__construct(): Failed to parse time string (18:00: 00) at position 5 (:): Unexpected character""]" -,2,0,"mappingError",1,0,,0,"[""Could not map incoming JSON-LD to target object: DateTimeImmutable::__construct(): Failed to parse time string (18:00: 00) at position 5 (:): Unexpected character""]" -,3,0,"mappingError",1,0,,0,"[""Could not map incoming JSON-LD to target object: DateTimeImmutable::__construct(): Failed to parse time string (18:00: 00) at position 5 (:): Unexpected character""]" -,4,0,"savingEntity",1,1,"tx_thuecat_organisation",1,"[]" -,5,0,"savingEntity",1,1,"tx_thuecat_town",0,"[]" -,6,0,"savingEntity",1,1,"tx_thuecat_tourist_attraction",1,"[]" -,7,0,"savingEntity",1,2,"tx_thuecat_tourist_attraction",0,"[]" -,8,0,"savingEntity",1,3,"tx_thuecat_tourist_attraction",0,"[]" diff --git a/Tests/Functional/Fixtures/Import/ImportsFollowingRecordsInCaseOfAnMappingExceptionOldPhp.php b/Tests/Functional/Fixtures/Import/ImportsFollowingRecordsInCaseOfAnMappingExceptionOldPhp.php new file mode 100644 index 0000000..d4a2fc1 --- /dev/null +++ b/Tests/Functional/Fixtures/Import/ImportsFollowingRecordsInCaseOfAnMappingExceptionOldPhp.php @@ -0,0 +1,119 @@ + [ + 0 => [ + 'uid' => '1', + 'pid' => '10', + 'sys_language_uid' => '0', + 'remote_id' => 'https://thuecat.org/resources/165868194223-zmqf', + 'title' => 'Alte Synagoge', + ], + 1 => [ + 'uid' => '2', + 'pid' => '10', + 'sys_language_uid' => '1', + 'remote_id' => 'https://thuecat.org/resources/165868194223-zmqf', + 'title' => 'Old Synagogue', + ], + 2 => [ + 'uid' => '3', + 'pid' => '10', + 'sys_language_uid' => '2', + 'remote_id' => 'https://thuecat.org/resources/165868194223-zmqf', + 'title' => 'La vieille synagogue', + ], + ], + 'tx_thuecat_import_log' => [ + 0 => [ + 'uid' => '1', + 'pid' => '0', + 'configuration' => '1', + 'log_entries' => '0', + ], + ], + 'tx_thuecat_import_log_entry' => [ + 0 => [ + 'uid' => '1', + 'pid' => '0', + 'type' => 'mappingError', + 'import_log' => '1', + 'record_uid' => '0', + 'table_name' => '', + 'insertion' => '0', + 'errors' => '["Could not map incoming JSON-LD to target object: DateTimeImmutable::__construct(): Failed to parse time string (18:00: 00) at position 5 (:): Unexpected character"]', + ], + 1 => [ + 'uid' => '2', + 'pid' => '0', + 'type' => 'mappingError', + 'import_log' => '1', + 'record_uid' => '0', + 'table_name' => '', + 'insertion' => '0', + 'errors' => '["Could not map incoming JSON-LD to target object: DateTimeImmutable::__construct(): Failed to parse time string (18:00: 00) at position 5 (:): Unexpected character"]', + ], + 2 => [ + 'uid' => '3', + 'pid' => '0', + 'type' => 'mappingError', + 'import_log' => '1', + 'record_uid' => '0', + 'table_name' => '', + 'insertion' => '0', + 'errors' => '["Could not map incoming JSON-LD to target object: DateTimeImmutable::__construct(): Failed to parse time string (18:00: 00) at position 5 (:): Unexpected character"]', + ], + 3 => [ + 'uid' => '4', + 'pid' => '0', + 'type' => 'savingEntity', + 'import_log' => '1', + 'record_uid' => '1', + 'table_name' => 'tx_thuecat_organisation', + 'insertion' => '1', + 'errors' => '[]', + ], + 4 => [ + 'uid' => '5', + 'pid' => '0', + 'type' => 'savingEntity', + 'import_log' => '1', + 'record_uid' => '1', + 'table_name' => 'tx_thuecat_town', + 'insertion' => '0', + 'errors' => '[]', + ], + 5 => [ + 'uid' => '6', + 'pid' => '0', + 'type' => 'savingEntity', + 'import_log' => '1', + 'record_uid' => '1', + 'table_name' => 'tx_thuecat_tourist_attraction', + 'insertion' => '1', + 'errors' => '[]', + ], + 6 => [ + 'uid' => '7', + 'pid' => '0', + 'type' => 'savingEntity', + 'import_log' => '1', + 'record_uid' => '2', + 'table_name' => 'tx_thuecat_tourist_attraction', + 'insertion' => '0', + 'errors' => '[]', + ], + 7 => [ + 'uid' => '8', + 'pid' => '0', + 'type' => 'savingEntity', + 'import_log' => '1', + 'record_uid' => '3', + 'table_name' => 'tx_thuecat_tourist_attraction', + 'insertion' => '0', + 'errors' => '[]', + ], + ], +]; diff --git a/Tests/Functional/Fixtures/Import/ImportsFreshOrganization.csv b/Tests/Functional/Fixtures/Import/ImportsFreshOrganization.csv deleted file mode 100644 index 72ebe26..0000000 --- a/Tests/Functional/Fixtures/Import/ImportsFreshOrganization.csv +++ /dev/null @@ -1,9 +0,0 @@ -tx_thuecat_organisation -,"uid","pid","remote_id","title" -,1,11,"https://thuecat.org/resources/018132452787-ngbe","Erfurt Tourismus und Marketing GmbH" -tx_thuecat_import_log -,"uid","pid","configuration" -,1,0,1 -tx_thuecat_import_log_entry -,"uid","pid","import_log","record_uid","table_name","insertion","errors" -,1,0,1,1,"tx_thuecat_organisation",1,"[]" diff --git a/Tests/Functional/Fixtures/Import/ImportsFreshOrganization.xml b/Tests/Functional/Fixtures/Import/ImportsFreshOrganization.php similarity index 54% rename from Tests/Functional/Fixtures/Import/ImportsFreshOrganization.xml rename to Tests/Functional/Fixtures/Import/ImportsFreshOrganization.php index 8ab2f77..c89b391 100644 --- a/Tests/Functional/Fixtures/Import/ImportsFreshOrganization.xml +++ b/Tests/Functional/Fixtures/Import/ImportsFreshOrganization.php @@ -1,35 +1,39 @@ - - - - 1 - 0 - 1613400587 - 1613400558 - 1 - 4 - Rootpage - 1 - - - 11 - 1 - 1613400587 - 1613400558 - 1 - 254 - Storage folder - + - 1 - 0 - 1613400587 - 1613400558 - 1 - 0 - Single Fresh Organisation - static - +declare(strict_types=1); + +use TYPO3\CMS\Core\Domain\Repository\PageRepository; + +return [ + 'pages' => [ + 0 => [ + 'uid' => '1', + 'pid' => '0', + 'tstamp' => '1613400587', + 'crdate' => '1613400558', + 'doktype' => PageRepository::DOKTYPE_DEFAULT, + 'title' => 'Rootpage', + 'is_siteroot' => '1', + ], + 1 => [ + 'uid' => '11', + 'pid' => '1', + 'tstamp' => '1613400587', + 'crdate' => '1613400558', + 'doktype' => PageRepository::DOKTYPE_SYSFOLDER, + 'title' => 'Storage folder', + ], + ], + 'tx_thuecat_import_configuration' => [ + 0 => [ + 'uid' => '1', + 'pid' => '0', + 'tstamp' => '1613400587', + 'crdate' => '1613400558', + 'disable' => '0', + 'title' => 'Single Fresh Organisation', + 'type' => 'static', + 'configuration' => ' @@ -55,6 +59,7 @@ - ]]> - - + ', + ], + ], +]; diff --git a/Tests/Functional/Fixtures/Import/ImportsSyncScope.csv b/Tests/Functional/Fixtures/Import/ImportsSyncScope.csv deleted file mode 100644 index 9df311f..0000000 --- a/Tests/Functional/Fixtures/Import/ImportsSyncScope.csv +++ /dev/null @@ -1,10 +0,0 @@ -"tx_thuecat_tourist_attraction",,,,,,,,,,,, -,"uid","pid","sys_language_uid","l18n_parent","l10n_source","l10n_state","remote_id","title","managed_by","town","address","offers" -,1,10,0,0,0,"\NULL","https://thuecat.org/resources/835224016581-dara","Dom St. Marien",1,1,"{""street"":""Domstufen 1"",""zip"":""99084"",""city"":""Erfurt"",""email"":""dominformation@domberg-erfurt.de"",""phone"":""+49 361 6461265"",""fax"":"""",""geo"":{""latitude"":50.975955358589545,""longitude"":11.023667024961856}}","[]" -,2,10,1,1,1,"\NULL","https://thuecat.org/resources/835224016581-dara","Cathedral of St. Mary",1,1,"{""street"":""Domstufen 1"",""zip"":""99084"",""city"":""Erfurt"",""email"":""dominformation@domberg-erfurt.de"",""phone"":""+49 361 6461265"",""fax"":"""",""geo"":{""latitude"":50.975955358589545,""longitude"":11.023667024961856}}","[]" -,3,10,0,0,0,"\NULL","https://thuecat.org/resources/165868194223-zmqf","Alte Synagoge",1,1,"{""street"":""Waagegasse 8"",""zip"":""99084"",""city"":""Erfurt"",""email"":""altesynagoge@erfurt.de"",""phone"":""+49 361 6551520"",""fax"":""+49 361 6551669"",""geo"":{""latitude"":50.978765,""longitude"":11.029133}}","[{""types"":[""GuidedTourOffer""],""title"":""F\u00fchrungen"",""description"":""Immer samstags, um 11:15 Uhr findet eine \u00f6ffentliche F\u00fchrung durch das Museum statt. Dauer etwa 90 Minuten"",""prices"":[{""title"":""Erwachsene"",""description"":"""",""price"":8,""currency"":""EUR"",""rule"":""PerPerson""},{""title"":""Erm\u00e4\u00dfigt"",""description"":""als erm\u00e4\u00dfigt gelten schulpflichtige Kinder, Auszubildende, Studierende, Rentner\/-innen, Menschen mit Behinderungen, Inhaber Sozialausweis der Landeshauptstadt Erfurt"",""price"":5,""currency"":""EUR"",""rule"":""PerPerson""}]},{""types"":[""EntryOffer""],""title"":""Eintritt"",""description"":""Schulklassen und Kitagruppen im Rahmen des Unterrichts: Eintritt frei\nAn jedem ersten Dienstag im Monat: Eintritt frei"",""prices"":[{""title"":""Erm\u00e4\u00dfigt"",""description"":""als erm\u00e4\u00dfigt gelten schulpflichtige Kinder, Auszubildende, Studierende, Rentner\/-innen, Menschen mit Behinderungen, Inhaber Sozialausweis der Landeshauptstadt Erfurt"",""price"":5,""currency"":""EUR"",""rule"":""PerPerson""},{""title"":""Familienkarte"",""description"":"""",""price"":17,""currency"":""EUR"",""rule"":""PerGroup""},{""title"":""ErfurtCard"",""description"":"""",""price"":14.9,""currency"":""EUR"",""rule"":""PerPackage""},{""title"":""Erwachsene"",""description"":"""",""price"":8,""currency"":""EUR"",""rule"":""PerPerson""}]}]" -,4,10,1,3,3,"\NULL","https://thuecat.org/resources/165868194223-zmqf","Old Synagogue",1,1,"{""street"":""Waagegasse 8"",""zip"":""99084"",""city"":""Erfurt"",""email"":""altesynagoge@erfurt.de"",""phone"":""+49 361 6551520"",""fax"":""+49 361 6551669"",""geo"":{""latitude"":50.978765,""longitude"":11.029133}}","[{""types"":[""GuidedTourOffer""],""title"":"""",""description"":"""",""prices"":[{""title"":"""",""description"":"""",""price"":8,""currency"":""EUR"",""rule"":""PerPerson""},{""title"":"""",""description"":"""",""price"":5,""currency"":""EUR"",""rule"":""PerPerson""}]},{""types"":[""EntryOffer""],""title"":"""",""description"":"""",""prices"":[{""title"":"""",""description"":"""",""price"":5,""currency"":""EUR"",""rule"":""PerPerson""},{""title"":"""",""description"":"""",""price"":17,""currency"":""EUR"",""rule"":""PerGroup""},{""title"":"""",""description"":"""",""price"":14.9,""currency"":""EUR"",""rule"":""PerPackage""},{""title"":"""",""description"":"""",""price"":8,""currency"":""EUR"",""rule"":""PerPerson""}]}]" -,5,10,2,3,3,"\NULL","https://thuecat.org/resources/165868194223-zmqf","La vieille synagogue",1,1,"{""street"":""Waagegasse 8"",""zip"":""99084"",""city"":""Erfurt"",""email"":""altesynagoge@erfurt.de"",""phone"":""+49 361 6551520"",""fax"":""+49 361 6551669"",""geo"":{""latitude"":50.978765,""longitude"":11.029133}}","[{""types"":[""GuidedTourOffer""],""title"":"""",""description"":"""",""prices"":[{""title"":"""",""description"":"""",""price"":8,""currency"":""EUR"",""rule"":""PerPerson""},{""title"":"""",""description"":"""",""price"":5,""currency"":""EUR"",""rule"":""PerPerson""}]},{""types"":[""EntryOffer""],""title"":"""",""description"":"""",""prices"":[{""title"":"""",""description"":"""",""price"":5,""currency"":""EUR"",""rule"":""PerPerson""},{""title"":"""",""description"":"""",""price"":17,""currency"":""EUR"",""rule"":""PerGroup""},{""title"":"""",""description"":"""",""price"":14.9,""currency"":""EUR"",""rule"":""PerPackage""},{""title"":"""",""description"":"""",""price"":8,""currency"":""EUR"",""rule"":""PerPerson""}]}]" -,6,10,0,0,0,"\NULL","https://thuecat.org/resources/215230952334-yyno","Krämerbrücke",1,1,"{""street"":""Benediktsplatz 1"",""zip"":""99084"",""city"":""Erfurt"",""email"":""service@erfurt-tourismus.de"",""phone"":""+49 361 66 400"",""fax"":"""",""geo"":{""latitude"":50.978772,""longitude"":11.031622}}","[]" -,7,10,1,6,6,"\NULL","https://thuecat.org/resources/215230952334-yyno","Merchants' Bridge",1,1,"{""street"":""Benediktsplatz 1"",""zip"":""99084"",""city"":""Erfurt"",""email"":""service@erfurt-tourismus.de"",""phone"":""+49 361 66 400"",""fax"":"""",""geo"":{""latitude"":50.978772,""longitude"":11.031622}}","[]" -,8,10,2,6,6,"\NULL","https://thuecat.org/resources/215230952334-yyno","Pont de l'épicier",1,1,"{""street"":""Benediktsplatz 1"",""zip"":""99084"",""city"":""Erfurt"",""email"":""service@erfurt-tourismus.de"",""phone"":""+49 361 66 400"",""fax"":"""",""geo"":{""latitude"":50.978772,""longitude"":11.031622}}","[]" diff --git a/Tests/Functional/Fixtures/Import/ImportsSyncScope.php b/Tests/Functional/Fixtures/Import/ImportsSyncScope.php new file mode 100644 index 0000000..548bb80 --- /dev/null +++ b/Tests/Functional/Fixtures/Import/ImportsSyncScope.php @@ -0,0 +1,66 @@ + [ + 0 => [ + 'uid' => '1', + 'pid' => '0', + 'tstamp' => '1613400587', + 'crdate' => '1613400558', + 'doktype' => PageRepository::DOKTYPE_DEFAULT, + 'title' => 'Rootpage', + 'is_siteroot' => '1', + ], + 1 => [ + 'uid' => '10', + 'pid' => '1', + 'tstamp' => '1613400587', + 'crdate' => '1613400558', + 'doktype' => PageRepository::DOKTYPE_SYSFOLDER, + 'title' => 'Storage folder', + ], + ], + 'tx_thuecat_import_configuration' => [ + 0 => [ + 'uid' => '1', + 'pid' => '0', + 'tstamp' => '1613400587', + 'crdate' => '1613400558', + 'disable' => '0', + 'title' => 'Sync Scope ID', + 'type' => 'syncScope', + 'configuration' => ' + + + + + + 10 + + + dd4615dc-58a6-4648-a7ce-4950293a06db + + + + + ', + ], + ], + 'tx_thuecat_town' => [ + 0 => [ + 'uid' => '1', + 'pid' => '10', + 'tstamp' => '1613401129', + 'crdate' => '1613401129', + 'disable' => '0', + 'remote_id' => 'https://thuecat.org/resources/043064193523-jcyt', + 'managed_by' => '1', + 'tourist_information' => '0', + 'title' => 'Erfurt', + ], + ], +]; diff --git a/Tests/Functional/Fixtures/Import/ImportsSyncScope.xml b/Tests/Functional/Fixtures/Import/ImportsSyncScope.xml deleted file mode 100644 index dfc6f48..0000000 --- a/Tests/Functional/Fixtures/Import/ImportsSyncScope.xml +++ /dev/null @@ -1,77 +0,0 @@ - - - - 1 - 0 - 1613400587 - 1613400558 - 1 - 4 - Rootpage - 1 - - - 10 - 1 - 1613400587 - 1613400558 - 1 - 254 - Storage folder - - - - 1 - 0 - English - en-us-gb - en - - - - 2 - 0 - French - fr - fr - - - - 1 - 0 - 1613400587 - 1613400558 - 1 - 0 - Sync Scope ID - syncScope - - - - - - - 10 - - - dd4615dc-58a6-4648-a7ce-4950293a06db - - - - - ]]> - - - - 1 - 10 - 1613401129 - 1613401129 - 1 - 0 - https://thuecat.org/resources/043064193523-jcyt - 1 - 0 - Erfurt - - diff --git a/Tests/Functional/Fixtures/Import/ImportsTouristAttractionWithAccessibilitySpecification.csv b/Tests/Functional/Fixtures/Import/ImportsTouristAttractionWithAccessibilitySpecification.csv deleted file mode 100644 index 4e41dfc..0000000 --- a/Tests/Functional/Fixtures/Import/ImportsTouristAttractionWithAccessibilitySpecification.csv +++ /dev/null @@ -1,4 +0,0 @@ -"tx_thuecat_tourist_attraction",,,,,,,, -,"uid","pid","sys_language_uid","l18n_parent","l10n_source","remote_id","title" -,1,10,0,0,0,"https://thuecat.org/resources/attraction-with-accessibility-specification","Attraktion mit accessibility specification" -,2,10,1,1,1,"https://thuecat.org/resources/attraction-with-accessibility-specification","Attraction with accessibility specification" diff --git a/Tests/Functional/Fixtures/Import/ImportsTouristAttractionWithAccessibilitySpecification.php b/Tests/Functional/Fixtures/Import/ImportsTouristAttractionWithAccessibilitySpecification.php new file mode 100644 index 0000000..665cde5 --- /dev/null +++ b/Tests/Functional/Fixtures/Import/ImportsTouristAttractionWithAccessibilitySpecification.php @@ -0,0 +1,65 @@ + [ + 0 => [ + 'uid' => '1', + 'pid' => '0', + 'tstamp' => '1613400587', + 'crdate' => '1613400558', + 'doktype' => PageRepository::DOKTYPE_DEFAULT, + 'title' => 'Rootpage', + 'is_siteroot' => '1', + ], + 1 => [ + 'uid' => '10', + 'pid' => '1', + 'tstamp' => '1613400587', + 'crdate' => '1613400558', + 'doktype' => PageRepository::DOKTYPE_SYSFOLDER, + 'title' => 'Storage folder', + ], + ], + 'tx_thuecat_import_configuration' => [ + 0 => [ + 'uid' => '1', + 'pid' => '0', + 'tstamp' => '1613400587', + 'crdate' => '1613400558', + 'disable' => '0', + 'title' => 'Tourist Attraction', + 'type' => 'static', + 'configuration' => ' + + + + + + 10 + + + + + + + + https://thuecat.org/resources/attraction-with-accessibility-certification + + + + 0 + + + + + + + + ', + ], + ], +]; diff --git a/Tests/Functional/Fixtures/Import/ImportsTouristAttractionWithAccessibilitySpecification.xml b/Tests/Functional/Fixtures/Import/ImportsTouristAttractionWithAccessibilitySpecification.xml deleted file mode 100644 index 0754c1b..0000000 --- a/Tests/Functional/Fixtures/Import/ImportsTouristAttractionWithAccessibilitySpecification.xml +++ /dev/null @@ -1,76 +0,0 @@ - - - - 1 - 0 - 1613400587 - 1613400558 - 1 - 4 - Rootpage - 1 - - - 10 - 1 - 1613400587 - 1613400558 - 1 - 254 - Storage folder - - - - 1 - 0 - English - en-us-gb - en - - - - 2 - 0 - French - fr - fr - - - - 1 - 0 - 1613400587 - 1613400558 - 1 - 0 - Tourist Attraction - static - - - - - - - 10 - - - - - - - - https://thuecat.org/resources/attraction-with-accessibility-certification - - - - 0 - - - - - - - - ]]> - - diff --git a/Tests/Functional/Fixtures/Import/ImportsTouristAttractionWithFilteredOpeningHours.php b/Tests/Functional/Fixtures/Import/ImportsTouristAttractionWithFilteredOpeningHours.php new file mode 100644 index 0000000..8c251b3 --- /dev/null +++ b/Tests/Functional/Fixtures/Import/ImportsTouristAttractionWithFilteredOpeningHours.php @@ -0,0 +1,65 @@ + [ + 0 => [ + 'uid' => '1', + 'pid' => '0', + 'tstamp' => '1613400587', + 'crdate' => '1613400558', + 'doktype' => PageRepository::DOKTYPE_DEFAULT, + 'title' => 'Rootpage', + 'is_siteroot' => '1', + ], + 1 => [ + 'uid' => '10', + 'pid' => '1', + 'tstamp' => '1613400587', + 'crdate' => '1613400558', + 'doktype' => PageRepository::DOKTYPE_SYSFOLDER, + 'title' => 'Storage folder', + ], + ], + 'tx_thuecat_import_configuration' => [ + 0 => [ + 'uid' => '1', + 'pid' => '0', + 'tstamp' => '1613400587', + 'crdate' => '1613400558', + 'disable' => '0', + 'title' => 'The tourist attraction', + 'type' => 'static', + 'configuration' => ' + + + + + + 10 + + + + + + + + https://thuecat.org/resources/opening-hours-to-filter + + + + 0 + + + + + + + + ', + ], + ], +]; diff --git a/Tests/Functional/Fixtures/Import/ImportsTouristAttractionWithFilteredOpeningHours.xml b/Tests/Functional/Fixtures/Import/ImportsTouristAttractionWithFilteredOpeningHours.xml deleted file mode 100644 index 8f0ca7e..0000000 --- a/Tests/Functional/Fixtures/Import/ImportsTouristAttractionWithFilteredOpeningHours.xml +++ /dev/null @@ -1,76 +0,0 @@ - - - - 1 - 0 - 1613400587 - 1613400558 - 1 - 4 - Rootpage - 1 - - - 10 - 1 - 1613400587 - 1613400558 - 1 - 254 - Storage folder - - - - 1 - 0 - English - en-us-gb - en - - - - 2 - 0 - French - fr - fr - - - - 1 - 0 - 1613400587 - 1613400558 - 1 - 0 - The tourist attraction - static - - - - - - - 10 - - - - - - - - https://thuecat.org/resources/opening-hours-to-filter - - - - 0 - - - - - - - - ]]> - - diff --git a/Tests/Functional/Fixtures/Import/ImportsTouristAttractionWithMedia.csv b/Tests/Functional/Fixtures/Import/ImportsTouristAttractionWithMedia.csv deleted file mode 100644 index 7d1f60c..0000000 --- a/Tests/Functional/Fixtures/Import/ImportsTouristAttractionWithMedia.csv +++ /dev/null @@ -1,4 +0,0 @@ -"tx_thuecat_tourist_attraction",,,,, -,"uid","pid","remote_id","title","media" -,1,10,"https://thuecat.org/resources/attraction-with-media","Attraktion mit Bildern","[{""mainImage"":false,""type"":""image"",""title"":""Bild mit externem Autor"",""description"":"""",""url"":""https:\/\/cms.thuecat.org\/o\/adaptive-media\/image\/5099196\/Preview-1280x0\/image"",""author"":""GivenName FamilyName"",""copyrightYear"":0,""license"":{""type"":"""",""author"":""""}},{""mainImage"":false,""type"":""image"",""title"":""Bild mit author"",""description"":"""",""url"":""https:\/\/cms.thuecat.org\/o\/adaptive-media\/image\/5099196\/Preview-1280x0\/image"",""author"":""Full Name"",""copyrightYear"":0,""license"":{""type"":""https:\/\/creativecommons.org\/licenses\/by\/4.0\/"",""author"":""""}},{""mainImage"":false,""type"":""image"",""title"":""Bild mit license author"",""description"":"""",""url"":""https:\/\/cms.thuecat.org\/o\/adaptive-media\/image\/5099196\/Preview-1280x0\/image"",""author"":"""",""copyrightYear"":0,""license"":{""type"":""https:\/\/creativecommons.org\/licenses\/by\/4.0\/"",""author"":""Autor aus Lizenz""}},{""mainImage"":false,""type"":""image"",""title"":""Bild mit author und license author"",""description"":"""",""url"":""https:\/\/cms.thuecat.org\/o\/adaptive-media\/image\/5099196\/Preview-1280x0\/image"",""author"":""Full Name"",""copyrightYear"":0,""license"":{""type"":""https:\/\/creativecommons.org\/licenses\/by\/4.0\/"",""author"":""Autor aus Lizenz""}}]" -,2,10,"https://thuecat.org/resources/attraction-with-media","Attraction with media","[{""mainImage"":false,""type"":""image"",""title"":""Bild mit externem Autor"",""description"":"""",""url"":""https:\/\/cms.thuecat.org\/o\/adaptive-media\/image\/5099196\/Preview-1280x0\/image"",""author"":""GivenName FamilyName"",""copyrightYear"":0,""license"":{""type"":"""",""author"":""""}},{""mainImage"":false,""type"":""image"",""title"":""Bild mit author"",""description"":"""",""url"":""https:\/\/cms.thuecat.org\/o\/adaptive-media\/image\/5099196\/Preview-1280x0\/image"",""author"":""Full Name"",""copyrightYear"":0,""license"":{""type"":""https:\/\/creativecommons.org\/licenses\/by\/4.0\/"",""author"":""""}},{""mainImage"":false,""type"":""image"",""title"":""Bild mit license author"",""description"":"""",""url"":""https:\/\/cms.thuecat.org\/o\/adaptive-media\/image\/5099196\/Preview-1280x0\/image"",""author"":"""",""copyrightYear"":0,""license"":{""type"":""https:\/\/creativecommons.org\/licenses\/by\/4.0\/"",""author"":""Autor aus Lizenz""}},{""mainImage"":false,""type"":""image"",""title"":""Bild mit author und license author"",""description"":"""",""url"":""https:\/\/cms.thuecat.org\/o\/adaptive-media\/image\/5099196\/Preview-1280x0\/image"",""author"":""Full Name"",""copyrightYear"":0,""license"":{""type"":""https:\/\/creativecommons.org\/licenses\/by\/4.0\/"",""author"":""Autor aus Lizenz""}}]" diff --git a/Tests/Functional/Fixtures/Import/ImportsTouristAttractionWithMedia.php b/Tests/Functional/Fixtures/Import/ImportsTouristAttractionWithMedia.php new file mode 100644 index 0000000..56dc92e --- /dev/null +++ b/Tests/Functional/Fixtures/Import/ImportsTouristAttractionWithMedia.php @@ -0,0 +1,65 @@ + [ + 0 => [ + 'uid' => '1', + 'pid' => '0', + 'tstamp' => '1613400587', + 'crdate' => '1613400558', + 'doktype' => PageRepository::DOKTYPE_DEFAULT, + 'title' => 'Rootpage', + 'is_siteroot' => '1', + ], + 1 => [ + 'uid' => '10', + 'pid' => '1', + 'tstamp' => '1613400587', + 'crdate' => '1613400558', + 'doktype' => PageRepository::DOKTYPE_SYSFOLDER, + 'title' => 'Storage folder', + ], + ], + 'tx_thuecat_import_configuration' => [ + 0 => [ + 'uid' => '1', + 'pid' => '0', + 'tstamp' => '1613400587', + 'crdate' => '1613400558', + 'disable' => '0', + 'title' => 'Tourist Attraction', + 'type' => 'static', + 'configuration' => ' + + + + + + 10 + + + + + + + + https://thuecat.org/resources/attraction-with-media + + + + 0 + + + + + + + + ', + ], + ], +]; diff --git a/Tests/Functional/Fixtures/Import/ImportsTouristAttractionWithMedia.xml b/Tests/Functional/Fixtures/Import/ImportsTouristAttractionWithMedia.xml deleted file mode 100644 index d48484f..0000000 --- a/Tests/Functional/Fixtures/Import/ImportsTouristAttractionWithMedia.xml +++ /dev/null @@ -1,76 +0,0 @@ - - - - 1 - 0 - 1613400587 - 1613400558 - 1 - 4 - Rootpage - 1 - - - 10 - 1 - 1613400587 - 1613400558 - 1 - 254 - Storage folder - - - - 1 - 0 - English - en-us-gb - en - - - - 2 - 0 - French - fr - fr - - - - 1 - 0 - 1613400587 - 1613400558 - 1 - 0 - Tourist Attraction - static - - - - - - - 10 - - - - - - - - https://thuecat.org/resources/attraction-with-media - - - - 0 - - - - - - - - ]]> - - diff --git a/Tests/Functional/Fixtures/Import/ImportsTouristAttractionWithSpecialOpeningHours.php b/Tests/Functional/Fixtures/Import/ImportsTouristAttractionWithSpecialOpeningHours.php new file mode 100644 index 0000000..74e887f --- /dev/null +++ b/Tests/Functional/Fixtures/Import/ImportsTouristAttractionWithSpecialOpeningHours.php @@ -0,0 +1,65 @@ + [ + 0 => [ + 'uid' => '1', + 'pid' => '0', + 'tstamp' => '1613400587', + 'crdate' => '1613400558', + 'doktype' => PageRepository::DOKTYPE_DEFAULT, + 'title' => 'Rootpage', + 'is_siteroot' => '1', + ], + 1 => [ + 'uid' => '10', + 'pid' => '1', + 'tstamp' => '1613400587', + 'crdate' => '1613400558', + 'doktype' => PageRepository::DOKTYPE_SYSFOLDER, + 'title' => 'Storage folder', + ], + ], + 'tx_thuecat_import_configuration' => [ + 0 => [ + 'uid' => '1', + 'pid' => '0', + 'tstamp' => '1613400587', + 'crdate' => '1613400558', + 'disable' => '0', + 'title' => 'The tourist attraction', + 'type' => 'static', + 'configuration' => ' + + + + + + 10 + + + + + + + + https://thuecat.org/resources/special-opening-hours + + + + 0 + + + + + + + + ', + ], + ], +]; diff --git a/Tests/Functional/Fixtures/Import/ImportsTouristAttractionWithSpecialOpeningHours.xml b/Tests/Functional/Fixtures/Import/ImportsTouristAttractionWithSpecialOpeningHours.xml deleted file mode 100644 index 50c2234..0000000 --- a/Tests/Functional/Fixtures/Import/ImportsTouristAttractionWithSpecialOpeningHours.xml +++ /dev/null @@ -1,76 +0,0 @@ - - - - 1 - 0 - 1613400587 - 1613400558 - 1 - 4 - Rootpage - 1 - - - 10 - 1 - 1613400587 - 1613400558 - 1 - 254 - Storage folder - - - - 1 - 0 - English - en-us-gb - en - - - - 2 - 0 - French - fr - fr - - - - 1 - 0 - 1613400587 - 1613400558 - 1 - 0 - The tourist attraction - static - - - - - - - 10 - - - - - - - - https://thuecat.org/resources/special-opening-hours - - - - 0 - - - - - - - - ]]> - - diff --git a/Tests/Functional/Fixtures/Import/ImportsTouristAttractionsWithFilteredOpeningHours.csv b/Tests/Functional/Fixtures/Import/ImportsTouristAttractionsWithFilteredOpeningHours.csv deleted file mode 100644 index 10e195d..0000000 --- a/Tests/Functional/Fixtures/Import/ImportsTouristAttractionsWithFilteredOpeningHours.csv +++ /dev/null @@ -1,4 +0,0 @@ -"tx_thuecat_tourist_attraction",,,,,,,, -,"uid","pid","sys_language_uid","l18n_parent","l10n_source","remote_id","title","opening_hours" -,1,10,0,0,0,"https://thuecat.org/resources/835224016581-dara","Dom St. Marien","[{""opens"":""13:00:00"",""closes"":""17:00:00"",""from"":{""date"":""2050-11-01 00:00:00.000000"",""timezone_type"":3,""timezone"":""UTC""},""through"":{""date"":""2050-04-30 00:00:00.000000"",""timezone_type"":3,""timezone"":""UTC""},""daysOfWeek"":[""Sunday""]}]" -,2,10,1,1,1,"https://thuecat.org/resources/835224016581-dara","Cathedral of St. Mary","[{""opens"":""13:00:00"",""closes"":""17:00:00"",""from"":{""date"":""2050-11-01 00:00:00.000000"",""timezone_type"":3,""timezone"":""UTC""},""through"":{""date"":""2050-04-30 00:00:00.000000"",""timezone_type"":3,""timezone"":""UTC""},""daysOfWeek"":[""Sunday""]}]" diff --git a/Tests/Functional/Fixtures/Import/ImportsTouristAttractionsWithFilteredOpeningHours.php b/Tests/Functional/Fixtures/Import/ImportsTouristAttractionsWithFilteredOpeningHours.php new file mode 100644 index 0000000..62d8aa2 --- /dev/null +++ b/Tests/Functional/Fixtures/Import/ImportsTouristAttractionsWithFilteredOpeningHours.php @@ -0,0 +1,28 @@ + [ + 0 => [ + 'uid' => '1', + 'pid' => '10', + 'sys_language_uid' => '0', + 'l18n_parent' => '0', + 'l10n_source' => '0', + 'remote_id' => 'https://thuecat.org/resources/835224016581-dara', + 'title' => 'Dom St. Marien', + 'opening_hours' => '[{"opens":"13:00:00","closes":"17:00:00","from":{"date":"2050-11-01 00:00:00.000000","timezone_type":3,"timezone":"UTC"},"through":{"date":"2050-04-30 00:00:00.000000","timezone_type":3,"timezone":"UTC"},"daysOfWeek":["Sunday"]}]', + ], + 1 => [ + 'uid' => '2', + 'pid' => '10', + 'sys_language_uid' => '1', + 'l18n_parent' => '1', + 'l10n_source' => '1', + 'remote_id' => 'https://thuecat.org/resources/835224016581-dara', + 'title' => 'Cathedral of St. Mary', + 'opening_hours' => '[{"opens":"13:00:00","closes":"17:00:00","from":{"date":"2050-11-01 00:00:00.000000","timezone_type":3,"timezone":"UTC"},"through":{"date":"2050-04-30 00:00:00.000000","timezone_type":3,"timezone":"UTC"},"daysOfWeek":["Sunday"]}]', + ], + ], +]; diff --git a/Tests/Functional/Fixtures/Import/ImportsTouristAttractionsWithRelations.csv b/Tests/Functional/Fixtures/Import/ImportsTouristAttractionsWithRelations.csv deleted file mode 100644 index 6d8057f..0000000 --- a/Tests/Functional/Fixtures/Import/ImportsTouristAttractionsWithRelations.csv +++ /dev/null @@ -1,35 +0,0 @@ -"tx_thuecat_tourist_attraction",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, -,"uid","pid","sys_language_uid","l18n_parent","l10n_source","l10n_state","remote_id","title","description","managed_by","town","address","offers","media","slogan","start_of_construction","sanitation","other_service","museum_service","architectural_style","traffic_infrastructure","payment_accepted","digital_offer","photography","pets_allowed","is_accessible_for_free","public_access","available_languages","distance_to_public_transport","parking_facility_near_by","accessibility_specification","url" -,1,10,0,0,0,"\NULL","https://thuecat.org/resources/835224016581-dara","Dom St. Marien","Über eine 70-stufige Freitreppe gelangt man vom Domplatz auf den Domberg mit seinen beiden ehemaligen Stiftskirchen. Der Dom, mit hochgotischem Chor, romanischem Turmbereich und spätgotischer Westhalle, ist Nachfolger des 724 von Rom veranlassten Sakralbaus. Er war die Hauptkirche des 742 von Bischof Bonifatius gegründeten Bistums Erfurt und während des Mittelalters bis in das frühe 19. Jahrhundert Sitz des Collegiatstifts St. Marien. 1507 erhielt Martin Luther hier die Priesterweihe. -Der ursprünglich romanische Kirchenbau wurde in der Zeit der Gotik entscheidend umgebaut. Besonders sehenswert sind die gotischen Chorfenster, das umfängliche Chorgestühl (14. Jhd.) sowie die romanischen Skulpturen einer thronenden Madonna und eines monumentalen Kerzenträgers im Innenraum. Berühmt ist er auch wegen der „Gloriosa“, der mit 2,56 m Durchmesser größten freischwingenden mittelalterlichen Glocke der Welt. -Das Ensemble von Dom und Severikirche bildet eine imposante Kulisse für die jährlich im Sommer stattfindenden DomStufen-Festspiele.",1,1,"{""street"":""Domstufen 1"",""zip"":""99084"",""city"":""Erfurt"",""email"":""dominformation@domberg-erfurt.de"",""phone"":""+49 361 6461265"",""fax"":"""",""geo"":{""latitude"":50.975955358589545,""longitude"":11.023667024961856}}","[]","[{""mainImage"":true,""type"":""image"",""title"":""Erfurt-Dom und Severikirche-beleuchtet.jpg"",""description"":"""",""url"":""https:\/\/cms.thuecat.org\/o\/adaptive-media\/image\/5159216\/Preview-1280x0\/image"",""author"":"""",""copyrightYear"":2016,""license"":{""type"":""https:\/\/creativecommons.org\/licenses\/by\/4.0\/"",""author"":""""}},{""mainImage"":false,""type"":""image"",""title"":""Erfurt-Dom-und-Severikirche.jpg"",""description"":""Sicht auf Dom St. Marien, St. Severikirche sowie die davor liegenden Klostergeb\u00e4ude und einem Ausschnitt des Biergartens umgeben von einem d\u00e4mmerungsverf\u00e4rten Himmel"",""url"":""https:\/\/cms.thuecat.org\/o\/adaptive-media\/image\/5159186\/Preview-1280x0\/image"",""author"":"""",""copyrightYear"":2020,""license"":{""type"":""https:\/\/creativecommons.org\/licenses\/by\/4.0\/"",""author"":""""}}]",,,"Toilets,DisabledToilets","SeatingPossibilitiesRestArea,SouvenirShop",,"GothicArt","BicycleLockersEnumMem,BusParkCoachParkEnumMem",,"AugmentedReality","Fotogenehmigung für innen","false","true","true","German,English","350:MTR:Streetcar:CityBus",1,"{}","http://www.dom-erfurt.de" -,2,10,1,1,1,"\NULL","https://thuecat.org/resources/835224016581-dara","Cathedral of St. Mary","The late Gothic cathedral with its high-Gothic choir and Romanesque tower replaced the church built on this site for Bishop Boniface in 742. The central tower houses the ""Gloriosa"", the world’s largest medieval free-swinging bell.",1,1,"{""street"":""Domstufen 1"",""zip"":""99084"",""city"":""Erfurt"",""email"":""dominformation@domberg-erfurt.de"",""phone"":""+49 361 6461265"",""fax"":"""",""geo"":{""latitude"":50.975955358589545,""longitude"":11.023667024961856}}","[]","[{""mainImage"":true,""type"":""image"",""title"":""Erfurt-Dom und Severikirche-beleuchtet.jpg"",""description"":"""",""url"":""https:\/\/cms.thuecat.org\/o\/adaptive-media\/image\/5159216\/Preview-1280x0\/image"",""author"":"""",""copyrightYear"":2016,""license"":{""type"":""https:\/\/creativecommons.org\/licenses\/by\/4.0\/"",""author"":""""}},{""mainImage"":false,""type"":""image"",""title"":""Erfurt-Dom-und-Severikirche.jpg"",""description"":""Sicht auf Dom St. Marien, St. Severikirche sowie die davor liegenden Klostergeb\u00e4ude und einem Ausschnitt des Biergartens umgeben von einem d\u00e4mmerungsverf\u00e4rten Himmel"",""url"":""https:\/\/cms.thuecat.org\/o\/adaptive-media\/image\/5159186\/Preview-1280x0\/image"",""author"":"""",""copyrightYear"":2020,""license"":{""type"":""https:\/\/creativecommons.org\/licenses\/by\/4.0\/"",""author"":""""}}]",,,"Toilets,DisabledToilets","SeatingPossibilitiesRestArea,SouvenirShop",,"GothicArt","BicycleLockersEnumMem,BusParkCoachParkEnumMem",,"AugmentedReality",,"false","true","true","German,English","350:MTR:Streetcar:CityBus",1,"{}","http://www.dom-erfurt.de" -,3,10,0,0,0,"\NULL","https://thuecat.org/resources/165868194223-zmqf","Alte Synagoge","Beispiel Beschreibung",1,1,"{""street"":""Waagegasse 8"",""zip"":""99084"",""city"":""Erfurt"",""email"":""altesynagoge@erfurt.de"",""phone"":""+49 361 6551520"",""fax"":""+49 361 6551669"",""geo"":{""latitude"":50.978765,""longitude"":11.029133}}","[{""types"":[""GuidedTourOffer""],""title"":""F\u00fchrungen"",""description"":""Immer samstags, um 11:15 Uhr findet eine \u00f6ffentliche F\u00fchrung durch das Museum statt. Dauer etwa 90 Minuten"",""prices"":[{""title"":""Erwachsene"",""description"":"""",""price"":8,""currency"":""EUR"",""rule"":""PerPerson""},{""title"":""Erm\u00e4\u00dfigt"",""description"":""als erm\u00e4\u00dfigt gelten schulpflichtige Kinder, Auszubildende, Studierende, Rentner\/-innen, Menschen mit Behinderungen, Inhaber Sozialausweis der Landeshauptstadt Erfurt"",""price"":5,""currency"":""EUR"",""rule"":""PerPerson""}]},{""types"":[""EntryOffer""],""title"":""Eintritt"",""description"":""Schulklassen und Kitagruppen im Rahmen des Unterrichts: Eintritt frei\nAn jedem ersten Dienstag im Monat: Eintritt frei"",""prices"":[{""title"":""Erm\u00e4\u00dfigt"",""description"":""als erm\u00e4\u00dfigt gelten schulpflichtige Kinder, Auszubildende, Studierende, Rentner\/-innen, Menschen mit Behinderungen, Inhaber Sozialausweis der Landeshauptstadt Erfurt"",""price"":5,""currency"":""EUR"",""rule"":""PerPerson""},{""title"":""Familienkarte"",""description"":"""",""price"":17,""currency"":""EUR"",""rule"":""PerGroup""},{""title"":""ErfurtCard"",""description"":"""",""price"":14.9,""currency"":""EUR"",""rule"":""PerPackage""},{""title"":""Erwachsene"",""description"":"""",""price"":8,""currency"":""EUR"",""rule"":""PerPerson""}]}]","[{""mainImage"":true,""type"":""image"",""title"":""Erfurt-Alte Synagoge"",""description"":""Frontaler Blick auf die Hausfront\/Hausfassade im Innenhof mit Zugang \u00fcber die Waagegasse"",""url"":""https:\/\/cms.thuecat.org\/o\/adaptive-media\/image\/5099196\/Preview-1280x0\/image"",""author"":"""",""copyrightYear"":2009,""license"":{""type"":""https:\/\/creativecommons.org\/licenses\/by\/4.0\/"",""author"":""F:\\Bilddatenbank\\Museen und Ausstellungen\\Alte Synagoge""}}]","Highlight","11. Jh.","Toilets,DisabledToilets,NappyChangingArea,FamilyAndChildFriendly","SeatingPossibilitiesRestArea,LockBoxes,SouvenirShop,BaggageStorage","MuseumShop","GothicArt","ZeroSpecialTrafficInfrastructure","CashPayment,EC","AudioGuide,VideoGuide","ZeroPhotography","Tiere sind im Gebäude nicht gestattet, ausgenommen sind Blinden- und Blindenbegleithunde.","false","true","German,English,French","200:MTR:CityBus",,"{""accessibilityCertificationStatus"":""AccessibilityChecked"",""certificationAccessibilityDeaf"":""None"",""certificationAccessibilityMental"":""None"",""certificationAccessibilityPartiallyDeaf"":""None"",""certificationAccessibilityPartiallyVisual"":""Info"",""certificationAccessibilityVisual"":""None"",""certificationAccessibilityWalking"":""Info"",""certificationAccessibilityWheelchair"":""Info"",""accessibilitySearchCriteria"":{""facilityAccessibilityWalking"":[""AllRoomsStepFreeAccess"",""HingedGrabRailToilet"",""LateralAccessibleToilet"",""StepFreeAccess"",""ToiletsPeopleWithDisabilities"",""NinetyCMWidthPassageWays"",""SpecialOffersWalkingImpairment"",""SpecialOffersWheelchairUsers""],""facilityAccessibilityVisual"":[""AssistanceDogsWelcome"",""VisuallyContrastingStepEdges"",""OffersInPictoralLanguage"",""SpecialOffersBlindPeople"",""SpecialOffersVisualImpairment"",""TactileOffers""],""facilityAccessibilityDeaf"":[""AudioInductionLoop"",""SpecialOffersHearingImpairment""],""facilityAccessibilityMental"":[""InformationWithPictogramsOrPictures""]},""shortDescriptionAccessibilityDeaf"":""Deutsche Beschreibung von shortDescriptionAccessibilityDeaf"",""shortDescriptionAccessibilityMental"":""Deutsche Beschreibung von shortDescriptionAccessibilityMental"",""shortDescriptionAccessibilityVisual"":""Deutsche Beschreibung von shortDescriptionAccessibilityVisual"",""shortDescriptionAccessibilityWalking"":""Deutsche Beschreibung von shortDescriptionAccessibilityWalking""}","http://www.alte-synagoge.erfurt.de" -,4,10,1,3,3,"\NULL","https://thuecat.org/resources/165868194223-zmqf","Old Synagogue","The Old Synagogue is one of very few preserved medieval synagogues in Europe. Thanks to the extensive preservation of the original structure, it has a special place in the history of art and architecture and is among the most impressive and highly rated architectural monuments in Erfurt and Thuringia. The synagogue was constructed during the Middle Ages on the ""via regia"", one of the major European trade routes, at the heart of the historical old quarter very close to the Merchants Bridge and the town hall. Many parts of the structure still remain today, including all four thick outer walls, the Roman­esque gemel window, the Gothic rose window and the entrance to the synagogue room.",1,1,"{""street"":""Waagegasse 8"",""zip"":""99084"",""city"":""Erfurt"",""email"":""altesynagoge@erfurt.de"",""phone"":""+49 361 6551520"",""fax"":""+49 361 6551669"",""geo"":{""latitude"":50.978765,""longitude"":11.029133}}","[{""types"":[""GuidedTourOffer""],""title"":"""",""description"":"""",""prices"":[{""title"":"""",""description"":"""",""price"":8,""currency"":""EUR"",""rule"":""PerPerson""},{""title"":"""",""description"":"""",""price"":5,""currency"":""EUR"",""rule"":""PerPerson""}]},{""types"":[""EntryOffer""],""title"":"""",""description"":"""",""prices"":[{""title"":"""",""description"":"""",""price"":5,""currency"":""EUR"",""rule"":""PerPerson""},{""title"":"""",""description"":"""",""price"":17,""currency"":""EUR"",""rule"":""PerGroup""},{""title"":"""",""description"":"""",""price"":14.9,""currency"":""EUR"",""rule"":""PerPackage""},{""title"":"""",""description"":"""",""price"":8,""currency"":""EUR"",""rule"":""PerPerson""}]}]","[{""mainImage"":true,""type"":""image"",""title"":""Erfurt-Alte Synagoge"",""description"":""Frontaler Blick auf die Hausfront\/Hausfassade im Innenhof mit Zugang \u00fcber die Waagegasse"",""url"":""https:\/\/cms.thuecat.org\/o\/adaptive-media\/image\/5099196\/Preview-1280x0\/image"",""author"":"""",""copyrightYear"":2009,""license"":{""type"":""https:\/\/creativecommons.org\/licenses\/by\/4.0\/"",""author"":""F:\\Bilddatenbank\\Museen und Ausstellungen\\Alte Synagoge""}}]","Highlight","11th century","Toilets,DisabledToilets,NappyChangingArea,FamilyAndChildFriendly","SeatingPossibilitiesRestArea,LockBoxes,SouvenirShop,BaggageStorage","MuseumShop","GothicArt","ZeroSpecialTrafficInfrastructure","CashPayment,EC","AudioGuide,VideoGuide","ZeroPhotography",,"false","true","German,English,French","200:MTR:CityBus",,"{""accessibilityCertificationStatus"":""AccessibilityChecked"",""certificationAccessibilityDeaf"":""None"",""certificationAccessibilityMental"":""None"",""certificationAccessibilityPartiallyDeaf"":""None"",""certificationAccessibilityPartiallyVisual"":""Info"",""certificationAccessibilityVisual"":""None"",""certificationAccessibilityWalking"":""Info"",""certificationAccessibilityWheelchair"":""Info"",""accessibilitySearchCriteria"":{""facilityAccessibilityWalking"":[""AllRoomsStepFreeAccess"",""HingedGrabRailToilet"",""LateralAccessibleToilet"",""StepFreeAccess"",""ToiletsPeopleWithDisabilities"",""NinetyCMWidthPassageWays"",""SpecialOffersWalkingImpairment"",""SpecialOffersWheelchairUsers""],""facilityAccessibilityVisual"":[""AssistanceDogsWelcome"",""VisuallyContrastingStepEdges"",""OffersInPictoralLanguage"",""SpecialOffersBlindPeople"",""SpecialOffersVisualImpairment"",""TactileOffers""],""facilityAccessibilityDeaf"":[""AudioInductionLoop"",""SpecialOffersHearingImpairment""],""facilityAccessibilityMental"":[""InformationWithPictogramsOrPictures""]},""shortDescriptionAccessibilityDeaf"":""English description of shortDescriptionAccessibilityDeaf"",""shortDescriptionAccessibilityMental"":""English description of shortDescriptionAccessibilityMental"",""shortDescriptionAccessibilityVisual"":""English description of shortDescriptionAccessibilityVisual"",""shortDescriptionAccessibilityWalking"":""English description of shortDescriptionAccessibilityWalking""}","http://www.alte-synagoge.erfurt.de" -,5,10,2,3,3,"\NULL","https://thuecat.org/resources/165868194223-zmqf","La vieille synagogue","La vieille synagogue (datant des années 1100) est la synagogue la plus vieille d’Europe totalement conservée, dans laquelle est exposé un trésor datant des 13/14èmes siècles avec une alliance juive unique et des écritures hébraïques (datant des 12ème, 13ème et 14èmes siècles). Après la redécouverte du Mikwé, Erfurt abrite des témoins uniques et fascinants d’une communauté juive médiévale.",1,1,"{""street"":""Waagegasse 8"",""zip"":""99084"",""city"":""Erfurt"",""email"":""altesynagoge@erfurt.de"",""phone"":""+49 361 6551520"",""fax"":""+49 361 6551669"",""geo"":{""latitude"":50.978765,""longitude"":11.029133}}","[{""types"":[""GuidedTourOffer""],""title"":"""",""description"":"""",""prices"":[{""title"":"""",""description"":"""",""price"":8,""currency"":""EUR"",""rule"":""PerPerson""},{""title"":"""",""description"":"""",""price"":5,""currency"":""EUR"",""rule"":""PerPerson""}]},{""types"":[""EntryOffer""],""title"":"""",""description"":"""",""prices"":[{""title"":"""",""description"":"""",""price"":5,""currency"":""EUR"",""rule"":""PerPerson""},{""title"":"""",""description"":"""",""price"":17,""currency"":""EUR"",""rule"":""PerGroup""},{""title"":"""",""description"":"""",""price"":14.9,""currency"":""EUR"",""rule"":""PerPackage""},{""title"":"""",""description"":"""",""price"":8,""currency"":""EUR"",""rule"":""PerPerson""}]}]","[{""mainImage"":true,""type"":""image"",""title"":""Erfurt-Alte Synagoge"",""description"":""Frontaler Blick auf die Hausfront\/Hausfassade im Innenhof mit Zugang \u00fcber die Waagegasse"",""url"":""https:\/\/cms.thuecat.org\/o\/adaptive-media\/image\/5099196\/Preview-1280x0\/image"",""author"":"""",""copyrightYear"":2009,""license"":{""type"":""https:\/\/creativecommons.org\/licenses\/by\/4.0\/"",""author"":""F:\\Bilddatenbank\\Museen und Ausstellungen\\Alte Synagoge""}}]","Highlight",,"Toilets,DisabledToilets,NappyChangingArea,FamilyAndChildFriendly","SeatingPossibilitiesRestArea,LockBoxes,SouvenirShop,BaggageStorage","MuseumShop","GothicArt","ZeroSpecialTrafficInfrastructure","CashPayment,EC","AudioGuide,VideoGuide","ZeroPhotography",,"false","true","German,English,French","200:MTR:CityBus",,"{""accessibilityCertificationStatus"":""AccessibilityChecked"",""certificationAccessibilityDeaf"":""None"",""certificationAccessibilityMental"":""None"",""certificationAccessibilityPartiallyDeaf"":""None"",""certificationAccessibilityPartiallyVisual"":""Info"",""certificationAccessibilityVisual"":""None"",""certificationAccessibilityWalking"":""Info"",""certificationAccessibilityWheelchair"":""Info"",""accessibilitySearchCriteria"":{""facilityAccessibilityWalking"":[""AllRoomsStepFreeAccess"",""HingedGrabRailToilet"",""LateralAccessibleToilet"",""StepFreeAccess"",""ToiletsPeopleWithDisabilities"",""NinetyCMWidthPassageWays"",""SpecialOffersWalkingImpairment"",""SpecialOffersWheelchairUsers""],""facilityAccessibilityVisual"":[""AssistanceDogsWelcome"",""VisuallyContrastingStepEdges"",""OffersInPictoralLanguage"",""SpecialOffersBlindPeople"",""SpecialOffersVisualImpairment"",""TactileOffers""],""facilityAccessibilityDeaf"":[""AudioInductionLoop"",""SpecialOffersHearingImpairment""],""facilityAccessibilityMental"":[""InformationWithPictogramsOrPictures""]}}","http://www.alte-synagoge.erfurt.de" -,6,10,0,0,0,"\NULL","https://thuecat.org/resources/215230952334-yyno","Krämerbrücke","Ein bekanntes Wahrzeichen Erfurts ist die Krämerbrücke, die längste bebaute und bewohnte Brücke Europas.Die Krämerbrücke wurde zu Beginn aus Holz und 1325 aus Stein erbaut. Zunächst war die 120 m lange Brücke mit 62 schmalen Häusern bebaut. Später wurden einige der Häuser auf nun mehr 32 zusammengefasst. An beiden Enden der Brücke standen zwei Brückenkopfkirchen. Heute existiert nur noch eine der beiden, die östlich gelegene Ägidienkirche.Auf der Krämerbrücke kann man in Galerien und Boutiquen sehr schön bummeln gehen. Man kann Thüringer Handwerksmeistern bei ihrer Arbeit über die Schulter schauen. Keramik, Porzellan und Holzschnitzereien, Blaudruck und Lauschaer Glas sind beliebte Souvenirs. Cafès, Weinhändler und Feinkostgeschäfte mit Thüringer Spezialitäten laden zum Verweilen ein.",1,1,"{""street"":""Benediktsplatz 1"",""zip"":""99084"",""city"":""Erfurt"",""email"":""service@erfurt-tourismus.de"",""phone"":""+49 361 66 400"",""fax"":"""",""geo"":{""latitude"":50.978772,""longitude"":11.031622}}","[]","[{""mainImage"":true,""type"":""image"",""title"":""Erfurt-Kraemerbruecke-11.jpg"",""description"":""Kr\u00e4merbr\u00fccke in Erfurt"",""url"":""https:\/\/cms.thuecat.org\/o\/adaptive-media\/image\/134362\/Preview-1280x0\/image"",""author"":""Florian Trykowski"",""copyrightYear"":2019,""license"":{""type"":""https:\/\/creativecommons.org\/publicdomain\/zero\/1.0\/deed.de"",""author"":""https:\/\/home.ttgnet.de\/ttg\/projekte\/10006\/90136\/Projektdokumente\/Vergabe%20Rahmenvertrag%20Fotoproduktion""}},{""mainImage"":false,""type"":""image"",""title"":""Erfurt-Kraemerbruecke.jpg"",""description"":""Kr\u00e4merbr\u00fccke in Erfurt"",""url"":""https:\/\/cms.thuecat.org\/o\/adaptive-media\/image\/134288\/Preview-1280x0\/image"",""author"":""Florian Trykowski"",""copyrightYear"":2019,""license"":{""type"":""https:\/\/creativecommons.org\/publicdomain\/zero\/1.0\/deed.de"",""author"":""https:\/\/home.ttgnet.de\/ttg\/projekte\/10006\/90136\/Projektdokumente\/Vergabe%20Rahmenvertrag%20Fotoproduktion""}},{""mainImage"":false,""type"":""image"",""title"":""Erfurt-Kraemerbruecke-13.jpg"",""description"":""Ansicht der Kr\u00e4merbr\u00fccke, Erfurt"",""url"":""https:\/\/cms.thuecat.org\/o\/adaptive-media\/image\/652340\/Preview-1280x0\/image"",""author"":""Florian Trykowski"",""copyrightYear"":2019,""license"":{""type"":""https:\/\/creativecommons.org\/publicdomain\/zero\/1.0\/deed.de"",""author"":""https:\/\/home.ttgnet.de\/ttg\/projekte\/10006\/90136\/Projektdokumente\/Vergabe%20Rahmenvertrag%20Fotoproduktion""}}]",,,"ZeroSanitation","Playground,SeatingPossibilitiesRestArea,SouvenirShop,PlayCornerOrPlayArea",,"ZeroInformationArchitecturalStyle","BicycleLockersEnumMem",,"ZeroDigitalOffer","TakingPicturesPermitted","true","true","true","German,English,French","250:MTR","1,4","{}","https://www.erfurt-tourismus.de/sehenswertes/kraemerbruecke" -,7,10,1,6,6,"\NULL","https://thuecat.org/resources/215230952334-yyno","Merchants' Bridge","Another Erfurt landmark is the Merchants' Bridge (Krämerbrücke), the longest series of inhabited buildings on any bridge in Europe. The Merchants' Bridge is Erfurts most interesting secular construction, initially in wood but rebuilt in stone in 1325. There were originally 62 narrow buildings along its 120-metre length, but subsequent redevelopment left just 32 buildings. Of what was once a pair of bridgehead churches, only the Church of St. Aegidius remains at the eastern end of the bridge today. The Merchants' Bridge is lined with galleries, cafés and boutiques offering traditional crafts, Thuringian blue printed fabrics, hand-painted ceramics, handblown glassware, jewellery, wood carvings, antiques and delicious Thuringian specialities - perfect for browsing.",1,1,"{""street"":""Benediktsplatz 1"",""zip"":""99084"",""city"":""Erfurt"",""email"":""service@erfurt-tourismus.de"",""phone"":""+49 361 66 400"",""fax"":"""",""geo"":{""latitude"":50.978772,""longitude"":11.031622}}","[]","[{""mainImage"":true,""type"":""image"",""title"":""Erfurt-Kraemerbruecke-11.jpg"",""description"":""Kr\u00e4merbr\u00fccke in Erfurt"",""url"":""https:\/\/cms.thuecat.org\/o\/adaptive-media\/image\/134362\/Preview-1280x0\/image"",""author"":""Florian Trykowski"",""copyrightYear"":2019,""license"":{""type"":""https:\/\/creativecommons.org\/publicdomain\/zero\/1.0\/deed.de"",""author"":""https:\/\/home.ttgnet.de\/ttg\/projekte\/10006\/90136\/Projektdokumente\/Vergabe%20Rahmenvertrag%20Fotoproduktion""}},{""mainImage"":false,""type"":""image"",""title"":""Erfurt-Kraemerbruecke.jpg"",""description"":""Kr\u00e4merbr\u00fccke in Erfurt"",""url"":""https:\/\/cms.thuecat.org\/o\/adaptive-media\/image\/134288\/Preview-1280x0\/image"",""author"":""Florian Trykowski"",""copyrightYear"":2019,""license"":{""type"":""https:\/\/creativecommons.org\/publicdomain\/zero\/1.0\/deed.de"",""author"":""https:\/\/home.ttgnet.de\/ttg\/projekte\/10006\/90136\/Projektdokumente\/Vergabe%20Rahmenvertrag%20Fotoproduktion""}},{""mainImage"":false,""type"":""image"",""title"":""Erfurt-Kraemerbruecke-13.jpg"",""description"":""Ansicht der Kr\u00e4merbr\u00fccke, Erfurt"",""url"":""https:\/\/cms.thuecat.org\/o\/adaptive-media\/image\/652340\/Preview-1280x0\/image"",""author"":""Florian Trykowski"",""copyrightYear"":2019,""license"":{""type"":""https:\/\/creativecommons.org\/publicdomain\/zero\/1.0\/deed.de"",""author"":""https:\/\/home.ttgnet.de\/ttg\/projekte\/10006\/90136\/Projektdokumente\/Vergabe%20Rahmenvertrag%20Fotoproduktion""}}]",,,"ZeroSanitation","Playground,SeatingPossibilitiesRestArea,SouvenirShop,PlayCornerOrPlayArea",,"ZeroInformationArchitecturalStyle","BicycleLockersEnumMem",,"ZeroDigitalOffer","TakingPicturesPermitted","true","true","true","German,English,French","250:MTR","1,4","{}","https://www.erfurt-tourismus.de/sehenswertes/kraemerbruecke" -,8,10,2,6,6,"\NULL","https://thuecat.org/resources/215230952334-yyno","Pont de l'épicier","Le pont de l’épicier est un des symboles de la ville d’Erfurt, le plus grand pont habité en continu d’Europe. A l’origine, le pont de l’épicier faisait 120 m de long et comptait 62 maisons étroites, qui furent plus tard regroupées en 32 maisons. Sur le pont de l’épicier se trouvent des galeries et des petites échoppes proposant des étoffes à motifs bleu indigo de Thuringe, des céramiques peintes main, du verre de Lauscha, des bijoux et des sculptures en bois.",1,1,"{""street"":""Benediktsplatz 1"",""zip"":""99084"",""city"":""Erfurt"",""email"":""service@erfurt-tourismus.de"",""phone"":""+49 361 66 400"",""fax"":"""",""geo"":{""latitude"":50.978772,""longitude"":11.031622}}","[]","[{""mainImage"":true,""type"":""image"",""title"":""Erfurt-Kraemerbruecke-11.jpg"",""description"":""Kr\u00e4merbr\u00fccke in Erfurt"",""url"":""https:\/\/cms.thuecat.org\/o\/adaptive-media\/image\/134362\/Preview-1280x0\/image"",""author"":""Florian Trykowski"",""copyrightYear"":2019,""license"":{""type"":""https:\/\/creativecommons.org\/publicdomain\/zero\/1.0\/deed.de"",""author"":""https:\/\/home.ttgnet.de\/ttg\/projekte\/10006\/90136\/Projektdokumente\/Vergabe%20Rahmenvertrag%20Fotoproduktion""}},{""mainImage"":false,""type"":""image"",""title"":""Erfurt-Kraemerbruecke.jpg"",""description"":""Kr\u00e4merbr\u00fccke in Erfurt"",""url"":""https:\/\/cms.thuecat.org\/o\/adaptive-media\/image\/134288\/Preview-1280x0\/image"",""author"":""Florian Trykowski"",""copyrightYear"":2019,""license"":{""type"":""https:\/\/creativecommons.org\/publicdomain\/zero\/1.0\/deed.de"",""author"":""https:\/\/home.ttgnet.de\/ttg\/projekte\/10006\/90136\/Projektdokumente\/Vergabe%20Rahmenvertrag%20Fotoproduktion""}},{""mainImage"":false,""type"":""image"",""title"":""Erfurt-Kraemerbruecke-13.jpg"",""description"":""Ansicht der Kr\u00e4merbr\u00fccke, Erfurt"",""url"":""https:\/\/cms.thuecat.org\/o\/adaptive-media\/image\/652340\/Preview-1280x0\/image"",""author"":""Florian Trykowski"",""copyrightYear"":2019,""license"":{""type"":""https:\/\/creativecommons.org\/publicdomain\/zero\/1.0\/deed.de"",""author"":""https:\/\/home.ttgnet.de\/ttg\/projekte\/10006\/90136\/Projektdokumente\/Vergabe%20Rahmenvertrag%20Fotoproduktion""}}]",,,"ZeroSanitation","Playground,SeatingPossibilitiesRestArea,SouvenirShop,PlayCornerOrPlayArea",,"ZeroInformationArchitecturalStyle","BicycleLockersEnumMem",,"ZeroDigitalOffer","TakingPicturesPermitted","true","true","true","German,English,French","250:MTR","1,4","{}","https://www.erfurt-tourismus.de/sehenswertes/kraemerbruecke" -"tx_thuecat_parking_facility",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, -,"uid","pid","sys_language_uid","l18n_parent","l10n_source","l10n_state","remote_id","title","description","managed_by","address","offers","media","sanitation","other_service","traffic_infrastructure","payment_accepted","distance_to_public_transport",,,,,,,,,,,,,, -,1,10,0,0,0,"\NULL","https://thuecat.org/resources/396420044896-drzt","Parkhaus Domplatz","Das Parkhaus Domplatz befindet sich unmittelbar unterhalb der Zitadelle Petersberg am nördlichen Rand des Domplatzes. Durch die zentrale Lage ist es ein idealer Ausgangspunkt für Stadtbummel und Erkundungen des Zentrums, des Petersbergs und des Andreasviertels.",1,"{""street"":""Bechtheimer Str. 1"",""zip"":""99084"",""city"":""Erfurt"",""email"":""info@stadtwerke-erfurt.de"",""phone"":""+49 361 5640"",""fax"":"""",""geo"":{""latitude"":50.977648905044,""longitude"":11.022127985954299}}","[{""types"":[""ParkingFee""],""title"":"""",""description"":"""",""prices"":[{""title"":"""",""description"":"""",""price"":35,""currency"":""EUR"",""rule"":""PerCar""}]},{""types"":[""ParkingFee""],""title"":"""",""description"":"""",""prices"":[{""title"":"""",""description"":"""",""price"":1.5,""currency"":""EUR"",""rule"":""PerCar""}]},{""types"":[""ParkingFee""],""title"":"""",""description"":"""",""prices"":[{""title"":"""",""description"":"""",""price"":10,""currency"":""EUR"",""rule"":""PerCar""}]},{""types"":[""ParkingFee""],""title"":"""",""description"":"""",""prices"":[{""title"":"""",""description"":"""",""price"":50,""currency"":""EUR"",""rule"":""PerCar""}]}]","[{""mainImage"":true,""type"":""image"",""title"":""Erfurt-Parkhaus-Domplatz.jpg"",""description"":"""",""url"":""https:\/\/cms.thuecat.org\/o\/adaptive-media\/image\/6486108\/Preview-1280x0\/image"",""author"":""Florian Trykowski"",""copyrightYear"":2021,""license"":{""type"":""https:\/\/creativecommons.org\/licenses\/by\/4.0\/"",""author"":""""}}]","ZeroSanitation","ZeroOtherServiceEnumMem","ElectricVehicleCarChargingStationEnumMem",,"240:MTR:CityBus",,,,,,,,,,,,,, -,2,10,1,1,1,"\NULL","https://thuecat.org/resources/396420044896-drzt","Car park Domplatz","The Domplatz multi-storey car park is located directly below the Petersberg Citadel on the northern edge of the Domplatz. Its central location makes it an ideal starting point for strolling through the city and exploring the centre, the Petersberg and the Andreasviertel.",1,"{""street"":""Bechtheimer Str. 1"",""zip"":""99084"",""city"":""Erfurt"",""email"":""info@stadtwerke-erfurt.de"",""phone"":""+49 361 5640"",""fax"":"""",""geo"":{""latitude"":50.977648905044,""longitude"":11.022127985954299}}","[{""types"":[""ParkingFee""],""title"":"""",""description"":"""",""prices"":[{""title"":"""",""description"":"""",""price"":35,""currency"":""EUR"",""rule"":""PerCar""}]},{""types"":[""ParkingFee""],""title"":"""",""description"":"""",""prices"":[{""title"":"""",""description"":"""",""price"":1.5,""currency"":""EUR"",""rule"":""PerCar""}]},{""types"":[""ParkingFee""],""title"":"""",""description"":"""",""prices"":[{""title"":"""",""description"":"""",""price"":10,""currency"":""EUR"",""rule"":""PerCar""}]},{""types"":[""ParkingFee""],""title"":"""",""description"":"""",""prices"":[{""title"":"""",""description"":"""",""price"":50,""currency"":""EUR"",""rule"":""PerCar""}]}]","[{""mainImage"":true,""type"":""image"",""title"":""Erfurt-Parkhaus-Domplatz.jpg"",""description"":"""",""url"":""https:\/\/cms.thuecat.org\/o\/adaptive-media\/image\/6486108\/Preview-1280x0\/image"",""author"":""Florian Trykowski"",""copyrightYear"":2021,""license"":{""type"":""https:\/\/creativecommons.org\/licenses\/by\/4.0\/"",""author"":""""}}]","ZeroSanitation","ZeroOtherServiceEnumMem","ElectricVehicleCarChargingStationEnumMem",,"240:MTR:CityBus",,,,,,,,,,,,,, -,3,10,2,1,1,"\NULL","https://thuecat.org/resources/396420044896-drzt","Parking Domplatz","Le parking à étages de la Domplatz est situé juste en dessous de la citadelle de Petersberg, sur le bord nord de la Domplatz. Son emplacement central en fait un point de départ idéal pour se promener dans la ville et explorer le centre, le Petersberg et l'Andreasviertel.",1,"{""street"":""Bechtheimer Str. 1"",""zip"":""99084"",""city"":""Erfurt"",""email"":""info@stadtwerke-erfurt.de"",""phone"":""+49 361 5640"",""fax"":"""",""geo"":{""latitude"":50.977648905044,""longitude"":11.022127985954299}}","[{""types"":[""ParkingFee""],""title"":"""",""description"":"""",""prices"":[{""title"":"""",""description"":"""",""price"":35,""currency"":""EUR"",""rule"":""PerCar""}]},{""types"":[""ParkingFee""],""title"":"""",""description"":"""",""prices"":[{""title"":"""",""description"":"""",""price"":1.5,""currency"":""EUR"",""rule"":""PerCar""}]},{""types"":[""ParkingFee""],""title"":"""",""description"":"""",""prices"":[{""title"":"""",""description"":"""",""price"":10,""currency"":""EUR"",""rule"":""PerCar""}]},{""types"":[""ParkingFee""],""title"":"""",""description"":"""",""prices"":[{""title"":"""",""description"":"""",""price"":50,""currency"":""EUR"",""rule"":""PerCar""}]}]","[{""mainImage"":true,""type"":""image"",""title"":""Erfurt-Parkhaus-Domplatz.jpg"",""description"":"""",""url"":""https:\/\/cms.thuecat.org\/o\/adaptive-media\/image\/6486108\/Preview-1280x0\/image"",""author"":""Florian Trykowski"",""copyrightYear"":2021,""license"":{""type"":""https:\/\/creativecommons.org\/licenses\/by\/4.0\/"",""author"":""""}}]","ZeroSanitation","ZeroOtherServiceEnumMem","ElectricVehicleCarChargingStationEnumMem",,"240:MTR:CityBus",,,,,,,,,,,,,, -,4,10,0,0,0,"\NULL","https://thuecat.org/resources/440055527204-ocar","Q-Park Anger 1 Parkhaus","Der Q-Park liegt direkt hinter dem Kaufhaus Anger 1 im Erfurter Stadtzentrum und ist über Juri-Gagarin-Ring/Meyfartstraße zu erreichen. Durch die direkte Anbindung an den Stadtring, ist das Parkhaus gut von außerhalb über Schnellstraßen und Autobahnen zu erreichen und befindet sich gleichzeitig im unmittelbaren modernen Zentrum Erfurts.",1,"{""street"":""Anger 1"",""zip"":""99084"",""city"":""Erfurt"",""email"":""servicecenter@q-park.de"",""phone"":""+49 218 18190290"",""fax"":"""",""geo"":{""latitude"":50.977999330565794,""longitude"":11.037503264052475}}","[{""types"":[""ParkingFee""],""title"":"""",""description"":"""",""prices"":[{""title"":"""",""description"":"""",""price"":2.2,""currency"":""EUR"",""rule"":""PerCar""}]},{""types"":[""ParkingFee""],""title"":"""",""description"":"""",""prices"":[{""title"":"""",""description"":"""",""price"":1,""currency"":""EUR"",""rule"":""PerCar""}]},{""types"":[""ParkingFee""],""title"":"""",""description"":"""",""prices"":[{""title"":"""",""description"":"""",""price"":13,""currency"":""EUR"",""rule"":""PerCar""}]}]","[{""mainImage"":true,""type"":""image"",""title"":""Q-Park-Parkhaus-Anger1-Juri-Gagarin-Ring.JPG"",""description"":""Stra\u00dfenansicht des Parkhauses Q-Park am Kaufhaus Anger 1, schr\u00e4g \u00fcber den Juri-Gagarin-Ring"",""url"":""https:\/\/cms.thuecat.org\/o\/adaptive-media\/image\/5197164\/Preview-1280x0\/image"",""author"":""Florian Trykowski"",""copyrightYear"":2020,""license"":{""type"":""https:\/\/creativecommons.org\/licenses\/by\/4.0\/"",""author"":""""}}]","Toilets","ZeroOtherServiceEnumMem",,,"120:MTR",,,,,,,,,,,,,, -,5,10,1,4,4,"\NULL","https://thuecat.org/resources/440055527204-ocar","Q-Park Anger 1 multi-storey car park","The Q-Park is located directly behind the department store Anger 1 in Erfurt's city centre and can be reached via Juri-Gagarin-Ring/Meyfartstraße.",1,"{""street"":""Anger 1"",""zip"":""99084"",""city"":""Erfurt"",""email"":""servicecenter@q-park.de"",""phone"":""+49 218 18190290"",""fax"":"""",""geo"":{""latitude"":50.977999330565794,""longitude"":11.037503264052475}}","[{""types"":[""ParkingFee""],""title"":"""",""description"":"""",""prices"":[{""title"":"""",""description"":"""",""price"":2.2,""currency"":""EUR"",""rule"":""PerCar""}]},{""types"":[""ParkingFee""],""title"":"""",""description"":"""",""prices"":[{""title"":"""",""description"":"""",""price"":1,""currency"":""EUR"",""rule"":""PerCar""}]},{""types"":[""ParkingFee""],""title"":"""",""description"":"""",""prices"":[{""title"":"""",""description"":"""",""price"":13,""currency"":""EUR"",""rule"":""PerCar""}]}]","[{""mainImage"":true,""type"":""image"",""title"":""Q-Park-Parkhaus-Anger1-Juri-Gagarin-Ring.JPG"",""description"":""Stra\u00dfenansicht des Parkhauses Q-Park am Kaufhaus Anger 1, schr\u00e4g \u00fcber den Juri-Gagarin-Ring"",""url"":""https:\/\/cms.thuecat.org\/o\/adaptive-media\/image\/5197164\/Preview-1280x0\/image"",""author"":""Florian Trykowski"",""copyrightYear"":2020,""license"":{""type"":""https:\/\/creativecommons.org\/licenses\/by\/4.0\/"",""author"":""""}}]","Toilets","ZeroOtherServiceEnumMem",,,"120:MTR",,,,,,,,,,,,,, -,6,10,2,4,4,"\NULL","https://thuecat.org/resources/440055527204-ocar","Q-Park Anger 1 parking à étages","Le Q-Park est situé directement derrière le grand magasin Anger 1 dans le centre-ville d'Erfurt et peut être atteint par la Juri-Gagarin-Ring/Meyfartstraße.",1,"{""street"":""Anger 1"",""zip"":""99084"",""city"":""Erfurt"",""email"":""servicecenter@q-park.de"",""phone"":""+49 218 18190290"",""fax"":"""",""geo"":{""latitude"":50.977999330565794,""longitude"":11.037503264052475}}","[{""types"":[""ParkingFee""],""title"":"""",""description"":"""",""prices"":[{""title"":"""",""description"":"""",""price"":2.2,""currency"":""EUR"",""rule"":""PerCar""}]},{""types"":[""ParkingFee""],""title"":"""",""description"":"""",""prices"":[{""title"":"""",""description"":"""",""price"":1,""currency"":""EUR"",""rule"":""PerCar""}]},{""types"":[""ParkingFee""],""title"":"""",""description"":"""",""prices"":[{""title"":"""",""description"":"""",""price"":13,""currency"":""EUR"",""rule"":""PerCar""}]}]","[{""mainImage"":true,""type"":""image"",""title"":""Q-Park-Parkhaus-Anger1-Juri-Gagarin-Ring.JPG"",""description"":""Stra\u00dfenansicht des Parkhauses Q-Park am Kaufhaus Anger 1, schr\u00e4g \u00fcber den Juri-Gagarin-Ring"",""url"":""https:\/\/cms.thuecat.org\/o\/adaptive-media\/image\/5197164\/Preview-1280x0\/image"",""author"":""Florian Trykowski"",""copyrightYear"":2020,""license"":{""type"":""https:\/\/creativecommons.org\/licenses\/by\/4.0\/"",""author"":""""}}]","Toilets","ZeroOtherServiceEnumMem",,,"120:MTR",,,,,,,,,,,,,, -"tx_thuecat_organisation",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, -,"uid","pid","remote_id","title","description",,,,,,,,,,,,,,,,,,,,,,,,,,, -,1,10,"https://thuecat.org/resources/018132452787-ngbe","Erfurt Tourismus und Marketing GmbH","Die Erfurt Tourismus & Marketing GmbH (ETMG) wurde 1997 als offizielle Organisation zur Tourismusförderung in der Landeshauptstadt Erfurt gegründet und nahm am 01.01.1998 die Geschäftstätigkeit auf. - -Zu den Aufgaben zählen die kommunale Tourismusförderung als wesentliches Instrument der Wirtschafts- und Stadtentwicklung der Landeshauptstadt Erfurt, die Positionierung der Stadt Erfurt auf dem nationalen und internationalen Tourismusmarkt als dynamische und sympathische Landeshauptstadt, attraktives Städtereiseziel und Tagungsstandort, die Vervollkommnung des touristischen Serviceangebotes entsprechend den Bedürfnissen der individuellen Gäste und der Tourismuswirtschaft und das Betreiben der Erfurt Tourist Information. - -Im Januar 2009 wurde das Marketing für die Landeshauptstadt Erfurt an die ETMG übertragen und neu geordnet. Die Hauptaufgaben im Stadtmarketing liegen darin, die Wahrnehmung der Stadt in folgenden Bereichen zu verstärken: traditionsreicher und innovativer Wirtschaftsstandort, lebendiger und kreativer Wissenschaftsstandort, attraktiver Wohnstandort mit Flair und Sportstandort mit exzellenten Bedingungen für Nachwuchs- und Spitzensportler. - -Gesellschafter: Stadt Erfurt - -Geschäftsführerin: Frau Dr. Carmen Hildebrandt - -Aufsichtsratsvorsitzender: Herr Dominik Kordon - -Mitarbeiter: ca. 30 Angestellte, 4 Auszubildende",,,,,,,,,,,,,,,,,,,,,,,,,,, diff --git a/Tests/Functional/Fixtures/Import/ImportsTouristAttractionsWithRelations.xml b/Tests/Functional/Fixtures/Import/ImportsTouristAttractionsWithRelations.php similarity index 58% rename from Tests/Functional/Fixtures/Import/ImportsTouristAttractionsWithRelations.xml rename to Tests/Functional/Fixtures/Import/ImportsTouristAttractionsWithRelations.php index 7a7fecb..2a149f8 100644 --- a/Tests/Functional/Fixtures/Import/ImportsTouristAttractionsWithRelations.xml +++ b/Tests/Functional/Fixtures/Import/ImportsTouristAttractionsWithRelations.php @@ -1,51 +1,39 @@ - - - - 1 - 0 - 1613400587 - 1613400558 - 1 - 4 - Rootpage - 1 - - - 10 - 1 - 1613400587 - 1613400558 - 1 - 254 - Storage folder - + - 1 - 0 - English - en-us-gb - en - +declare(strict_types=1); - - 2 - 0 - French - fr - fr - +use TYPO3\CMS\Core\Domain\Repository\PageRepository; - - 1 - 0 - 1613400587 - 1613400558 - 1 - 0 - Three tourist attractions - static - +return [ + 'pages' => [ + 0 => [ + 'uid' => '1', + 'pid' => '0', + 'tstamp' => '1613400587', + 'crdate' => '1613400558', + 'doktype' => PageRepository::DOKTYPE_DEFAULT, + 'title' => 'Rootpage', + 'is_siteroot' => '1', + ], + 1 => [ + 'uid' => '10', + 'pid' => '1', + 'tstamp' => '1613400587', + 'crdate' => '1613400558', + 'doktype' => PageRepository::DOKTYPE_SYSFOLDER, + 'title' => 'Storage folder', + ], + ], + 'tx_thuecat_import_configuration' => [ + 0 => [ + 'uid' => '1', + 'pid' => '0', + 'tstamp' => '1613400587', + 'crdate' => '1613400558', + 'disable' => '0', + 'title' => 'Three tourist attractions', + 'type' => 'static', + 'configuration' => ' @@ -91,19 +79,20 @@ - ]]> - - - - 1 - 10 - 1613401129 - 1613401129 - 1 - 0 - https://thuecat.org/resources/043064193523-jcyt - 1 - 0 - Erfurt - - + ', + ], + ], + 'tx_thuecat_town' => [ + 0 => [ + 'uid' => '1', + 'pid' => '10', + 'tstamp' => '1613401129', + 'crdate' => '1613401129', + 'disable' => '0', + 'remote_id' => 'https://thuecat.org/resources/043064193523-jcyt', + 'managed_by' => '1', + 'tourist_information' => '0', + 'title' => 'Erfurt', + ], + ], +]; diff --git a/Tests/Functional/Fixtures/Import/ImportsTouristAttractionsWithSpecialOpeningHours.csv b/Tests/Functional/Fixtures/Import/ImportsTouristAttractionsWithSpecialOpeningHours.csv deleted file mode 100644 index 8e2b176..0000000 --- a/Tests/Functional/Fixtures/Import/ImportsTouristAttractionsWithSpecialOpeningHours.csv +++ /dev/null @@ -1,4 +0,0 @@ -"tx_thuecat_tourist_attraction",,,,,,,, -,"uid","pid","sys_language_uid","l18n_parent","l10n_source","remote_id","title","special_opening_hours" -,1,10,0,0,0,"https://thuecat.org/resources/835224016581-dara","Dom St. Marien","[{""opens"":""10:00:00"",""closes"":""14:00:00"",""from"":{""date"":""2050-12-31 00:00:00.000000"",""timezone_type"":3,""timezone"":""UTC""},""through"":{""date"":""2050-12-31 00:00:00.000000"",""timezone_type"":3,""timezone"":""UTC""},""daysOfWeek"":[""Saturday""]}]" -,2,10,1,1,1,"https://thuecat.org/resources/835224016581-dara","Cathedral of St. Mary","[{""opens"":""10:00:00"",""closes"":""14:00:00"",""from"":{""date"":""2050-12-31 00:00:00.000000"",""timezone_type"":3,""timezone"":""UTC""},""through"":{""date"":""2050-12-31 00:00:00.000000"",""timezone_type"":3,""timezone"":""UTC""},""daysOfWeek"":[""Saturday""]}]" diff --git a/Tests/Functional/Fixtures/Import/ImportsTouristAttractionsWithSpecialOpeningHours.php b/Tests/Functional/Fixtures/Import/ImportsTouristAttractionsWithSpecialOpeningHours.php new file mode 100644 index 0000000..3be421f --- /dev/null +++ b/Tests/Functional/Fixtures/Import/ImportsTouristAttractionsWithSpecialOpeningHours.php @@ -0,0 +1,28 @@ + [ + 0 => [ + 'uid' => '1', + 'pid' => '10', + 'sys_language_uid' => '0', + 'l18n_parent' => '0', + 'l10n_source' => '0', + 'remote_id' => 'https://thuecat.org/resources/835224016581-dara', + 'title' => 'Dom St. Marien', + 'special_opening_hours' => '[{"opens":"10:00:00","closes":"14:00:00","from":{"date":"2050-12-31 00:00:00.000000","timezone_type":3,"timezone":"UTC"},"through":{"date":"2050-12-31 00:00:00.000000","timezone_type":3,"timezone":"UTC"},"daysOfWeek":["Saturday"]}]', + ], + 1 => [ + 'uid' => '2', + 'pid' => '10', + 'sys_language_uid' => '1', + 'l18n_parent' => '1', + 'l10n_source' => '1', + 'remote_id' => 'https://thuecat.org/resources/835224016581-dara', + 'title' => 'Cathedral of St. Mary', + 'special_opening_hours' => '[{"opens":"10:00:00","closes":"14:00:00","from":{"date":"2050-12-31 00:00:00.000000","timezone_type":3,"timezone":"UTC"},"through":{"date":"2050-12-31 00:00:00.000000","timezone_type":3,"timezone":"UTC"},"daysOfWeek":["Saturday"]}]', + ], + ], +]; diff --git a/Tests/Functional/Fixtures/Import/ImportsTouristInformationWithRelation.csv b/Tests/Functional/Fixtures/Import/ImportsTouristInformationWithRelation.csv deleted file mode 100644 index 8e13dd4..0000000 --- a/Tests/Functional/Fixtures/Import/ImportsTouristInformationWithRelation.csv +++ /dev/null @@ -1,9 +0,0 @@ -"tx_thuecat_tourist_information",,,,,,, -,"uid","pid","remote_id","title","description","managed_by","town" -,1,10,"https://thuecat.org/resources/333039283321-xxwg","Erfurt Tourist Information","Direkt an der Krämerbrücke liegt die Erfurter Tourist Information. Nach einer Modernisierung im Frühjahr 2017 erstrahlt diese in neuem Glanz und ist auch technisch auf dem neuesten Stand. Hier erhalten Sie Stadtpläne, Broschüren zu Erfurt und originelle Souvenirs. Zudem bietet die Tourist Information vielfältige Stadtführungen und Rundfahrten mit Straßenbahn oder Bus sowie kompetente Beratung zu Hotels, Pensionen und Privatunterkünften.",1,1 -"tx_thuecat_town",,,,,,, -,"uid","pid","remote_id","title","description","managed_by", -,1,10,"https://thuecat.org/resources/043064193523-jcyt","Erfurt","Krämerbrücke, Dom, Alte Synagoge – die Thüringer Landeshauptstadt Erfurt hat viele Kulturschätze. Und ein wunderbar junges, studentisches Flair.Eine gute Mischung für alle, die beim Schlendern und Bummeln gerne Städte entdecken: Denn in Erfurt findet man einen wunderbaren mittelalterlichen Stadtkern – mit vielen netten Läden, Cafès und Restaurants. Urlauber wie Einheimische bummeln durch die Gassen der Altstadt, aus allen Ecken wispern Geschichte und alte Geschichten. Stolze historische Bügerhäuser bilden eine der schönsten Altstädte Europas, mittendrin das neugotische Rathaus aus den 1870er-Jahren am Fischmarkt, die spitztürmige St. Severikirche und der mächtige Dom, 1117 erstmals urkundlich erwähnt – auf seiner schier endlosen, kaskadenförmigen Freitreppe chillen Jung und Alt gern in der Abendsonne. Ehe sie weiter ziehen zum Tagesausklang in eine der coolen Kneipen und Bars (Tipp: Oma Lilo oder Cafè Hilgenfeld), in die Wein-Destille am benachbarten Petersberg oder in eins der lässigen Restaurants (Tipp: Mathilda oder Ballenberger), wo zum freundlichen Miteinander eine frische und moderne Küche serviert wird.In Erfurt pulsiert das Leben, lassen Sie sich einfach treiben. Von Ihrer Neugierde ...",1, -"tx_thuecat_organisation",,,,,,, -,"uid","pid","remote_id","title",,, -,1,10,"https://thuecat.org/resources/018132452787-ngbe","Erfurt Tourismus und Marketing GmbH",,, diff --git a/Tests/Functional/Fixtures/Import/ImportsTouristInformationWithRelation.php b/Tests/Functional/Fixtures/Import/ImportsTouristInformationWithRelation.php new file mode 100644 index 0000000..5c30d9b --- /dev/null +++ b/Tests/Functional/Fixtures/Import/ImportsTouristInformationWithRelation.php @@ -0,0 +1,65 @@ + [ + 0 => [ + 'uid' => '1', + 'pid' => '0', + 'tstamp' => '1613400587', + 'crdate' => '1613400558', + 'doktype' => PageRepository::DOKTYPE_DEFAULT, + 'title' => 'Rootpage', + 'is_siteroot' => '1', + ], + 1 => [ + 'uid' => '10', + 'pid' => '1', + 'tstamp' => '1613400587', + 'crdate' => '1613400558', + 'doktype' => PageRepository::DOKTYPE_SYSFOLDER, + 'title' => 'Storage folder', + ], + ], + 'tx_thuecat_import_configuration' => [ + 0 => [ + 'uid' => '1', + 'pid' => '0', + 'tstamp' => '1613400587', + 'crdate' => '1613400558', + 'disable' => '0', + 'title' => 'Tourist Information', + 'type' => 'static', + 'configuration' => ' + + + + + + 10 + + + + + + + + https://thuecat.org/resources/333039283321-xxwg + + + + 0 + + + + + + + + ', + ], + ], +]; diff --git a/Tests/Functional/Fixtures/Import/ImportsTouristInformationWithRelation.xml b/Tests/Functional/Fixtures/Import/ImportsTouristInformationWithRelation.xml deleted file mode 100644 index 853f080..0000000 --- a/Tests/Functional/Fixtures/Import/ImportsTouristInformationWithRelation.xml +++ /dev/null @@ -1,76 +0,0 @@ - - - - 1 - 0 - 1613400587 - 1613400558 - 1 - 4 - Rootpage - 1 - - - 10 - 1 - 1613400587 - 1613400558 - 1 - 254 - Storage folder - - - - 1 - 0 - English - en-us-gb - en - - - - 2 - 0 - French - fr - fr - - - - 1 - 0 - 1613400587 - 1613400558 - 1 - 0 - Tourist Information - static - - - - - - - 10 - - - - - - - - https://thuecat.org/resources/333039283321-xxwg - - - - 0 - - - - - - - - ]]> - - diff --git a/Tests/Functional/Fixtures/Import/ImportsTown.csv b/Tests/Functional/Fixtures/Import/ImportsTown.csv deleted file mode 100644 index ad43804..0000000 --- a/Tests/Functional/Fixtures/Import/ImportsTown.csv +++ /dev/null @@ -1,6 +0,0 @@ -"tx_thuecat_town",,,,,, -,"uid","pid","remote_id","title","description","managed_by" -,1,10,"https://thuecat.org/resources/043064193523-jcyt","Erfurt","Krämerbrücke, Dom, Alte Synagoge – die Thüringer Landeshauptstadt Erfurt hat viele Kulturschätze. Und ein wunderbar junges, studentisches Flair.Eine gute Mischung für alle, die beim Schlendern und Bummeln gerne Städte entdecken: Denn in Erfurt findet man einen wunderbaren mittelalterlichen Stadtkern – mit vielen netten Läden, Cafès und Restaurants. Urlauber wie Einheimische bummeln durch die Gassen der Altstadt, aus allen Ecken wispern Geschichte und alte Geschichten. Stolze historische Bügerhäuser bilden eine der schönsten Altstädte Europas, mittendrin das neugotische Rathaus aus den 1870er-Jahren am Fischmarkt, die spitztürmige St. Severikirche und der mächtige Dom, 1117 erstmals urkundlich erwähnt – auf seiner schier endlosen, kaskadenförmigen Freitreppe chillen Jung und Alt gern in der Abendsonne. Ehe sie weiter ziehen zum Tagesausklang in eine der coolen Kneipen und Bars (Tipp: Oma Lilo oder Cafè Hilgenfeld), in die Wein-Destille am benachbarten Petersberg oder in eins der lässigen Restaurants (Tipp: Mathilda oder Ballenberger), wo zum freundlichen Miteinander eine frische und moderne Küche serviert wird.In Erfurt pulsiert das Leben, lassen Sie sich einfach treiben. Von Ihrer Neugierde ...",1 -"tx_thuecat_organisation",,,,,, -,"uid","pid","remote_id","title",, -,1,10,"https://thuecat.org/resources/018132452787-ngbe","Erfurt Tourismus und Marketing GmbH",, diff --git a/Tests/Functional/Fixtures/Import/ImportsTown.php b/Tests/Functional/Fixtures/Import/ImportsTown.php new file mode 100644 index 0000000..0c36017 --- /dev/null +++ b/Tests/Functional/Fixtures/Import/ImportsTown.php @@ -0,0 +1,65 @@ + [ + 0 => [ + 'uid' => '1', + 'pid' => '0', + 'tstamp' => '1613400587', + 'crdate' => '1613400558', + 'doktype' => PageRepository::DOKTYPE_DEFAULT, + 'title' => 'Rootpage', + 'is_siteroot' => '1', + ], + 1 => [ + 'uid' => '10', + 'pid' => '1', + 'tstamp' => '1613400587', + 'crdate' => '1613400558', + 'doktype' => PageRepository::DOKTYPE_SYSFOLDER, + 'title' => 'Storage folder', + ], + ], + 'tx_thuecat_import_configuration' => [ + 0 => [ + 'uid' => '1', + 'pid' => '0', + 'tstamp' => '1613400587', + 'crdate' => '1613400558', + 'disable' => '0', + 'title' => 'Town', + 'type' => 'static', + 'configuration' => ' + + + + + + 10 + + + + + + + + https://thuecat.org/resources/043064193523-jcyt + + + + 0 + + + + + + + + ', + ], + ], +]; diff --git a/Tests/Functional/Fixtures/Import/ImportsTown.xml b/Tests/Functional/Fixtures/Import/ImportsTown.xml deleted file mode 100644 index 42a0445..0000000 --- a/Tests/Functional/Fixtures/Import/ImportsTown.xml +++ /dev/null @@ -1,76 +0,0 @@ - - - - 1 - 0 - 1613400587 - 1613400558 - 1 - 4 - Rootpage - 1 - - - 10 - 1 - 1613400587 - 1613400558 - 1 - 254 - Storage folder - - - - 1 - 0 - English - en-us-gb - en - - - - 2 - 0 - French - fr - fr - - - - 1 - 0 - 1613400587 - 1613400558 - 1 - 0 - Town - static - - - - - - - 10 - - - - - - - - https://thuecat.org/resources/043064193523-jcyt - - - - 0 - - - - - - - - ]]> - - diff --git a/Tests/Functional/Fixtures/Import/ImportsTownWithRelation.csv b/Tests/Functional/Fixtures/Import/ImportsTownWithRelation.csv deleted file mode 100644 index ad43804..0000000 --- a/Tests/Functional/Fixtures/Import/ImportsTownWithRelation.csv +++ /dev/null @@ -1,6 +0,0 @@ -"tx_thuecat_town",,,,,, -,"uid","pid","remote_id","title","description","managed_by" -,1,10,"https://thuecat.org/resources/043064193523-jcyt","Erfurt","Krämerbrücke, Dom, Alte Synagoge – die Thüringer Landeshauptstadt Erfurt hat viele Kulturschätze. Und ein wunderbar junges, studentisches Flair.Eine gute Mischung für alle, die beim Schlendern und Bummeln gerne Städte entdecken: Denn in Erfurt findet man einen wunderbaren mittelalterlichen Stadtkern – mit vielen netten Läden, Cafès und Restaurants. Urlauber wie Einheimische bummeln durch die Gassen der Altstadt, aus allen Ecken wispern Geschichte und alte Geschichten. Stolze historische Bügerhäuser bilden eine der schönsten Altstädte Europas, mittendrin das neugotische Rathaus aus den 1870er-Jahren am Fischmarkt, die spitztürmige St. Severikirche und der mächtige Dom, 1117 erstmals urkundlich erwähnt – auf seiner schier endlosen, kaskadenförmigen Freitreppe chillen Jung und Alt gern in der Abendsonne. Ehe sie weiter ziehen zum Tagesausklang in eine der coolen Kneipen und Bars (Tipp: Oma Lilo oder Cafè Hilgenfeld), in die Wein-Destille am benachbarten Petersberg oder in eins der lässigen Restaurants (Tipp: Mathilda oder Ballenberger), wo zum freundlichen Miteinander eine frische und moderne Küche serviert wird.In Erfurt pulsiert das Leben, lassen Sie sich einfach treiben. Von Ihrer Neugierde ...",1 -"tx_thuecat_organisation",,,,,, -,"uid","pid","remote_id","title",, -,1,10,"https://thuecat.org/resources/018132452787-ngbe","Erfurt Tourismus und Marketing GmbH",, diff --git a/Tests/Functional/Fixtures/Import/ImportsTownWithRelation.php b/Tests/Functional/Fixtures/Import/ImportsTownWithRelation.php new file mode 100644 index 0000000..9c277ca --- /dev/null +++ b/Tests/Functional/Fixtures/Import/ImportsTownWithRelation.php @@ -0,0 +1,76 @@ + [ + 0 => [ + 'uid' => '1', + 'pid' => '0', + 'tstamp' => '1613400587', + 'crdate' => '1613400558', + 'doktype' => PageRepository::DOKTYPE_DEFAULT, + 'title' => 'Rootpage', + 'is_siteroot' => '1', + ], + 1 => [ + 'uid' => '10', + 'pid' => '1', + 'tstamp' => '1613400587', + 'crdate' => '1613400558', + 'doktype' => PageRepository::DOKTYPE_SYSFOLDER, + 'title' => 'Storage folder', + ], + ], + 'tx_thuecat_import_configuration' => [ + 0 => [ + 'uid' => '1', + 'pid' => '0', + 'tstamp' => '1613400587', + 'crdate' => '1613400558', + 'disable' => '0', + 'title' => 'Town', + 'type' => 'static', + 'configuration' => ' + + + + + + 10 + + + + + + + + https://thuecat.org/resources/043064193523-jcyt + + + + 0 + + + + + + + + ', + ], + ], + 'tx_thuecat_organisation' => [ + 0 => [ + 'uid' => '1', + 'pid' => '10', + 'tstamp' => '1613400587', + 'crdate' => '1613400558', + 'disable' => '0', + 'remote_id' => 'https://thuecat.org/resources/018132452787-ngbe', + 'title' => 'Old title', + ], + ], +]; diff --git a/Tests/Functional/Fixtures/Import/ImportsTownWithRelation.xml b/Tests/Functional/Fixtures/Import/ImportsTownWithRelation.xml deleted file mode 100644 index 1920bf9..0000000 --- a/Tests/Functional/Fixtures/Import/ImportsTownWithRelation.xml +++ /dev/null @@ -1,87 +0,0 @@ - - - - 1 - 0 - 1613400587 - 1613400558 - 1 - 4 - Rootpage - 1 - - - 10 - 1 - 1613400587 - 1613400558 - 1 - 254 - Storage folder - - - - 1 - 0 - English - en-us-gb - en - - - - 2 - 0 - French - fr - fr - - - - 1 - 0 - 1613400587 - 1613400558 - 1 - 0 - Town - static - - - - - - - 10 - - - - - - - - https://thuecat.org/resources/043064193523-jcyt - - - - 0 - - - - - - - - ]]> - - - - 1 - 10 - 1613400587 - 1613400558 - 1 - 0 - https://thuecat.org/resources/018132452787-ngbe - Old title - - diff --git a/Tests/Functional/Fixtures/Import/UpdatesExistingOrganization.php b/Tests/Functional/Fixtures/Import/UpdatesExistingOrganization.php new file mode 100644 index 0000000..4cc81eb --- /dev/null +++ b/Tests/Functional/Fixtures/Import/UpdatesExistingOrganization.php @@ -0,0 +1,76 @@ + [ + 0 => [ + 'uid' => '1', + 'pid' => '0', + 'tstamp' => '1613400587', + 'crdate' => '1613400558', + 'doktype' => PageRepository::DOKTYPE_DEFAULT, + 'title' => 'Rootpage', + 'is_siteroot' => '1', + ], + 1 => [ + 'uid' => '10', + 'pid' => '1', + 'tstamp' => '1613400587', + 'crdate' => '1613400558', + 'doktype' => PageRepository::DOKTYPE_SYSFOLDER, + 'title' => 'Storage folder', + ], + ], + 'tx_thuecat_import_configuration' => [ + 0 => [ + 'uid' => '1', + 'pid' => '0', + 'tstamp' => '1613400587', + 'crdate' => '1613400558', + 'disable' => '0', + 'title' => 'Single Fresh Organisation', + 'type' => 'static', + 'configuration' => ' + + + + + + 10 + + + + + + + + https://thuecat.org/resources/018132452787-ngbe + + + + 0 + + + + + + + + ', + ], + ], + 'tx_thuecat_organisation' => [ + 0 => [ + 'uid' => '1', + 'pid' => '10', + 'tstamp' => '1613400587', + 'crdate' => '1613400558', + 'disable' => '0', + 'remote_id' => 'https://thuecat.org/resources/018132452787-ngbe', + 'title' => 'Old title', + ], + ], +]; diff --git a/Tests/Functional/Fixtures/Import/UpdatesExistingOrganization.xml b/Tests/Functional/Fixtures/Import/UpdatesExistingOrganization.xml deleted file mode 100644 index fb46747..0000000 --- a/Tests/Functional/Fixtures/Import/UpdatesExistingOrganization.xml +++ /dev/null @@ -1,71 +0,0 @@ - - - - 1 - 0 - 1613400587 - 1613400558 - 1 - 4 - Rootpage - 1 - - - 10 - 1 - 1613400587 - 1613400558 - 1 - 254 - Storage folder - - - - 1 - 0 - 1613400587 - 1613400558 - 1 - 0 - Single Fresh Organisation - static - - - - - - - 10 - - - - - - - - https://thuecat.org/resources/018132452787-ngbe - - - - 0 - - - - - - - - ]]> - - - - 1 - 10 - 1613400587 - 1613400558 - 1 - 0 - https://thuecat.org/resources/018132452787-ngbe - Old title - - diff --git a/Tests/Functional/FrontendTest.php b/Tests/Functional/FrontendTest.php index 4d204f4..7848a6a 100644 --- a/Tests/Functional/FrontendTest.php +++ b/Tests/Functional/FrontendTest.php @@ -23,11 +23,16 @@ declare(strict_types=1); namespace WerkraumMedia\ThueCat\Tests\Functional; +use Codappix\Typo3PhpDatasets\TestingFramework; +use DateTimeImmutable; +use PHPUnit\Framework\Attributes\Test; use TYPO3\TestingFramework\Core\Functional\Framework\Frontend\InternalRequest; use TYPO3\TestingFramework\Core\Functional\FunctionalTestCase; class FrontendTest extends FunctionalTestCase { + use TestingFramework; + protected function setUp(): void { $this->coreExtensionsToLoad = [ @@ -35,7 +40,7 @@ class FrontendTest extends FunctionalTestCase ]; $this->testExtensionsToLoad = [ - 'typo3conf/ext/thuecat/', + 'werkraummedia/thuecat', ]; $this->pathsToLinkInTestInstance = [ @@ -44,7 +49,7 @@ class FrontendTest extends FunctionalTestCase parent::setUp(); - $this->importDataSet('EXT:thuecat/Tests/Functional/Fixtures/Frontend/Content.xml'); + $this->importPHPDataSet(__DIR__ . '/Fixtures/Frontend/Content.php'); $this->setUpFrontendRootPage(1, [ 'EXT:fluid_styled_content/Configuration/TypoScript/setup.typoscript', 'EXT:thuecat/Configuration/TypoScript/ContentElements/setup.typoscript', @@ -52,17 +57,15 @@ class FrontendTest extends FunctionalTestCase ]); } - /** - * @test - */ + #[Test] public function touristAttractionContentElementIsRendered(): void { - $this->importDataSet('EXT:thuecat/Tests/Functional/Fixtures/Frontend/TouristAttractions.xml'); + $this->importPHPDataSet(__DIR__ . '/Fixtures/Frontend/TouristAttractions.php'); $request = new InternalRequest(); $request = $request->withPageId(2); - $result = $this->executeFrontendRequest($request); + $result = $this->executeFrontendSubRequest($request); self::assertSame(200, $result->getStatusCode()); @@ -252,13 +255,11 @@ class FrontendTest extends FunctionalTestCase self::assertStringContainsString('WC für Menschen mit Behinderung', (string)$result->getBody()); } - /** - * @test - */ + #[Test] public function touristAttractionContentElementRespectsEditorialSorting(): void { - $this->importDataSet('EXT:thuecat/Tests/Functional/Fixtures/Frontend/TouristAttractions.xml'); - $this->importDataSet('EXT:thuecat/Tests/Functional/Fixtures/Frontend/SecondTouristAttraction.xml'); + $this->importPHPDataSet(__DIR__ . '/Fixtures/Frontend/TouristAttractions.php'); + $this->importPHPDataSet(__DIR__ . '/Fixtures/Frontend/SecondTouristAttraction.php'); $this->getConnectionPool()->getConnectionForTable('tt_content')->update( 'tt_content', @@ -271,7 +272,7 @@ class FrontendTest extends FunctionalTestCase $request = new InternalRequest(); $request = $request->withPageId(2); - $html = (string)$this->executeFrontendRequest($request)->getBody(); + $html = (string)$this->executeFrontendSubRequest($request)->getBody(); self::assertGreaterThan( stripos($html, 'Eine weitere Attraktion'), @@ -279,119 +280,105 @@ class FrontendTest extends FunctionalTestCase ); } - /** - * @test - */ + #[Test] public function touristAttractionWithPetsFalse(): void { - $this->importDataSet('EXT:thuecat/Tests/Functional/Fixtures/Frontend/TouristAttractionsForPets.xml'); + $this->importPHPDataSet(__DIR__ . '/Fixtures/Frontend/TouristAttractionsForPets.php'); $request = new InternalRequest(); $request = $request->withPageId(4); - $result = $this->executeFrontendRequest($request); + $result = $this->executeFrontendSubRequest($request); self::assertSame(200, $result->getStatusCode()); self::assertStringContainsString('Keine Tiere erlaubt', (string)$result->getBody()); } - /** - * @test - */ + #[Test] public function touristAttractionWithPetsTrue(): void { - $this->importDataSet('EXT:thuecat/Tests/Functional/Fixtures/Frontend/TouristAttractionsForPets.xml'); + $this->importPHPDataSet(__DIR__ . '/Fixtures/Frontend/TouristAttractionsForPets.php'); $request = new InternalRequest(); $request = $request->withPageId(5); - $result = $this->executeFrontendRequest($request); + $result = $this->executeFrontendSubRequest($request); self::assertSame(200, $result->getStatusCode()); self::assertStringContainsString('Tiere erlaubt', (string)$result->getBody()); } - /** - * @test - */ + #[Test] public function touristAttractionWithIsAccessibleForFreeFalse(): void { - $this->importDataSet('EXT:thuecat/Tests/Functional/Fixtures/Frontend/TouristAttractionsForIsAccessibleForFree.xml'); + $this->importPHPDataSet(__DIR__ . '/Fixtures/Frontend/TouristAttractionsForIsAccessibleForFree.php'); $request = new InternalRequest(); $request = $request->withPageId(4); - $result = $this->executeFrontendRequest($request); + $result = $this->executeFrontendSubRequest($request); self::assertSame(200, $result->getStatusCode()); self::assertStringContainsString('kein freier Eintritt', (string)$result->getBody()); } - /** - * @test - */ + #[Test] public function touristAttractionWithIsAccessibleForFreeTrue(): void { - $this->importDataSet('EXT:thuecat/Tests/Functional/Fixtures/Frontend/TouristAttractionsForIsAccessibleForFree.xml'); + $this->importPHPDataSet(__DIR__ . '/Fixtures/Frontend/TouristAttractionsForIsAccessibleForFree.php'); $request = new InternalRequest(); $request = $request->withPageId(5); - $result = $this->executeFrontendRequest($request); + $result = $this->executeFrontendSubRequest($request); self::assertSame(200, $result->getStatusCode()); self::assertStringContainsString('freier Eintritt', (string)$result->getBody()); } - /** - * @test - */ + #[Test] public function touristAttractionWithPublicAccessFalse(): void { - $this->importDataSet('EXT:thuecat/Tests/Functional/Fixtures/Frontend/TouristAttractionsForPublicAccess.xml'); + $this->importPHPDataSet(__DIR__ . '/Fixtures/Frontend/TouristAttractionsForPublicAccess.php'); $request = new InternalRequest(); $request = $request->withPageId(4); - $result = $this->executeFrontendRequest($request); + $result = $this->executeFrontendSubRequest($request); self::assertSame(200, $result->getStatusCode()); self::assertStringContainsString('nicht öffentlich zugänglich', (string)$result->getBody()); } - /** - * @test - */ + #[Test] public function touristAttractionWithPublicAccessTrue(): void { - $this->importDataSet('EXT:thuecat/Tests/Functional/Fixtures/Frontend/TouristAttractionsForPublicAccess.xml'); + $this->importPHPDataSet(__DIR__ . '/Fixtures/Frontend/TouristAttractionsForPublicAccess.php'); $request = new InternalRequest(); $request = $request->withPageId(5); - $result = $this->executeFrontendRequest($request); + $result = $this->executeFrontendSubRequest($request); self::assertSame(200, $result->getStatusCode()); self::assertStringContainsString('öffentlich zugänglich', (string)$result->getBody()); } - /** - * @test - */ + #[Test] public function pricesAreSorted(): void { - $this->importDataSet('EXT:thuecat/Tests/Functional/Fixtures/Frontend/TouristAttractionWithPrices.xml'); + $this->importPHPDataSet(__DIR__ . '/Fixtures/Frontend/TouristAttractionWithPrices.php'); $request = new InternalRequest(); $request = $request->withPageId(2); - $result = $this->executeFrontendRequest($request); + $result = $this->executeFrontendSubRequest($request); self::assertSame(200, $result->getStatusCode()); @@ -414,17 +401,15 @@ class FrontendTest extends FunctionalTestCase ); } - /** - * @test - */ + #[Test] public function offersAreSortedByType(): void { - $this->importDataSet('EXT:thuecat/Tests/Functional/Fixtures/Frontend/TouristAttractionWithOfferTypes.xml'); + $this->importPHPDataSet(__DIR__ . '/Fixtures/Frontend/TouristAttractionWithOfferTypes.php'); $request = new InternalRequest(); $request = $request->withPageId(2); - $result = $this->executeFrontendRequest($request); + $result = $this->executeFrontendSubRequest($request); self::assertSame(200, $result->getStatusCode()); @@ -452,15 +437,13 @@ class FrontendTest extends FunctionalTestCase ); } - /** - * @test - */ + #[Test] public function openingHoursAreFilteredByThough(): void { - $this->importDataSet('EXT:thuecat/Tests/Functional/Fixtures/Frontend/TouristAttractionsOpeningHours.xml'); + $this->importPHPDataSet(__DIR__ . '/Fixtures/Frontend/TouristAttractionsOpeningHours.php'); - $hidden = new \DateTimeImmutable('yesterday'); - $available = new \DateTimeImmutable('tomorrow'); + $hidden = new DateTimeImmutable('yesterday'); + $available = new DateTimeImmutable('tomorrow'); $this->getConnectionPool() ->getConnectionForTable('tx_thuecat_tourist_attraction') @@ -499,12 +482,13 @@ class FrontendTest extends FunctionalTestCase ], ])], ['uid' => 1] - ); + ) + ; $request = new InternalRequest(); $request = $request->withPageId(2); - $result = (string)$this->executeFrontendRequest($request)->getBody(); + $result = (string)$this->executeFrontendSubRequest($request)->getBody(); self::assertStringNotContainsString('14:00', $result); self::assertStringNotContainsString('13:00', $result); @@ -519,16 +503,14 @@ class FrontendTest extends FunctionalTestCase self::assertStringContainsString($available->format('d.m.Y'), $result); } - /** - * @test - */ + #[Test] public function openingHoursAreSortedByFrom(): void { - $this->importDataSet('EXT:thuecat/Tests/Functional/Fixtures/Frontend/TouristAttractionsOpeningHours.xml'); + $this->importPHPDataSet(__DIR__ . '/Fixtures/Frontend/TouristAttractionsOpeningHours.php'); - $fromFirstOpening = new \DateTimeImmutable('today'); - $fromSecondOpening = new \DateTimeImmutable('+2 days'); - $fromThirdOpening = new \DateTimeImmutable('+7 days'); + $fromFirstOpening = new DateTimeImmutable('today'); + $fromSecondOpening = new DateTimeImmutable('+2 days'); + $fromThirdOpening = new DateTimeImmutable('+7 days'); $this->getConnectionPool() ->getConnectionForTable('tx_thuecat_tourist_attraction') @@ -582,12 +564,13 @@ class FrontendTest extends FunctionalTestCase ], ])], ['uid' => 1] - ); + ) + ; $request = new InternalRequest(); $request = $request->withPageId(2); - $result = (string)$this->executeFrontendRequest($request)->getBody(); + $result = (string)$this->executeFrontendSubRequest($request)->getBody(); $positionFirstHour = mb_strpos($result, $fromFirstOpening->format('d.m.Y')); $positionSecondHour = mb_strpos($result, $fromSecondOpening->format('d.m.Y')); @@ -597,16 +580,14 @@ class FrontendTest extends FunctionalTestCase self::assertLessThan($positionSecondHour, $positionFirstHour, 'Second hour does not come after first hour.'); } - /** - * @test - */ + #[Test] public function specialOpeningHoursAreRendered(): void { - $this->importDataSet('EXT:thuecat/Tests/Functional/Fixtures/Frontend/TouristAttractionsOpeningHours.xml'); + $this->importPHPDataSet(__DIR__ . '/Fixtures/Frontend/TouristAttractionsOpeningHours.php'); - $hidden = new \DateTimeImmutable('yesterday'); - $available = new \DateTimeImmutable('tomorrow'); - $available2 = new \DateTimeImmutable('+3 days'); + $hidden = new DateTimeImmutable('yesterday'); + $available = new DateTimeImmutable('tomorrow'); + $available2 = new DateTimeImmutable('+3 days'); $this->getConnectionPool() ->getConnectionForTable('tx_thuecat_tourist_attraction') @@ -660,12 +641,13 @@ class FrontendTest extends FunctionalTestCase ], ])], ['uid' => 1] - ); + ) + ; $request = new InternalRequest(); $request = $request->withPageId(2); - $result = (string)$this->executeFrontendRequest($request)->getBody(); + $result = (string)$this->executeFrontendSubRequest($request)->getBody(); self::assertStringNotContainsString('11:00', $result); self::assertStringNotContainsString('12:00', $result); @@ -691,17 +673,15 @@ class FrontendTest extends FunctionalTestCase self::assertLessThan($positionSecondHour, $positionFirstHour, 'Second hour does not come after first hour.'); } - /** - * @test - */ + #[Test] public function editorialImagesOfTouristAttractionAreRenderedForDefaultLanguage(): void { - $this->importDataSet('EXT:thuecat/Tests/Functional/Fixtures/Frontend/TouristAttractionWithEditorialImages.xml'); + $this->importPHPDataSet(__DIR__ . '/Fixtures/Frontend/TouristAttractionWithEditorialImages.php'); $request = new InternalRequest(); $request = $request->withPageId(2); - $html = (string)$this->executeFrontendRequest($request)->getBody(); + $html = (string)$this->executeFrontendSubRequest($request)->getBody(); self::assertStringContainsString( '', diff --git a/Tests/Functional/GuzzleClientFaker.php b/Tests/Functional/GuzzleClientFaker.php index 27295b6..515a1fe 100644 --- a/Tests/Functional/GuzzleClientFaker.php +++ b/Tests/Functional/GuzzleClientFaker.php @@ -4,6 +4,7 @@ declare(strict_types=1); namespace WerkraumMedia\ThueCat\Tests\Functional; +use Exception; use GuzzleHttp\Handler\MockHandler; use GuzzleHttp\Psr7\Response; use Symfony\Component\HttpFoundation\Response as SymfonyResponse; @@ -21,7 +22,6 @@ class GuzzleClientFaker $GLOBALS['TYPO3_CONF_VARS']['HTTP']['handler']['faker'] = function (callable $handler) { return self::getMockHandler(); }; - } /** @@ -40,7 +40,7 @@ class GuzzleClientFaker { $fileContent = file_get_contents($fileName); if ($fileContent === false) { - throw new \Exception('Could not load file: ' . $fileName, 1656485162); + throw new Exception('Could not load file: ' . $fileName, 1656485162); } self::appendResponseFromContent($fileContent); diff --git a/Tests/Functional/Import/EntityMapping/BaseInfosTest.php b/Tests/Functional/Import/EntityMapping/BaseInfosTest.php index e9d46d8..c46ef5f 100644 --- a/Tests/Functional/Import/EntityMapping/BaseInfosTest.php +++ b/Tests/Functional/Import/EntityMapping/BaseInfosTest.php @@ -23,23 +23,16 @@ declare(strict_types=1); namespace WerkraumMedia\ThueCat\Tests\Functional\Import\EntityMapping; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; -use WerkraumMedia\ThueCat\Domain\Import\EntityMapper; -use WerkraumMedia\ThueCat\Domain\Import\EntityMapper\JsonDecode; use WerkraumMedia\ThueCat\Domain\Import\Entity\Base; use WerkraumMedia\ThueCat\Domain\Import\Entity\Properties\ForeignReference; +use WerkraumMedia\ThueCat\Domain\Import\EntityMapper; +use WerkraumMedia\ThueCat\Domain\Import\EntityMapper\JsonDecode; - -/** - * @covers \WerkraumMedia\ThueCat\Domain\Import\Converter\ObjectMapping - * @covers \WerkraumMedia\ThueCat\Domain\Import\Entity\Base - * @covers \WerkraumMedia\ThueCat\Domain\Import\Entity\Properies\ForeignReference - */ class BaseInfosTest extends TestCase { - /** - * @test - */ + #[Test] public function instanceOfBaseIsReturnedIfRequestes(): void { $subject = new EntityMapper(); @@ -52,9 +45,7 @@ class BaseInfosTest extends TestCase self::assertInstanceOf(Base::class, $result); } - /** - * @test - */ + #[Test] public function returnsDefaultValuesIfNotProvidedForMapping(): void { $subject = new EntityMapper(); @@ -74,9 +65,7 @@ class BaseInfosTest extends TestCase self::assertNull($result->getManagedBy()); } - /** - * @test - */ + #[Test] public function mapsIncomingDataToProperties(): void { $subject = new EntityMapper(); @@ -97,9 +86,7 @@ class BaseInfosTest extends TestCase self::assertSame(['https://example.com/the-thing'], $result->getUrls()); } - /** - * @test - */ + #[Test] public function mapsIncomingPhoto(): void { $subject = new EntityMapper(); @@ -117,9 +104,7 @@ class BaseInfosTest extends TestCase self::assertSame('https://thuecat.org/resources/835224016581-dara', $result->getPhoto()->getId()); } - /** - * @test - */ + #[Test] public function mapsIncomingImages(): void { $subject = new EntityMapper(); @@ -146,9 +131,7 @@ class BaseInfosTest extends TestCase self::assertSame('https://thuecat.org/resources/835224016581-2nd', $result->getImages()[1]->getId()); } - /** - * @test - */ + #[Test] public function mapsIncomingManagedBy(): void { $subject = new EntityMapper(); diff --git a/Tests/Functional/Import/EntityMapping/JsonDecodingTest.php b/Tests/Functional/Import/EntityMapping/JsonDecodingTest.php index 3fead38..1feb744 100644 --- a/Tests/Functional/Import/EntityMapping/JsonDecodingTest.php +++ b/Tests/Functional/Import/EntityMapping/JsonDecodingTest.php @@ -23,17 +23,13 @@ declare(strict_types=1); namespace WerkraumMedia\ThueCat\Tests\Functional\Import\EntityMapping; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; use WerkraumMedia\ThueCat\Domain\Import\EntityMapper\JsonDecode; -/** - * @covers \WerkraumMedia\ThueCat\Domain\Import\EntityMapper\JsonDecode; - */ class JsonDecodingTest extends TestCase { - /** - * @test - */ + #[Test] public function canBeCreated(): void { $subject = new JsonDecode(); @@ -44,13 +40,11 @@ class JsonDecodingTest extends TestCase ); } - /** - * @test - */ + #[Test] public function decodesPropertyWithMultipleLanguagesProvidingActiveOne(): void { $subject = new JsonDecode(); - $result = $subject->decode((string) json_encode([ + $result = $subject->decode((string)json_encode([ 'schema:name' => [ [ '@language' => 'de', @@ -70,13 +64,11 @@ class JsonDecodingTest extends TestCase ], $result); } - /** - * @test - */ + #[Test] public function decodesPropertyWithSingleLanguageMatchingActive(): void { $subject = new JsonDecode(); - $result = $subject->decode((string) json_encode([ + $result = $subject->decode((string)json_encode([ 'schema:name' => [ '@language' => 'en', '@value' => 'English Text', @@ -90,13 +82,11 @@ class JsonDecodingTest extends TestCase ], $result); } - /** - * @test - */ + #[Test] public function decodesPropertyWithSingleLanguageNotMatchingActive(): void { $subject = new JsonDecode(); - $result = $subject->decode((string) json_encode([ + $result = $subject->decode((string)json_encode([ 'schema:name' => [ '@language' => 'de', '@value' => 'German Text', @@ -110,13 +100,11 @@ class JsonDecodingTest extends TestCase ], $result); } - /** - * @test - */ + #[Test] public function decodesPropertyWithMultipleLanguagesAndFormatsProvidingActiveLanguage(): void { $subject = new JsonDecode(); - $result = $subject->decode((string) json_encode([ + $result = $subject->decode((string)json_encode([ 'schema:description' => [ 0 => [ '@language' => 'en', @@ -156,13 +144,11 @@ class JsonDecodingTest extends TestCase ], $result); } - /** - * @test - */ + #[Test] public function decodesPropertyWithMultipleLanguagesNotMatchingRequestOne(): void { $subject = new JsonDecode(); - $result = $subject->decode((string) json_encode([ + $result = $subject->decode((string)json_encode([ 'schema:description' => [ 0 => [ '@language' => 'en', @@ -182,13 +168,11 @@ class JsonDecodingTest extends TestCase ], $result); } - /** - * @test - */ + #[Test] public function decodesSingleValueNotRelatedToLanguage(): void { $subject = new JsonDecode(); - $result = $subject->decode((string) json_encode([ + $result = $subject->decode((string)json_encode([ 'schema:geo' => [ 'schema:latitude' => [ '@type' => 'schema:Number', @@ -211,13 +195,11 @@ class JsonDecodingTest extends TestCase ], $result); } - /** - * @test - */ + #[Test] public function decodesNestedObjectStructures(): void { $subject = new JsonDecode(); - $result = $subject->decode((string) json_encode([ + $result = $subject->decode((string)json_encode([ '@id' => 'https://thuecat.org/resources/835224016581-dara', 'schema:name' => [ '@language' => 'en', @@ -261,13 +243,11 @@ class JsonDecodingTest extends TestCase ], $result); } - /** - * @test - */ + #[Test] public function decodesOpeningHours(): void { $subject = new JsonDecode(); - $result = $subject->decode((string) json_encode([ + $result = $subject->decode((string)json_encode([ 'schema:openingHoursSpecification' => [ 0 => [ '@id' => 'genid-7bb7d92bd6624bdf84634c86e8acdbb4-b4', @@ -371,13 +351,11 @@ class JsonDecodingTest extends TestCase ], $result); } - /** - * @test - */ + #[Test] public function keepsArrayOfValueAndTypeIfConfigured(): void { $subject = new JsonDecode(); - $result = $subject->decode((string) json_encode([ + $result = $subject->decode((string)json_encode([ 'thuecat:AccessibilitySearchCriteria' => [ 0 => [ '@type' => 'thuecat:facilityAccessibilityWalking', diff --git a/Tests/Functional/Import/EntityMapping/PlaceInfosTest.php b/Tests/Functional/Import/EntityMapping/PlaceInfosTest.php index 654d4ff..1b6f77b 100644 --- a/Tests/Functional/Import/EntityMapping/PlaceInfosTest.php +++ b/Tests/Functional/Import/EntityMapping/PlaceInfosTest.php @@ -21,25 +21,18 @@ declare(strict_types=1); * 02110-1301, USA. */ -namespace WerkraumMedia\ThueCat\Tests\Functional\ObjectMapping; +namespace WerkraumMedia\ThueCat\Tests\Functional\Import\EntityMapping; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; -use WerkraumMedia\ThueCat\Domain\Import\EntityMapper; -use WerkraumMedia\ThueCat\Domain\Import\EntityMapper\JsonDecode; use WerkraumMedia\ThueCat\Domain\Import\Entity\Place; use WerkraumMedia\ThueCat\Domain\Import\Entity\Properties\Address; +use WerkraumMedia\ThueCat\Domain\Import\EntityMapper; +use WerkraumMedia\ThueCat\Domain\Import\EntityMapper\JsonDecode; -/** - * @covers \WerkraumMedia\ThueCat\Domain\Import\EntityMapper - * @covers \WerkraumMedia\ThueCat\Domain\Import\EntityMapper\JsonDecode - * @uses \WerkraumMedia\ThueCat\Domain\Import\Entity\Place - * @uses \WerkraumMedia\ThueCat\Domain\Import\Entity\Properties\Address - */ class PlaceInfosTest extends TestCase { - /** - * @test - */ + #[Test] public function instanceOfPlaceIsReturnedIfRequestes(): void { $subject = new EntityMapper(); @@ -52,9 +45,7 @@ class PlaceInfosTest extends TestCase self::assertInstanceOf(Place::class, $result); } - /** - * @test - */ + #[Test] public function returnsDefaultValuesIfNotProvidedForMapping(): void { $subject = new EntityMapper(); @@ -68,9 +59,7 @@ class PlaceInfosTest extends TestCase self::assertSame([], $result->getOpeningHoursSpecification()); } - /** - * @test - */ + #[Test] public function mapsIncomingAddress(): void { $subject = new EntityMapper(); @@ -136,9 +125,7 @@ class PlaceInfosTest extends TestCase self::assertSame('dominformation@domberg-erfurt.de', $result->getAddress()->getEmail()); } - /** - * @test - */ + #[Test] public function mapsIncomingMultipleUrls(): void { $subject = new EntityMapper(); @@ -165,9 +152,7 @@ class PlaceInfosTest extends TestCase ], $result->getUrls()); } - /** - * @test - */ + #[Test] public function mapsIncomingSingleUrl(): void { $subject = new EntityMapper(); diff --git a/Tests/Functional/ImportConfigurationCommandTest.php b/Tests/Functional/ImportConfigurationCommandTest.php index eb5e1e5..5289f2b 100644 --- a/Tests/Functional/ImportConfigurationCommandTest.php +++ b/Tests/Functional/ImportConfigurationCommandTest.php @@ -24,37 +24,30 @@ declare(strict_types=1); namespace WerkraumMedia\ThueCat\Tests\Functional; use Exception; +use PHPUnit\Framework\Attributes\Test; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Exception\RuntimeException; use Symfony\Component\Console\Tester\CommandTester; use WerkraumMedia\ThueCat\Command\ImportConfigurationCommand; -/** - * @covers \WerkraumMedia\ThueCat\Command\ImportConfigurationCommand - * @testdox The 'thuecat:importviaconfiguration' command - */ -final class ImportConfigurationCommandTest extends AbstractImportTest +final class ImportConfigurationCommandTest extends AbstractImportTestCase { - /** - * @test - */ + #[Test] public function canImport(): void { $subject = $this->getContainer()->get(ImportConfigurationCommand::class); self::assertInstanceOf(Command::class, $subject); - $this->importDataSet(__DIR__ . '/Fixtures/Import/ImportsFreshOrganization.xml'); + $this->importPHPDataSet(__DIR__ . '/Fixtures/Import/ImportsFreshOrganization.php'); GuzzleClientFaker::appendResponseFromFile(__DIR__ . '/Fixtures/Import/Guzzle/thuecat.org/resources/018132452787-ngbe.json'); $tester = new CommandTester($subject); $tester->execute(['configuration' => 1], ['capture_stderr_separately' => true]); - $this->assertCSVDataSet('EXT:thuecat/Tests/Functional/Fixtures/Import/ImportsFreshOrganization.csv'); + $this->assertPHPDataSet(__DIR__ . '/Assertions/Import/ImportsFreshOrganization.php'); } - /** - * @test - */ + #[Test] public function throwsExceptionOnNoneExistingConfiguration(): void { $subject = $this->getContainer()->get(ImportConfigurationCommand::class); @@ -69,9 +62,7 @@ final class ImportConfigurationCommandTest extends AbstractImportTest $tester->execute(['configuration' => 1], ['capture_stderr_separately' => true]); } - /** - * @test - */ + #[Test] public function throwsExceptionOnMissingArgument(): void { $subject = $this->getContainer()->get(ImportConfigurationCommand::class); @@ -86,9 +77,7 @@ final class ImportConfigurationCommandTest extends AbstractImportTest $tester->execute([], ['capture_stderr_separately' => true]); } - /** - * @test - */ + #[Test] public function throwsExceptionOnNoneNumericConfigurationArgument(): void { $subject = $this->getContainer()->get(ImportConfigurationCommand::class); diff --git a/Tests/Functional/ImportTest.php b/Tests/Functional/ImportTest.php index 2a570f2..a30e2fe 100644 --- a/Tests/Functional/ImportTest.php +++ b/Tests/Functional/ImportTest.php @@ -23,66 +23,31 @@ namespace WerkraumMedia\ThueCat\Tests\Functional; * 02110-1301, USA. */ +use PHPUnit\Framework\Attributes\Test; +use WerkraumMedia\ThueCat\Domain\Import\ImportConfiguration; use WerkraumMedia\ThueCat\Domain\Import\Importer; use WerkraumMedia\ThueCat\Domain\Repository\Backend\ImportConfigurationRepository; -/** - * @covers \WerkraumMedia\ThueCat\DependencyInjection\ConverterPass - * @covers \WerkraumMedia\ThueCat\DependencyInjection\UrlProvidersPass - * @covers \WerkraumMedia\ThueCat\Domain\Import\Importer\SaveData - * @covers \WerkraumMedia\ThueCat\Domain\Repository\Backend\ImportLogRepository - * @covers \WerkraumMedia\ThueCat\Domain\Repository\Backend\OrganisationRepository - * @covers \WerkraumMedia\ThueCat\Domain\Repository\Backend\TownRepository - * @covers \WerkraumMedia\ThueCat\Extension - * @covers \WerkraumMedia\ThueCat\Typo3Wrapper\TranslationService - * - * @uses \WerkraumMedia\ThueCat\Domain\Import\Converter\Organisation - * @uses \WerkraumMedia\ThueCat\Domain\Import\Converter\Registry - * @uses \WerkraumMedia\ThueCat\Domain\Import\Converter\TouristAttraction - * @uses \WerkraumMedia\ThueCat\Domain\Import\Converter\TouristInformation - * @uses \WerkraumMedia\ThueCat\Domain\Import\Converter\Town - * @uses \WerkraumMedia\ThueCat\Domain\Import\Importer - * @uses \WerkraumMedia\ThueCat\Domain\Import\Importer\FetchData - * @uses \WerkraumMedia\ThueCat\Domain\Import\Importer\LanguageHandling - * @uses \WerkraumMedia\ThueCat\Domain\Import\Model\EntityCollection - * @uses \WerkraumMedia\ThueCat\Domain\Import\Model\GenericEntity - * @uses \WerkraumMedia\ThueCat\Domain\Import\RequestFactory - * @uses \WerkraumMedia\ThueCat\Domain\Import\UrlProvider\Registry - * @uses \WerkraumMedia\ThueCat\Domain\Import\UrlProvider\StaticUrlProvider - * @uses \WerkraumMedia\ThueCat\Domain\Import\UrlProvider\SyncScopeUrlProvider - * @uses \WerkraumMedia\ThueCat\Domain\Model\Backend\ImportConfiguration - * @uses \WerkraumMedia\ThueCat\Domain\Model\Backend\ImportLog - * @uses \WerkraumMedia\ThueCat\Domain\Model\Backend\ImportLogEntry - * @uses \WerkraumMedia\ThueCat\Domain\Model\Backend\ImportLogEntry - * - * @testdox The import - */ -class ImportTest extends AbstractImportTest +class ImportTest extends AbstractImportTestCase { - /** - * @test - */ + #[Test] public function importsFreshOrganization(): void { - $this->importDataSet(__DIR__ . '/Fixtures/Import/ImportsFreshOrganization.xml'); + $this->importPHPDataSet(__DIR__ . '/Fixtures/Import/ImportsFreshOrganization.php'); GuzzleClientFaker::appendResponseFromFile(__DIR__ . '/Fixtures/Import/Guzzle/thuecat.org/resources/018132452787-ngbe.json'); - $configuration = $this->get(ImportConfigurationRepository::class)->findByUid(1); - $this->get(Importer::class)->importConfiguration($configuration); + $this->importConfiguration(); - $this->assertCSVDataSet('EXT:thuecat/Tests/Functional/Fixtures/Import/ImportsFreshOrganization.csv'); + $this->assertPHPDataSet(__DIR__ . '/Assertions/Import/ImportsFreshOrganization.php'); } - /** - * @test - */ + #[Test] public function updatesExistingOrganization(): void { - $this->importDataSet(__DIR__ . '/Fixtures/Import/UpdatesExistingOrganization.xml'); + $this->importPHPDataSet(__DIR__ . '/Fixtures/Import/UpdatesExistingOrganization.php'); GuzzleClientFaker::appendResponseFromFile(__DIR__ . '/Fixtures/Import/Guzzle/thuecat.org/resources/018132452787-ngbe.json'); - $configuration = $this->get(ImportConfigurationRepository::class)->findByUid(1); - $this->get(Importer::class)->importConfiguration($configuration); + $this->importConfiguration(); $organisations = $this->getAllRecords('tx_thuecat_organisation'); self::assertCount(1, $organisations); @@ -104,45 +69,37 @@ class ImportTest extends AbstractImportTest self::assertSame('[]', $importLogEntries[0]['errors']); } - /** - * @test - */ + #[Test] public function importsTown(): void { - $this->importDataSet(__DIR__ . '/Fixtures/Import/ImportsTown.xml'); + $this->importPHPDataSet(__DIR__ . '/Fixtures/Import/ImportsTown.php'); // TODO: Check why we request both twice. GuzzleClientFaker::appendResponseFromFile(__DIR__ . '/Fixtures/Import/Guzzle/thuecat.org/resources/043064193523-jcyt.json'); GuzzleClientFaker::appendResponseFromFile(__DIR__ . '/Fixtures/Import/Guzzle/thuecat.org/resources/018132452787-ngbe.json'); GuzzleClientFaker::appendResponseFromFile(__DIR__ . '/Fixtures/Import/Guzzle/thuecat.org/resources/043064193523-jcyt.json'); GuzzleClientFaker::appendResponseFromFile(__DIR__ . '/Fixtures/Import/Guzzle/thuecat.org/resources/018132452787-ngbe.json'); - $configuration = $this->get(ImportConfigurationRepository::class)->findByUid(1); - $this->get(Importer::class)->importConfiguration($configuration); + $this->importConfiguration(); - $this->assertCSVDataSet('EXT:thuecat/Tests/Functional/Fixtures/Import/ImportsTown.csv'); + $this->assertPHPDataSet(__DIR__ . '/Assertions/Import/ImportsTown.php'); } - /** - * @test - */ + #[Test] public function importsTownWithRelation(): void { - $this->importDataSet(__DIR__ . '/Fixtures/Import/ImportsTownWithRelation.xml'); + $this->importPHPDataSet(__DIR__ . '/Fixtures/Import/ImportsTownWithRelation.php'); GuzzleClientFaker::appendResponseFromFile(__DIR__ . '/Fixtures/Import/Guzzle/thuecat.org/resources/043064193523-jcyt.json'); GuzzleClientFaker::appendResponseFromFile(__DIR__ . '/Fixtures/Import/Guzzle/thuecat.org/resources/018132452787-ngbe.json'); - $configuration = $this->get(ImportConfigurationRepository::class)->findByUid(1); - $this->get(Importer::class)->importConfiguration($configuration); + $this->importConfiguration(); - $this->assertCSVDataSet('EXT:thuecat/Tests/Functional/Fixtures/Import/ImportsTownWithRelation.csv'); + $this->assertPHPDataSet(__DIR__ . '/Assertions/Import/ImportsTownWithRelation.php'); } - /** - * @test - */ + #[Test] public function importsTouristAttractionsWithRelations(): void { - $this->importDataSet(__DIR__ . '/Fixtures/Import/ImportsTouristAttractionsWithRelations.xml'); + $this->importPHPDataSet(__DIR__ . '/Fixtures/Import/ImportsTouristAttractionsWithRelations.php'); GuzzleClientFaker::appendResponseFromFile(__DIR__ . '/Fixtures/Import/Guzzle/thuecat.org/resources/835224016581-dara.json'); GuzzleClientFaker::appendResponseFromFile(__DIR__ . '/Fixtures/Import/Guzzle/thuecat.org/resources/018132452787-ngbe.json'); GuzzleClientFaker::appendResponseFromFile(__DIR__ . '/Fixtures/Import/Guzzle/thuecat.org/resources/043064193523-jcyt.json'); @@ -166,66 +123,54 @@ class ImportTest extends AbstractImportTest GuzzleClientFaker::appendResponseFromFile(__DIR__ . '/Fixtures/Import/Guzzle/thuecat.org/resources/440055527204-ocar.json'); GuzzleClientFaker::appendResponseFromFile(__DIR__ . '/Fixtures/Import/Guzzle/thuecat.org/resources/dms_5197164.json'); - $configuration = $this->get(ImportConfigurationRepository::class)->findByUid(1); - $this->get(Importer::class)->importConfiguration($configuration); + $this->importConfiguration(); - $this->assertCSVDataSet('EXT:thuecat/Tests/Functional/Fixtures/Import/ImportsTouristAttractionsWithRelations.csv'); + $this->assertPHPDataSet(__DIR__ . '/Assertions/Import/ImportsTouristAttractionsWithRelations.php'); } - /** - * @test - */ + #[Test] public function importsTouristAttractionsWithFilteredOpeningHours(): void { - $this->importDataSet(__DIR__ . '/Fixtures/Import/ImportsTouristAttractionWithFilteredOpeningHours.xml'); + $this->importPHPDataSet(__DIR__ . '/Fixtures/Import/ImportsTouristAttractionWithFilteredOpeningHours.php'); GuzzleClientFaker::appendResponseFromFile(__DIR__ . '/Fixtures/Import/Guzzle/thuecat.org/resources/opening-hours-to-filter.json'); GuzzleClientFaker::appendResponseFromFile(__DIR__ . '/Fixtures/Import/Guzzle/thuecat.org/resources/018132452787-ngbe.json'); - $configuration = $this->get(ImportConfigurationRepository::class)->findByUid(1); - $this->get(Importer::class)->importConfiguration($configuration); + $this->importConfiguration(); - $this->assertCSVDataSet('EXT:thuecat/Tests/Functional/Fixtures/Import/ImportsTouristAttractionsWithFilteredOpeningHours.csv'); + $this->assertPHPDataSet(__DIR__ . '/Assertions/Import/ImportsTouristAttractionsWithFilteredOpeningHours.php'); } - /** - * @test - */ + #[Test] public function importsTouristAttractionsWithSpecialOpeningHours(): void { - $this->importDataSet(__DIR__ . '/Fixtures/Import/ImportsTouristAttractionWithSpecialOpeningHours.xml'); + $this->importPHPDataSet(__DIR__ . '/Fixtures/Import/ImportsTouristAttractionWithSpecialOpeningHours.php'); GuzzleClientFaker::appendResponseFromFile(__DIR__ . '/Fixtures/Import/Guzzle/thuecat.org/resources/special-opening-hours.json'); GuzzleClientFaker::appendResponseFromFile(__DIR__ . '/Fixtures/Import/Guzzle/thuecat.org/resources/018132452787-ngbe.json'); - $configuration = $this->get(ImportConfigurationRepository::class)->findByUid(1); - $this->get(Importer::class)->importConfiguration($configuration); + $this->importConfiguration(); - $this->assertCSVDataSet('EXT:thuecat/Tests/Functional/Fixtures/Import/ImportsTouristAttractionsWithSpecialOpeningHours.csv'); + $this->assertPHPDataSet(__DIR__ . '/Assertions/Import/ImportsTouristAttractionsWithSpecialOpeningHours.php'); } - /** - * @test - */ + #[Test] public function importsTouristInformationWithRelation(): void { - $this->importDataSet(__DIR__ . '/Fixtures/Import/ImportsTouristInformationWithRelation.xml'); + $this->importPHPDataSet(__DIR__ . '/Fixtures/Import/ImportsTouristInformationWithRelation.php'); GuzzleClientFaker::appendResponseFromFile(__DIR__ . '/Fixtures/Import/Guzzle/thuecat.org/resources/333039283321-xxwg.json'); GuzzleClientFaker::appendResponseFromFile(__DIR__ . '/Fixtures/Import/Guzzle/thuecat.org/resources/018132452787-ngbe.json'); GuzzleClientFaker::appendResponseFromFile(__DIR__ . '/Fixtures/Import/Guzzle/thuecat.org/resources/043064193523-jcyt.json'); GuzzleClientFaker::appendResponseFromFile(__DIR__ . '/Fixtures/Import/Guzzle/thuecat.org/resources/573211638937-gmqb.json'); GuzzleClientFaker::appendResponseFromFile(__DIR__ . '/Fixtures/Import/Guzzle/thuecat.org/resources/356133173991-cryw.json'); - $configuration = $this->get(ImportConfigurationRepository::class)->findByUid(1); - $this->get(Importer::class)->importConfiguration($configuration); + $this->importConfiguration(); - $this->assertCSVDataSet('EXT:thuecat/Tests/Functional/Fixtures/Import/ImportsTouristInformationWithRelation.csv'); + $this->assertPHPDataSet(__DIR__ . '/Assertions/Import/ImportsTouristInformationWithRelation.php'); } - /** - * @test - */ + #[Test] public function importsBasedOnSyncScope(): void { - $this->importDataSet(__DIR__ . '/Fixtures/Import/ImportsSyncScope.xml'); + $this->importPHPDataSet(__DIR__ . '/Fixtures/Import/ImportsSyncScope.php'); GuzzleClientFaker::appendResponseFromFile(__DIR__ . '/Fixtures/Import/Guzzle/cdb.thuecat.org/api/ext-sync/get-updated-nodes/dd4615dc-58a6-4648-a7ce-4950293a06db.json'); GuzzleClientFaker::appendResponseFromFile(__DIR__ . '/Fixtures/Import/Guzzle/thuecat.org/resources/835224016581-dara.json'); GuzzleClientFaker::appendResponseFromFile(__DIR__ . '/Fixtures/Import/Guzzle/thuecat.org/resources/018132452787-ngbe.json'); @@ -250,18 +195,15 @@ class ImportTest extends AbstractImportTest GuzzleClientFaker::appendResponseFromFile(__DIR__ . '/Fixtures/Import/Guzzle/thuecat.org/resources/440055527204-ocar.json'); GuzzleClientFaker::appendResponseFromFile(__DIR__ . '/Fixtures/Import/Guzzle/thuecat.org/resources/dms_5197164.json'); - $configuration = $this->get(ImportConfigurationRepository::class)->findByUid(1); - $this->get(Importer::class)->importConfiguration($configuration); + $this->importConfiguration(); - $this->assertCSVDataSet('EXT:thuecat/Tests/Functional/Fixtures/Import/ImportsSyncScope.csv'); + $this->assertPHPDataSet(__DIR__ . '/Assertions/Import/ImportsSyncScope.php'); } - /** - * @test - */ + #[Test] public function importsBasedOnContainsPlace(): void { - $this->importDataSet(__DIR__ . '/Fixtures/Import/ImportsContainsPlace.xml'); + $this->importPHPDataSet(__DIR__ . '/Fixtures/Import/ImportsContainsPlace.php'); GuzzleClientFaker::appendResponseFromFile(__DIR__ . '/Fixtures/Import/Guzzle/thuecat.org/resources/043064193523-contains.json'); GuzzleClientFaker::appendResponseFromFile(__DIR__ . '/Fixtures/Import/Guzzle/thuecat.org/resources/835224016581-dara.json'); GuzzleClientFaker::appendResponseFromFile(__DIR__ . '/Fixtures/Import/Guzzle/thuecat.org/resources/018132452787-ngbe.json'); @@ -294,19 +236,16 @@ class ImportTest extends AbstractImportTest GuzzleClientFaker::appendNotFoundResponse(); } - $configuration = $this->get(ImportConfigurationRepository::class)->findByUid(1); - $this->get(Importer::class)->importConfiguration($configuration); + $this->importConfiguration(); - $this->assertCSVDataSet('EXT:thuecat/Tests/Functional/Fixtures/Import/ImportsContainsPlace.csv'); + $this->assertPHPDataSet(__DIR__ . '/Assertions/Import/ImportsContainsPlace.php'); } - /** - * @test - */ + #[Test] public function importsFollowingRecordsInCaseOfAnMappingException(): void { $this->expectErrors = true; - $this->importDataSet(__DIR__ . '/Fixtures/Import/ImportsFollowingRecordsInCaseOfAnMappingException.xml'); + $this->importPHPDataSet(__DIR__ . '/Fixtures/Import/ImportsFollowingRecordsInCaseOfAnMappingException.php'); GuzzleClientFaker::appendResponseFromFile(__DIR__ . '/Fixtures/Import/Guzzle/thuecat.org/resources/mapping-exception.json'); GuzzleClientFaker::appendResponseFromFile(__DIR__ . '/Fixtures/Import/Guzzle/thuecat.org/resources/165868194223-zmqf.json'); GuzzleClientFaker::appendResponseFromFile(__DIR__ . '/Fixtures/Import/Guzzle/thuecat.org/resources/018132452787-ngbe.json'); @@ -317,23 +256,19 @@ class ImportTest extends AbstractImportTest GuzzleClientFaker::appendNotFoundResponse(); } - $configuration = $this->get(ImportConfigurationRepository::class)->findByUid(1); - $this->get(Importer::class)->importConfiguration($configuration); + $this->importConfiguration(); if (version_compare(PHP_VERSION, '8.1.0', '<')) { - $this->assertCSVDataSet('EXT:thuecat/Tests/Functional/Fixtures/Import/ImportsFollowingRecordsInCaseOfAnMappingExceptionOldPhp.csv'); + $this->assertPHPDataSet(__DIR__ . '/Assertions/Import/ImportsFollowingRecordsInCaseOfAnMappingExceptionOldPhp.php'); } else { - $this->assertCSVDataSet('EXT:thuecat/Tests/Functional/Fixtures/Import/ImportsFollowingRecordsInCaseOfAnMappingException.csv'); + $this->assertPHPDataSet(__DIR__ . '/Assertions/Import/ImportsFollowingRecordsInCaseOfAnMappingException.php'); } } - /** - * @test - * @testdox Referencing the same thing multiple times only adds it once. - */ + #[Test] public function importWithMultipleReferencesToSameObject(): void { - $this->importDataSet(__DIR__ . '/Fixtures/Import/ImportWithMultipleReferencesToSameObject.xml'); + $this->importPHPDataSet(__DIR__ . '/Fixtures/Import/ImportWithMultipleReferencesToSameObject.php'); GuzzleClientFaker::appendResponseFromFile(__DIR__ . '/Fixtures/Import/Guzzle/thuecat.org/resources/835224016581-dara.json'); GuzzleClientFaker::appendResponseFromFile(__DIR__ . '/Fixtures/Import/Guzzle/thuecat.org/resources/018132452787-ngbe.json'); @@ -358,18 +293,15 @@ class ImportTest extends AbstractImportTest GuzzleClientFaker::appendResponseFromFile(__DIR__ . '/Fixtures/Import/Guzzle/thuecat.org/resources/440055527204-ocar.json'); GuzzleClientFaker::appendResponseFromFile(__DIR__ . '/Fixtures/Import/Guzzle/thuecat.org/resources/dms_5197164.json'); - $configuration = $this->get(ImportConfigurationRepository::class)->findByUid(1); - $this->get(Importer::class)->importConfiguration($configuration); + $this->importConfiguration(); - $this->assertCSVDataSet('EXT:thuecat/Tests/Functional/Fixtures/Import/ImportWithMultipleReferencesToSameObject.csv'); + $this->assertPHPDataSet(__DIR__ . '/Assertions/Import/ImportWithMultipleReferencesToSameObject.php'); } - /** - * @test - */ + #[Test] public function importsTouristAttractionWithMedia(): void { - $this->importDataSet(__DIR__ . '/Fixtures/Import/ImportsTouristAttractionWithMedia.xml'); + $this->importPHPDataSet(__DIR__ . '/Fixtures/Import/ImportsTouristAttractionWithMedia.php'); GuzzleClientFaker::appendResponseFromFile(__DIR__ . '/Fixtures/Import/Guzzle/thuecat.org/resources/attraction-with-media.json'); GuzzleClientFaker::appendResponseFromFile(__DIR__ . '/Fixtures/Import/Guzzle/thuecat.org/resources/018132452787-ngbe.json'); @@ -379,29 +311,32 @@ class ImportTest extends AbstractImportTest GuzzleClientFaker::appendResponseFromFile(__DIR__ . '/Fixtures/Import/Guzzle/thuecat.org/resources/image-with-license-author.json'); GuzzleClientFaker::appendResponseFromFile(__DIR__ . '/Fixtures/Import/Guzzle/thuecat.org/resources/image-with-author-and-license-author.json'); - $configuration = $this->get(ImportConfigurationRepository::class)->findByUid(1); - $this->get(Importer::class)->importConfiguration($configuration); + $this->importConfiguration(); - $this->assertCSVDataSet('EXT:thuecat/Tests/Functional/Fixtures/Import/ImportsTouristAttractionWithMedia.csv'); + $this->assertPHPDataSet(__DIR__ . '/Assertions/Import/ImportsTouristAttractionWithMedia.php'); } - /** - * @test - */ + #[Test] public function importsTouristAttractionWithAccessibilitySpecification(): void { - $this->importDataSet(__DIR__ . '/Fixtures/Import/ImportsTouristAttractionWithAccessibilitySpecification.xml'); + $this->importPHPDataSet(__DIR__ . '/Fixtures/Import/ImportsTouristAttractionWithAccessibilitySpecification.php'); GuzzleClientFaker::appendResponseFromFile(__DIR__ . '/Fixtures/Import/Guzzle/thuecat.org/resources/attraction-with-accessibility-specification.json'); GuzzleClientFaker::appendResponseFromFile(__DIR__ . '/Fixtures/Import/Guzzle/thuecat.org/resources/018132452787-ngbe.json'); GuzzleClientFaker::appendResponseFromFile(__DIR__ . '/Fixtures/Import/Guzzle/thuecat.org/resources/e_331baf4eeda4453db920dde62f7e6edc-rfa-accessibility-specification.json'); - $configuration = $this->get(ImportConfigurationRepository::class)->findByUid(1); - $this->get(Importer::class)->importConfiguration($configuration); + $this->importConfiguration(); - $this->assertCSVDataSet('EXT:thuecat/Tests/Functional/Fixtures/Import/ImportsTouristAttractionWithAccessibilitySpecification.csv'); + $this->assertPHPDataSet(__DIR__ . '/Assertions/Import/ImportsTouristAttractionWithAccessibilitySpecification.php'); $records = $this->getAllRecords('tx_thuecat_tourist_attraction'); self::assertStringEqualsFile(__DIR__ . '/Fixtures/Import/ImportsTouristAttractionWithAccessibilitySpecificationGerman.txt', $records[0]['accessibility_specification'] . PHP_EOL); self::assertStringEqualsFile(__DIR__ . '/Fixtures/Import/ImportsTouristAttractionWithAccessibilitySpecificationEnglish.txt', $records[1]['accessibility_specification'] . PHP_EOL); } + + private function importConfiguration(): void + { + $configuration = $this->get(ImportConfigurationRepository::class)->findByUid(1); + self::assertInstanceOf(ImportConfiguration::class, $configuration); + $this->get(Importer::class)->importConfiguration($configuration); + } } diff --git a/Tests/Unit/Domain/Import/EntityMapper/EntityRegistryTest.php b/Tests/Unit/Domain/Import/EntityMapper/EntityRegistryTest.php new file mode 100644 index 0000000..01bc871 --- /dev/null +++ b/Tests/Unit/Domain/Import/EntityMapper/EntityRegistryTest.php @@ -0,0 +1,50 @@ + + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +namespace WerkraumMedia\ThueCat\Tests\Unit\Domain\Import\EntityMapper; + +use PHPUnit\Framework\Attributes\Test; +use PHPUnit\Framework\TestCase; +use WerkraumMedia\ThueCat\Domain\Import\EntityMapper\EntityRegistry; + +final class EntityRegistryTest extends TestCase +{ + #[Test] + public function returnsEntityWithHighestPriority(): void + { + $subject = new EntityRegistry(); + + $subject->registerEntityClass( + 'ClassA', + 10, + ['TypeA'] + ); + $subject->registerEntityClass( + 'ClassB', + 20, + ['TypeA'] + ); + + self::assertSame('ClassB', $subject->getEntityByTypes(['TypeA'])); + } +} diff --git a/Tests/Unit/Domain/Import/ImportTest.php b/Tests/Unit/Domain/Import/ImportTest.php index 403e40c..93bcd36 100644 --- a/Tests/Unit/Domain/Import/ImportTest.php +++ b/Tests/Unit/Domain/Import/ImportTest.php @@ -23,20 +23,16 @@ declare(strict_types=1); namespace WerkraumMedia\ThueCat\Tests\Unit\Domain\Import; -use WerkraumMedia\ThueCat\Domain\Import\Import; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; +use WerkraumMedia\ThueCat\Domain\Import\Import; use WerkraumMedia\ThueCat\Domain\Model\Backend\ImportConfiguration; use WerkraumMedia\ThueCat\Domain\Model\Backend\ImportLog; use WerkraumMedia\ThueCat\Domain\Model\Backend\ImportLogEntry; -/** - * @covers \WerkraumMedia\ThueCat\Domain\Import\Import - */ class ImportTest extends TestCase { - /** - * @test - */ + #[Test] public function canBeCreated(): void { $subject = new Import(); @@ -47,9 +43,7 @@ class ImportTest extends TestCase ); } - /** - * @test - */ + #[Test] public function canStart(): void { $configuration = new ImportConfiguration(); @@ -66,9 +60,7 @@ class ImportTest extends TestCase ); } - /** - * @test - */ + #[Test] public function canEndAfterStart(): void { $configuration = new ImportConfiguration(); @@ -86,9 +78,7 @@ class ImportTest extends TestCase ); } - /** - * @test - */ + #[Test] public function isDoneAfterStartAndEnd(): void { $configuration = new ImportConfiguration(); @@ -99,9 +89,7 @@ class ImportTest extends TestCase self::assertTrue($subject->done()); } - /** - * @test - */ + #[Test] public function isNotDoneAfterJustStartWithoutEnd(): void { $configuration = new ImportConfiguration(); @@ -111,9 +99,7 @@ class ImportTest extends TestCase self::assertFalse($subject->done()); } - /** - * @test - */ + #[Test] public function nestedStartReturnsExpectedConfiguration(): void { $configuration1 = new ImportConfiguration(); @@ -129,9 +115,7 @@ class ImportTest extends TestCase ); } - /** - * @test - */ + #[Test] public function nestedStartReturnsExpectedLog(): void { $configuration1 = new ImportConfiguration(); @@ -159,9 +143,7 @@ class ImportTest extends TestCase ); } - /** - * @test - */ + #[Test] public function nestedImportMergesLog(): void { $configuration1 = new ImportConfiguration(); @@ -183,15 +165,13 @@ class ImportTest extends TestCase self::assertSame( [ - $importLogEntry + $importLogEntry, ], $log1->getEntries()->toArray() ); } - /** - * @test - */ + #[Test] public function nestedImportReturnsHandledForRemoteId(): void { $configuration1 = new ImportConfiguration(); diff --git a/Tests/Unit/Domain/Import/Importer/FetchDataTest.php b/Tests/Unit/Domain/Import/Importer/FetchDataTest.php index 107c695..96b44f6 100644 --- a/Tests/Unit/Domain/Import/Importer/FetchDataTest.php +++ b/Tests/Unit/Domain/Import/Importer/FetchDataTest.php @@ -23,23 +23,21 @@ namespace WerkraumMedia\ThueCat\Tests\Unit\Domain\Import\Importer; * 02110-1301, USA. */ +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; use Psr\Http\Client\ClientInterface; use Psr\Http\Message\RequestFactoryInterface; use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseInterface; +use Psr\Http\Message\StreamInterface; +use Psr\Http\Message\UriInterface; use TYPO3\CMS\Core\Cache\Frontend\FrontendInterface; use WerkraumMedia\ThueCat\Domain\Import\Importer\FetchData; use WerkraumMedia\ThueCat\Domain\Import\Importer\FetchData\InvalidResponseException; -/** - * @covers \WerkraumMedia\ThueCat\Domain\Import\Importer\FetchData - */ class FetchDataTest extends TestCase { - /** - * @test - */ + #[Test] public function canBeCreated(): void { $requestFactory = $this->createStub(RequestFactoryInterface::class); @@ -55,9 +53,7 @@ class FetchDataTest extends TestCase self::assertInstanceOf(FetchData::class, $subject); } - /** - * @test - */ + #[Test] public function returnsParsedJsonLdBasedOnUrl(): void { $requestFactory = $this->createStub(RequestFactoryInterface::class); @@ -70,8 +66,11 @@ class FetchDataTest extends TestCase $requestFactory->method('createRequest')->willReturn($request); $httpClient->method('sendRequest')->willReturn($response); + $body = $this->createStub(StreamInterface::class); + $body->method('__toString')->willReturn('{"@graph":[{"@id":"https://example.com/resources/018132452787-ngbe"}]}'); + $response->method('getStatusCode')->willReturn(200); - $response->method('getBody')->willReturn('{"@graph":[{"@id":"https://example.com/resources/018132452787-ngbe"}]}'); + $response->method('getBody')->willReturn($body); $subject = new FetchData( $requestFactory, @@ -89,9 +88,7 @@ class FetchDataTest extends TestCase ], $result); } - /** - * @test - */ + #[Test] public function returnsEmptyArrayInCaseOfError(): void { $requestFactory = $this->createStub(RequestFactoryInterface::class); @@ -105,8 +102,11 @@ class FetchDataTest extends TestCase $httpClient->method('sendRequest')->willReturn($response); + $body = $this->createStub(StreamInterface::class); + $body->method('__toString')->willReturn(''); + $response->method('getStatusCode')->willReturn(200); - $response->method('getBody')->willReturn(''); + $response->method('getBody')->willReturn($body); $subject = new FetchData( $requestFactory, @@ -118,9 +118,7 @@ class FetchDataTest extends TestCase self::assertSame([], $result); } - /** - * @test - */ + #[Test] public function returnsResultFromCacheIfAvailable(): void { $requestFactory = $this->createStub(RequestFactoryInterface::class); @@ -151,9 +149,7 @@ class FetchDataTest extends TestCase ], $result); } - /** - * @test - */ + #[Test] public function throwsExceptionOn404(): void { $requestFactory = $this->createStub(RequestFactoryInterface::class); @@ -163,14 +159,19 @@ class FetchDataTest extends TestCase $request = $this->createStub(RequestInterface::class); $response = $this->createStub(ResponseInterface::class); - $request->method('getUri')->willReturn('https://example.com/resources/018132452787-ngbe'); + $uri = $this->createStub(UriInterface::class); + $uri->method('__toString')->willReturn('https://example.com/resources/018132452787-ngbe'); + $request->method('getUri')->willReturn($uri); $requestFactory->method('createRequest')->willReturn($request); $httpClient->method('sendRequest')->willReturn($response); + $body = $this->createStub(StreamInterface::class); + $body->method('__toString')->willReturn('{"error":"404"}'); + $response->method('getStatusCode')->willReturn(404); - $response->method('getBody')->willReturn('{"error":"404"}'); + $response->method('getBody')->willReturn($body); $subject = new FetchData( $requestFactory, @@ -185,9 +186,7 @@ class FetchDataTest extends TestCase $subject->jsonLDFromUrl('https://example.com/resources/018132452787-ngbe'); } - /** - * @test - */ + #[Test] public function throwsExceptionOn401(): void { $requestFactory = $this->createStub(RequestFactoryInterface::class); diff --git a/Tests/Unit/Domain/Import/Model/EntityCollectionTest.php b/Tests/Unit/Domain/Import/Model/EntityCollectionTest.php index 1864a99..674010d 100644 --- a/Tests/Unit/Domain/Import/Model/EntityCollectionTest.php +++ b/Tests/Unit/Domain/Import/Model/EntityCollectionTest.php @@ -23,18 +23,14 @@ namespace WerkraumMedia\ThueCat\Tests\Unit\Domain\Import\Model; * 02110-1301, USA. */ +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; use WerkraumMedia\ThueCat\Domain\Import\Model\Entity; use WerkraumMedia\ThueCat\Domain\Import\Model\EntityCollection; -/** - * @covers \WerkraumMedia\ThueCat\Domain\Import\Model\EntityCollection - */ class EntityCollectionTest extends TestCase { - /** - * @test - */ + #[Test] public function canBeCreated(): void { $subject = new EntityCollection(); @@ -42,9 +38,7 @@ class EntityCollectionTest extends TestCase self::assertInstanceOf(EntityCollection::class, $subject); } - /** - * @test - */ + #[Test] public function returnsEmptyArrayAsDefaultEntities(): void { $subject = new EntityCollection(); @@ -52,9 +46,7 @@ class EntityCollectionTest extends TestCase self::assertSame([], $subject->getEntities()); } - /** - * @test - */ + #[Test] public function returnsFirstEntityForDefaultLanguage(): void { $entityWithTranslation = $this->createStub(Entity::class); @@ -73,9 +65,7 @@ class EntityCollectionTest extends TestCase ); } - /** - * @test - */ + #[Test] public function returnsNullIfNoEntityForDefaultLanguageExists(): void { $entityWithTranslation = $this->createStub(Entity::class); @@ -89,9 +79,7 @@ class EntityCollectionTest extends TestCase ); } - /** - * @test - */ + #[Test] public function returnsEntitiesToTranslate(): void { $entityWithTranslation = $this->createStub(Entity::class); @@ -109,9 +97,7 @@ class EntityCollectionTest extends TestCase ); } - /** - * @test - */ + #[Test] public function returnsExistingEntities(): void { $entityWithTranslation = $this->createStub(Entity::class); diff --git a/Tests/Unit/Domain/Import/Model/GenericEntityTest.php b/Tests/Unit/Domain/Import/Model/GenericEntityTest.php index e02cf20..6d5a129 100644 --- a/Tests/Unit/Domain/Import/Model/GenericEntityTest.php +++ b/Tests/Unit/Domain/Import/Model/GenericEntityTest.php @@ -23,17 +23,13 @@ namespace WerkraumMedia\ThueCat\Tests\Unit\Domain\Import\Model; * 02110-1301, USA. */ +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; use WerkraumMedia\ThueCat\Domain\Import\Model\GenericEntity; -/** - * @covers \WerkraumMedia\ThueCat\Domain\Import\Model\GenericEntity - */ class GenericEntityTest extends TestCase { - /** - * @test - */ + #[Test] public function canBeCreated(): void { $subject = new GenericEntity( @@ -46,9 +42,7 @@ class GenericEntityTest extends TestCase self::assertInstanceOf(GenericEntity::class, $subject); } - /** - * @test - */ + #[Test] public function returnsTypo3StoragePid(): void { $subject = new GenericEntity( @@ -61,9 +55,7 @@ class GenericEntityTest extends TestCase self::assertSame(10, $subject->getTypo3StoragePid()); } - /** - * @test - */ + #[Test] public function returnsTypo3DatabaseTableName(): void { $subject = new GenericEntity( @@ -76,9 +68,7 @@ class GenericEntityTest extends TestCase self::assertSame('tx_thuecat_entity', $subject->getTypo3DatabaseTableName()); } - /** - * @test - */ + #[Test] public function returnsTypo3SystemLanguageUid(): void { $subject = new GenericEntity( @@ -91,9 +81,7 @@ class GenericEntityTest extends TestCase self::assertSame(10, $subject->getTypo3SystemLanguageUid()); } - /** - * @test - */ + #[Test] public function claimsIsForDefaultLanguage(): void { $subject = new GenericEntity( @@ -106,9 +94,7 @@ class GenericEntityTest extends TestCase self::assertTrue($subject->isForDefaultLanguage()); } - /** - * @test - */ + #[Test] public function claimsIsTranslation(): void { $subject = new GenericEntity( @@ -121,9 +107,7 @@ class GenericEntityTest extends TestCase self::assertTrue($subject->isTranslation()); } - /** - * @test - */ + #[Test] public function returnsRemoteId(): void { $subject = new GenericEntity( @@ -139,9 +123,7 @@ class GenericEntityTest extends TestCase ); } - /** - * @test - */ + #[Test] public function returnsData(): void { $subject = new GenericEntity( @@ -163,9 +145,7 @@ class GenericEntityTest extends TestCase ); } - /** - * @test - */ + #[Test] public function returnsNotCreatedByDefault(): void { $subject = new GenericEntity( @@ -180,9 +160,7 @@ class GenericEntityTest extends TestCase ); } - /** - * @test - */ + #[Test] public function returnsNotExistingByDefault(): void { $subject = new GenericEntity( @@ -197,9 +175,7 @@ class GenericEntityTest extends TestCase ); } - /** - * @test - */ + #[Test] public function returnsZeroAsDefaultTypo3Uid(): void { $subject = new GenericEntity( @@ -215,9 +191,7 @@ class GenericEntityTest extends TestCase ); } - /** - * @test - */ + #[Test] public function canBeMarkedAsImported(): void { $subject = new GenericEntity( @@ -234,9 +208,7 @@ class GenericEntityTest extends TestCase self::assertSame(10, $subject->getTypo3Uid()); } - /** - * @test - */ + #[Test] public function canBeMarkedAsExisting(): void { $subject = new GenericEntity( diff --git a/Tests/Unit/Domain/Import/RequestFactoryTest.php b/Tests/Unit/Domain/Import/RequestFactoryTest.php index 73dae8e..54306d4 100644 --- a/Tests/Unit/Domain/Import/RequestFactoryTest.php +++ b/Tests/Unit/Domain/Import/RequestFactoryTest.php @@ -23,25 +23,22 @@ namespace WerkraumMedia\ThueCat\Tests\Unit\Domain\Import; * 02110-1301, USA. */ +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; use TYPO3\CMS\Core\Configuration\Exception\ExtensionConfigurationExtensionNotConfiguredException; use TYPO3\CMS\Core\Configuration\ExtensionConfiguration; +use TYPO3\CMS\Core\Http\Client\GuzzleClientFactory; use TYPO3\CMS\Core\Http\RequestFactory as Typo3RequestFactory; use TYPO3\CMS\Core\Http\UriFactory; use WerkraumMedia\ThueCat\Domain\Import\RequestFactory; -/** - * @covers \WerkraumMedia\ThueCat\Domain\Import\RequestFactory - */ class RequestFactoryTest extends TestCase { - /** - * @test - */ + #[Test] public function canBeCreated(): void { $extensionConfiguration = $this->createStub(ExtensionConfiguration::class); - $requestFactory = new Typo3RequestFactory(); + $requestFactory = $this->createStub(Typo3RequestFactory::class); $uriFactory = new UriFactory(); $subject = new RequestFactory( @@ -53,13 +50,11 @@ class RequestFactoryTest extends TestCase self::assertInstanceOf(RequestFactory::class, $subject); } - /** - * @test - */ + #[Test] public function returnsRequestWithJsonIdFormat(): void { $extensionConfiguration = $this->createStub(ExtensionConfiguration::class); - $requestFactory = new Typo3RequestFactory(); + $requestFactory = new Typo3RequestFactory($this->createStub(GuzzleClientFactory::class)); $uriFactory = new UriFactory(); $subject = new RequestFactory( @@ -73,14 +68,12 @@ class RequestFactoryTest extends TestCase self::assertSame('syncScopeId=dd3738dc-58a6-4748-a6ce-4950293a06db&format=jsonld', $request->getUri()->getQuery()); } - /** - * @test - */ + #[Test] public function returnsRequestWithApiKeyWhenConfigured(): void { $extensionConfiguration = $this->createStub(ExtensionConfiguration::class); $extensionConfiguration->method('get')->willReturn('some-api-key'); - $requestFactory = new Typo3RequestFactory(); + $requestFactory = new Typo3RequestFactory($this->createStub(GuzzleClientFactory::class)); $uriFactory = new UriFactory(); $subject = new RequestFactory( @@ -94,14 +87,12 @@ class RequestFactoryTest extends TestCase self::assertSame('syncScopeId=dd3738dc-58a6-4748-a6ce-4950293a06db&format=jsonld&api_key=some-api-key', $request->getUri()->getQuery()); } - /** - * @test - */ + #[Test] public function returnsRequestWithoutApiKeyWhenUnkown(): void { $extensionConfiguration = $this->createStub(ExtensionConfiguration::class); $extensionConfiguration->method('get')->willThrowException(new ExtensionConfigurationExtensionNotConfiguredException()); - $requestFactory = new Typo3RequestFactory(); + $requestFactory = new Typo3RequestFactory($this->createStub(GuzzleClientFactory::class)); $uriFactory = new UriFactory(); $subject = new RequestFactory( diff --git a/Tests/Unit/Domain/Import/Typo3Converter/GeneralConverterTest.php b/Tests/Unit/Domain/Import/Typo3Converter/GeneralConverterTest.php index 699aec0..99aea4c 100644 --- a/Tests/Unit/Domain/Import/Typo3Converter/GeneralConverterTest.php +++ b/Tests/Unit/Domain/Import/Typo3Converter/GeneralConverterTest.php @@ -23,14 +23,15 @@ declare(strict_types=1); namespace WerkraumMedia\ThueCat\Tests\Unit\Domain\Import\Typo3Converter; -use TYPO3\CMS\Core\Log\LogManager; +use PHPUnit\Framework\Attributes\Test; +use PHPUnit\Framework\TestCase; use TYPO3\CMS\Core\Log\Logger; +use TYPO3\CMS\Core\Log\LogManager; use WerkraumMedia\ThueCat\Domain\Import\Entity\Properties\ForeignReference; use WerkraumMedia\ThueCat\Domain\Import\Entity\Town; use WerkraumMedia\ThueCat\Domain\Import\Importer; -use WerkraumMedia\ThueCat\Domain\Import\Typo3Converter\GeneralConverter; -use PHPUnit\Framework\TestCase; use WerkraumMedia\ThueCat\Domain\Import\ResolveForeignReference; +use WerkraumMedia\ThueCat\Domain\Import\Typo3Converter\GeneralConverter; use WerkraumMedia\ThueCat\Domain\Import\Typo3Converter\LanguageHandling; use WerkraumMedia\ThueCat\Domain\Import\Typo3Converter\NameExtractor; use WerkraumMedia\ThueCat\Domain\Model\Backend\ImportConfiguration; @@ -39,14 +40,9 @@ use WerkraumMedia\ThueCat\Domain\Repository\Backend\OrganisationRepository; use WerkraumMedia\ThueCat\Domain\Repository\Backend\ParkingFacilityRepository; use WerkraumMedia\ThueCat\Domain\Repository\Backend\TownRepository; -/** - * @covers \WerkraumMedia\ThueCat\Domain\Import\Typo3Converter\GeneralConverter - */ class GeneralConverterTest extends TestCase { - /** - * @test - */ + #[Test] public function canBeCreated(): void { $resolveForeignReference = $this->createStub(ResolveForeignReference::class); @@ -75,9 +71,7 @@ class GeneralConverterTest extends TestCase ); } - /** - * @test - */ + #[Test] public function skipsWithoutManager(): void { $resolveForeignReference = $this->createStub(ResolveForeignReference::class); diff --git a/Tests/Unit/Domain/Import/Typo3Converter/NameExtractorTest.php b/Tests/Unit/Domain/Import/Typo3Converter/NameExtractorTest.php index 50d3e18..c1d175d 100644 --- a/Tests/Unit/Domain/Import/Typo3Converter/NameExtractorTest.php +++ b/Tests/Unit/Domain/Import/Typo3Converter/NameExtractorTest.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace WerkraumMedia\ThueCat\Tests\Unit\Domain\Import\Typo3Converter; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\Stub; use PHPUnit\Framework\TestCase; use WerkraumMedia\ThueCat\Domain\Import\Entity\Person; @@ -31,14 +32,9 @@ use WerkraumMedia\ThueCat\Domain\Import\Entity\Properties\ForeignReference; use WerkraumMedia\ThueCat\Domain\Import\ResolveForeignReference; use WerkraumMedia\ThueCat\Domain\Import\Typo3Converter\NameExtractor; -/** - * @covers \WerkraumMedia\ThueCat\Domain\Import\Typo3Converter\NameExtractor - */ class NameExtractorTest extends TestCase { - /** - * @test - */ + #[Test] public function canBeCreated(): void { $resolveForeignReference = $this->createStub(ResolveForeignReference::class); @@ -53,9 +49,7 @@ class NameExtractorTest extends TestCase ); } - /** - * @test - */ + #[Test] public function extractsNameFromString(): void { $resolveForeignReference = $this->createStub(ResolveForeignReference::class); @@ -70,9 +64,7 @@ class NameExtractorTest extends TestCase ); } - /** - * @test - */ + #[Test] public function extractsNameFromForeignReference(): void { $place = $this->createStub(Place::class); @@ -91,9 +83,7 @@ class NameExtractorTest extends TestCase ); } - /** - * @test - */ + #[Test] public function extractsCombinedNameFromForeignReference(): void { $person = $this->createStub(Person::class); @@ -113,9 +103,7 @@ class NameExtractorTest extends TestCase ); } - /** - * @test - */ + #[Test] public function extractsCombinedNameFromForeignReferenceInsteadOfName(): void { $person = $this->createStub(Person::class); diff --git a/Tests/Unit/Domain/Import/UrlProvider/RegistryTest.php b/Tests/Unit/Domain/Import/UrlProvider/RegistryTest.php index af77d8b..a0f1f62 100644 --- a/Tests/Unit/Domain/Import/UrlProvider/RegistryTest.php +++ b/Tests/Unit/Domain/Import/UrlProvider/RegistryTest.php @@ -23,19 +23,15 @@ namespace WerkraumMedia\ThueCat\Tests\Unit\Domain\Import\UrlProvider; * 02110-1301, USA. */ +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; use WerkraumMedia\ThueCat\Domain\Import\UrlProvider\Registry; use WerkraumMedia\ThueCat\Domain\Import\UrlProvider\StaticUrlProvider; use WerkraumMedia\ThueCat\Domain\Model\Backend\ImportConfiguration; -/** - * @covers \WerkraumMedia\ThueCat\Domain\Import\UrlProvider\Registry - */ class RegistryTest extends TestCase { - /** - * @test - */ + #[Test] public function canBeCreated(): void { $subject = new Registry(); @@ -43,9 +39,7 @@ class RegistryTest extends TestCase self::assertInstanceOf(Registry::class, $subject); } - /** - * @test - */ + #[Test] public function allowsRegistrationOfUrlProvider(): void { $subject = new Registry(); @@ -55,9 +49,7 @@ class RegistryTest extends TestCase self::assertTrue(true); } - /** - * @test - */ + #[Test] public function returnsNullIfNoProviderExistsForConfiguration(): void { $configuration = new ImportConfiguration(); @@ -68,9 +60,7 @@ class RegistryTest extends TestCase self::assertNull($result); } - /** - * @test - */ + #[Test] public function returnsProviderForConfiguration(): void { $configuration = new ImportConfiguration(); diff --git a/Tests/Unit/Domain/Import/UrlProvider/StaticUrlProviderTest.php b/Tests/Unit/Domain/Import/UrlProvider/StaticUrlProviderTest.php index 58e1122..ea04d46 100644 --- a/Tests/Unit/Domain/Import/UrlProvider/StaticUrlProviderTest.php +++ b/Tests/Unit/Domain/Import/UrlProvider/StaticUrlProviderTest.php @@ -23,27 +23,21 @@ namespace WerkraumMedia\ThueCat\Tests\Unit\Domain\Import\UrlProvider; * 02110-1301, USA. */ +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; use WerkraumMedia\ThueCat\Domain\Import\UrlProvider\StaticUrlProvider; use WerkraumMedia\ThueCat\Domain\Model\Backend\ImportConfiguration; -/** - * @covers \WerkraumMedia\ThueCat\Domain\Import\UrlProvider\StaticUrlProvider - */ class StaticUrlProviderTest extends TestCase { - /** - * @test - */ + #[Test] public function canBeCreated(): void { $subject = new StaticUrlProvider(); self::assertInstanceOf(StaticUrlProvider::class, $subject); } - /** - * @test - */ + #[Test] public function canProvideForStaticConfiguration(): void { $configuration = new ImportConfiguration(); @@ -55,9 +49,7 @@ class StaticUrlProviderTest extends TestCase self::assertTrue($result); } - /** - * @test - */ + #[Test] public function returnsConcreteProviderForConfiguration(): void { $configuration = new ImportConfiguration(); @@ -69,9 +61,7 @@ class StaticUrlProviderTest extends TestCase self::assertInstanceOf(StaticUrlProvider::class, $result); } - /** - * @test - */ + #[Test] public function concreteProviderReturnsUrls(): void { $configuration = new ImportConfiguration(); diff --git a/Tests/Unit/Domain/Import/UrlProvider/SyncScopeUrlProviderTest.php b/Tests/Unit/Domain/Import/UrlProvider/SyncScopeUrlProviderTest.php index 563345f..085cd03 100644 --- a/Tests/Unit/Domain/Import/UrlProvider/SyncScopeUrlProviderTest.php +++ b/Tests/Unit/Domain/Import/UrlProvider/SyncScopeUrlProviderTest.php @@ -23,19 +23,15 @@ namespace WerkraumMedia\ThueCat\Tests\Unit\Domain\Import\UrlProvider; * 02110-1301, USA. */ +use PHPUnit\Framework\Attributes\Test; +use PHPUnit\Framework\TestCase; use WerkraumMedia\ThueCat\Domain\Import\Importer\FetchData; use WerkraumMedia\ThueCat\Domain\Import\UrlProvider\SyncScopeUrlProvider; -use PHPUnit\Framework\TestCase; use WerkraumMedia\ThueCat\Domain\Model\Backend\ImportConfiguration; -/** - * @covers \WerkraumMedia\ThueCat\Domain\Import\UrlProvider\SyncScopeUrlProvider - */ class SyncScopeUrlProviderTest extends TestCase { - /** - * @test - */ + #[Test] public function canBeCreated(): void { $fetchData = $this->createStub(FetchData::class); @@ -47,9 +43,7 @@ class SyncScopeUrlProviderTest extends TestCase self::assertInstanceOf(SyncScopeUrlProvider::class, $subject); } - /** - * @test - */ + #[Test] public function canProvideForSyncScope(): void { $configuration = new ImportConfiguration(); @@ -65,9 +59,7 @@ class SyncScopeUrlProviderTest extends TestCase self::assertTrue($result); } - /** - * @test - */ + #[Test] public function returnsConcreteProviderForConfiguration(): void { $configuration = new ImportConfiguration(); @@ -92,9 +84,7 @@ class SyncScopeUrlProviderTest extends TestCase self::assertInstanceOf(SyncScopeUrlProvider::class, $result); } - /** - * @test - */ + #[Test] public function concreteProviderReturnsUrls(): void { $configuration = new ImportConfiguration(); diff --git a/Tests/Unit/Domain/Model/Backend/ImportConfigurationTest.php b/Tests/Unit/Domain/Model/Backend/ImportConfigurationTest.php index 9c7bfc4..3fba4ec 100644 --- a/Tests/Unit/Domain/Model/Backend/ImportConfigurationTest.php +++ b/Tests/Unit/Domain/Model/Backend/ImportConfigurationTest.php @@ -23,17 +23,14 @@ namespace WerkraumMedia\ThueCat\Tests\Unit\Domain\Model\Backend; * 02110-1301, USA. */ +use DateTimeImmutable; +use PHPUnit\Framework\Attributes\Test; use TYPO3\TestingFramework\Core\Functional\FunctionalTestCase as TestCase; use WerkraumMedia\ThueCat\Domain\Model\Backend\ImportConfiguration; -/** - * @covers \WerkraumMedia\ThueCat\Domain\Model\Backend\ImportConfiguration - */ class ImportConfigurationTest extends TestCase { - /** - * @test - */ + #[Test] public function canBeCreated(): void { $subject = new ImportConfiguration(); @@ -41,9 +38,7 @@ class ImportConfigurationTest extends TestCase self::assertInstanceOf(ImportConfiguration::class, $subject); } - /** - * @test - */ + #[Test] public function returnsTitle(): void { $subject = new ImportConfiguration(); @@ -52,9 +47,7 @@ class ImportConfigurationTest extends TestCase self::assertSame('Example Title', $subject->getTitle()); } - /** - * @test - */ + #[Test] public function returnsType(): void { $subject = new ImportConfiguration(); @@ -63,9 +56,7 @@ class ImportConfigurationTest extends TestCase self::assertSame('static', $subject->getType()); } - /** - * @test - */ + #[Test] public function returnsTableName(): void { $subject = new ImportConfiguration(); @@ -73,12 +64,10 @@ class ImportConfigurationTest extends TestCase self::assertSame('tx_thuecat_import_configuration', $subject->getTableName()); } - /** - * @test - */ + #[Test] public function returnsLastChanged(): void { - $lastChanged = new \DateTimeImmutable(); + $lastChanged = new DateTimeImmutable(); $subject = new ImportConfiguration(); @@ -87,23 +76,21 @@ class ImportConfigurationTest extends TestCase self::assertSame($lastChanged, $subject->getLastChanged()); } - /** - * @test - */ + #[Test] public function returnsStoragePidWhenSet(): void { $flexForm = implode(PHP_EOL, [ '', '', - '', - '', - '', - '', - '20', - '', - '', - '', - '', + '', + '', + '', + '', + '20', + '', + '', + '', + '', '', ]); @@ -114,9 +101,7 @@ class ImportConfigurationTest extends TestCase self::assertSame(20, $subject->getStoragePid()); } - /** - * @test - */ + #[Test] public function returnsZeroAsStoragePidWhenNoConfigurationExists(): void { $flexForm = ''; @@ -128,23 +113,21 @@ class ImportConfigurationTest extends TestCase self::assertSame(0, $subject->getStoragePid()); } - /** - * @test - */ + #[Test] public function returnsZeroAsStoragePidWhenNegativePidIsConfigured(): void { $flexForm = implode(PHP_EOL, [ '', '', - '', - '', - '', - '', - '-1', - '', - '', - '', - '', + '', + '', + '', + '', + '-1', + '', + '', + '', + '', '', ]); @@ -155,23 +138,21 @@ class ImportConfigurationTest extends TestCase self::assertSame(0, $subject->getStoragePid()); } - /** - * @test - */ + #[Test] public function returnsZeroAsStoragePidWhenNoneNumericPidIsConfigured(): void { $flexForm = implode(PHP_EOL, [ '', '', - '', - '', - '', - '', - 'abc', - '', - '', - '', - '', + '', + '', + '', + '', + 'abc', + '', + '', + '', + '', '', ]); @@ -182,34 +163,32 @@ class ImportConfigurationTest extends TestCase self::assertSame(0, $subject->getStoragePid()); } - /** - * @test - */ + #[Test] public function returnsUrlsWhenSet(): void { $flexForm = implode(PHP_EOL, [ '', '', - '', - '', - '', - '', - '', - '', - '', - '', - '', - 'https://thuecat.org/resources/942302009360-jopp', - '', - '', - '', - '0', - '', - '', - '', - '', - '', - '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + 'https://thuecat.org/resources/942302009360-jopp', + '', + '', + '', + '0', + '', + '', + '', + '', + '', + '', '', ]); @@ -222,9 +201,7 @@ class ImportConfigurationTest extends TestCase ], $subject->getUrls()); } - /** - * @test - */ + #[Test] public function returnsEmptyArrayAsUrlsWhenNoConfigurationExists(): void { $flexForm = ''; @@ -236,23 +213,21 @@ class ImportConfigurationTest extends TestCase self::assertSame([], $subject->getUrls()); } - /** - * @test - */ + #[Test] public function returnsEmptyArrayAsUrlsWhenNoUrlsAreConfigured(): void { $flexForm = implode(PHP_EOL, [ '', '', - '', - '', - '', - '', - '10', - '', - '', - '', - '', + '', + '', + '', + '', + '10', + '', + '', + '', + '', '', ]); @@ -263,23 +238,21 @@ class ImportConfigurationTest extends TestCase self::assertSame([], $subject->getUrls()); } - /** - * @test - */ + #[Test] public function returnsSyncScopeIdWhenSet(): void { $flexForm = implode(PHP_EOL, [ '', '', - '', - '', - '', - '', - 'dd4639dc-58a7-4648-a6ce-4950293a06db', - '', - '', - '', - '', + '', + '', + '', + '', + 'dd4639dc-58a7-4648-a6ce-4950293a06db', + '', + '', + '', + '', '', ]); @@ -290,9 +263,7 @@ class ImportConfigurationTest extends TestCase self::assertSame('dd4639dc-58a7-4648-a6ce-4950293a06db', $subject->getSyncScopeId()); } - /** - * @test - */ + #[Test] public function returnsEmptyStringAsSyncScopeIdWhenNoConfigurationExists(): void { $flexForm = ''; @@ -304,23 +275,21 @@ class ImportConfigurationTest extends TestCase self::assertSame('', $subject->getSyncScopeId()); } - /** - * @test - */ + #[Test] public function returnsEmptyStringAsSyncScopeIdWhenNoSyncScopeIdAreConfigured(): void { $flexForm = implode(PHP_EOL, [ '', '', - '', - '', - '', - '', - '10', - '', - '', - '', - '', + '', + '', + '', + '', + '10', + '', + '', + '', + '', '', ]); diff --git a/Tests/Unit/Domain/Model/Backend/ImportLogTest.php b/Tests/Unit/Domain/Model/Backend/ImportLogTest.php index 2d19474..3369e39 100644 --- a/Tests/Unit/Domain/Model/Backend/ImportLogTest.php +++ b/Tests/Unit/Domain/Model/Backend/ImportLogTest.php @@ -23,18 +23,14 @@ namespace WerkraumMedia\ThueCat\Tests\Unit\Domain\Model\Backend; * 02110-1301, USA. */ +use PHPUnit\Framework\Attributes\Test; +use PHPUnit\Framework\TestCase; use WerkraumMedia\ThueCat\Domain\Model\Backend\ImportConfiguration; use WerkraumMedia\ThueCat\Domain\Model\Backend\ImportLog; -use PHPUnit\Framework\TestCase; -/** - * @covers \WerkraumMedia\ThueCat\Domain\Model\Backend\ImportLog - */ class ImportLogTest extends TestCase { - /** - * @test - */ + #[Test] public function canBeCreated(): void { $subject = new ImportLog(); @@ -42,9 +38,7 @@ class ImportLogTest extends TestCase self::assertInstanceOf(ImportLog::class, $subject); } - /** - * @test - */ + #[Test] public function returnsConfigurationIfSet(): void { $configuration = new ImportConfiguration(); @@ -53,9 +47,7 @@ class ImportLogTest extends TestCase self::assertSame($configuration, $subject->getConfiguration()); } - /** - * @test - */ + #[Test] public function returnsNullForConfigurationIfNotSet(): void { $subject = new ImportLog(); @@ -63,9 +55,7 @@ class ImportLogTest extends TestCase self::assertNull($subject->getConfiguration()); } - /** - * @test - */ + #[Test] public function returnsConfigurationUidIfSet(): void { $configuration = new ImportConfiguration(); @@ -75,9 +65,7 @@ class ImportLogTest extends TestCase self::assertSame(10, $subject->getConfigurationUid()); } - /** - * @test - */ + #[Test] public function returnsZeroForConfigurationIfNotSet(): void { $subject = new ImportLog(); diff --git a/Tests/Unit/Domain/Model/Frontend/AddressTest.php b/Tests/Unit/Domain/Model/Frontend/AddressTest.php index 0530066..5042e54 100644 --- a/Tests/Unit/Domain/Model/Frontend/AddressTest.php +++ b/Tests/Unit/Domain/Model/Frontend/AddressTest.php @@ -23,17 +23,13 @@ namespace WerkraumMedia\ThueCat\Tests\Unit\Domain\Model\Frontend; * 02110-1301, USA. */ +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; use WerkraumMedia\ThueCat\Domain\Model\Frontend\Address; -/** - * @covers \WerkraumMedia\ThueCat\Domain\Model\Frontend\Address - */ class AddressTest extends TestCase { - /** - * @test - */ + #[Test] public function canBeCreated(): void { $subject = new Address('[]'); @@ -41,9 +37,7 @@ class AddressTest extends TestCase self::assertInstanceOf(Address::class, $subject); } - /** - * @test - */ + #[Test] public function returnsProperDefaults(): void { $subject = new Address('[]'); @@ -56,9 +50,7 @@ class AddressTest extends TestCase self::assertSame('', $subject->getFax()); } - /** - * @test - */ + #[Test] public function returnsStreet(): void { $subject = new Address('{"street": "Example Street 10"}'); @@ -66,9 +58,7 @@ class AddressTest extends TestCase self::assertSame('Example Street 10', $subject->getStreet()); } - /** - * @test - */ + #[Test] public function returnsZip(): void { $subject = new Address('{"zip": "09084"}'); @@ -76,9 +66,7 @@ class AddressTest extends TestCase self::assertSame('09084', $subject->getZip()); } - /** - * @test - */ + #[Test] public function returnsCity(): void { $subject = new Address('{"city": "Erfurt"}'); @@ -86,9 +74,7 @@ class AddressTest extends TestCase self::assertSame('Erfurt', $subject->getCity()); } - /** - * @test - */ + #[Test] public function returnsEmail(): void { $subject = new Address('{"email": "example@example.com"}'); @@ -96,9 +82,7 @@ class AddressTest extends TestCase self::assertSame('example@example.com', $subject->getEmail()); } - /** - * @test - */ + #[Test] public function returnsPhone(): void { $subject = new Address('{"phone": "+49 361 99999"}'); @@ -106,9 +90,7 @@ class AddressTest extends TestCase self::assertSame('+49 361 99999', $subject->getPhone()); } - /** - * @test - */ + #[Test] public function returnsFax(): void { $subject = new Address('{"fax": "+49 361 99998"}'); @@ -116,9 +98,7 @@ class AddressTest extends TestCase self::assertSame('+49 361 99998', $subject->getFax()); } - /** - * @test - */ + #[Test] public function returnsLatitude(): void { $subject = new Address('{"geo": {"latitude": 50.978765}}'); @@ -126,9 +106,7 @@ class AddressTest extends TestCase self::assertSame(50.978765, $subject->getLatitute()); } - /** - * @test - */ + #[Test] public function returnsLongitude(): void { $subject = new Address('{"geo": {"longitude": 11.029133}}'); @@ -136,13 +114,11 @@ class AddressTest extends TestCase self::assertSame(11.029133, $subject->getLongitude()); } - /** - * @test - */ + #[Test] public function returnsSerializedString(): void { $subject = new Address('{"street": "Example Street 10"}'); - self::assertSame('{"street": "Example Street 10"}', (string) $subject); + self::assertSame('{"street": "Example Street 10"}', (string)$subject); } } diff --git a/Tests/Unit/Domain/Model/Frontend/MediaTest.php b/Tests/Unit/Domain/Model/Frontend/MediaTest.php index f41f15d..0b08d64 100644 --- a/Tests/Unit/Domain/Model/Frontend/MediaTest.php +++ b/Tests/Unit/Domain/Model/Frontend/MediaTest.php @@ -23,18 +23,14 @@ namespace WerkraumMedia\ThueCat\Tests\Unit\Domain\Model\Frontend; * 02110-1301, USA. */ +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; use TYPO3\CMS\Core\Resource\FileReference; use WerkraumMedia\ThueCat\Domain\Model\Frontend\Media; -/** - * @covers \WerkraumMedia\ThueCat\Domain\Model\Frontend\Media - */ class MediaTest extends TestCase { - /** - * @test - */ + #[Test] public function canBeCreated(): void { $subject = new Media('[]'); @@ -42,9 +38,7 @@ class MediaTest extends TestCase self::assertInstanceOf(Media::class, $subject); } - /** - * @test - */ + #[Test] public function returnsMainImageIfPresent(): void { $subject = new Media('[{"mainImage":false,"type":"image","title":"Erfurt-Dom-und-Severikirche.jpg"},{"mainImage":true,"type":"image","title":"Erfurt-Dom und Severikirche-beleuchtet.jpg"}]'); @@ -56,9 +50,7 @@ class MediaTest extends TestCase ], $subject->getMainImage()); } - /** - * @test - */ + #[Test] public function returnsEmptyArrayAsMainImageFallback(): void { $subject = new Media('[]'); @@ -66,9 +58,7 @@ class MediaTest extends TestCase self::assertSame([], $subject->getMainImage()); } - /** - * @test - */ + #[Test] public function returnsImagesAsArray(): void { $subject = new Media('[{"mainImage":false,"type":"image","title":"Erfurt-Dom-und-Severikirche.jpg"},{"mainImage":true,"type":"image","title":"Erfurt-Dom und Severikirche-beleuchtet.jpg"}]'); @@ -87,9 +77,7 @@ class MediaTest extends TestCase ], $subject->getImages()); } - /** - * @test - */ + #[Test] public function returnsExtraImagesAsArray(): void { $subject = new Media('[{"mainImage":false,"type":"image","title":"Erfurt-Dom-und-Severikirche.jpg"},{"mainImage":true,"type":"image","title":"Erfurt-Dom und Severikirche-beleuchtet.jpg"}]'); @@ -103,9 +91,7 @@ class MediaTest extends TestCase ], $subject->getExtraImages()); } - /** - * @test - */ + #[Test] public function doesNotAddCopyrightAuthorIfItDoesntExist(): void { $subject = new Media(json_encode([ @@ -131,9 +117,7 @@ class MediaTest extends TestCase ); } - /** - * @test - */ + #[Test] public function addsCopyrightAuthorFromLicenseAuthor(): void { $subject = new Media(json_encode([ @@ -165,9 +149,7 @@ class MediaTest extends TestCase ); } - /** - * @test - */ + #[Test] public function addsCopyrightAuthorFromAuthor(): void { $subject = new Media(json_encode([ @@ -195,9 +177,7 @@ class MediaTest extends TestCase ); } - /** - * @test - */ + #[Test] public function addsCopyrightAuthorFromAuthorWithHigherPrio(): void { $subject = new Media(json_encode([ @@ -231,9 +211,7 @@ class MediaTest extends TestCase ); } - /** - * @test - */ + #[Test] public function returnsEmptyArrayAsDefaultForEditorialImages(): void { $subject = new Media(''); @@ -243,9 +221,7 @@ class MediaTest extends TestCase ); } - /** - * @test - */ + #[Test] public function returnsSetEditorialImages(): void { $subject = new Media(''); @@ -263,9 +239,7 @@ class MediaTest extends TestCase self::assertSame($reference2, $images[1]); } - /** - * @test - */ + #[Test] public function returnsEmptyArrayAsDefaultForAllImages(): void { $subject = new Media(''); @@ -275,9 +249,7 @@ class MediaTest extends TestCase ); } - /** - * @test - */ + #[Test] public function returnsAllImages(): void { $subject = new Media(json_encode([ diff --git a/Tests/Unit/Domain/Model/Frontend/OfferTest.php b/Tests/Unit/Domain/Model/Frontend/OfferTest.php index dda9021..bfbb920 100644 --- a/Tests/Unit/Domain/Model/Frontend/OfferTest.php +++ b/Tests/Unit/Domain/Model/Frontend/OfferTest.php @@ -23,17 +23,13 @@ declare(strict_types=1); namespace WerkraumMedia\ThueCat\Tests\Unit\Domain\Model\Frontend; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; use WerkraumMedia\ThueCat\Domain\Model\Frontend\Offer; -/** - * @covers \WerkraumMedia\ThueCat\Domain\Model\Frontend\Offer - */ class OfferTest extends TestCase { - /** - * @test - */ + #[Test] public function canBeCreatedWithLegacyTypeAsString(): void { $subject = Offer::createFromArray([ @@ -51,9 +47,7 @@ class OfferTest extends TestCase self::assertSame('LegacyType', $subject->getType()); } - /** - * @test - */ + #[Test] public function canBeCreatedWithSingleType(): void { $subject = Offer::createFromArray([ @@ -71,9 +65,7 @@ class OfferTest extends TestCase self::assertSame('ParkingFee', $subject->getType()); } - /** - * @test - */ + #[Test] public function canBeCreatedWithMultipleTypes(): void { $subject = Offer::createFromArray([ @@ -91,9 +83,7 @@ class OfferTest extends TestCase self::assertSame('CourseOffer', $subject->getType()); } - /** - * @test - */ + #[Test] public function canBeCreatedWithoutType(): void { $subject = Offer::createFromArray([ diff --git a/Tests/Unit/Domain/Model/Frontend/OffersTest.php b/Tests/Unit/Domain/Model/Frontend/OffersTest.php index 6e929a3..d0a0c73 100644 --- a/Tests/Unit/Domain/Model/Frontend/OffersTest.php +++ b/Tests/Unit/Domain/Model/Frontend/OffersTest.php @@ -23,22 +23,16 @@ namespace WerkraumMedia\ThueCat\Tests\Unit\Domain\Model\Frontend; * 02110-1301, USA. */ +use Countable; +use Iterator; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; use WerkraumMedia\ThueCat\Domain\Model\Frontend\Offers; -/** - * @covers \WerkraumMedia\ThueCat\Domain\Model\Frontend\Offers - * - * @uses \WerkraumMedia\ThueCat\Domain\Model\Frontend\Offer - * @uses \WerkraumMedia\ThueCat\Domain\Model\Frontend\Price - * - * @testdox Frontend model for offers - */ class OffersTest extends TestCase { - /** - * @test - */ + #[Test] public function canBeCreated(): void { $subject = new Offers('{}'); @@ -46,31 +40,24 @@ class OffersTest extends TestCase self::assertInstanceOf(Offers::class, $subject); } - /** - * @test - */ + #[Test] public function isCountable(): void { $subject = new Offers('{}'); - self::assertInstanceOf(\Countable::class, $subject); + self::assertInstanceOf(Countable::class, $subject); } - /** - * @test - */ + #[Test] public function isIterator(): void { $subject = new Offers('{}'); - self::assertInstanceOf(\Iterator::class, $subject); + self::assertInstanceOf(Iterator::class, $subject); } - /** - * @test - * @dataProvider forCount - * @testdox returns $expected for count - */ + #[Test] + #[DataProvider('forCount')] public function returnsExpectedCount(string $serialized, int $expected): void { $subject = new Offers($serialized); @@ -78,7 +65,7 @@ class OffersTest extends TestCase self::assertCount($expected, $subject); } - public function forCount(): array + public static function forCount(): array { return [ 'zero' => [ diff --git a/Tests/Unit/Domain/Model/Frontend/OpeningHourTest.php b/Tests/Unit/Domain/Model/Frontend/OpeningHourTest.php index 2f896c0..38b91cd 100644 --- a/Tests/Unit/Domain/Model/Frontend/OpeningHourTest.php +++ b/Tests/Unit/Domain/Model/Frontend/OpeningHourTest.php @@ -23,17 +23,13 @@ declare(strict_types=1); namespace WerkraumMedia\ThueCat\Tests\Unit\Domain\Model\Frontend; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; use WerkraumMedia\ThueCat\Domain\Model\Frontend\OpeningHour; -/** - * @covers \WerkraumMedia\Domain\Model\Frontend\OpeningHour - */ class OpeningHourTest extends TestCase { - /** - * @test - */ + #[Test] public function returnsReducedOpens(): void { $subject = OpeningHour::createFromArray([ @@ -46,9 +42,7 @@ class OpeningHourTest extends TestCase ); } - /** - * @test - */ + #[Test] public function returnsOpensForEmptyString(): void { $subject = OpeningHour::createFromArray([]); @@ -59,9 +53,7 @@ class OpeningHourTest extends TestCase ); } - /** - * @test - */ + #[Test] public function returnsReducedCloses(): void { $subject = OpeningHour::createFromArray([ @@ -74,9 +66,7 @@ class OpeningHourTest extends TestCase ); } - /** - * @test - */ + #[Test] public function returnsClosesForEmptyString(): void { $subject = OpeningHour::createFromArray([]); @@ -87,9 +77,7 @@ class OpeningHourTest extends TestCase ); } - /** - * @test - */ + #[Test] public function returnsThatThisIsOnlyASingleDay(): void { $subject = OpeningHour::createFromArray([ @@ -108,9 +96,7 @@ class OpeningHourTest extends TestCase self::assertTrue($subject->isSingleDay()); } - /** - * @test - */ + #[Test] public function returnsThatThisIsATimeframe(): void { $subject = OpeningHour::createFromArray([ diff --git a/Tests/Unit/Domain/Model/Frontend/TouristAttractionTest.php b/Tests/Unit/Domain/Model/Frontend/TouristAttractionTest.php index 5159d56..61d99f7 100644 --- a/Tests/Unit/Domain/Model/Frontend/TouristAttractionTest.php +++ b/Tests/Unit/Domain/Model/Frontend/TouristAttractionTest.php @@ -23,6 +23,9 @@ declare(strict_types=1); namespace WerkraumMedia\ThueCat\Tests\Unit\Domain\Model\Frontend; +use DateTimeImmutable; +use PHPUnit\Framework\Attributes\Test; +use PHPUnit\Framework\TestCase; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Extbase\Persistence\ObjectStorage; use WerkraumMedia\ThueCat\Domain\Model\Frontend\MergedOpeningHour; @@ -30,17 +33,11 @@ use WerkraumMedia\ThueCat\Domain\Model\Frontend\MergedOpeningHours; use WerkraumMedia\ThueCat\Domain\Model\Frontend\OpeningHours; use WerkraumMedia\ThueCat\Domain\Model\Frontend\ParkingFacility; use WerkraumMedia\ThueCat\Domain\Model\Frontend\TouristAttraction; -use PHPUnit\Framework\TestCase; use WerkraumMedia\ThueCat\Service\DateBasedFilter; -/** - * @covers \WerkraumMedia\ThueCat\Domain\Model\Frontend\TouristAttraction - */ class TouristAttractionTest extends TestCase { - /** - * @test - */ + #[Test] public function returnsParkingFacilitiesNearBySorted(): void { $unsortedFacilities = new ObjectStorage(); @@ -73,9 +70,7 @@ class TouristAttractionTest extends TestCase return $facility; } - /** - * @test - */ + #[Test] public function returnsDistanceToPublicTransportArrayWithoutTypes(): void { $subject = new TouristAttraction(); @@ -88,9 +83,7 @@ class TouristAttractionTest extends TestCase ], $subject->getDistanceToPublicTransport()); } - /** - * @test - */ + #[Test] public function returnsDistanceToPublicTransportArrayWithTwoTypes(): void { $subject = new TouristAttraction(); @@ -106,12 +99,10 @@ class TouristAttractionTest extends TestCase ], $subject->getDistanceToPublicTransport()); } - /** - * @test - */ + #[Test] public function returnsMergedOpeningHours(): void { - GeneralUtility::addInstance(DateBasedFilter::class, new class implements DateBasedFilter { + GeneralUtility::addInstance(DateBasedFilter::class, new class() implements DateBasedFilter { public function filterOutPreviousDates( array $listToFilter, callable $provideDate @@ -128,10 +119,10 @@ class TouristAttractionTest extends TestCase 'Sunday', ], 'from' => [ - 'date' => '@' . (new \DateTimeImmutable())->format('U'), + 'date' => '@' . (new DateTimeImmutable())->format('U'), ], 'through' => [ - 'date' => '@' . (new \DateTimeImmutable())->modify('+2 days')->format('U'), + 'date' => '@' . (new DateTimeImmutable())->modify('+2 days')->format('U'), ], ], [ @@ -142,10 +133,10 @@ class TouristAttractionTest extends TestCase 'Tuesday', ], 'from' => [ - 'date' => '@' . (new \DateTimeImmutable())->format('U'), + 'date' => '@' . (new DateTimeImmutable())->format('U'), ], 'through' => [ - 'date' => '@' . (new \DateTimeImmutable())->modify('+2 days')->format('U'), + 'date' => '@' . (new DateTimeImmutable())->modify('+2 days')->format('U'), ], ], [ @@ -155,10 +146,10 @@ class TouristAttractionTest extends TestCase 'Saturday', ], 'from' => [ - 'date' => '@' . (new \DateTimeImmutable())->format('U'), + 'date' => '@' . (new DateTimeImmutable())->format('U'), ], 'through' => [ - 'date' => '@' . (new \DateTimeImmutable())->modify('+3 days')->format('U'), + 'date' => '@' . (new DateTimeImmutable())->modify('+3 days')->format('U'), ], ], ]) ?: ''); @@ -171,9 +162,9 @@ class TouristAttractionTest extends TestCase self::assertCount(2, $result); foreach ($result as $index => $mergedHour) { self::assertInstanceOf(MergedOpeningHour::class, $mergedHour); - $today = (new \DateTimeImmutable())->format('Y-m-d'); - $inTwoDays = (new \DateTimeImmutable())->modify('+2 days')->format('Y-m-d'); - $inThreeDays = (new \DateTimeImmutable())->modify('+3 days')->format('Y-m-d'); + $today = (new DateTimeImmutable())->format('Y-m-d'); + $inTwoDays = (new DateTimeImmutable())->modify('+2 days')->format('Y-m-d'); + $inThreeDays = (new DateTimeImmutable())->modify('+3 days')->format('Y-m-d'); if ($index === 0) { self::assertSame($today, $mergedHour->getFrom() ? $mergedHour->getFrom()->format('Y-m-d') : ''); @@ -199,12 +190,10 @@ class TouristAttractionTest extends TestCase } } - /** - * @test - */ + #[Test] public function returnsMergedSpecialOpeningHours(): void { - GeneralUtility::addInstance(DateBasedFilter::class, new class implements DateBasedFilter { + GeneralUtility::addInstance(DateBasedFilter::class, new class() implements DateBasedFilter { public function filterOutPreviousDates( array $listToFilter, callable $provideDate @@ -221,10 +210,10 @@ class TouristAttractionTest extends TestCase 'Sunday', ], 'from' => [ - 'date' => '@' . (new \DateTimeImmutable())->format('U'), + 'date' => '@' . (new DateTimeImmutable())->format('U'), ], 'through' => [ - 'date' => '@' . (new \DateTimeImmutable())->modify('+2 days')->format('U'), + 'date' => '@' . (new DateTimeImmutable())->modify('+2 days')->format('U'), ], ], [ @@ -235,10 +224,10 @@ class TouristAttractionTest extends TestCase 'Tuesday', ], 'from' => [ - 'date' => '@' . (new \DateTimeImmutable())->format('U'), + 'date' => '@' . (new DateTimeImmutable())->format('U'), ], 'through' => [ - 'date' => '@' . (new \DateTimeImmutable())->modify('+2 days')->format('U'), + 'date' => '@' . (new DateTimeImmutable())->modify('+2 days')->format('U'), ], ], [ @@ -248,10 +237,10 @@ class TouristAttractionTest extends TestCase 'Saturday', ], 'from' => [ - 'date' => '@' . (new \DateTimeImmutable())->format('U'), + 'date' => '@' . (new DateTimeImmutable())->format('U'), ], 'through' => [ - 'date' => '@' . (new \DateTimeImmutable())->modify('+3 days')->format('U'), + 'date' => '@' . (new DateTimeImmutable())->modify('+3 days')->format('U'), ], ], ]) ?: ''); @@ -264,9 +253,9 @@ class TouristAttractionTest extends TestCase self::assertCount(2, $result); foreach ($result as $index => $mergedHour) { self::assertInstanceOf(MergedOpeningHour::class, $mergedHour); - $today = (new \DateTimeImmutable())->format('Y-m-d'); - $inTwoDays = (new \DateTimeImmutable())->modify('+2 days')->format('Y-m-d'); - $inThreeDays = (new \DateTimeImmutable())->modify('+3 days')->format('Y-m-d'); + $today = (new DateTimeImmutable())->format('Y-m-d'); + $inTwoDays = (new DateTimeImmutable())->modify('+2 days')->format('Y-m-d'); + $inThreeDays = (new DateTimeImmutable())->modify('+3 days')->format('Y-m-d'); if ($index === 0) { self::assertSame($today, $mergedHour->getFrom() ? $mergedHour->getFrom()->format('Y-m-d') : ''); diff --git a/Tests/Unit/ExtensionTest.php b/Tests/Unit/ExtensionTest.php index 492bc49..ff8d40b 100644 --- a/Tests/Unit/ExtensionTest.php +++ b/Tests/Unit/ExtensionTest.php @@ -23,18 +23,13 @@ namespace WerkraumMedia\ThueCat\Tests\Unit; * 02110-1301, USA. */ +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; use WerkraumMedia\ThueCat\Extension; -/** - * @covers \WerkraumMedia\ThueCat\Extension - * @testdox The extension class - */ class ExtensionTest extends TestCase { - /** - * @test - */ + #[Test] public function returnsLanguagePath(): void { self::assertSame('LLL:EXT:thuecat/Resources/Private/Language/', Extension::getLanguagePath()); diff --git a/composer.json b/composer.json index ba129f4..336dd7d 100644 --- a/composer.json +++ b/composer.json @@ -35,42 +35,35 @@ } }, "require": { - "php": "~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0", + "php": "~8.1.0 || ~8.2.0 || ~8.3.0", "ext-json": "*", "ext-mbstring": "*", "psr/http-client": "^1.0", "psr/http-factory": "^1.0", - "psr/http-message": "^1.0", - "psr/log": "^1.1", - "symfony/console": "^5.2", - "symfony/dependency-injection": "^5.2", - "symfony/polyfill-php80": "^1.26", - "symfony/property-access": "^5.3", - "symfony/property-info": "^5.3", - "symfony/serializer": "^5.3", - "typo3/cms-backend": "^10.4 || ^11.5", - "typo3/cms-core": "^10.4 || ^11.5", - "typo3/cms-extbase": "^10.4 || ^11.5", - "typo3/cms-frontend": "^10.4 || ^11.5" + "psr/http-message": "^2.0", + "psr/log": "^2.0 || ^3.0", + "symfony/console": "^6.4", + "symfony/dependency-injection": "^6.4", + "symfony/property-access": "^6.4", + "symfony/property-info": "^6.4", + "symfony/serializer": "^6.4", + "typo3/cms-backend": "^12.4", + "typo3/cms-core": "^12.4", + "typo3/cms-extbase": "^12.4", + "typo3/cms-frontend": "^12.4" }, "require-dev": { - "codeception/codeception": "^4.2", - "codeception/module-webdriver": "^2.0", - "jangregor/phpstan-prophecy": "^1.0", + "codappix/typo3-php-datasets": "^1.4", + "codeception/codeception": "^5.0", + "codeception/module-webdriver": "^4.0", + "friendsofphp/php-cs-fixer": "^3.40", "phpstan/extension-installer": "^1.1", - "phpstan/phpstan": "1.1.0", - "phpstan/phpstan-phpunit": "^1.0", - "phpunit/phpunit": "^8.5", - "saschaegerer/phpstan-typo3": "^1.1", - "symplify/easy-coding-standard": "^9.0", - "typo3/cms-fluid-styled-content": "^10.4 || ^11.5", - "typo3/testing-framework": "^6.6" - }, - "scripts": { - "post-autoload-dump": [ - "mkdir -p .Build/web/typo3conf/ext/", - "[ -L .Build/web/typo3conf/ext/thuecat ] || ln -snvf ../../../../. .Build/web/typo3conf/ext/thuecat" - ] + "phpstan/phpstan": "1.10.46", + "phpstan/phpstan-phpunit": "^1.3", + "phpunit/phpunit": "^10.4", + "saschaegerer/phpstan-typo3": "^1.9", + "typo3/cms-fluid-styled-content": "^12.4", + "typo3/testing-framework": "^8.0" }, "config": { "sort-packages": true, @@ -86,9 +79,6 @@ "cms-package-dir": "{$vendor-dir}/typo3/cms", "extension-key": "thuecat", "web-dir": ".Build/web" - }, - "branch-alias": { - "dev-main": "1.1.x-dev" } } } diff --git a/ecs.php b/ecs.php deleted file mode 100644 index 2307d86..0000000 --- a/ecs.php +++ /dev/null @@ -1,64 +0,0 @@ -parameters(); - $services = $containerConfigurator->services(); - - $parameters->set(Option::PATHS, [ - __DIR__ . '/Classes/', - __DIR__ . '/Configuration/', - __DIR__ . '/Tests/', - __DIR__ . '/ecs.php', - __DIR__ . '/ext_emconf.php', - ]); - - $parameters->set(Option::SETS, [ - SetList::PSR_12, - SetList::PHPUNIT, - ]); - - $parameters->set(Option::SKIP, [ - __DIR__ . '/Classes/Domain/Import/EntityMapper/CustomAnnotationExtractor.php', - DeclareStrictTypesFixer::class => [ - __DIR__ . '/Configuration/', - __DIR__ . '/ext_emconf.php', - ], - ]); - - $services->set(DeclareStrictTypesFixer::class); - - $services->set(NoUnusedImportsFixer::class); - $services->set(FullyQualifiedStrictTypesFixer::class); - $services->set(NoMultilineWhitespaceAroundDoubleArrowFixer::class); - $services->set(ArraySyntaxFixer::class)->call('configure', [[ - 'syntax' => 'short', - ]]); - $services->set(SingleQuoteFixer::class); - $services->set(TrailingCommaInMultilineArrayFixer::class); - - $services->set(PhpUnitTestAnnotationFixer::class)->call('configure', [[ - 'style' => 'annotation', - ]]); - $services->set(ClassAttributesSeparationFixer::class)->call('configure', [[ - 'elements' => [ - 'const' => 'one', - 'method' => 'one', - 'property' => 'one', - ], - ]]); -}; diff --git a/ext_emconf.php b/ext_emconf.php index d1288ee..1d92258 100644 --- a/ext_emconf.php +++ b/ext_emconf.php @@ -7,9 +7,6 @@ $EM_CONF['thuecat'] = [ 'description' => 'Integration of ThüCAT into TYPO3 CMS.', 'category' => 'fe', 'state' => 'stable', - 'uploadfolder' => 0, - 'createDirs' => '', - 'clearCacheOnLoad' => 0, 'author' => 'Daniel Siepmann', 'author_email' => 'coding@daniel-siepmann.de', 'author_company' => '', diff --git a/ext_localconf.php b/ext_localconf.php index 5fd4423..537e04f 100644 --- a/ext_localconf.php +++ b/ext_localconf.php @@ -1,13 +1,17 @@ 'crdate', 'expirePeriod' => '180', ]; } -})(\WerkraumMedia\ThueCat\Extension::EXTENSION_KEY); +})(Extension::EXTENSION_KEY); diff --git a/ext_tables.php b/ext_tables.php deleted file mode 100644 index f338cb8..0000000 --- a/ext_tables.php +++ /dev/null @@ -1,5 +0,0 @@ -\\) does not accept array\\.$#" - count: 1 - path: Classes/Domain/Model/Backend/ImportLogEntry.php - - - - message: "#^Property WerkraumMedia\\\\ThueCat\\\\Domain\\\\Model\\\\Backend\\\\ImportLogEntry\\:\\:\\$errorsAsArray \\(array\\\\) does not accept mixed\\.$#" - count: 1 - path: Classes/Domain/Model/Backend/ImportLogEntry.php - - message: "#^Method WerkraumMedia\\\\ThueCat\\\\Domain\\\\Model\\\\Frontend\\\\AccessiblitySpecification\\:\\:getCertificationDeaf\\(\\) should return string but returns mixed\\.$#" count: 1 @@ -244,97 +215,27 @@ parameters: count: 1 path: Classes/Domain/Model/Frontend/OpeningHours.php - - - message: "#^Argument of an invalid type Doctrine\\\\DBAL\\\\Driver\\\\ResultStatement\\|int supplied for foreach, only iterables are supported\\.$#" - count: 1 - path: Classes/Frontend/DataProcessing/ResolveEntities.php - - - - message: "#^Argument of an invalid type Doctrine\\\\DBAL\\\\Result\\|int supplied for foreach, only iterables are supported\\.$#" - count: 1 - path: Classes/Frontend/DataProcessing/ResolveEntities.php - - message: "#^Cannot call method getLanguageOverlay\\(\\) on string\\|TYPO3\\\\CMS\\\\Core\\\\Domain\\\\Repository\\\\PageRepository\\.$#" count: 1 path: Classes/Frontend/DataProcessing/ResolveEntities.php - - message: "#^Right side of \\|\\| is always false\\.$#" + message: "#^Parameter \\#1 \\$className of method TYPO3\\\\CMS\\\\Extbase\\\\Persistence\\\\Generic\\\\Mapper\\\\DataMapper\\:\\:map\\(\\) expects class\\-string\\, string given\\.$#" count: 1 - path: Configuration/TCA/Overrides/pages.php + path: Classes/Frontend/DataProcessing/ResolveEntities.php - - message: "#^Right side of \\|\\| is always false\\.$#" + message: "#^Unable to resolve the template type T in call to method TYPO3\\\\CMS\\\\Extbase\\\\Persistence\\\\Generic\\\\Mapper\\\\DataMapper\\:\\:map\\(\\)$#" count: 1 - path: Configuration/TCA/Overrides/pages_tourist_attraction.php + path: Classes/Frontend/DataProcessing/ResolveEntities.php - - message: "#^Right side of \\|\\| is always false\\.$#" + message: "#^Parameter \\#1 \\$mods of method WerkraumMedia\\\\ThueCat\\\\Updates\\\\BackendModuleUserPermission\\:\\:updateMods\\(\\) expects string, mixed given\\.$#" count: 1 - path: Configuration/TCA/Overrides/sys_template.php + path: Classes/Updates/BackendModuleUserPermission.php - - message: "#^Right side of \\|\\| is always false\\.$#" + message: "#^Method WerkraumMedia\\\\ThueCat\\\\Tests\\\\Acceptance\\\\Support\\\\Environment\\:\\:bootstrapTypo3Environment\\(\\) has no return type specified\\.$#" count: 1 - path: Configuration/TCA/Overrides/tt_content.php - - - - message: "#^Right side of \\|\\| is always false\\.$#" - count: 1 - path: Configuration/TCA/Overrides/tt_content_tourist_attraction.php - - - - message: "#^Right side of \\|\\| is always false\\.$#" - count: 1 - path: Configuration/TCA/tx_thuecat_import_configuration.php - - - - message: "#^Right side of \\|\\| is always false\\.$#" - count: 1 - path: Configuration/TCA/tx_thuecat_import_log.php - - - - message: "#^Right side of \\|\\| is always false\\.$#" - count: 1 - path: Configuration/TCA/tx_thuecat_import_log_entry.php - - - - message: "#^Right side of \\|\\| is always false\\.$#" - count: 1 - path: Configuration/TCA/tx_thuecat_organisation.php - - - - message: "#^Right side of \\|\\| is always false\\.$#" - count: 1 - path: Configuration/TCA/tx_thuecat_parking_facility.php - - - - message: "#^Right side of \\|\\| is always false\\.$#" - count: 1 - path: Configuration/TCA/tx_thuecat_tourist_attraction.php - - - - message: "#^Right side of \\|\\| is always false\\.$#" - count: 1 - path: Configuration/TCA/tx_thuecat_tourist_information.php - - - - message: "#^Right side of \\|\\| is always false\\.$#" - count: 1 - path: Configuration/TCA/tx_thuecat_town.php - - - - message: "#^Cannot call method findByUid\\(\\) on mixed\\.$#" - count: 14 - path: Tests/Functional/ImportTest.php - - - - message: "#^Cannot call method importConfiguration\\(\\) on mixed\\.$#" - count: 14 - path: Tests/Functional/ImportTest.php - - - - message: "#^Parameter \\#2 \\$callback of function usort expects callable\\(TEntity, TEntity\\)\\: int, Closure\\(WerkraumMedia\\\\ThueCat\\\\Domain\\\\Model\\\\Frontend\\\\ParkingFacility, WerkraumMedia\\\\ThueCat\\\\Domain\\\\Model\\\\Frontend\\\\ParkingFacility\\)\\: int\\<\\-1, 1\\> given\\.$#" - count: 1 - path: Classes/Domain/Model/Frontend/Place.php + path: Tests/Acceptance/Support/Environment.php diff --git a/phpstan.neon b/phpstan.neon index 5df3728..bef4063 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -10,13 +10,5 @@ parameters: - Tests/Acceptance/Support/_generated/ - Classes/Domain/Import/EntityMapper/CustomAnnotationExtractor.php checkMissingIterableValueType: false - reportUnmatchedIgnoredErrors: false + reportUnmatchedIgnoredErrors: true checkGenericClassInNonGenericObjectType: false - ignoreErrors: - # Depending on TYPO3 version - - "#^Argument of an invalid type Doctrine\\\\DBAL\\\\Driver\\\\ResultStatement\\|int supplied for foreach, only iterables are supported\\.$#" - - "#^Argument of an invalid type Doctrine\\\\DBAL\\\\Result\\|int supplied for foreach, only iterables are supported\\.$#" - - "#^Cannot call method fetchColumn\\(\\) on Doctrine\\\\DBAL\\\\Driver\\\\ResultStatement\\|int\\.$#" - - "#^Cannot call method fetchColumn\\(\\) on Doctrine\\\\DBAL\\\\Result\\|int\\.$#" - - "#^Cannot call method fetchOne\\(\\) on Doctrine\\\\DBAL\\\\Driver\\\\ResultStatement\\|int\\.$#" - - "#^Cannot call method fetchOne\\(\\) on Doctrine\\\\DBAL\\\\Result\\|int\\.$#" diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 4d4f27c..95cb5b7 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,22 +1,27 @@ + cacheDirectory=".phpunit.cache" + backupStaticProperties="false" + requireCoverageMetadata="false" + beStrictAboutCoverageMetadata="false" +> + + + Classes + + + + @@ -27,12 +32,6 @@ - - - Classes - - - diff --git a/shell.nix b/shell.nix index 613b42c..9ca6aee 100644 --- a/shell.nix +++ b/shell.nix @@ -24,6 +24,31 @@ let composer update --prefer-dist --no-progress --working-dir="$PROJECT_ROOT" ''; }; + + projectCgl = pkgs.writeShellApplication { + name = "project-cgl"; + + runtimeInputs = [ + php + ]; + + text = '' + PHP_CS_FIXER_IGNORE_ENV=1 ./vendor/bin/php-cs-fixer fix --dry-run --diff + ''; + }; + + projectCglFix = pkgs.writeShellApplication { + name = "project-cgl-fix"; + + runtimeInputs = [ + php + ]; + + text = '' + PHP_CS_FIXER_IGNORE_ENV=1 ./vendor/bin/php-cs-fixer fix + ''; + }; + projectTestAcceptance = pkgs.writeShellApplication { name = "project-test-acceptance"; runtimeInputs = [ @@ -50,6 +75,8 @@ in pkgs.mkShell { php composer projectInstall + projectCgl + projectCglFix projectTestAcceptance ];