From cc216429a51a506d0a2ddfdceb0d1d53d077d62d Mon Sep 17 00:00:00 2001 From: Daniel Siepmann Date: Wed, 18 Aug 2021 13:54:18 +0200 Subject: [PATCH] Add parking_facility_near_by - Removed individual converters for TYPO3. Conversion is now handled in a single converter. - The new converter will import necessary dependencies upfront, e.g. town or organisation. - Move import state into extra class. Relates: #34 --- Classes/DependencyInjection/EntityPass.php | 8 +- Classes/Domain/Import/Entity/MapsToType.php | 5 + Classes/Domain/Import/Entity/MediaObject.php | 5 + Classes/Domain/Import/Entity/Minimum.php | 7 +- .../Domain/Import/Entity/ParkingFacility.php | 34 ++ Classes/Domain/Import/Entity/Place.php | 165 ++++++++ .../Import/Entity/Properties/OpeningHour.php | 12 +- .../Entity/Properties/PriceSpecification.php | 9 +- .../Import/Entity/TouristAttraction.php | 158 +------- .../Import/EntityMapper/EntityRegistry.php | 36 +- .../Import/EntityMapper/PropertyValues.php | 43 ++ Classes/Domain/Import/Import.php | 115 ++++++ Classes/Domain/Import/ImportConfiguration.php | 54 +++ Classes/Domain/Import/Importer.php | 65 ++- Classes/Domain/Import/Importer/Converter.php | 2 +- Classes/Domain/Import/Importer/Languages.php | 2 +- .../Domain/Import/ResolveForeignReference.php | 18 + Classes/Domain/Import/Typo3Converter.php | 7 +- .../Import/Typo3Converter/Converter.php | 2 - .../Typo3Converter/GeneralConverter.php | 373 ++++++++++++++++++ .../Typo3Converter/LanguageHandling.php | 5 +- .../Import/Typo3Converter/Organisation.php | 63 --- .../Domain/Import/Typo3Converter/Registry.php | 12 +- .../Typo3Converter/TouristAttraction.php | 252 ------------ .../Typo3Converter/TouristInformation.php | 95 ----- Classes/Domain/Import/Typo3Converter/Town.php | 84 ---- .../Domain/Import/UrlProvider/Registry.php | 2 +- .../Import/UrlProvider/StaticUrlProvider.php | 2 +- .../UrlProvider/SyncScopeUrlProvider.php | 5 +- .../Domain/Import/UrlProvider/UrlProvider.php | 2 +- .../Model/Backend/ImportConfiguration.php | 39 +- Classes/Domain/Model/Backend/ImportLog.php | 18 + .../Domain/Model/Backend/ImportLogEntry.php | 11 + .../Domain/Model/Backend/ParkingFacility.php | 28 ++ Classes/Domain/Model/Frontend/Base.php | 59 +++ .../Domain/Model/Frontend/ParkingFacility.php | 28 ++ Classes/Domain/Model/Frontend/Place.php | 122 ++++++ .../Model/Frontend/TouristAttraction.php | 110 +----- Classes/Domain/Model/Frontend/Town.php | 23 +- .../Backend/ParkingFacilityRepository.php | 65 +++ .../Repository/Backend/TownRepository.php | 6 +- Configuration/Extbase/Persistence/Classes.php | 7 + .../TCA/tx_thuecat_parking_facility.php | 207 ++++++++++ .../TCA/tx_thuecat_tourist_attraction.php | 18 +- Resources/Private/Language/de.locallang.xlf | 80 ++++ Resources/Private/Language/locallang.xlf | 47 +++ Resources/Private/Language/locallang_tca.xlf | 52 +++ .../ContentElement/TouristAttraction.html | 26 +- .../Icons/tx_thuecat_parking_facility.svg | 1 + .../Frontend/Sites/example/config.yaml | 2 +- .../Fixtures/Frontend/TouristAttractions.xml | 13 + .../GET_3a853d7e61b18de6551c00872dd19186.txt | 19 + .../GET_fb3c1440c67b1c9a421a2df91f8048f9.txt | 2 +- .../GET_976c32c50e2a09718c35138281482010.txt | 19 + .../GET_e234b318dcfb8dfae8661f8c07530fa6.txt | 19 + .../GET_ed2b49df916e1c2dba1a679b9866de31.txt | 19 + .../GET_68f53911ca843d0b5c0f792784fe3000.txt | 19 + .../GET_8a1f3581a2447dd37e646da1707ad9e7.txt | 19 + .../GET_54e220a05e132d4644a58f33c065152d.txt | 19 + .../GET_84507add0ca543b4283a096d965d6b32.txt | 19 + .../GET_b54332e6fc5338f57621cba67faf4fd4.txt | 19 + ...portWithMultipleReferencesToSameObject.csv | 33 ++ ...portWithMultipleReferencesToSameObject.xml | 85 ++++ ...ncScopeResult.csv => ImportsSyncScope.csv} | 0 .../Fixtures/Import/ImportsSyncScope.xml | 14 - ...ImportsTouristAttractionsWithRelations.csv | 35 ++ ...ImportsTouristAttractionsWithRelations.xml | 14 - ...sTouristAttractionsWithRelationsResult.csv | 10 - .../ImportsTouristInformationWithRelation.csv | 9 + .../ImportsTouristInformationWithRelation.xml | 27 -- ...tsTouristInformationWithRelationResult.csv | 3 - .../Fixtures/Import/ImportsTown.csv | 7 +- .../Import/ImportsTownWithRelation.csv | 5 +- .../Import/ImportsTownWithRelation.xml | 9 +- Tests/Functional/FrontendTest.php | 12 + Tests/Functional/ImportTest.php | 50 +-- Tests/Unit/Domain/Import/ImportTest.php | 217 ++++++++++ ext_tables.sql | 18 + phpstan-baseline.neon | 22 +- 79 files changed, 2389 insertions(+), 958 deletions(-) create mode 100644 Classes/Domain/Import/Entity/ParkingFacility.php create mode 100644 Classes/Domain/Import/EntityMapper/PropertyValues.php create mode 100644 Classes/Domain/Import/Import.php create mode 100644 Classes/Domain/Import/ImportConfiguration.php create mode 100644 Classes/Domain/Import/Typo3Converter/GeneralConverter.php delete mode 100644 Classes/Domain/Import/Typo3Converter/Organisation.php delete mode 100644 Classes/Domain/Import/Typo3Converter/TouristAttraction.php delete mode 100644 Classes/Domain/Import/Typo3Converter/TouristInformation.php delete mode 100644 Classes/Domain/Import/Typo3Converter/Town.php create mode 100644 Classes/Domain/Model/Backend/ParkingFacility.php create mode 100644 Classes/Domain/Model/Frontend/Base.php create mode 100644 Classes/Domain/Model/Frontend/ParkingFacility.php create mode 100644 Classes/Domain/Model/Frontend/Place.php create mode 100644 Classes/Domain/Repository/Backend/ParkingFacilityRepository.php create mode 100644 Configuration/TCA/tx_thuecat_parking_facility.php create mode 100644 Resources/Public/Icons/tx_thuecat_parking_facility.svg create mode 100644 Tests/Functional/Fixtures/Import/Guzzle/thuecat.org/resources/052821473718-oxfq/GET_3a853d7e61b18de6551c00872dd19186.txt create mode 100644 Tests/Functional/Fixtures/Import/Guzzle/thuecat.org/resources/356133173991-cryw/GET_976c32c50e2a09718c35138281482010.txt create mode 100644 Tests/Functional/Fixtures/Import/Guzzle/thuecat.org/resources/396420044896-drzt/GET_e234b318dcfb8dfae8661f8c07530fa6.txt create mode 100644 Tests/Functional/Fixtures/Import/Guzzle/thuecat.org/resources/440055527204-ocar/GET_ed2b49df916e1c2dba1a679b9866de31.txt create mode 100644 Tests/Functional/Fixtures/Import/Guzzle/thuecat.org/resources/497839263245-edbm/GET_68f53911ca843d0b5c0f792784fe3000.txt create mode 100644 Tests/Functional/Fixtures/Import/Guzzle/thuecat.org/resources/508431710173-wwne/GET_8a1f3581a2447dd37e646da1707ad9e7.txt create mode 100644 Tests/Functional/Fixtures/Import/Guzzle/thuecat.org/resources/573211638937-gmqb/GET_54e220a05e132d4644a58f33c065152d.txt create mode 100644 Tests/Functional/Fixtures/Import/Guzzle/thuecat.org/resources/dms_5197164/GET_84507add0ca543b4283a096d965d6b32.txt create mode 100644 Tests/Functional/Fixtures/Import/Guzzle/thuecat.org/resources/dms_6486108/GET_b54332e6fc5338f57621cba67faf4fd4.txt create mode 100644 Tests/Functional/Fixtures/Import/ImportWithMultipleReferencesToSameObject.csv create mode 100644 Tests/Functional/Fixtures/Import/ImportWithMultipleReferencesToSameObject.xml rename Tests/Functional/Fixtures/Import/{ImportsSyncScopeResult.csv => ImportsSyncScope.csv} (100%) create mode 100644 Tests/Functional/Fixtures/Import/ImportsTouristAttractionsWithRelations.csv delete mode 100644 Tests/Functional/Fixtures/Import/ImportsTouristAttractionsWithRelationsResult.csv create mode 100644 Tests/Functional/Fixtures/Import/ImportsTouristInformationWithRelation.csv delete mode 100644 Tests/Functional/Fixtures/Import/ImportsTouristInformationWithRelationResult.csv create mode 100644 Tests/Unit/Domain/Import/ImportTest.php diff --git a/Classes/DependencyInjection/EntityPass.php b/Classes/DependencyInjection/EntityPass.php index 48b32f6..8bff4b6 100644 --- a/Classes/DependencyInjection/EntityPass.php +++ b/Classes/DependencyInjection/EntityPass.php @@ -36,14 +36,18 @@ class EntityPass implements CompilerPassInterface $registry = $container->findDefinition(EntityRegistry::class); foreach ($container->findTaggedServiceIds(self::TAG) as $id => $tags) { $definition = $container->findDefinition($id); - if (!$definition->isAutoconfigured() || $definition->isAbstract()) { + if ( + !$definition->isAutoconfigured() + || $definition->isAbstract() + || $definition->getClass() === null + ) { continue; } - $registry->addMethodCall( 'registerEntityClass', [ $definition->getClass(), + call_user_func([$definition->getClass(), 'getPriority']), call_user_func([$definition->getClass(), 'getSupportedTypes']), ] ); diff --git a/Classes/Domain/Import/Entity/MapsToType.php b/Classes/Domain/Import/Entity/MapsToType.php index fb845fe..c65c57a 100644 --- a/Classes/Domain/Import/Entity/MapsToType.php +++ b/Classes/Domain/Import/Entity/MapsToType.php @@ -38,4 +38,9 @@ interface MapsToType * @return string[] */ public static function getSupportedTypes(): array; + + /** + * Priority if multiple entities match + */ + public static function getPriority(): int; } diff --git a/Classes/Domain/Import/Entity/MediaObject.php b/Classes/Domain/Import/Entity/MediaObject.php index aa957a0..2906b96 100644 --- a/Classes/Domain/Import/Entity/MediaObject.php +++ b/Classes/Domain/Import/Entity/MediaObject.php @@ -105,4 +105,9 @@ class MediaObject extends Minimum implements MapsToType 'schema:MediaObject', ]; } + + public static function getPriority(): int + { + return 10; + } } diff --git a/Classes/Domain/Import/Entity/Minimum.php b/Classes/Domain/Import/Entity/Minimum.php index 0976a53..a553af0 100644 --- a/Classes/Domain/Import/Entity/Minimum.php +++ b/Classes/Domain/Import/Entity/Minimum.php @@ -23,7 +23,7 @@ declare(strict_types=1); namespace WerkraumMedia\ThueCat\Domain\Import\Entity; -class Minimum +abstract class Minimum { /** * URL to the original source at ThüCAT. @@ -113,4 +113,9 @@ class Minimum { $this->url = $url; } + + public static function getPriority(): int + { + return 10; + } } diff --git a/Classes/Domain/Import/Entity/ParkingFacility.php b/Classes/Domain/Import/Entity/ParkingFacility.php new file mode 100644 index 0000000..f8a4d4b --- /dev/null +++ b/Classes/Domain/Import/Entity/ParkingFacility.php @@ -0,0 +1,34 @@ + + * + * 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\Domain\Import\Entity; + +class ParkingFacility extends Place implements MapsToType +{ + public static function getSupportedTypes(): array + { + return [ + 'schema:ParkingFacility', + ]; + } +} diff --git a/Classes/Domain/Import/Entity/Place.php b/Classes/Domain/Import/Entity/Place.php index e14fbff..34b1d6b 100644 --- a/Classes/Domain/Import/Entity/Place.php +++ b/Classes/Domain/Import/Entity/Place.php @@ -23,7 +23,9 @@ declare(strict_types=1); namespace WerkraumMedia\ThueCat\Domain\Import\Entity; +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; @@ -49,6 +51,36 @@ class Place extends Base */ protected $openingHours = []; + /** + * @var ForeignReference[] + */ + protected $parkingFacilitiesNearBy = []; + + /** + * @var string[] + */ + protected $sanitations = []; + + /** + * @var string[] + */ + protected $otherServices = []; + + /** + * @var string[] + */ + protected $trafficInfrastructures = []; + + /** + * @var string[] + */ + protected $paymentsAccepted = []; + + /** + * @var string + */ + protected $distanceToPublicTransport = ''; + public function getAddress(): ?Address { return $this->address; @@ -59,6 +91,51 @@ class Place extends Base return $this->geo; } + /** + * @return ForeignReference[] + */ + public function getParkingFacilitiesNearBy(): array + { + return $this->parkingFacilitiesNearBy; + } + + /** + * @return string[] + */ + public function getSanitations(): array + { + return $this->sanitations; + } + + /** + * @return string[] + */ + public function getOtherServices(): array + { + return $this->otherServices; + } + + /** + * @return string[] + */ + public function getTrafficInfrastructures(): array + { + return $this->trafficInfrastructures; + } + + /** + * @return string[] + */ + public function getPaymentsAccepted(): array + { + return $this->paymentsAccepted; + } + + public function getDistanceToPublicTransport(): string + { + return $this->distanceToPublicTransport; + } + /** * @internal for mapping via Symfony component. */ @@ -98,4 +175,92 @@ class Place extends Base public function removeOpeningHoursSpecification(OpeningHour $openingHour): void { } + + /** + * @internal for mapping via Symfony component. + * @return ForeignReference[] + */ + public function getParkingFacilityNearBy(): array + { + return $this->parkingFacilitiesNearBy; + } + + /** + * @internal for mapping via Symfony component. + */ + public function addParkingFacilityNearBy(ForeignReference $parkingFacilityNearBy): void + { + $this->parkingFacilitiesNearBy[] = $parkingFacilityNearBy; + } + + /** + * @internal for mapping via Symfony component. + */ + public function removeParkingFacilityNearBy(ForeignReference $parkingFacilityNearBy): void + { + } + + /** + * @internal for mapping via Symfony component. + * @param string|array $sanitation + */ + public function setSanitation($sanitation): void + { + if (is_string($sanitation)) { + $sanitation = [$sanitation]; + } + + $this->sanitations = PropertyValues::removePrefixFromEntries($sanitation); + } + + /** + * @internal for mapping via Symfony component. + * @param string|array $otherService + */ + public function setOtherService($otherService): void + { + if (is_string($otherService)) { + $otherService = [$otherService]; + } + + $this->otherServices = PropertyValues::removePrefixFromEntries($otherService); + } + + /** + * @internal for mapping via Symfony component. + * @param string|array $trafficInfrastructure + */ + public function setTrafficInfrastructure($trafficInfrastructure): void + { + if (is_string($trafficInfrastructure)) { + $trafficInfrastructure = [$trafficInfrastructure]; + } + + $this->trafficInfrastructures = PropertyValues::removePrefixFromEntries($trafficInfrastructure); + } + + /** + * @internal for mapping via Symfony component. + * @param string|array $paymentAccepted + */ + public function setPaymentAccepted($paymentAccepted): void + { + if (is_string($paymentAccepted)) { + $paymentAccepted = [$paymentAccepted]; + } + + $this->paymentsAccepted = PropertyValues::removePrefixFromEntries($paymentAccepted); + } + + /** + * @internal for mapping via Symfony component. + */ + public function setDistanceToPublicTransport(array $distanceToPublicTransport): void + { + $unit = $distanceToPublicTransport['unitCode'] ?? ''; + $value = $distanceToPublicTransport['value'] ?? ''; + if ($unit && $value) { + $this->distanceToPublicTransport = $value . ':' . PropertyValues::removePrefixFromEntry($unit); + } + } } diff --git a/Classes/Domain/Import/Entity/Properties/OpeningHour.php b/Classes/Domain/Import/Entity/Properties/OpeningHour.php index 2d8b3b8..357da02 100644 --- a/Classes/Domain/Import/Entity/Properties/OpeningHour.php +++ b/Classes/Domain/Import/Entity/Properties/OpeningHour.php @@ -26,14 +26,14 @@ namespace WerkraumMedia\ThueCat\Domain\Import\Entity\Properties; class OpeningHour { /** - * @var \DateTimeImmutable + * @var \DateTimeImmutable|null */ - protected $validFrom; + protected $validFrom = null; /** - * @var \DateTimeImmutable + * @var \DateTimeImmutable|null */ - protected $validThrough; + protected $validThrough = null; /** * @var \DateTimeImmutable @@ -50,12 +50,12 @@ 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; } diff --git a/Classes/Domain/Import/Entity/Properties/PriceSpecification.php b/Classes/Domain/Import/Entity/Properties/PriceSpecification.php index 78e274c..46db11e 100644 --- a/Classes/Domain/Import/Entity/Properties/PriceSpecification.php +++ b/Classes/Domain/Import/Entity/Properties/PriceSpecification.php @@ -23,6 +23,7 @@ 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; class PriceSpecification extends Minimum @@ -76,9 +77,7 @@ class PriceSpecification extends Minimum */ public function setPriceCurrency(string $currency): void { - // TODO: Move to serializer process while decoding json?! - // Check for @type and @value, if type is currency … - $this->currency = str_replace('thuecat:', '', $currency); + $this->currency = PropertyValues::removePrefixFromEntry($currency); } /** @@ -86,8 +85,6 @@ class PriceSpecification extends Minimum */ public function setCalculationRule(string $calculationRule): void { - // TODO: Move to serializer process while decoding json?! - // Check for @type and @value, if type is currency … - $this->calculationRule = str_replace('thuecat:', '', $calculationRule); + $this->calculationRule = PropertyValues::removePrefixFromEntry($calculationRule); } } diff --git a/Classes/Domain/Import/Entity/TouristAttraction.php b/Classes/Domain/Import/Entity/TouristAttraction.php index cb4e729..fd2579a 100644 --- a/Classes/Domain/Import/Entity/TouristAttraction.php +++ b/Classes/Domain/Import/Entity/TouristAttraction.php @@ -23,6 +23,8 @@ declare(strict_types=1); namespace WerkraumMedia\ThueCat\Domain\Import\Entity; +use WerkraumMedia\ThueCat\Domain\Import\EntityMapper\PropertyValues; + class TouristAttraction extends Place implements MapsToType { /** @@ -35,16 +37,6 @@ class TouristAttraction extends Place implements MapsToType */ protected $startOfConstruction = ''; - /** - * @var string[] - */ - protected $sanitations = []; - - /** - * @var string[] - */ - protected $otherServices = []; - /** * @var string[] */ @@ -55,16 +47,6 @@ class TouristAttraction extends Place implements MapsToType */ protected $architecturalStyles = []; - /** - * @var string[] - */ - protected $trafficInfrastructures = []; - - /** - * @var string[] - */ - protected $paymentsAccepted = []; - /** * @var string[] */ @@ -95,11 +77,6 @@ class TouristAttraction extends Place implements MapsToType */ protected $availableLanguages = []; - /** - * @var string - */ - protected $distanceToPublicTransport = ''; - public function getSlogan(): string { return $this->slogan; @@ -110,22 +87,6 @@ class TouristAttraction extends Place implements MapsToType return $this->startOfConstruction; } - /** - * @return string[] - */ - public function getSanitations(): array - { - return $this->sanitations; - } - - /** - * @return string[] - */ - public function getOtherServices(): array - { - return $this->otherServices; - } - /** * @return string[] */ @@ -142,22 +103,6 @@ class TouristAttraction extends Place implements MapsToType return $this->architecturalStyles; } - /** - * @return string[] - */ - public function getTrafficInfrastructures(): array - { - return $this->trafficInfrastructures; - } - - /** - * @return string[] - */ - public function getPaymentsAccepted(): array - { - return $this->paymentsAccepted; - } - /** * @return string[] */ @@ -197,17 +142,12 @@ class TouristAttraction extends Place implements MapsToType return $this->availableLanguages; } - public function getDistanceToPublicTransport(): string - { - return $this->distanceToPublicTransport; - } - /** * @internal for mapping via Symfony component. */ public function setSlogan(string $slogan): void { - $this->slogan = str_replace('thuecat:', '', $slogan); + $this->slogan = PropertyValues::removePrefixFromEntry($slogan); } /** @@ -218,36 +158,6 @@ class TouristAttraction extends Place implements MapsToType $this->startOfConstruction = $startOfConstruction; } - /** - * @internal for mapping via Symfony component. - * @param string|array $sanitation - */ - public function setSanitation($sanitation): void - { - if (is_string($sanitation)) { - $sanitation = [$sanitation]; - } - - $this->sanitations = array_map(function (string $sanitation) { - return str_replace('thuecat:', '', $sanitation); - }, $sanitation); - } - - /** - * @internal for mapping via Symfony component. - * @param string|array $otherService - */ - public function setOtherService($otherService): void - { - if (is_string($otherService)) { - $otherService = [$otherService]; - } - - $this->otherServices = array_map(function (string $otherService) { - return str_replace('thuecat:', '', $otherService); - }, $otherService); - } - /** * @internal for mapping via Symfony component. * @param string|array $museumService @@ -258,9 +168,7 @@ class TouristAttraction extends Place implements MapsToType $museumService = [$museumService]; } - $this->museumServices = array_map(function (string $museumService) { - return str_replace('thuecat:', '', $museumService); - }, $museumService); + $this->museumServices = PropertyValues::removePrefixFromEntries($museumService); } /** @@ -273,39 +181,7 @@ class TouristAttraction extends Place implements MapsToType $architecturalStyle = [$architecturalStyle]; } - $this->architecturalStyles = array_map(function (string $architecturalStyle) { - return str_replace('thuecat:', '', $architecturalStyle); - }, $architecturalStyle); - } - - /** - * @internal for mapping via Symfony component. - * @param string|array $trafficInfrastructure - */ - public function setTrafficInfrastructure($trafficInfrastructure): void - { - if (is_string($trafficInfrastructure)) { - $trafficInfrastructure = [$trafficInfrastructure]; - } - - $this->trafficInfrastructures = array_map(function (string $trafficInfrastructure) { - return str_replace('thuecat:', '', $trafficInfrastructure); - }, $trafficInfrastructure); - } - - /** - * @internal for mapping via Symfony component. - * @param string|array $paymentAccepted - */ - public function setPaymentAccepted($paymentAccepted): void - { - if (is_string($paymentAccepted)) { - $paymentAccepted = [$paymentAccepted]; - } - - $this->paymentsAccepted = array_map(function (string $paymentAccepted) { - return str_replace('thuecat:', '', $paymentAccepted); - }, $paymentAccepted); + $this->architecturalStyles = PropertyValues::removePrefixFromEntries($architecturalStyle); } /** @@ -318,9 +194,7 @@ class TouristAttraction extends Place implements MapsToType $digitalOffer = [$digitalOffer]; } - $this->digitalOffers = array_map(function (string $digitalOffer) { - return str_replace('thuecat:', '', $digitalOffer); - }, $digitalOffer); + $this->digitalOffers = PropertyValues::removePrefixFromEntries($digitalOffer); } /** @@ -333,9 +207,7 @@ class TouristAttraction extends Place implements MapsToType $photography = [$photography]; } - $this->photographies = array_map(function (string $photography) { - return str_replace('thuecat:', '', $photography); - }, $photography); + $this->photographies = PropertyValues::removePrefixFromEntries($photography); } /** @@ -372,21 +244,7 @@ class TouristAttraction extends Place implements MapsToType $availableLanguage = [$availableLanguage]; } - $this->availableLanguages = array_map(function (string $availableLanguage) { - return str_replace('thuecat:', '', $availableLanguage); - }, $availableLanguage); - } - - /** - * @internal for mapping via Symfony component. - */ - public function setDistanceToPublicTransport(array $distanceToPublicTransport): void - { - $unit = $distanceToPublicTransport['unitCode'] ?? ''; - $value = $distanceToPublicTransport['value'] ?? ''; - if ($unit && $value) { - $this->distanceToPublicTransport = $value . ':' . str_replace('thuecat:', '', $unit); - } + $this->availableLanguages = PropertyValues::removePrefixFromEntries($availableLanguage); } public static function getSupportedTypes(): array diff --git a/Classes/Domain/Import/EntityMapper/EntityRegistry.php b/Classes/Domain/Import/EntityMapper/EntityRegistry.php index 3e2a1f0..ad94dfb 100644 --- a/Classes/Domain/Import/EntityMapper/EntityRegistry.php +++ b/Classes/Domain/Import/EntityMapper/EntityRegistry.php @@ -23,6 +23,9 @@ declare(strict_types=1); namespace WerkraumMedia\ThueCat\Domain\Import\EntityMapper; +use TYPO3\CMS\Core\Utility\ArrayUtility; + + /** * Registry with supported entities and their types. */ @@ -31,28 +34,47 @@ class EntityRegistry /** * @var array[] */ - private $entityClassNames = []; + private $entities = []; /** * @param string[] $supportedTypes */ public function registerEntityClass( string $entityClassName, + int $priority, array $supportedTypes ): void { - $this->entityClassNames[$entityClassName] = $supportedTypes; + foreach ($supportedTypes as $supportedType) { + $this->entities[$supportedType][] = [ + 'priority' => $priority, + 'entityClassName' => $entityClassName, + ]; + } } public function getEntityByTypes(array $types): string { + $matches = []; + foreach ($types as $type) { - foreach ($this->entityClassNames as $className => $supportedTypes) { - if (in_array($type, $supportedTypes)) { - return $className; - } + if (isset($this->entities[$type]) === false) { + continue; + } + + foreach ($this->entities[$type] as $entityConfiguration) { + $matches[] = $entityConfiguration; } } - return ''; + if ($matches === []) { + return ''; + } + + $matches = ArrayUtility::sortArraysByKey( + $matches, + 'priority' + ); + + return end($matches)['entityClassName']; } } diff --git a/Classes/Domain/Import/EntityMapper/PropertyValues.php b/Classes/Domain/Import/EntityMapper/PropertyValues.php new file mode 100644 index 0000000..fb4969c --- /dev/null +++ b/Classes/Domain/Import/EntityMapper/PropertyValues.php @@ -0,0 +1,43 @@ + + * + * 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\Domain\Import\EntityMapper; + +/** + * API to work with values of properties. + */ +class PropertyValues +{ + public static function removePrefixFromEntry(string $entryWithPrefix): string + { + return str_replace('thuecat:', '', $entryWithPrefix); + } + + public static function removePrefixFromEntries(array $entriesWithPrefix): array + { + return array_map( + [PropertyValues::class, 'removePrefixFromEntry'], + $entriesWithPrefix + ); + } +} diff --git a/Classes/Domain/Import/Import.php b/Classes/Domain/Import/Import.php new file mode 100644 index 0000000..e117892 --- /dev/null +++ b/Classes/Domain/Import/Import.php @@ -0,0 +1,115 @@ + + * + * 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\Domain\Import; + +use TYPO3\CMS\Core\Utility\StringUtility; +use WerkraumMedia\ThueCat\Domain\Model\Backend\ImportLog; + +/** + * State of an import. + * + * Imports can be nested, e.g. an entity during import triggers an import of sub entities. + * The state is handled here to allow a single import result with all affected entities and errors. + */ +class Import +{ + /** + * @var ImportLog[] + */ + private $importLogStack = []; + + /** + * @var ImportConfiguration[] + */ + private $configurationStack = []; + + /** + * @var ImportLog + */ + private $currentImportLog; + + /** + * @var ImportConfiguration + */ + private $currentConfiguration; + + public function start(ImportConfiguration $configuration): void + { + $this->currentConfiguration = $configuration; + $this->currentImportLog = new ImportLog($configuration); + + $this->configurationStack[] = $this->currentConfiguration; + $this->importLogStack[] = $this->currentImportLog; + } + + public function end(): void + { + array_pop($this->configurationStack); + $outerConfiguration = end($this->configurationStack); + if ($outerConfiguration instanceof ImportConfiguration) { + $this->currentConfiguration = $outerConfiguration; + } + + $lastImportLog = array_pop($this->importLogStack); + $outerImportLog = end($this->importLogStack); + if ($outerImportLog instanceof ImportLog) { + $this->currentImportLog = $outerImportLog; + } + if ($lastImportLog instanceof ImportLog) { + $this->currentImportLog->merge($lastImportLog); + } + } + + public function done(): bool + { + return $this->importLogStack === []; + } + + public function getConfiguration(): ImportConfiguration + { + return $this->currentConfiguration; + } + + public function getLog(): ImportLog + { + return $this->currentImportLog; + } + + public function handledRemoteId(string $remoteId): bool + { + // Tours are not supported yet. + // So skip them here to save time. + if (StringUtility::endsWith($remoteId, '-oatour')) { + return true; + } + + foreach ($this->importLogStack as $importLog) { + if ($importLog->handledRemoteId($remoteId)) { + return true; + } + } + + return false; + } +} diff --git a/Classes/Domain/Import/ImportConfiguration.php b/Classes/Domain/Import/ImportConfiguration.php new file mode 100644 index 0000000..3cb5efa --- /dev/null +++ b/Classes/Domain/Import/ImportConfiguration.php @@ -0,0 +1,54 @@ + + * + * 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\Domain\Import; + +interface ImportConfiguration +{ + /** + * Defines type of configuration, e.g.: + * - static + * - syncScope + * + * A UrlProvider is necessary for the type in order to process the configuration. + */ + public function getType(): string; + + /** + * Return URLs to import, full path to resources. + * + * @return string[] + */ + public function getUrls(): array; + + /** + * Defines a limited set of types to process, e.g.: + * - thuecat:Town + * + * The import will only process resources of this type. + * Empty array will allow all. + * + * @return string[] + */ + public function getAllowedTypes(): array; +} diff --git a/Classes/Domain/Import/Importer.php b/Classes/Domain/Import/Importer.php index 18873af..b5f8e86 100644 --- a/Classes/Domain/Import/Importer.php +++ b/Classes/Domain/Import/Importer.php @@ -23,7 +23,6 @@ declare(strict_types=1); namespace WerkraumMedia\ThueCat\Domain\Import; -use TYPO3\CMS\Core\Utility\GeneralUtility; use WerkraumMedia\ThueCat\Domain\Import\EntityMapper\EntityRegistry; use WerkraumMedia\ThueCat\Domain\Import\EntityMapper\JsonDecode; use WerkraumMedia\ThueCat\Domain\Import\Entity\MapsToType; @@ -34,7 +33,7 @@ use WerkraumMedia\ThueCat\Domain\Import\Importer\SaveData; use WerkraumMedia\ThueCat\Domain\Import\Model\EntityCollection; use WerkraumMedia\ThueCat\Domain\Import\UrlProvider\Registry as UrlProviderRegistry; use WerkraumMedia\ThueCat\Domain\Import\UrlProvider\UrlProvider; -use WerkraumMedia\ThueCat\Domain\Model\Backend\ImportConfiguration; +use WerkraumMedia\ThueCat\Domain\Model\Backend\ImportConfiguration as Typo3ImportConfiguration; use WerkraumMedia\ThueCat\Domain\Model\Backend\ImportLog; use WerkraumMedia\ThueCat\Domain\Repository\Backend\ImportLogRepository; @@ -75,20 +74,15 @@ class Importer */ private $saveData; - /** - * @var ImportLog - */ - private $importLog; - /** * @var ImportLogRepository */ private $importLogRepository; /** - * @var ImportConfiguration + * @var Import */ - private $configuration; + private $import; public function __construct( UrlProviderRegistry $urls, @@ -108,29 +102,43 @@ class Importer $this->importLogRepository = $importLogRepository; $this->fetchData = $fetchData; $this->saveData = $saveData; + $this->import = new Import(); } public function importConfiguration(ImportConfiguration $configuration): ImportLog { - $this->configuration = $configuration; + if (!$configuration instanceof Typo3ImportConfiguration) { + throw new \InvalidArgumentException('Currently only can process ImportConfiguration of TYPO3.', 1629708772); + } - $this->importLog = GeneralUtility::makeInstance(ImportLog::class, $this->configuration); + $this->import->start($configuration); + $this->import(); + $this->import->end(); - $urlProvider = $this->urls->getProviderForConfiguration($this->configuration); + if ($this->import->done()) { + $this->importLogRepository->addLog($this->import->getLog()); + } + + return $this->import->getLog(); + } + + private function import(): void + { + $urlProvider = $this->urls->getProviderForConfiguration($this->import->getConfiguration()); if (!$urlProvider instanceof UrlProvider) { - return $this->importLog; + throw new \Exception('No URL Provider available for given configuration.', 1629296635); } foreach ($urlProvider->getUrls() as $url) { $this->importResourceByUrl($url); } - - $this->importLogRepository->addLog($this->importLog); - return clone $this->importLog; } private function importResourceByUrl(string $url): void { + if ($this->import->handledRemoteId($url)) { + return; + } $content = $this->fetchData->jsonLDFromUrl($url); if ($content === []) { @@ -144,6 +152,10 @@ class Importer private function importJsonEntity(array $jsonEntity): void { + if ($this->entityAllowed($jsonEntity) === false) { + return; + } + $targetEntity = $this->entityRegistry->getEntityByTypes($jsonEntity['@type']); if ($targetEntity === '') { return; @@ -151,7 +163,7 @@ class Importer $entities = new EntityCollection(); - foreach ($this->languages->getAvailable($this->configuration) as $language) { + foreach ($this->languages->getAvailable($this->import->getConfiguration()) as $language) { $mappedEntity = $this->entityMapper->mapDataToEntity( $jsonEntity, $targetEntity, @@ -164,7 +176,7 @@ class Importer } $convertedEntity = $this->converter->convert( $mappedEntity, - $this->configuration, + $this->import->getConfiguration(), $language ); @@ -176,7 +188,22 @@ class Importer $this->saveData->import( $entities, - $this->importLog + $this->import->getLog() ); } + + private function entityAllowed(array $jsonEntity): bool + { + if ($this->import->getConfiguration()->getAllowedTypes() === []) { + return true; + } + + foreach ($jsonEntity['@type'] as $type) { + if (in_array($type, $this->import->getConfiguration()->getAllowedTypes()) === true) { + return true; + } + } + + return false; + } } diff --git a/Classes/Domain/Import/Importer/Converter.php b/Classes/Domain/Import/Importer/Converter.php index a6e0fa8..476077b 100644 --- a/Classes/Domain/Import/Importer/Converter.php +++ b/Classes/Domain/Import/Importer/Converter.php @@ -24,8 +24,8 @@ declare(strict_types=1); namespace WerkraumMedia\ThueCat\Domain\Import\Importer; use WerkraumMedia\ThueCat\Domain\Import\Entity\MapsToType; +use WerkraumMedia\ThueCat\Domain\Import\ImportConfiguration; use WerkraumMedia\ThueCat\Domain\Import\Model\Entity; -use WerkraumMedia\ThueCat\Domain\Model\Backend\ImportConfiguration; interface Converter { diff --git a/Classes/Domain/Import/Importer/Languages.php b/Classes/Domain/Import/Importer/Languages.php index b4b8ec4..4210118 100644 --- a/Classes/Domain/Import/Importer/Languages.php +++ b/Classes/Domain/Import/Importer/Languages.php @@ -23,7 +23,7 @@ declare(strict_types=1); namespace WerkraumMedia\ThueCat\Domain\Import\Importer; -use WerkraumMedia\ThueCat\Domain\Model\Backend\ImportConfiguration; +use WerkraumMedia\ThueCat\Domain\Import\ImportConfiguration; interface Languages { diff --git a/Classes/Domain/Import/ResolveForeignReference.php b/Classes/Domain/Import/ResolveForeignReference.php index 31d8f71..b225b64 100644 --- a/Classes/Domain/Import/ResolveForeignReference.php +++ b/Classes/Domain/Import/ResolveForeignReference.php @@ -28,6 +28,13 @@ use WerkraumMedia\ThueCat\Domain\Import\EntityMapper\JsonDecode; use WerkraumMedia\ThueCat\Domain\Import\Entity\Properties\ForeignReference; use WerkraumMedia\ThueCat\Domain\Import\Importer\FetchData; +/** + * Can be used to resolve foreign references. + * + * The reference will be resolved and returned as entity. + * It will not be imported! + * Use Importer instead to import foreign references. + */ class ResolveForeignReference { /** @@ -78,4 +85,15 @@ class ResolveForeignReference ] ); } + + /** + * @param ForeignReference[] $foreignReferences + * @return string[] + */ + public static function convertToRemoteIds(array $foreignReferences): array + { + return array_map(function (ForeignReference $reference) { + return $reference->getId(); + }, $foreignReferences); + } } diff --git a/Classes/Domain/Import/Typo3Converter.php b/Classes/Domain/Import/Typo3Converter.php index b4e0c25..d5719f3 100644 --- a/Classes/Domain/Import/Typo3Converter.php +++ b/Classes/Domain/Import/Typo3Converter.php @@ -28,7 +28,7 @@ use WerkraumMedia\ThueCat\Domain\Import\Importer\Converter; use WerkraumMedia\ThueCat\Domain\Import\Model\Entity; use WerkraumMedia\ThueCat\Domain\Import\Typo3Converter\Converter as Typo3ConcreteConverter; use WerkraumMedia\ThueCat\Domain\Import\Typo3Converter\Registry; -use WerkraumMedia\ThueCat\Domain\Model\Backend\ImportConfiguration; +use WerkraumMedia\ThueCat\Domain\Model\Backend\ImportConfiguration as Typo3ImportConfiguration; class Typo3Converter implements Converter { @@ -48,6 +48,10 @@ class Typo3Converter implements Converter ImportConfiguration $configuration, string $language ): ?Entity { + if (!$configuration instanceof Typo3ImportConfiguration) { + throw new \InvalidArgumentException('Only supports TYPO3 import configuration.', 1629710386); + } + $concreteConverter = $this->registry->getConverterBasedOnType($mapped); if (!$concreteConverter instanceof Typo3ConcreteConverter) { throw new \Exception( @@ -55,6 +59,7 @@ class Typo3Converter implements Converter 1628244329 ); } + return $concreteConverter->convert( $mapped, $configuration, diff --git a/Classes/Domain/Import/Typo3Converter/Converter.php b/Classes/Domain/Import/Typo3Converter/Converter.php index ae149fc..df27916 100644 --- a/Classes/Domain/Import/Typo3Converter/Converter.php +++ b/Classes/Domain/Import/Typo3Converter/Converter.php @@ -29,8 +29,6 @@ use WerkraumMedia\ThueCat\Domain\Model\Backend\ImportConfiguration; interface Converter { - public function canConvert(MapsToType $entity): bool; - public function convert( MapsToType $entity, ImportConfiguration $configuration, diff --git a/Classes/Domain/Import/Typo3Converter/GeneralConverter.php b/Classes/Domain/Import/Typo3Converter/GeneralConverter.php new file mode 100644 index 0000000..30b780f --- /dev/null +++ b/Classes/Domain/Import/Typo3Converter/GeneralConverter.php @@ -0,0 +1,373 @@ + + * + * 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\Domain\Import\Typo3Converter; + +use TYPO3\CMS\Extbase\Persistence\QueryResultInterface; +use WerkraumMedia\ThueCat\Domain\Import\Entity\Base; +use WerkraumMedia\ThueCat\Domain\Import\Entity\MapsToType; +use WerkraumMedia\ThueCat\Domain\Import\Entity\MediaObject; +use WerkraumMedia\ThueCat\Domain\Import\Entity\Minimum; +use WerkraumMedia\ThueCat\Domain\Import\Entity\ParkingFacility; +use WerkraumMedia\ThueCat\Domain\Import\Entity\Place; +use WerkraumMedia\ThueCat\Domain\Import\Entity\Properties\ForeignReference; +use WerkraumMedia\ThueCat\Domain\Import\Entity\Properties\PriceSpecification; +use WerkraumMedia\ThueCat\Domain\Import\Entity\TouristAttraction; +use WerkraumMedia\ThueCat\Domain\Import\Entity\TouristInformation; +use WerkraumMedia\ThueCat\Domain\Import\Entity\TouristMarketingCompany; +use WerkraumMedia\ThueCat\Domain\Import\Entity\Town; +use WerkraumMedia\ThueCat\Domain\Import\Importer; +use WerkraumMedia\ThueCat\Domain\Import\Model\Entity; +use WerkraumMedia\ThueCat\Domain\Import\Model\GenericEntity; +use WerkraumMedia\ThueCat\Domain\Import\ResolveForeignReference; +use WerkraumMedia\ThueCat\Domain\Model\Backend\ImportConfiguration; +use WerkraumMedia\ThueCat\Domain\Repository\Backend\OrganisationRepository; +use WerkraumMedia\ThueCat\Domain\Repository\Backend\ParkingFacilityRepository; +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 ImportConfiguration + */ + private $importConfiguration; + + /** + * @var string[] + */ + private $classToTableMapping = [ + TouristAttraction::class => 'tx_thuecat_tourist_attraction', + ParkingFacility::class => 'tx_thuecat_parking_facility', + Town::class => 'tx_thuecat_town', + TouristInformation::class => 'tx_thuecat_tourist_information', + TouristMarketingCompany::class => 'tx_thuecat_organisation', + ]; + + public function __construct( + ResolveForeignReference $resolveForeignReference, + Importer $importer, + LanguageHandling $languageHandling, + OrganisationRepository $organisationRepository, + TownRepository $townRepository, + ParkingFacilityRepository $parkingFacilityRepository + ) { + $this->resolveForeignReference = $resolveForeignReference; + $this->importer = $importer; + $this->languageHandling = $languageHandling; + $this->organisationRepository = $organisationRepository; + $this->townRepository = $townRepository; + $this->parkingFacilityRepository = $parkingFacilityRepository; + } + + public function convert( + MapsToType $entity, + ImportConfiguration $importConfiguration, + string $language + ): ?Entity { + $this->importConfiguration = $importConfiguration; + + if (!$entity instanceof Minimum || $entity->hasName() === false) { + return null; + } + + return new GenericEntity( + $importConfiguration->getStoragePid(), + $this->getTableNameByEntityClass(get_class($entity)), + $this->languageHandling->getLanguageUidForString( + $importConfiguration->getStoragePid(), + $language + ), + $entity->getId(), + $this->buildDataArrayFromEntity( + $entity, + $language + ) + ); + } + + private function getTableNameByEntityClass(string $className): string + { + $tableName = $this->classToTableMapping[$className] ?? ''; + if ($tableName == '') { + throw new \Exception('No table name configured for class ' . $className, 1629376990); + } + + return $tableName; + } + + private function buildDataArrayFromEntity( + Minimum $entity, + string $language + ): array { + return [ + 'title' => $entity->getName(), + 'description' => trim($entity->getDescription()), + 'sanitation' => method_exists($entity, 'getSanitations') ? implode(',', $entity->getSanitations()) : '', + 'managed_by' => $this->getManagerUid($entity), + 'town' => $this->getTownUid($entity), + 'media' => $entity instanceof Base ? $this->getMedia($entity, $language) : '', + + 'parking_facility_near_by' => $entity instanceof Base ? implode(',', $this->getParkingFacilitiesNearByUids($entity)) : '', + + 'opening_hours' => $entity instanceof Place ? $this->getOpeningHours($entity) : '', + 'address' => $entity instanceof Place ? $this->getAddress($entity) : '', + 'offers' => $entity instanceof Place ? $this->getOffers($entity) : '', + 'other_service' => method_exists($entity, 'getOtherServices') ? implode(',', $entity->getOtherServices()) : '', + 'traffic_infrastructure' => method_exists($entity, 'getTrafficInfrastructures') ? implode(',', $entity->getTrafficInfrastructures()) : '', + 'payment_accepted' => method_exists($entity, 'getPaymentsAccepted') ? implode(',', $entity->getPaymentsAccepted()) : '', + 'distance_to_public_transport' => method_exists($entity, 'getDistanceToPublicTransport') ? $entity->getDistanceToPublicTransport() : '', + + 'slogan' => method_exists($entity, 'getSlogan') ? $entity->getSlogan() : '', + 'start_of_construction' => method_exists($entity, 'getStartOfConstruction') ? $entity->getStartOfConstruction() : '', + 'museum_service' => method_exists($entity, 'getMuseumServices') ? implode(',', $entity->getMuseumServices()) : '', + 'architectural_style' => method_exists($entity, 'getArchitecturalStyles') ? implode(',', $entity->getArchitecturalStyles()) : '', + 'digital_offer' => method_exists($entity, 'getDigitalOffers') ? implode(',', $entity->getDigitalOffers()) : '', + 'photography' => method_exists($entity, 'getPhotographies') ? implode(',', $entity->getPhotographies()) : '', + 'pets_allowed' => method_exists($entity, 'getPetsAllowed') ? $entity->getPetsAllowed() : '', + 'is_accessible_for_free' => method_exists($entity, 'getIsAccessibleForFree') ? $entity->getIsAccessibleForFree() : '', + 'public_access' => method_exists($entity, 'getPublicAccess') ? $entity->getPublicAccess() : '', + 'available_languages' => method_exists($entity, 'getAvailableLanguages') ? implode(',', $entity->getAvailableLanguages()) : '', + ]; + } + + private function getManagerUid(object $entity): string + { + if ( + method_exists($entity, 'getManagedBy') === false + || !$entity->getManagedBy() instanceof ForeignReference + ) { + return ''; + } + + $this->importer->importConfiguration( + ImportConfiguration::createFromBaseWithForeignReferences( + $this->importConfiguration, + [$entity->getManagedBy()] + ) + ); + $manager = $this->organisationRepository->findOneByRemoteId( + $entity->getManagedBy()->getId() + ); + + return $manager ? (string)$manager->getUid() : ''; + } + + private function getTownUid(object $entity): string + { + if ( + $entity instanceof Town + || method_exists($entity, 'getContainedInPlaces') === false + ) { + return ''; + } + + $this->importer->importConfiguration( + ImportConfiguration::createFromBaseWithForeignReferences( + $this->importConfiguration, + $entity->getContainedInPlaces(), + ['thuecat:Town'] + ) + ); + $town = $this->townRepository->findOneByEntity($entity); + return $town ? (string) $town->getUid() : ''; + } + + private function getParkingFacilitiesNearByUids(Base $entity): array + { + if (method_exists($entity, 'getParkingFacilitiesNearBy') === false) { + return []; + } + + $this->importer->importConfiguration( + ImportConfiguration::createFromBaseWithForeignReferences( + $this->importConfiguration, + $entity->getParkingFacilitiesNearBy() + ) + ); + + return $this->getUids( + $this->parkingFacilityRepository->findByEntity($entity) + ); + } + + private function getMedia( + Base $entity, + string $language + ): string { + $data = []; + + if ($entity->getPhoto() instanceof ForeignReference) { + $photo = $this->resolveForeignReference->resolve( + $entity->getPhoto(), + $language + ); + if ($photo instanceof MediaObject) { + $data[] = $this->getSingleMedia($photo, true); + } + } + + foreach ($entity->getImages() as $image) { + $image = $this->resolveForeignReference->resolve( + $image, + $language + ); + if ($image instanceof MediaObject) { + $data[] = $this->getSingleMedia($image, false); + } + } + + return json_encode($data) ?: ''; + } + + private function getSingleMedia( + MediaObject $mediaObject, + bool $mainImage + ): array { + return [ + 'mainImage' => $mainImage, + 'type' => $mediaObject->getType(), + 'title' => $mediaObject->getName(), + 'description' => $mediaObject->getDescription(), + 'url' => $mediaObject->getUrl(), + 'copyrightYear' => $mediaObject->getCopyrightYear(), + 'license' => [ + 'type' => $mediaObject->getLicense(), + 'author' => $mediaObject->getLicenseAuthor(), + ], + ]; + } + + private function getOpeningHours(Place $entity): string + { + $data = []; + + foreach ($entity->getOpeningHoursSpecification() as $openingHour) { + $data[] = [ + 'opens' => $openingHour->getOpens()->format('H:i:s'), + 'closes' => $openingHour->getCloses()->format('H:i:s'), + 'from' => $openingHour->getValidFrom() ?? '', + 'through' => $openingHour->getValidThrough() ?? '', + 'daysOfWeek' => $openingHour->getDaysOfWeek(), + ]; + } + + return json_encode($data) ?: ''; + } + + private function getAddress(Place $entity): string + { + $data = []; + + $address = $entity->getAddress(); + if ($address !== null) { + $data += [ + 'street' => $address->getStreetAddress(), + 'zip' => $address->getPostalCode(), + 'city' => $address->getAddressLocality(), + 'email' => $address->getEmail(), + 'phone' => $address->getTelephone(), + 'fax' => $address->getFaxNumber(), + ]; + } + + $geo = $entity->getGeo(); + if ($geo !== null) { + $data += [ + 'geo' => [ + 'latitude' => $geo->getLatitude(), + 'longitude' => $geo->getLongitude(), + ], + ]; + } + + return json_encode($data) ?: ''; + } + + private function getOffers(Place $entity): string + { + $data = []; + foreach ($entity->getOffers() as $offer) { + $data[] = [ + 'title' => $offer->getName(), + 'description' => $offer->getDescription(), + 'prices' => array_map([$this, 'getPrice'], $offer->getPrices()), + ]; + } + + return json_encode($data) ?: ''; + } + + private function getPrice(PriceSpecification $priceSpecification): array + { + return [ + 'title' => $priceSpecification->getName(), + 'description' => $priceSpecification->getDescription(), + 'price' => $priceSpecification->getPrice(), + 'currency' => $priceSpecification->getCurrency(), + 'rule' => $priceSpecification->getCalculationRule(), + ]; + } + + private function getUids(?QueryResultInterface $result): array + { + if ($result === null) { + return []; + } + + $uids = []; + foreach ($result as $entry) { + $uids[] = $entry->getUid(); + } + return $uids; + } +} diff --git a/Classes/Domain/Import/Typo3Converter/LanguageHandling.php b/Classes/Domain/Import/Typo3Converter/LanguageHandling.php index 940f957..9b024d6 100644 --- a/Classes/Domain/Import/Typo3Converter/LanguageHandling.php +++ b/Classes/Domain/Import/Typo3Converter/LanguageHandling.php @@ -25,8 +25,8 @@ namespace WerkraumMedia\ThueCat\Domain\Import\Typo3Converter; use TYPO3\CMS\Core\Site\Entity\SiteLanguage; use TYPO3\CMS\Core\Site\SiteFinder; +use WerkraumMedia\ThueCat\Domain\Import\ImportConfiguration; use WerkraumMedia\ThueCat\Domain\Import\Importer\Languages; -use WerkraumMedia\ThueCat\Domain\Model\Backend\ImportConfiguration; class LanguageHandling implements Languages { @@ -43,6 +43,9 @@ class LanguageHandling implements Languages public function getAvailable(ImportConfiguration $configuration): array { + if (method_exists($configuration, 'getStoragePid') === false) { + throw new \InvalidArgumentException('Unsupported configuration, need to retrieve storage pid.', 1629710300); + } return array_map(function (SiteLanguage $language) { return $language->getTwoLetterIsoCode(); }, $this->getLanguages($configuration->getStoragePid())); diff --git a/Classes/Domain/Import/Typo3Converter/Organisation.php b/Classes/Domain/Import/Typo3Converter/Organisation.php deleted file mode 100644 index f0a1bed..0000000 --- a/Classes/Domain/Import/Typo3Converter/Organisation.php +++ /dev/null @@ -1,63 +0,0 @@ - - * - * 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\Domain\Import\Typo3Converter; - -use WerkraumMedia\ThueCat\Domain\Import\Entity\MapsToType; -use WerkraumMedia\ThueCat\Domain\Import\Entity\TouristMarketingCompany; -use WerkraumMedia\ThueCat\Domain\Import\Model\Entity; -use WerkraumMedia\ThueCat\Domain\Import\Model\GenericEntity; -use WerkraumMedia\ThueCat\Domain\Model\Backend\ImportConfiguration; - -class Organisation implements Converter -{ - public function canConvert(MapsToType $entity): bool - { - return $entity instanceof TouristMarketingCompany; - } - - public function convert( - MapsToType $entity, - ImportConfiguration $configuration, - string $language - ): ?Entity { - if (!$entity instanceof TouristMarketingCompany) { - throw new \InvalidArgumentException('Did not get entity of expected type.', 1628243431); - } - - if ($entity->hasName() === false) { - return null; - } - - return new GenericEntity( - $configuration->getStoragePid(), - 'tx_thuecat_organisation', - 0, - $entity->getId(), - [ - 'title' => $entity->getName(), - 'description' => $entity->getDescription(), - ] - ); - } -} diff --git a/Classes/Domain/Import/Typo3Converter/Registry.php b/Classes/Domain/Import/Typo3Converter/Registry.php index 448cdcf..2b038e2 100644 --- a/Classes/Domain/Import/Typo3Converter/Registry.php +++ b/Classes/Domain/Import/Typo3Converter/Registry.php @@ -27,6 +27,10 @@ use WerkraumMedia\ThueCat\Domain\Import\Entity\MapsToType; /** * Central registry of all available converters. + * + * Kept for now even if only a single exists. + * Necessary to prevent cycle dependency between Importer and Typo3Converter. + * Check if we still can reduce used code. */ class Registry { @@ -42,12 +46,6 @@ class Registry public function getConverterBasedOnType(MapsToType $entity): ?Converter { - foreach ($this->converters as $converter) { - if ($converter->canConvert($entity)) { - return $converter; - } - } - - return null; + return $this->converters[0]; } } diff --git a/Classes/Domain/Import/Typo3Converter/TouristAttraction.php b/Classes/Domain/Import/Typo3Converter/TouristAttraction.php deleted file mode 100644 index 2b484b0..0000000 --- a/Classes/Domain/Import/Typo3Converter/TouristAttraction.php +++ /dev/null @@ -1,252 +0,0 @@ - - * - * 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\Domain\Import\Typo3Converter; - -use WerkraumMedia\ThueCat\Domain\Import\Entity\MapsToType; -use WerkraumMedia\ThueCat\Domain\Import\Entity\MediaObject; -use WerkraumMedia\ThueCat\Domain\Import\Entity\Properties\ForeignReference; -use WerkraumMedia\ThueCat\Domain\Import\Entity\Properties\PriceSpecification; -use WerkraumMedia\ThueCat\Domain\Import\Entity\TouristAttraction as TouristAttractionEntity; -use WerkraumMedia\ThueCat\Domain\Import\Model\Entity; -use WerkraumMedia\ThueCat\Domain\Import\Model\GenericEntity; -use WerkraumMedia\ThueCat\Domain\Import\ResolveForeignReference; -use WerkraumMedia\ThueCat\Domain\Model\Backend\ImportConfiguration; -use WerkraumMedia\ThueCat\Domain\Repository\Backend\OrganisationRepository; -use WerkraumMedia\ThueCat\Domain\Repository\Backend\TownRepository; - -class TouristAttraction implements Converter -{ - /** - * @var ResolveForeignReference - */ - private $resolveForeignReference; - - /** - * @var LanguageHandling - */ - private $languageHandling; - - /** - * @var OrganisationRepository - */ - private $organisationRepository; - - /** - * @var TownRepository - */ - private $townRepository; - - public function __construct( - ResolveForeignReference $resolveForeignReference, - LanguageHandling $languageHandling, - OrganisationRepository $organisationRepository, - TownRepository $townRepository - ) { - $this->resolveForeignReference = $resolveForeignReference; - $this->languageHandling = $languageHandling; - $this->organisationRepository = $organisationRepository; - $this->townRepository = $townRepository; - } - - public function canConvert(MapsToType $entity): bool - { - return $entity instanceof TouristAttractionEntity; - } - - public function convert( - MapsToType $entity, - ImportConfiguration $configuration, - string $language - ): ?Entity { - if (!$entity instanceof TouristAttractionEntity) { - throw new \InvalidArgumentException('Did not get entity of expected type.', 1628243431); - } - - if ($entity->hasName() === false) { - return null; - } - - $manager = null; - if ($entity->getManagedBy() instanceof ForeignReference) { - $manager = $this->organisationRepository->findOneByRemoteId( - $entity->getManagedBy()->getId() - ); - } - - $town = $this->townRepository->findOneByEntity($entity); - - return new GenericEntity( - $configuration->getStoragePid(), - 'tx_thuecat_tourist_attraction', - $this->languageHandling->getLanguageUidForString( - $configuration->getStoragePid(), - $language - ), - $entity->getId(), - [ - 'title' => $entity->getName(), - 'description' => $entity->getDescription(), - 'slogan' => $entity->getSlogan(), - 'start_of_construction' => $entity->getStartOfConstruction(), - 'sanitation' => implode(',', $entity->getSanitations()), - 'managed_by' => $manager ? $manager->getUid() : 0, - 'town' => $town ? $town->getUid() : 0, - 'media' => $this->getMedia($entity, $language), - 'opening_hours' => $this->getOpeningHours($entity), - 'address' => $this->getAddress($entity), - 'offers' => $this->getOffers($entity), - 'other_service' => implode(',', $entity->getOtherServices()), - 'museum_service' => implode(',', $entity->getMuseumServices()), - 'architectural_style' => implode(',', $entity->getArchitecturalStyles()), - 'traffic_infrastructure' => implode(',', $entity->getTrafficInfrastructures()), - 'payment_accepted' => implode(',', $entity->getPaymentsAccepted()), - 'digital_offer' => implode(',', $entity->getDigitalOffers()), - 'photography' => implode(',', $entity->getPhotographies()), - 'pets_allowed' => $entity->getPetsAllowed(), - 'is_accessible_for_free' => $entity->getIsAccessibleForFree(), - 'public_access' => $entity->getPublicAccess(), - 'available_languages' => implode(',', $entity->getAvailableLanguages()), - 'distance_to_public_transport' => $entity->getDistanceToPublicTransport(), - ] - ); - } - - private function getMedia( - TouristAttractionEntity $entity, - string $language - ): string { - $data = []; - - if ($entity->getPhoto() instanceof ForeignReference) { - $photo = $this->resolveForeignReference->resolve( - $entity->getPhoto(), - $language - ); - if ($photo instanceof MediaObject) { - $data[] = $this->getSingleMedia($photo, true); - } - } - - foreach ($entity->getImages() as $image) { - $image = $this->resolveForeignReference->resolve( - $image, - $language - ); - if ($image instanceof MediaObject) { - $data[] = $this->getSingleMedia($image, false); - } - } - - return json_encode($data) ?: ''; - } - - private function getSingleMedia( - MediaObject $mediaObject, - bool $mainImage - ): array { - return [ - 'mainImage' => $mainImage, - 'type' => $mediaObject->getType(), - 'title' => $mediaObject->getName(), - 'description' => $mediaObject->getDescription(), - 'url' => $mediaObject->getUrl(), - 'copyrightYear' => $mediaObject->getCopyrightYear(), - 'license' => [ - 'type' => $mediaObject->getLicense(), - 'author' => $mediaObject->getLicenseAuthor(), - ], - ]; - } - - private function getOpeningHours(TouristAttractionEntity $entity): string - { - $data = []; - - foreach ($entity->getOpeningHoursSpecification() as $openingHour) { - $data[] = [ - 'opens' => $openingHour->getOpens()->format('H:i:s'), - 'closes' => $openingHour->getCloses()->format('H:i:s'), - 'from' => $openingHour->getValidFrom(), - 'through' => $openingHour->getValidThrough(), - 'daysOfWeek' => $openingHour->getDaysOfWeek(), - ]; - } - - return json_encode($data) ?: ''; - } - - private function getAddress(TouristAttractionEntity $entity): string - { - $data = []; - - $address = $entity->getAddress(); - if ($address !== null) { - $data += [ - 'street' => $address->getStreetAddress(), - 'zip' => $address->getPostalCode(), - 'city' => $address->getAddressLocality(), - 'email' => $address->getEmail(), - 'phone' => $address->getTelephone(), - 'fax' => $address->getFaxNumber(), - ]; - } - - $geo = $entity->getGeo(); - if ($geo !== null) { - $data += [ - 'geo' => [ - 'latitude' => $geo->getLatitude(), - 'longitude' => $geo->getLongitude(), - ], - ]; - } - - return json_encode($data) ?: ''; - } - - private function getOffers(TouristAttractionEntity $entity): string - { - $data = []; - foreach ($entity->getOffers() as $offer) { - $data[] = [ - 'title' => $offer->getName(), - 'description' => $offer->getDescription(), - 'prices' => array_map([$this, 'getPrice'], $offer->getPrices()), - ]; - } - - return json_encode($data) ?: ''; - } - - private function getPrice(PriceSpecification $priceSpecification): array - { - return [ - 'title' => $priceSpecification->getName(), - 'description' => $priceSpecification->getDescription(), - 'price' => $priceSpecification->getPrice(), - 'currency' => $priceSpecification->getCurrency(), - 'rule' => $priceSpecification->getCalculationRule(), - ]; - } -} diff --git a/Classes/Domain/Import/Typo3Converter/TouristInformation.php b/Classes/Domain/Import/Typo3Converter/TouristInformation.php deleted file mode 100644 index ec82dd8..0000000 --- a/Classes/Domain/Import/Typo3Converter/TouristInformation.php +++ /dev/null @@ -1,95 +0,0 @@ - - * - * 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\Domain\Import\Typo3Converter; - -use WerkraumMedia\ThueCat\Domain\Import\Entity\MapsToType; -use WerkraumMedia\ThueCat\Domain\Import\Entity\Properties\ForeignReference; -use WerkraumMedia\ThueCat\Domain\Import\Entity\TouristInformation as TouristInformationEntity; -use WerkraumMedia\ThueCat\Domain\Import\Model\Entity; -use WerkraumMedia\ThueCat\Domain\Import\Model\GenericEntity; -use WerkraumMedia\ThueCat\Domain\Model\Backend\ImportConfiguration; -use WerkraumMedia\ThueCat\Domain\Repository\Backend\OrganisationRepository; -use WerkraumMedia\ThueCat\Domain\Repository\Backend\TownRepository; - -class TouristInformation implements Converter -{ - /** - * @var OrganisationRepository - */ - private $organisationRepository; - - /** - * @var TownRepository - */ - private $townRepository; - - public function __construct( - OrganisationRepository $organisationRepository, - TownRepository $townRepository - ) { - $this->organisationRepository = $organisationRepository; - $this->townRepository = $townRepository; - } - - public function canConvert(MapsToType $entity): bool - { - return $entity instanceof TouristInformationEntity; - } - - public function convert( - MapsToType $entity, - ImportConfiguration $configuration, - string $language - ): ?Entity { - if (!$entity instanceof TouristInformationEntity) { - throw new \InvalidArgumentException('Did not get entity of expected type.', 1628243431); - } - - if ($entity->hasName() === false) { - return null; - } - - $manager = null; - if ($entity->getManagedBy() instanceof ForeignReference) { - $manager = $this->organisationRepository->findOneByRemoteId( - $entity->getManagedBy()->getId() - ); - } - - $town = $this->townRepository->findOneByEntity($entity); - - return new GenericEntity( - $configuration->getStoragePid(), - 'tx_thuecat_tourist_information', - 0, - $entity->getId(), - [ - 'title' => $entity->getName(), - 'description' => $entity->getDescription(), - 'managed_by' => $manager ? $manager->getUid() : 0, - 'town' => $town ? $town->getUid() : 0, - ] - ); - } -} diff --git a/Classes/Domain/Import/Typo3Converter/Town.php b/Classes/Domain/Import/Typo3Converter/Town.php deleted file mode 100644 index 5d2cf4a..0000000 --- a/Classes/Domain/Import/Typo3Converter/Town.php +++ /dev/null @@ -1,84 +0,0 @@ - - * - * 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\Domain\Import\Typo3Converter; - -use WerkraumMedia\ThueCat\Domain\Import\Entity\MapsToType; -use WerkraumMedia\ThueCat\Domain\Import\Entity\Properties\ForeignReference; -use WerkraumMedia\ThueCat\Domain\Import\Entity\Town as TownEntity; -use WerkraumMedia\ThueCat\Domain\Import\Model\Entity; -use WerkraumMedia\ThueCat\Domain\Import\Model\GenericEntity; -use WerkraumMedia\ThueCat\Domain\Model\Backend\ImportConfiguration; -use WerkraumMedia\ThueCat\Domain\Repository\Backend\OrganisationRepository; - -class Town implements Converter -{ - /** - * @var OrganisationRepository - */ - private $organisationRepository; - - public function __construct( - OrganisationRepository $organisationRepository - ) { - $this->organisationRepository = $organisationRepository; - } - - public function canConvert(MapsToType $entity): bool - { - return $entity instanceof TownEntity; - } - - public function convert( - MapsToType $entity, - ImportConfiguration $configuration, - string $language - ): ?Entity { - if (!$entity instanceof TownEntity) { - throw new \InvalidArgumentException('Did not get entity of expected type.', 1628243431); - } - - if ($entity->hasName() === false) { - return null; - } - - $manager = null; - if ($entity->getManagedBy() instanceof ForeignReference) { - $manager = $this->organisationRepository->findOneByRemoteId( - $entity->getManagedBy()->getId() - ); - } - - return new GenericEntity( - $configuration->getStoragePid(), - 'tx_thuecat_town', - 0, - $entity->getId(), - [ - 'title' => $entity->getName(), - 'description' => $entity->getDescription(), - 'managed_by' => $manager ? $manager->getUid() : 0, - ] - ); - } -} diff --git a/Classes/Domain/Import/UrlProvider/Registry.php b/Classes/Domain/Import/UrlProvider/Registry.php index 825d42f..6595f5f 100644 --- a/Classes/Domain/Import/UrlProvider/Registry.php +++ b/Classes/Domain/Import/UrlProvider/Registry.php @@ -23,7 +23,7 @@ declare(strict_types=1); namespace WerkraumMedia\ThueCat\Domain\Import\UrlProvider; -use WerkraumMedia\ThueCat\Domain\Model\Backend\ImportConfiguration; +use WerkraumMedia\ThueCat\Domain\Import\ImportConfiguration; /** * Central registry of all available url provider. diff --git a/Classes/Domain/Import/UrlProvider/StaticUrlProvider.php b/Classes/Domain/Import/UrlProvider/StaticUrlProvider.php index c77b2a8..5b3b836 100644 --- a/Classes/Domain/Import/UrlProvider/StaticUrlProvider.php +++ b/Classes/Domain/Import/UrlProvider/StaticUrlProvider.php @@ -23,7 +23,7 @@ declare(strict_types=1); namespace WerkraumMedia\ThueCat\Domain\Import\UrlProvider; -use WerkraumMedia\ThueCat\Domain\Model\Backend\ImportConfiguration; +use WerkraumMedia\ThueCat\Domain\Import\ImportConfiguration; class StaticUrlProvider implements UrlProvider { diff --git a/Classes/Domain/Import/UrlProvider/SyncScopeUrlProvider.php b/Classes/Domain/Import/UrlProvider/SyncScopeUrlProvider.php index d91cce9..f2ff758 100644 --- a/Classes/Domain/Import/UrlProvider/SyncScopeUrlProvider.php +++ b/Classes/Domain/Import/UrlProvider/SyncScopeUrlProvider.php @@ -23,8 +23,8 @@ declare(strict_types=1); namespace WerkraumMedia\ThueCat\Domain\Import\UrlProvider; +use WerkraumMedia\ThueCat\Domain\Import\ImportConfiguration; use WerkraumMedia\ThueCat\Domain\Import\Importer\FetchData; -use WerkraumMedia\ThueCat\Domain\Model\Backend\ImportConfiguration; class SyncScopeUrlProvider implements UrlProvider { @@ -53,6 +53,9 @@ class SyncScopeUrlProvider implements UrlProvider public function createWithConfiguration( ImportConfiguration $configuration ): UrlProvider { + if (method_exists($configuration, 'getSyncScopeId') === false) { + throw new \InvalidArgumentException('Received incompatible import configuration.', 1629709276); + } $instance = clone $this; $instance->syncScopeId = $configuration->getSyncScopeId(); diff --git a/Classes/Domain/Import/UrlProvider/UrlProvider.php b/Classes/Domain/Import/UrlProvider/UrlProvider.php index ca333ad..6deab24 100644 --- a/Classes/Domain/Import/UrlProvider/UrlProvider.php +++ b/Classes/Domain/Import/UrlProvider/UrlProvider.php @@ -23,7 +23,7 @@ declare(strict_types=1); namespace WerkraumMedia\ThueCat\Domain\Import\UrlProvider; -use WerkraumMedia\ThueCat\Domain\Model\Backend\ImportConfiguration; +use WerkraumMedia\ThueCat\Domain\Import\ImportConfiguration; interface UrlProvider { diff --git a/Classes/Domain/Model/Backend/ImportConfiguration.php b/Classes/Domain/Model/Backend/ImportConfiguration.php index ad2e97e..3fcc810 100644 --- a/Classes/Domain/Model/Backend/ImportConfiguration.php +++ b/Classes/Domain/Model/Backend/ImportConfiguration.php @@ -26,8 +26,11 @@ namespace WerkraumMedia\ThueCat\Domain\Model\Backend; use TYPO3\CMS\Core\Utility\ArrayUtility; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Extbase\DomainObject\AbstractEntity; +use WerkraumMedia\ThueCat\Domain\Import\Entity\Properties\ForeignReference; +use WerkraumMedia\ThueCat\Domain\Import\ImportConfiguration as ImportConfigurationInterface; +use WerkraumMedia\ThueCat\Domain\Import\ResolveForeignReference; -class ImportConfiguration extends AbstractEntity +class ImportConfiguration extends AbstractEntity implements ImportConfigurationInterface { /** * @var string @@ -49,6 +52,16 @@ class ImportConfiguration extends AbstractEntity */ protected $tstamp = null; + /** + * @var string[]|null + */ + protected $urls = null; + + /** + * @var string[] + */ + protected $allowedTypes = []; + public function getTitle(): string { return $this->title; @@ -89,6 +102,10 @@ class ImportConfiguration extends AbstractEntity public function getUrls(): array { + if ($this->urls !== null) { + return $this->urls; + } + if ($this->configuration === '') { return []; } @@ -102,6 +119,11 @@ class ImportConfiguration extends AbstractEntity return array_values($entries); } + public function getAllowedTypes(): array + { + return $this->allowedTypes; + } + public function getSyncScopeId(): string { if ($this->configuration === '') { @@ -139,4 +161,19 @@ class ImportConfiguration extends AbstractEntity { return GeneralUtility::xml2array($this->configuration); } + + /** + * @param ForeignReference[] $foreignReferences + */ + public static function createFromBaseWithForeignReferences( + self $base, + array $foreignReferences, + array $allowedTypes = [] + ): self { + $configuration = clone $base; + $configuration->urls = ResolveForeignReference::convertToRemoteIds($foreignReferences); + $configuration->type = 'static'; + $configuration->allowedTypes = $allowedTypes; + return $configuration; + } } diff --git a/Classes/Domain/Model/Backend/ImportLog.php b/Classes/Domain/Model/Backend/ImportLog.php index 655c568..fd35105 100644 --- a/Classes/Domain/Model/Backend/ImportLog.php +++ b/Classes/Domain/Model/Backend/ImportLog.php @@ -121,4 +121,22 @@ class ImportLog extends Typo3AbstractEntity return $summary; } + + public function handledRemoteId(string $remoteId): bool + { + foreach ($this->logEntries as $entry) { + if ($entry->getRemoteId() === $remoteId) { + return true; + } + } + + return false; + } + + public function merge(self $importLog): void + { + foreach ($importLog->getEntries() as $entry) { + $this->addEntry($entry); + } + } } diff --git a/Classes/Domain/Model/Backend/ImportLogEntry.php b/Classes/Domain/Model/Backend/ImportLogEntry.php index f40eab1..2412c3b 100644 --- a/Classes/Domain/Model/Backend/ImportLogEntry.php +++ b/Classes/Domain/Model/Backend/ImportLogEntry.php @@ -28,6 +28,11 @@ use WerkraumMedia\ThueCat\Domain\Import\Model\Entity; class ImportLogEntry extends Typo3AbstractEntity { + /** + * @var string + */ + protected $remoteId = ''; + /** * @var bool */ @@ -62,6 +67,7 @@ class ImportLogEntry extends Typo3AbstractEntity Entity $entity, array $dataHandlerErrorLog ) { + $this->remoteId = $entity->getRemoteId(); $this->insertion = $entity->wasCreated(); $this->recordUid = $entity->getTypo3Uid(); $this->recordPid = $entity->getTypo3StoragePid(); @@ -69,6 +75,11 @@ class ImportLogEntry extends Typo3AbstractEntity $this->errorsAsArray = $dataHandlerErrorLog; } + public function getRemoteId(): string + { + return $this->remoteId; + } + public function wasInsertion(): bool { return $this->insertion; diff --git a/Classes/Domain/Model/Backend/ParkingFacility.php b/Classes/Domain/Model/Backend/ParkingFacility.php new file mode 100644 index 0000000..04af376 --- /dev/null +++ b/Classes/Domain/Model/Backend/ParkingFacility.php @@ -0,0 +1,28 @@ + + * + * 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\Domain\Model\Backend; + +class ParkingFacility extends AbstractEntity +{ +} diff --git a/Classes/Domain/Model/Frontend/Base.php b/Classes/Domain/Model/Frontend/Base.php new file mode 100644 index 0000000..985c415 --- /dev/null +++ b/Classes/Domain/Model/Frontend/Base.php @@ -0,0 +1,59 @@ + + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +namespace WerkraumMedia\ThueCat\Domain\Model\Frontend; + +use TYPO3\CMS\Extbase\DomainObject\AbstractEntity; + +abstract class Base extends AbstractEntity +{ + /** + * @var string + */ + protected $title = ''; + + /** + * @var string + */ + protected $description = ''; + + /** + * @var Media|null + */ + protected $media = null; + + public function getTitle(): string + { + return $this->title; + } + + public function getDescription(): string + { + return $this->description; + } + + public function getMedia(): ?Media + { + return $this->media; + } +} diff --git a/Classes/Domain/Model/Frontend/ParkingFacility.php b/Classes/Domain/Model/Frontend/ParkingFacility.php new file mode 100644 index 0000000..e1ac3e8 --- /dev/null +++ b/Classes/Domain/Model/Frontend/ParkingFacility.php @@ -0,0 +1,28 @@ + + * + * 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\Domain\Model\Frontend; + +class ParkingFacility extends Place +{ +} diff --git a/Classes/Domain/Model/Frontend/Place.php b/Classes/Domain/Model/Frontend/Place.php new file mode 100644 index 0000000..e558c55 --- /dev/null +++ b/Classes/Domain/Model/Frontend/Place.php @@ -0,0 +1,122 @@ + + * + * 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\Domain\Model\Frontend; + +use TYPO3\CMS\Core\Utility\GeneralUtility; +use TYPO3\CMS\Extbase\Persistence\ObjectStorage; + +abstract class Place extends Base +{ + /** + * @var Address|null + */ + protected $address = null; + + /** + * @var OpeningHours|null + */ + protected $openingHours = null; + + /** + * @var ObjectStorage + */ + protected $parkingFacilityNearBy; + + /** + * @var string + */ + protected $sanitation = ''; + + /** + * @var string + */ + protected $otherService = ''; + + /** + * @var string + */ + protected $trafficInfrastructure = ''; + + /** + * @var string + */ + protected $paymentAccepted = ''; + + /** + * @var string + */ + protected $distanceToPublicTransport = ''; + + public function initializeObject(): void + { + $this->parkingFacilityNearBy = new ObjectStorage(); + } + + public function getAddress(): ?Address + { + return $this->address; + } + + public function getOpeningHours(): ?OpeningHours + { + return $this->openingHours; + } + + public function getParkingFacilitiesNearBy(): ObjectStorage + { + return $this->parkingFacilityNearBy; + } + + public function getSanitation(): array + { + return GeneralUtility::trimExplode(',', $this->sanitation, true); + } + + public function getOtherServices(): array + { + return GeneralUtility::trimExplode(',', $this->otherService, true); + } + + public function getTrafficInfrastructures(): array + { + return GeneralUtility::trimExplode(',', $this->trafficInfrastructure, true); + } + + public function getPaymentAccepted(): array + { + return GeneralUtility::trimExplode(',', $this->paymentAccepted, true); + } + + public function getDistanceToPublicTransport(): array + { + $values = GeneralUtility::trimExplode(':', $this->distanceToPublicTransport, true, 2); + if ($values === []) { + return []; + } + return [ + 'value' => $values[0] ?? '', + 'unit' => $values[1] ?? '', + ]; + } +} diff --git a/Classes/Domain/Model/Frontend/TouristAttraction.php b/Classes/Domain/Model/Frontend/TouristAttraction.php index 510c8b8..1f3f169 100644 --- a/Classes/Domain/Model/Frontend/TouristAttraction.php +++ b/Classes/Domain/Model/Frontend/TouristAttraction.php @@ -24,65 +24,29 @@ declare(strict_types=1); namespace WerkraumMedia\ThueCat\Domain\Model\Frontend; use TYPO3\CMS\Core\Utility\GeneralUtility; -use TYPO3\CMS\Extbase\DomainObject\AbstractEntity; -class TouristAttraction extends AbstractEntity +class TouristAttraction extends Place { - /** - * @var string - */ - protected $title = ''; - - /** - * @var string - */ - protected $description = ''; - /** * @var string */ protected $slogan = ''; - /** - * @var OpeningHours|null - */ - protected $openingHours = null; - /** * @var Offers|null */ protected $offers = null; - /** - * @var Address|null - */ - protected $address = null; - /** * @var Town|null */ protected $town = null; - /** - * @var Media|null - */ - protected $media = null; - /** * @var string */ protected $startOfConstruction = ''; - /** - * @var string - */ - protected $sanitation = ''; - - /** - * @var string - */ - protected $otherService = ''; - /** * @var string */ @@ -93,16 +57,6 @@ class TouristAttraction extends AbstractEntity */ protected $architecturalStyle = ''; - /** - * @var string - */ - protected $trafficInfrastructure = ''; - - /** - * @var string - */ - protected $paymentAccepted = ''; - /** * @var string */ @@ -128,66 +82,26 @@ class TouristAttraction extends AbstractEntity */ protected $publicAccess = ''; - /** - * @var string - */ - protected $distanceToPublicTransport = ''; - - public function getTitle(): string - { - return $this->title; - } - - public function getDescription(): string - { - return $this->description; - } - public function getSlogan(): string { return $this->slogan; } - public function getOpeningHours(): ?OpeningHours - { - return $this->openingHours; - } - public function getOffers(): ?Offers { return $this->offers; } - public function getAddress(): ?Address - { - return $this->address; - } - public function getTown(): ?Town { return $this->town; } - public function getMedia(): ?Media - { - return $this->media; - } - public function getStartOfConstruction(): string { return $this->startOfConstruction; } - public function getSanitation(): array - { - return GeneralUtility::trimExplode(',', $this->sanitation, true); - } - - public function getOtherServices(): array - { - return GeneralUtility::trimExplode(',', $this->otherService, true); - } - public function getMuseumServices(): array { return GeneralUtility::trimExplode(',', $this->museumService, true); @@ -198,16 +112,6 @@ class TouristAttraction extends AbstractEntity return GeneralUtility::trimExplode(',', $this->architecturalStyle, true); } - public function getTrafficInfrastructures(): array - { - return GeneralUtility::trimExplode(',', $this->trafficInfrastructure, true); - } - - public function getPaymentAccepted(): array - { - return GeneralUtility::trimExplode(',', $this->paymentAccepted, true); - } - public function getDigitalOffer(): array { return GeneralUtility::trimExplode(',', $this->digitalOffer, true); @@ -232,16 +136,4 @@ class TouristAttraction extends AbstractEntity { return $this->publicAccess; } - - public function getDistanceToPublicTransport(): array - { - $values = GeneralUtility::trimExplode(':', $this->distanceToPublicTransport, true, 2); - if ($values === []) { - return []; - } - return [ - 'value' => $values[0] ?? '', - 'unit' => $values[1] ?? '', - ]; - } } diff --git a/Classes/Domain/Model/Frontend/Town.php b/Classes/Domain/Model/Frontend/Town.php index 444d79f..9c16238 100644 --- a/Classes/Domain/Model/Frontend/Town.php +++ b/Classes/Domain/Model/Frontend/Town.php @@ -23,27 +23,6 @@ declare(strict_types=1); namespace WerkraumMedia\ThueCat\Domain\Model\Frontend; -use TYPO3\CMS\Extbase\DomainObject\AbstractEntity; - -class Town extends AbstractEntity +class Town extends Base { - /** - * @var string - */ - protected $title = ''; - - /** - * @var string - */ - protected $description = ''; - - public function getTitle(): string - { - return $this->title; - } - - public function getDescription(): string - { - return $this->description; - } } diff --git a/Classes/Domain/Repository/Backend/ParkingFacilityRepository.php b/Classes/Domain/Repository/Backend/ParkingFacilityRepository.php new file mode 100644 index 0000000..fc48131 --- /dev/null +++ b/Classes/Domain/Repository/Backend/ParkingFacilityRepository.php @@ -0,0 +1,65 @@ + + * + * 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\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; +use WerkraumMedia\ThueCat\Domain\Import\Entity\Properties\ForeignReference; + +class ParkingFacilityRepository extends Repository +{ + public function __construct( + ObjectManagerInterface $objectManager, + Typo3QuerySettings $querySettings + ) { + parent::__construct($objectManager); + + $querySettings->setRespectStoragePage(false); + + $this->setDefaultQuerySettings($querySettings); + } + + public function findByEntity(object $entity): ?QueryResultInterface + { + if (method_exists($entity, 'getParkingFacilitiesNearBy') === false) { + return null; + } + + $remoteIds = array_map(function (ForeignReference $reference) { + return $reference->getId(); + }, $entity->getParkingFacilitiesNearBy()); + + if ($remoteIds === []) { + return null; + } + + $query = $this->createQuery(); + + $query->in('remoteId', $remoteIds); + + return $query->execute(); + } +} diff --git a/Classes/Domain/Repository/Backend/TownRepository.php b/Classes/Domain/Repository/Backend/TownRepository.php index 799ff12..dac86bd 100644 --- a/Classes/Domain/Repository/Backend/TownRepository.php +++ b/Classes/Domain/Repository/Backend/TownRepository.php @@ -26,7 +26,7 @@ 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\Entity\Properties\ForeignReference; +use WerkraumMedia\ThueCat\Domain\Import\ResolveForeignReference; use WerkraumMedia\ThueCat\Domain\Model\Backend\Town; class TownRepository extends Repository @@ -48,9 +48,7 @@ class TownRepository extends Repository return null; } - $remoteIds = array_map(function (ForeignReference $reference) { - return $reference->getId(); - }, $entity->getContainedInPlaces()); + $remoteIds = ResolveForeignReference::convertToRemoteIds($entity->getContainedInPlaces()); if ($remoteIds === []) { return null; diff --git a/Configuration/Extbase/Persistence/Classes.php b/Configuration/Extbase/Persistence/Classes.php index 8cd3d03..209d03f 100644 --- a/Configuration/Extbase/Persistence/Classes.php +++ b/Configuration/Extbase/Persistence/Classes.php @@ -1,5 +1,6 @@ [ 'tableName' => 'tx_thuecat_organisation', @@ -10,6 +11,9 @@ return [ \WerkraumMedia\ThueCat\Domain\Model\Backend\TouristInformation::class => [ 'tableName' => 'tx_thuecat_tourist_information', ], + WerkraumMedia\ThueCat\Domain\Model\Backend\ParkingFacility::class => [ + 'tableName' => 'tx_thuecat_parking_facility', + ], \WerkraumMedia\ThueCat\Domain\Model\Backend\ImportConfiguration::class => [ 'tableName' => 'tx_thuecat_import_configuration', ], @@ -25,4 +29,7 @@ return [ \WerkraumMedia\ThueCat\Domain\Model\Frontend\Town::class => [ 'tableName' => 'tx_thuecat_town', ], + WerkraumMedia\ThueCat\Domain\Model\Frontend\ParkingFacility::class => [ + 'tableName' => 'tx_thuecat_parking_facility', + ], ]; diff --git a/Configuration/TCA/tx_thuecat_parking_facility.php b/Configuration/TCA/tx_thuecat_parking_facility.php new file mode 100644 index 0000000..06b0797 --- /dev/null +++ b/Configuration/TCA/tx_thuecat_parking_facility.php @@ -0,0 +1,207 @@ + [ + 'label' => 'title', + 'iconfile' => \WerkraumMedia\ThueCat\Extension::getIconPath() . $tableName . '.svg', + 'default_sortby' => 'title', + 'tstamp' => 'tstamp', + 'crdate' => 'crdate', + 'cruser_id' => 'cruser_id', + 'title' => $languagePath, + 'enablecolumns' => [ + 'disabled' => 'disable', + ], + 'searchFields' => 'title, description', + 'transOrigPointerField' => 'l18n_parent', + 'transOrigDiffSourceField' => 'l18n_diffsource', + 'languageField' => 'sys_language_uid', + 'translationSource' => 'l10n_source', + ], + 'columns' => [ + '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, + ], + ], + 'l18n_parent' => [ + 'displayCond' => 'FIELD:sys_language_uid:>:0', + 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.l18n_parent', + 'config' => [ + 'type' => 'select', + 'renderType' => 'selectSingle', + 'items' => [['', 0]], + 'foreign_table' => $tableName, + 'foreign_table_where' => 'AND ' . $tableName . '.pid=###CURRENT_PID### AND ' . $tableName . '.sys_language_uid IN (-1,0)', + 'default' => 0, + ], + ], + 'l10n_source' => [ + 'config' => [ + 'type' => 'passthrough', + ], + ], + + 'title' => [ + 'label' => $languagePath . '.title', + 'l10n_mode' => 'prefixLangTitle', + 'config' => [ + 'type' => 'input', + 'size' => 20, + 'max' => 255, + 'readOnly' => true, + ], + ], + 'description' => [ + 'label' => $languagePath . '.description', + 'l10n_mode' => 'prefixLangTitle', + 'config' => [ + 'type' => 'text', + 'readOnly' => true, + ], + ], + 'sanitation' => [ + 'label' => $languagePath . '.sanitation', + 'l10n_mode' => 'prefixLangTitle', + 'config' => [ + 'type' => 'input', + 'readOnly' => true, + ], + ], + 'other_service' => [ + 'label' => $languagePath . '.other_service', + 'l10n_mode' => 'prefixLangTitle', + 'config' => [ + 'type' => 'input', + 'readOnly' => true, + ], + ], + 'traffic_infrastructure' => [ + 'label' => $languagePath . '.traffic_infrastructure', + 'l10n_mode' => 'prefixLangTitle', + 'config' => [ + 'type' => 'input', + 'readOnly' => true, + ], + ], + 'payment_accepted' => [ + 'label' => $languagePath . '.payment_accepted', + 'l10n_mode' => 'prefixLangTitle', + 'config' => [ + 'type' => 'input', + 'readOnly' => true, + ], + ], + 'distance_to_public_transport' => [ + 'label' => $languagePath . '.distance_to_public_transport', + 'l10n_mode' => 'prefixLangTitle', + 'config' => [ + 'type' => 'input', + 'readOnly' => true, + ], + ], + 'opening_hours' => [ + 'label' => $languagePath . '.opening_hours', + 'l10n_mode' => 'exclude', + 'config' => [ + 'type' => 'text', + 'readOnly' => true, + ], + ], + 'address' => [ + 'label' => $languagePath . '.address', + 'l10n_mode' => 'exclude', + 'config' => [ + 'type' => 'text', + 'readOnly' => true, + ], + ], + 'media' => [ + 'label' => $languagePath . '.media', + 'l10n_mode' => 'exclude', + 'config' => [ + 'type' => 'text', + 'readOnly' => true, + ], + ], + 'offers' => [ + 'label' => $languagePath . '.offers', + 'l10n_mode' => 'exclude', + 'config' => [ + 'type' => 'text', + 'readOnly' => true, + ], + ], + 'remote_id' => [ + 'label' => $languagePath . '.remote_id', + 'l10n_mode' => 'exclude', + 'config' => [ + 'type' => 'input', + 'readOnly' => true, + ], + ], + 'town' => [ + 'label' => $languagePath . '.town', + 'l10n_mode' => 'exclude', + 'config' => [ + 'type' => 'select', + 'renderType' => 'selectSingle', + 'foreign_table' => 'tx_thuecat_town', + 'default' => '0', + 'items' => [ + [ + $languagePath . '.town.unkown', + 0, + ], + ], + 'readOnly' => true, + ], + ], + 'managed_by' => [ + 'label' => $languagePath . '.managed_by', + 'l10n_mode' => 'exclude', + 'config' => [ + 'type' => 'select', + 'renderType' => 'selectSingle', + 'foreign_table' => 'tx_thuecat_organisation', + 'default' => '0', + 'items' => [ + [ + $languagePath . '.managed_by.unkown', + 0, + ], + ], + 'readOnly' => true, + ], + ], + ], + 'palettes' => [ + 'language' => [ + 'label' => $languagePath . '.palette.language', + 'showitem' => 'sys_language_uid,l18n_parent', + ], + ], + 'types' => [ + '0' => [ + 'showitem' => '--palette--;;language, title, description, sanitation, other_service, traffic_infrastructure, payment_accepted, distance_to_public_transport, opening_hours, offers, address, media, remote_id, --div--;' . $languagePath . '.tab.relations, town, managed_by', + ], + ], + ]; +})(\WerkraumMedia\ThueCat\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 53c9c21..cb196b1 100644 --- a/Configuration/TCA/tx_thuecat_tourist_attraction.php +++ b/Configuration/TCA/tx_thuecat_tourist_attraction.php @@ -271,6 +271,22 @@ return (static function (string $extensionKey, string $tableName) { 'readOnly' => true, ], ], + 'parking_facility_near_by' => [ + 'label' => $languagePath . '.parking_facility_near_by', + '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)' + ], + ], + 'readOnly' => true, + ], + ], ], 'palettes' => [ 'language' => [ @@ -280,7 +296,7 @@ return (static function (string $extensionKey, string $tableName) { ], 'types' => [ '0' => [ - 'showitem' => '--palette--;;language, title, description, 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, opening_hours, offers, address, media, remote_id, --div--;' . $languagePath . '.tab.relations, town, managed_by', + 'showitem' => '--palette--;;language, title, description, 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, opening_hours, offers, address, media, remote_id, --div--;' . $languagePath . '.tab.relations, town, managed_by, parking_facility_near_by', ], ], ]; diff --git a/Resources/Private/Language/de.locallang.xlf b/Resources/Private/Language/de.locallang.xlf index 8bc4bec..cf54dd4 100644 --- a/Resources/Private/Language/de.locallang.xlf +++ b/Resources/Private/Language/de.locallang.xlf @@ -15,6 +15,38 @@ per person pro Person + + per bike + pro Krad + + + per bus + pro Bus + + + per car + pro PKW + + + per car or bike + pro PKW/Krad + + + per hour + pro Stunde + + + per person and night + pro Person und Nacht + + + per piece + pro Stück + + + per unit and night + pro Einheit und Nacht + Toilets Toilette @@ -370,11 +402,59 @@ Distance to Public Transport Entfernung zum ÖPNV: + + Parking Facilities near by + Parkhäuser in der Nähe + + + Years + Jahre + + + Celsius + Grad Celsius + + + Centimeter + Zentimeter + + + Hectare + Hektar + + + Hours + Stunden + + + Kilometer + Kilometer + + + Minutes + Minuten + + + Square Metres + Quadratmeter + Meters Meter + + Percent + Prozent + + + Pixel + Pixel + + + Seconds + Sekunden + diff --git a/Resources/Private/Language/locallang.xlf b/Resources/Private/Language/locallang.xlf index 02abe08..e887f83 100644 --- a/Resources/Private/Language/locallang.xlf +++ b/Resources/Private/Language/locallang.xlf @@ -96,6 +96,9 @@ Tourist Attraction + + Parking Facility + Import finished @@ -384,6 +387,50 @@ French + + + Distance to Public Transport + + + Parking Facilities near by + + + + Years + + + Celsius + + + Centimeter + + + Hectare + + + Hours + + + Kilometer + + + Minutes + + + Square Metres + + + Meters + + + Percent + + + Pixel + + + Seconds + diff --git a/Resources/Private/Language/locallang_tca.xlf b/Resources/Private/Language/locallang_tca.xlf index 06ac27a..3073428 100644 --- a/Resources/Private/Language/locallang_tca.xlf +++ b/Resources/Private/Language/locallang_tca.xlf @@ -163,6 +163,58 @@ Unkown + + Parking Facility + + + Title + + + Description + + + Sanitation + + + Other Service + + + Traffic Infrastructure + + + Payment Accepted + + + Distance to Public Transport + + + Opening Hours + + + Address + + + Media + + + Offers + + + Remote ID + + + Town + + + Managed by + + + Language + + + Relations + + Import Configuration diff --git a/Resources/Private/Templates/Frontend/ContentElement/TouristAttraction.html b/Resources/Private/Templates/Frontend/ContentElement/TouristAttraction.html index cfe2758..6c9bfb4 100644 --- a/Resources/Private/Templates/Frontend/ContentElement/TouristAttraction.html +++ b/Resources/Private/Templates/Frontend/ContentElement/TouristAttraction.html @@ -20,13 +20,7 @@ -

- {entity.address.street}
- {entity.address.zip} {entity.address.city}
- {entity.address.email}
- {entity.address.phone}
- {entity.address.fax} -

+ {f:render(section: 'Address', arguments: {address: entity.address})}
@@ -91,5 +85,23 @@ {f:translate(id: 'content.distanceToPublicTransport', extensionName: 'thuecat')} {entity.distanceToPublicTransport.value} {f:translate(id: 'content.unit.{entity.distanceToPublicTransport.unit}', default: entity.distanceToPublicTransport.unit, extensionName: 'thuecat')} + + + {f:translate(id: 'content.parkingFacilitiesNearBy', extensionName: 'Thuecat')} + + {parkingFacility.title} + {f:render(section: 'Address', arguments: {address: parkingFacility.address})} + + + + +

+ {address.street}
+ {address.zip} {address.city}
+ {address.email}
+ {address.phone}
+ {address.fax} +

+
diff --git a/Resources/Public/Icons/tx_thuecat_parking_facility.svg b/Resources/Public/Icons/tx_thuecat_parking_facility.svg new file mode 100644 index 0000000..35905ca --- /dev/null +++ b/Resources/Public/Icons/tx_thuecat_parking_facility.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/Tests/Functional/Fixtures/Frontend/Sites/example/config.yaml b/Tests/Functional/Fixtures/Frontend/Sites/example/config.yaml index 142345f..2d35db7 100644 --- a/Tests/Functional/Fixtures/Frontend/Sites/example/config.yaml +++ b/Tests/Functional/Fixtures/Frontend/Sites/example/config.yaml @@ -1,4 +1,4 @@ -base: '/' +base: / languages: - title: Deutsch diff --git a/Tests/Functional/Fixtures/Frontend/TouristAttractions.xml b/Tests/Functional/Fixtures/Frontend/TouristAttractions.xml index 6f8a99b..2f4ff1e 100644 --- a/Tests/Functional/Fixtures/Frontend/TouristAttractions.xml +++ b/Tests/Functional/Fixtures/Frontend/TouristAttractions.xml @@ -23,6 +23,7 @@ Tiere sind im Gebäude nicht gestattet, ausgenommen sind Blinden- und Blindenbegleithunde. German,English,French 250:MTR + 1,2 1 @@ -30,5 +31,17 @@ 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/Import/Guzzle/thuecat.org/resources/052821473718-oxfq/GET_3a853d7e61b18de6551c00872dd19186.txt b/Tests/Functional/Fixtures/Import/Guzzle/thuecat.org/resources/052821473718-oxfq/GET_3a853d7e61b18de6551c00872dd19186.txt new file mode 100644 index 0000000..86ef6e3 --- /dev/null +++ b/Tests/Functional/Fixtures/Import/Guzzle/thuecat.org/resources/052821473718-oxfq/GET_3a853d7e61b18de6551c00872dd19186.txt @@ -0,0 +1,19 @@ +HTTP/1.1 200 OK +Date: Mon, 09 Aug 2021 06:28:07 GMT +Content-Type: application/ld+json; charset=utf-8 +Content-Length: 30967 +Connection: keep-alive +Set-Cookie: ahSession=ce38109539e852ab96dd57bc3c1a153b30a79a54;path=/;expires=Thu, 09 Sep 2021 06:28:07 GMT;httpOnly=true; +Access-Control-Allow-Methods: HEAD, GET, POST, DELETE, OPTIONS +Access-Control-Allow-Headers: Authorization, Content-Type +Strict-Transport-Security: max-age=15724800; includeSubDomains +Access-Control-Allow-Credentials: true +X-Frame-Options: deny +X-XSS-Protection: 1; mode=block +X-Content-Type-Options: nosniff +Referrer-Policy: same-origin +Feature-Policy: microphone 'none'; camera 'none'; payment 'none' +Content-Security-Policy: default-src 'self'; script-src 'self' 'sha256-xfTbtWk8kVI65iLJs8LB3lWf2g0g10DS71pDdoutFHc=' 'sha256-tuKkEf3LPSeyF8feKxOP/mEsa6nRR8toFxvAwO9cuhE='; style-src 'self' 'unsafe-inline' https://stackpath.bootstrapcdn.com; img-src 'self' data: blob: * +Access-Control-Allow-Origin: https://cdb.thuecat.org + +{"@context":{"schema":"http://schema.org/","dbo":"http://dbpedia.org/ontology/","dsv":"http://ontologies.sti-innsbruck.at/dsv/","foaf":"http://xmlns.com/foaf/0.1/","owl":"http://www.w3.org/2002/07/owl#","rdf":"http://www.w3.org/1999/02/22-rdf-syntax-ns#","rdfs":"http://www.w3.org/2000/01/rdf-schema#","sh":"http://www.w3.org/ns/shacl#","xsd":"http://www.w3.org/2001/XMLSchema#","ttgds":"https://thuecat.org/ontology/ttgds/1.0/","cdb":"https://thuecat.org/ontology/cdb/1.0/","dachkg":"https://thuecat.org/ontology/dachkg/1.0/","thuecat":"https://thuecat.org/ontology/thuecat/1.0/","epapp":"https://thuecat.org/ontology/epapp/1.0/"},"@graph":[{"@id":"https://thuecat.org/resources/052821473718-oxfq","@type":["schema:Place","schema:Organization","schema:LocalBusiness","schema:Thing","schema:TouristAttraction","ttgds:OtherInfraStructure","thuecat:OtherPOI","thuecat:StrollingMile"],"schema:description":[{"@language":"de","@value":"Der Wenigemarkt befindet sich am östlichen Zugang der Krämerbrücke. Hier finden Sie eine Vielzahl Cafés und Restaurants, die zum Verbleiben und Entspannen einladen."},{"@language":"fr","@value":"Le Wenigemarkt est situé à l'entrée orientale du Krämerbrücke. Vous y trouverez une variété de cafés et de restaurants qui vous invitent à rester et à vous détendre."},{"@language":"en","@value":"The Wenigemarkt is located at the eastern entrance of the Krämerbrücke. Here you will find a variety of cafes and restaurants that invite you to stay and relax."},{"@id":"genid-0f944fd40aa04d3d85374be0fe18c485-b1","@type":["schema:Intangible","schema:Thing","schema:ComputerLanguage","thuecat:Html"],"schema:value":{"@language":"de","@value":"

Der Wenigemarkt befindet sich am östlichen Zugang der Krämerbrücke. Hier finden Sie eine Vielzahl Cafés und Restaurants, die zum Verbleiben und Entspannen einladen.

"}},{"@id":"genid-0f944fd40aa04d3d85374be0fe18c485-b2","@type":["schema:Intangible","schema:Thing","schema:ComputerLanguage","thuecat:Html"],"schema:value":{"@language":"en","@value":"

The Wenigemarkt is located at the eastern entrance of the Krämerbrücke. Here you will find a variety of cafes and restaurants that invite you to stay and relax.

"}},{"@id":"genid-0f944fd40aa04d3d85374be0fe18c485-b3","@type":["schema:Intangible","schema:Thing","schema:ComputerLanguage","thuecat:Html"],"schema:value":{"@language":"fr","@value":"

Le Wenigemarkt est situé à l'entrée orientale du Krämerbrücke. Vous y trouverez une variété de cafés et de restaurants qui vous invitent à rester et à vous détendre.

"}}],"schema:name":{"@language":"de","@value":"Wenigemarkt Erfurt"},"schema:containedInPlace":{"@id":"https://thuecat.org/resources/043064193523-jcyt"},"schema:containsPlace":[{"@id":"https://thuecat.org/resources/215230952334-yyno"},{"@id":"https://thuecat.org/resources/r_16573254-oapoi"},{"@id":"https://thuecat.org/resources/455305021239-hmfe"}],"schema:photo":{"@id":"https://thuecat.org/resources/dms_5143698"},"schema:image":{"@id":"https://thuecat.org/resources/dms_5143698"},"schema:petsAllowed":{"@type":"schema:Boolean","@value":"true"},"schema:hasMap":{"@type":"schema:URL","@value":"https://www.google.de/maps/@50.9785793,11.0319168,21z"},"schema:geo":{"@id":"genid-0f944fd40aa04d3d85374be0fe18c485-b4","@type":["schema:Intangible","schema:StructuredValue","schema:Thing","schema:GeoCoordinates"],"schema:longitude":{"@type":"schema:Number","@value":"11.031994832523964"},"schema:latitude":{"@type":"schema:Number","@value":"50.97859562923252"}},"schema:smokingAllowed":{"@type":"schema:Boolean","@value":"true"},"schema:address":{"@id":"genid-0f944fd40aa04d3d85374be0fe18c485-b0","@type":["schema:Intangible","schema:PostalAddress","schema:StructuredValue","schema:Thing","schema:ContactPoint"],"schema:addressLocality":{"@language":"de","@value":"Erfurt"},"schema:addressCountry":{"@type":"thuecat:AddressCountry","@value":"thuecat:Germany"},"schema:postalCode":{"@language":"de","@value":"99084"},"schema:addressRegion":{"@type":"thuecat:AddressFederalState","@value":"thuecat:Thuringia"},"schema:streetAddress":{"@language":"de","@value":"Wenigermarkt"},"thuecat:typOfAddress":{"@type":"thuecat:TypOfAddress","@value":"thuecat:HouseAddress"}},"thuecat:contentResponsible":{"@id":"https://thuecat.org/resources/018132452787-ngbe"},"thuecat:gastro":[{"@type":"thuecat:GastroPoi","@value":"thuecat:TakeawayShop"},{"@type":"thuecat:GastroPoi","@value":"thuecat:Cafe"},{"@type":"thuecat:GastroPoi","@value":"thuecat:BarEnumMem"},{"@type":"thuecat:GastroPoi","@value":"thuecat:Restaurant"}],"thuecat:sanitation":{"@type":"thuecat:Sanitation","@value":"thuecat:ZeroSanitation"}}]} diff --git a/Tests/Functional/Fixtures/Import/Guzzle/thuecat.org/resources/165868194223-zmqf/GET_fb3c1440c67b1c9a421a2df91f8048f9.txt b/Tests/Functional/Fixtures/Import/Guzzle/thuecat.org/resources/165868194223-zmqf/GET_fb3c1440c67b1c9a421a2df91f8048f9.txt index bcb2173..3f98827 100644 --- a/Tests/Functional/Fixtures/Import/Guzzle/thuecat.org/resources/165868194223-zmqf/GET_fb3c1440c67b1c9a421a2df91f8048f9.txt +++ b/Tests/Functional/Fixtures/Import/Guzzle/thuecat.org/resources/165868194223-zmqf/GET_fb3c1440c67b1c9a421a2df91f8048f9.txt @@ -16,4 +16,4 @@ Feature-Policy: microphone 'none'; camera 'none'; payment 'none' Content-Security-Policy: default-src 'self'; script-src 'self' 'sha256-xfTbtWk8kVI65iLJs8LB3lWf2g0g10DS71pDdoutFHc='; style-src 'self' 'unsafe-inline' https://stackpath.bootstrapcdn.com; img-src 'self' data: blob: * Access-Control-Allow-Origin: https://cdb.thuecat.org -{"@context":{"schema":"http://schema.org/","dbo":"http://dbpedia.org/ontology/","dsv":"http://ontologies.sti-innsbruck.at/dsv/","foaf":"http://xmlns.com/foaf/0.1/","owl":"http://www.w3.org/2002/07/owl#","rdf":"http://www.w3.org/1999/02/22-rdf-syntax-ns#","rdfs":"http://www.w3.org/2000/01/rdf-schema#","sh":"http://www.w3.org/ns/shacl#","xsd":"http://www.w3.org/2001/XMLSchema#","ttgds":"https://thuecat.org/ontology/ttgds/1.0/","cdb":"https://thuecat.org/ontology/cdb/1.0/","dachkg":"https://thuecat.org/ontology/dachkg/1.0/","thuecat":"https://thuecat.org/ontology/thuecat/1.0/"},"@graph":[{"@id":"https://thuecat.org/resources/165868194223-zmqf","@type":["schema:Place","schema:CivicStructure","schema:PlaceOfWorship","schema:Thing","schema:Museum","schema:TouristAttraction","schema:Synagogue","ttgds:PointOfInterest","thuecat:Building","thuecat:ReligiousBuilding","thuecat:CultureHistoricalMuseum"],"schema:description":[{"@language":"fr","@value":"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. "},{"@language":"en","@value":"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. "},{"@language":"de","@value":"Mit der Alten Synagoge weist Erfurt die älteste bis zum Dach erhaltene Synagoge in Mitteleuropa vor. Hier waren bis Ende der 90er Jahre nur die Spitzen zweier Giebel sichtbar, welche aus einem Gewirr von Anbauten herausragten. Nach dem Abriss einiger Bauten ringsum konnte ein Bauforscher klar vier Bauphasen der Synagoge unterscheiden, dessen älteste um 1100 zu datieren ist. \nDer Bau von 1270, mit der heute sichtbaren Westfassade samt Maßwerkrosette, wurde nach Norden erweitert. Brandspuren am Mauerwerk verweisen auf einen Vorgängerbau, der wahrscheinlich einem Pogrom zum Opfer fiel. Die Synagoge diente bis 1349 als Gotteshaus. In diesem Jahr löschte ein barbarisches Pestpogrom die erste jüdische Gemeinde Erfurts aus. Die Stadt verkaufte das Gebäude an einen Händler, der es zum Speicher umbauen ließ. Dabei wurde der hohe Raum von Balkendecken unterteilt, ein breiterer Eingang an Stelle des Thoraschreins geschaffen und die Synagoge unterkellert. Im Erdgeschoss zeugen noch einige Spuren von der Erstnutzung, wie bspw. ein Lichtergesims. \nDas Erdgeschoss mit der wuchtigen gotischen Balkendecke und der Keller werden ebenso wie das Obergeschoss, welches von der Festkultur des 19. Jahrhunderts zeugt, museal genutzt. Wer heute den Saal betritt, der fühlt sich in die vergangene Welt von Tango und Foxtrott unter Gouvernantenaufsicht zurückversetzt. Schablonenmalerei sowie einige Tapetenreste schmücken die Wände. \nIm Erdgeschoss wird die Baugeschichte thematisiert, der Keller ist dem Erfurter Schatz aus Münzen, Gefäßen, gotischem Schmuck und dem jüdischen Hochzeitsring vorbehalten. \nIm Saal zeigt das Haus eine Sammlung von hebräischen Handschriften, welche der Erfurter Gemeinde gehörten. Diese Hebraica werden heute in der Staatsbibliothek Berlin aufbewahrt. Abwechselnd können sie in Erfurt als Original oder Faksimile bestaunt werden. \nMit der Alten Synagoge und einer 2007 an der Krämerbrücke gefundenen Mikwe aus der Gotik, deren wissenschaftliche Erforschung noch andauert, kann Erfurt einmalige und faszinierende Zeugnisse der noch wenig bekannten Geschichte einer mittelalterlichen Gemeinde vorweisen."},{"@id":"genid-28b33237f71b41e3ad54a99e1da769b9-b1","@type":["thuecat:Html"],"schema:value":{"@language":"de","@value":"Mit der Alten Synagoge weist Erfurt die älteste bis zum Dach erhaltene Synagoge in Mitteleuropa vor. Hier waren bis Ende der 90er Jahre nur die Spitzen zweier Giebel sichtbar, welche aus einem Gewirr von Anbauten herausragten. Nach dem Abriss einiger Bauten ringsum konnte ein Bauforscher klar vier Bauphasen der Synagoge unterscheiden, dessen älteste um 1100 zu datieren ist. \n\nDer Bau von 1270, mit der heute sichtbaren Westfassade samt Maßwerkrosette, wurde nach Norden erweitert. Brandspuren am Mauerwerk verweisen auf einen Vorgängerbau, der wahrscheinlich einem Pogrom zum Opfer fiel. Die Synagoge diente bis 1349 als Gotteshaus. In diesem Jahr löschte ein barbarisches Pestpogrom die erste jüdische Gemeinde Erfurts aus. Die Stadt verkaufte das Gebäude an einen Händler, der es zum Speicher umbauen ließ. Dabei wurde der hohe Raum von Balkendecken unterteilt, ein breiterer Eingang an Stelle des Thoraschreins geschaffen und die Synagoge unterkellert. Im Erdgeschoss zeugen noch einige Spuren von der Erstnutzung, wie bspw. ein Lichtergesims. \n\nDas Erdgeschoss mit der wuchtigen gotischen Balkendecke und der Keller werden ebenso wie das Obergeschoss, welches von der Festkultur des 19. Jahrhunderts zeugt, museal genutzt. Wer heute den Saal betritt, der fühlt sich in die vergangene Welt von Tango und Foxtrott unter Gouvernantenaufsicht zurückversetzt. Schablonenmalerei sowie einige Tapetenreste schmücken die Wände. \nIm Erdgeschoss wird die Baugeschichte thematisiert, der Keller ist dem Erfurter Schatz aus Münzen, Gefäßen, gotischem Schmuck und dem jüdischen Hochzeitsring vorbehalten. \n\nIm Saal zeigt das Haus eine Sammlung von hebräischen Handschriften, welche der Erfurter Gemeinde gehörten. Diese Hebraica werden heute in der Staatsbibliothek Berlin aufbewahrt. Abwechselnd können sie in Erfurt als Original oder Faksimile bestaunt werden. \n\nMit der Alten Synagoge und einer 2007 an der Krämerbrücke gefundenen Mikwe aus der Gotik, deren wissenschaftliche Erforschung noch andauert, kann Erfurt einmalige und faszinierende Zeugnisse der noch wenig bekannten Geschichte einer mittelalterlichen Gemeinde vorweisen."}},{"@id":"genid-28b33237f71b41e3ad54a99e1da769b9-b2","@type":["thuecat:Html"],"schema:value":{"@language":"fr","@value":"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. "}},{"@id":"genid-28b33237f71b41e3ad54a99e1da769b9-b3","@type":["thuecat:Html"],"schema:value":{"@language":"en","@value":"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. "}}],"schema:sameAs":[{"@type":"xsd:string","@value":"http://whc.unesco.org/en/tentativelists/5982/"},{"@type":"schema:URL","@value":"https://www.outdooractive.com/de/51497737"}],"schema:identifier":{"@type":"schema:URL","@value":"https://www.thueringen-entdecken.de/urlaub-hotel-reisen/alte-synagoge-erfurt-115157.html"},"schema:name":[{"@language":"de","@value":"Alte Synagoge"},{"@language":"fr","@value":"La vieille synagogue"},{"@language":"en","@value":"Old Synagogue"}],"schema:slogan":{"@type":"thuecat:ThuSlogan","@value":"thuecat:Highlight"},"schema:containedInPlace":[{"@id":"https://thuecat.org/resources/043064193523-jcyt"},{"@id":"https://thuecat.org/resources/573211638937-gmqb"},{"@id":"https://thuecat.org/resources/497839263245-edbm"}],"schema:photo":{"@id":"https://thuecat.org/resources/dms_5099196"},"schema:image":{"@id":"https://thuecat.org/resources/dms_5099196"},"schema:audience":[{"@id":"https://thuecat.org/resources/290287712606-zkwq"},{"@id":"https://thuecat.org/resources/312868368592-wnce"},{"@id":"https://thuecat.org/resources/301753337945-akzy"},{"@id":"https://thuecat.org/resources/304061111979-rmed"},{"@id":"https://thuecat.org/resources/668239314161-keen"}],"schema:petsAllowed":{"@language":"de","@value":"Tiere sind im Gebäude nicht gestattet, ausgenommen sind Blinden- und Blindenbegleithunde."},"schema:hasMap":{"@type":"schema:URL","@value":"https://www.google.com/maps/search/?api=1&query=50.978765,11.029133"},"schema:geo":{"@id":"genid-28b33237f71b41e3ad54a99e1da769b9-b4","@type":["schema:Intangible","schema:StructuredValue","schema:Thing","schema:GeoCoordinates"],"schema:longitude":{"@type":"schema:Number","@value":"11.029133"},"schema:latitude":{"@type":"schema:Number","@value":"50.978765"}},"schema:openingHoursSpecification":{"@id":"genid-28b33237f71b41e3ad54a99e1da769b9-b13","@type":["schema:Intangible","schema:StructuredValue","schema:Thing","schema:OpeningHoursSpecification"],"schema:validFrom":{"@type":"schema:Date","@value":"2021-03-01"},"schema:dayOfWeek":[{"@type":"schema:DayOfWeek","@value":"schema:Saturday"},{"@type":"schema:DayOfWeek","@value":"schema:Sunday"},{"@type":"schema:DayOfWeek","@value":"schema:Friday"},{"@type":"schema:DayOfWeek","@value":"schema:Thursday"},{"@type":"schema:DayOfWeek","@value":"schema:Tuesday"},{"@type":"schema:DayOfWeek","@value":"schema:Wednesday"}],"schema:opens":{"@type":"schema:Time","@value":"10:00:00"},"schema:validThrough":{"@type":"schema:Date","@value":"2021-12-31"},"schema:closes":{"@type":"schema:Time","@value":"18:00:00"}},"schema:isAccessibleForFree":{"@type":"schema:Boolean","@value":"false"},"schema:smokingAllowed":{"@type":"schema:Boolean","@value":"false"},"schema:url":{"@type":"schema:URL","@value":"http://www.alte-synagoge.erfurt.de"},"schema:availableLanguage":[{"@type":"thuecat:Language","@value":"thuecat:German"},{"@type":"thuecat:Language","@value":"thuecat:English"},{"@type":"thuecat:Language","@value":"thuecat:French"}],"schema:publicAccess":{"@type":"schema:Boolean","@value":"true"},"schema:paymentAccepted":[{"@type":"thuecat:PaymentAcceptedEnum","@value":"thuecat:CashPayment"},{"@type":"thuecat:PaymentAcceptedEnum","@value":"thuecat:EC"}],"schema:address":{"@id":"genid-28b33237f71b41e3ad54a99e1da769b9-b0","@type":["schema:Intangible","schema:PostalAddress","schema:StructuredValue","schema:Thing","schema:ContactPoint"],"schema:addressLocality":{"@language":"de","@value":"Erfurt"},"schema:addressCountry":{"@type":"thuecat:AddressCountry","@value":"thuecat:Germany"},"schema:postalCode":{"@language":"de","@value":"99084"},"schema:addressRegion":{"@type":"thuecat:AddressFederalState","@value":"thuecat:Thuringia"},"schema:telephone":{"@language":"de","@value":"+49 361 6551520"},"schema:email":{"@language":"de","@value":"altesynagoge@erfurt.de"},"schema:streetAddress":{"@language":"de","@value":"Waagegasse 8"},"schema:faxNumber":{"@language":"de","@value":"+49 361 6551669"},"thuecat:typOfAddress":{"@type":"thuecat:TypOfAddress","@value":"thuecat:HouseAddress"}},"schema:makesOffer":[{"@id":"genid-28b33237f71b41e3ad54a99e1da769b9-b5","@type":["schema:Intangible","schema:Thing","schema:Offer"],"schema:description":{"@language":"de","@value":"Immer samstags, um 11:15 Uhr findet eine öffentliche Führung durch das Museum statt. Dauer etwa 90 Minuten"},"schema:offeredBy":{"@id":"https://thuecat.org/resources/165868194223-zmqf"},"schema:name":{"@language":"de","@value":"Führungen"},"schema:priceSpecification":[{"@id":"genid-28b33237f71b41e3ad54a99e1da769b9-b6","@type":["schema:Intangible","schema:StructuredValue","schema:PriceSpecification","schema:Thing"],"schema:price":{"@type":"schema:Number","@value":"8"},"schema:name":{"@language":"de","@value":"Erwachsene"},"schema:priceCurrency":{"@type":"thuecat:Currency","@value":"thuecat:EUR"},"thuecat:calculationRule":{"@type":"thuecat:CalculationRule","@value":"thuecat:PerPerson"}},{"@id":"genid-28b33237f71b41e3ad54a99e1da769b9-b7","@type":["schema:Intangible","schema:StructuredValue","schema:PriceSpecification","schema:Thing"],"schema:description":{"@language":"de","@value":"als ermäßigt gelten schulpflichtige Kinder, Auszubildende, Studierende, Rentner/-innen, Menschen mit Behinderungen, Inhaber Sozialausweis der Landeshauptstadt Erfurt"},"schema:price":{"@type":"schema:Number","@value":"5"},"schema:name":{"@language":"de","@value":"Ermäßigt"},"schema:priceCurrency":{"@type":"thuecat:Currency","@value":"thuecat:EUR"},"thuecat:calculationRule":{"@type":"thuecat:CalculationRule","@value":"thuecat:PerPerson"}}],"thuecat:offerType":{"@type":"thuecat:OfferType","@value":"thuecat:GuidedTourOffer"}},{"@id":"genid-28b33237f71b41e3ad54a99e1da769b9-b8","@type":["schema:Intangible","schema:Thing","schema:Offer"],"schema:description":{"@language":"de","@value":"Schulklassen und Kitagruppen im Rahmen des Unterrichts: Eintritt frei\nAn jedem ersten Dienstag im Monat: Eintritt frei"},"schema:offeredBy":{"@id":"https://thuecat.org/resources/165868194223-zmqf"},"schema:name":{"@language":"de","@value":"Eintritt"},"schema:priceSpecification":[{"@id":"genid-28b33237f71b41e3ad54a99e1da769b9-b10","@type":["schema:Intangible","schema:StructuredValue","schema:PriceSpecification","schema:Thing"],"schema:description":{"@language":"de","@value":"als ermäßigt gelten schulpflichtige Kinder, Auszubildende, Studierende, Rentner/-innen, Menschen mit Behinderungen, Inhaber Sozialausweis der Landeshauptstadt Erfurt"},"schema:price":{"@type":"schema:Number","@value":"5"},"schema:name":{"@language":"de","@value":"Ermäßigt"},"schema:priceCurrency":{"@type":"thuecat:Currency","@value":"thuecat:EUR"},"thuecat:calculationRule":{"@type":"thuecat:CalculationRule","@value":"thuecat:PerPerson"}},{"@id":"genid-28b33237f71b41e3ad54a99e1da769b9-b11","@type":["schema:Intangible","schema:StructuredValue","schema:PriceSpecification","schema:Thing"],"schema:price":{"@type":"schema:Number","@value":"17"},"schema:name":{"@language":"de","@value":"Familienkarte"},"schema:priceCurrency":{"@type":"thuecat:Currency","@value":"thuecat:EUR"},"thuecat:calculationRule":{"@type":"thuecat:CalculationRule","@value":"thuecat:PerGroup"}},{"@id":"genid-28b33237f71b41e3ad54a99e1da769b9-b12","@type":["schema:Intangible","schema:StructuredValue","schema:PriceSpecification","schema:Thing"],"schema:price":{"@type":"schema:Number","@value":"14.90"},"schema:name":{"@language":"de","@value":"ErfurtCard"},"schema:priceCurrency":{"@type":"thuecat:Currency","@value":"thuecat:EUR"},"thuecat:calculationRule":{"@type":"thuecat:CalculationRule","@value":"thuecat:PerPackage"}},{"@id":"genid-28b33237f71b41e3ad54a99e1da769b9-b9","@type":["schema:Intangible","schema:StructuredValue","schema:PriceSpecification","schema:Thing"],"schema:price":{"@type":"schema:Number","@value":"8"},"schema:name":{"@language":"de","@value":"Erwachsene"},"schema:priceCurrency":{"@type":"thuecat:Currency","@value":"thuecat:EUR"},"thuecat:calculationRule":{"@type":"thuecat:CalculationRule","@value":"thuecat:PerPerson"}}],"thuecat:offerType":{"@type":"thuecat:OfferType","@value":"thuecat:EntryOffer"}}],"thuecat:exibitionObjekt":[{"@type":"thuecat:ExhibitionObject","@value":"thuecat:ReligiousHistoryExhibition"},{"@language":"de","@value":"Bau- und Nutzungsgeschichte der Alten Synagoge"},{"@language":"de","@value":"Erfurter Schatz"},{"@language":"de","@value":"Mittelalterliche Handschriften als Faksimile"}],"thuecat:museumService":{"@type":"thuecat:MuseumService","@value":"thuecat:MuseumShop"},"thuecat:contentResponsible":{"@id":"https://thuecat.org/resources/018132452787-ngbe"},"thuecat:monumentEnum":[{"@type":"thuecat:MonumentEnum","@value":"thuecat:ArchitecturalMonumentSingle"},{"@language":"de","@value":"Kulturdenkmal"}],"thuecat:digitalOffer":[{"@type":"thuecat:DigitalOffer","@value":"thuecat:AudioGuide"},{"@type":"thuecat:DigitalOffer","@value":"thuecat:VideoGuide"}],"thuecat:entrance":{"@type":"thuecat:Entrance","@value":"thuecat:IndoorActivities"},"thuecat:gastro":{"@type":"thuecat:GastroPoi","@value":"thuecat:ZeroGastronomy"},"thuecat:guidedTour":[{"@type":"thuecat:EnumGuidedTour","@value":"thuecat:GuidedTourOnlyWithRegistration"},{"@type":"thuecat:EnumGuidedTour","@value":"thuecat:GuidedTourRegistrationNotRequired"}],"thuecat:otherService":[{"@type":"thuecat:OtherService","@value":"thuecat:SeatingPossibilitiesRestArea"},{"@type":"thuecat:OtherService","@value":"thuecat:LockBoxes"},{"@type":"thuecat:OtherService","@value":"thuecat:SouvenirShop"},{"@type":"thuecat:OtherService","@value":"thuecat:BaggageStorage"}],"thuecat:photography":{"@type":"thuecat:Photography","@value":"thuecat:ZeroPhotography"},"thuecat:sanitation":[{"@type":"thuecat:Sanitation","@value":"thuecat:Toilets"},{"@type":"thuecat:Sanitation","@value":"thuecat:DisabledToilets"},{"@type":"thuecat:Sanitation","@value":"thuecat:NappyChangingArea"},{"@type":"thuecat:Sanitation","@value":"thuecat:FamilyAndChildFriendly"}],"thuecat:trafficInfrastructure":{"@type":"thuecat:TrafficInfrastructure","@value":"thuecat:ZeroSpecialTrafficInfrastructure"},"thuecat:distanceToPublicTransport":{"@id":"genid-28b33237f71b41e3ad54a99e1da769b9-b14","@type":["schema:Intangible","schema:QuantitativeValue","schema:StructuredValue","schema:Thing"],"schema:unitCode":{"@type":"thuecat:Unit","@value":"thuecat:MTR"},"schema:value":{"@type":"schema:Number","@value":"200"}},"thuecat:architecturalStyle":{"@type":"thuecat:ArchitecturalStyle","@value":"thuecat:GothicArt"},"thuecat:endOfConstruction":[{"@language":"de","@value":"12. Jh."},{"@language":"de","@value":"13. Jh."},{"@language":"de","@value":"19. Jh."},{"@language":"de","@value":"20. Jh."},{"@language":"de","@value":"14. Jh."},{"@language":"de","@value":"2009"}],"thuecat:startOfConstruction":[{"@language":"de","@value":"11. Jh."},{"@language":"en","@value":"11th century"}],"thuecat:openAirMuseum":{"@type":"schema:Boolean","@value":"false"}}]} +{"@context":{"schema":"http://schema.org/","dbo":"http://dbpedia.org/ontology/","dsv":"http://ontologies.sti-innsbruck.at/dsv/","foaf":"http://xmlns.com/foaf/0.1/","owl":"http://www.w3.org/2002/07/owl#","rdf":"http://www.w3.org/1999/02/22-rdf-syntax-ns#","rdfs":"http://www.w3.org/2000/01/rdf-schema#","sh":"http://www.w3.org/ns/shacl#","xsd":"http://www.w3.org/2001/XMLSchema#","ttgds":"https://thuecat.org/ontology/ttgds/1.0/","cdb":"https://thuecat.org/ontology/cdb/1.0/","dachkg":"https://thuecat.org/ontology/dachkg/1.0/","thuecat":"https://thuecat.org/ontology/thuecat/1.0/"},"@graph":[{"@id":"https://thuecat.org/resources/165868194223-zmqf","@type":["schema:Place","schema:CivicStructure","schema:PlaceOfWorship","schema:Thing","schema:Museum","schema:TouristAttraction","schema:Synagogue","ttgds:PointOfInterest","thuecat:Building","thuecat:ReligiousBuilding","thuecat:CultureHistoricalMuseum"],"schema:description":[{"@language":"fr","@value":"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. "},{"@language":"en","@value":"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. "},{"@language":"de","@value":"Beispiel Beschreibung"},{"@id":"genid-28b33237f71b41e3ad54a99e1da769b9-b1","@type":["thuecat:Html"],"schema:value":{"@language":"de","@value":"Mit der Alten Synagoge weist Erfurt die älteste bis zum Dach erhaltene Synagoge in Mitteleuropa vor. Hier waren bis Ende der 90er Jahre nur die Spitzen zweier Giebel sichtbar, welche aus einem Gewirr von Anbauten herausragten. Nach dem Abriss einiger Bauten ringsum konnte ein Bauforscher klar vier Bauphasen der Synagoge unterscheiden, dessen älteste um 1100 zu datieren ist. \n\nDer Bau von 1270, mit der heute sichtbaren Westfassade samt Maßwerkrosette, wurde nach Norden erweitert. Brandspuren am Mauerwerk verweisen auf einen Vorgängerbau, der wahrscheinlich einem Pogrom zum Opfer fiel. Die Synagoge diente bis 1349 als Gotteshaus. In diesem Jahr löschte ein barbarisches Pestpogrom die erste jüdische Gemeinde Erfurts aus. Die Stadt verkaufte das Gebäude an einen Händler, der es zum Speicher umbauen ließ. Dabei wurde der hohe Raum von Balkendecken unterteilt, ein breiterer Eingang an Stelle des Thoraschreins geschaffen und die Synagoge unterkellert. Im Erdgeschoss zeugen noch einige Spuren von der Erstnutzung, wie bspw. ein Lichtergesims. \n\nDas Erdgeschoss mit der wuchtigen gotischen Balkendecke und der Keller werden ebenso wie das Obergeschoss, welches von der Festkultur des 19. Jahrhunderts zeugt, museal genutzt. Wer heute den Saal betritt, der fühlt sich in die vergangene Welt von Tango und Foxtrott unter Gouvernantenaufsicht zurückversetzt. Schablonenmalerei sowie einige Tapetenreste schmücken die Wände. \nIm Erdgeschoss wird die Baugeschichte thematisiert, der Keller ist dem Erfurter Schatz aus Münzen, Gefäßen, gotischem Schmuck und dem jüdischen Hochzeitsring vorbehalten. \n\nIm Saal zeigt das Haus eine Sammlung von hebräischen Handschriften, welche der Erfurter Gemeinde gehörten. Diese Hebraica werden heute in der Staatsbibliothek Berlin aufbewahrt. Abwechselnd können sie in Erfurt als Original oder Faksimile bestaunt werden. \n\nMit der Alten Synagoge und einer 2007 an der Krämerbrücke gefundenen Mikwe aus der Gotik, deren wissenschaftliche Erforschung noch andauert, kann Erfurt einmalige und faszinierende Zeugnisse der noch wenig bekannten Geschichte einer mittelalterlichen Gemeinde vorweisen."}},{"@id":"genid-28b33237f71b41e3ad54a99e1da769b9-b2","@type":["thuecat:Html"],"schema:value":{"@language":"fr","@value":"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. "}},{"@id":"genid-28b33237f71b41e3ad54a99e1da769b9-b3","@type":["thuecat:Html"],"schema:value":{"@language":"en","@value":"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. "}}],"schema:sameAs":[{"@type":"xsd:string","@value":"http://whc.unesco.org/en/tentativelists/5982/"},{"@type":"schema:URL","@value":"https://www.outdooractive.com/de/51497737"}],"schema:identifier":{"@type":"schema:URL","@value":"https://www.thueringen-entdecken.de/urlaub-hotel-reisen/alte-synagoge-erfurt-115157.html"},"schema:name":[{"@language":"de","@value":"Alte Synagoge"},{"@language":"fr","@value":"La vieille synagogue"},{"@language":"en","@value":"Old Synagogue"}],"schema:slogan":{"@type":"thuecat:ThuSlogan","@value":"thuecat:Highlight"},"schema:containedInPlace":[{"@id":"https://thuecat.org/resources/043064193523-jcyt"},{"@id":"https://thuecat.org/resources/573211638937-gmqb"},{"@id":"https://thuecat.org/resources/497839263245-edbm"}],"schema:photo":{"@id":"https://thuecat.org/resources/dms_5099196"},"schema:image":{"@id":"https://thuecat.org/resources/dms_5099196"},"schema:audience":[{"@id":"https://thuecat.org/resources/290287712606-zkwq"},{"@id":"https://thuecat.org/resources/312868368592-wnce"},{"@id":"https://thuecat.org/resources/301753337945-akzy"},{"@id":"https://thuecat.org/resources/304061111979-rmed"},{"@id":"https://thuecat.org/resources/668239314161-keen"}],"schema:petsAllowed":{"@language":"de","@value":"Tiere sind im Gebäude nicht gestattet, ausgenommen sind Blinden- und Blindenbegleithunde."},"schema:hasMap":{"@type":"schema:URL","@value":"https://www.google.com/maps/search/?api=1&query=50.978765,11.029133"},"schema:geo":{"@id":"genid-28b33237f71b41e3ad54a99e1da769b9-b4","@type":["schema:Intangible","schema:StructuredValue","schema:Thing","schema:GeoCoordinates"],"schema:longitude":{"@type":"schema:Number","@value":"11.029133"},"schema:latitude":{"@type":"schema:Number","@value":"50.978765"}},"schema:openingHoursSpecification":{"@id":"genid-28b33237f71b41e3ad54a99e1da769b9-b13","@type":["schema:Intangible","schema:StructuredValue","schema:Thing","schema:OpeningHoursSpecification"],"schema:validFrom":{"@type":"schema:Date","@value":"2021-03-01"},"schema:dayOfWeek":[{"@type":"schema:DayOfWeek","@value":"schema:Saturday"},{"@type":"schema:DayOfWeek","@value":"schema:Sunday"},{"@type":"schema:DayOfWeek","@value":"schema:Friday"},{"@type":"schema:DayOfWeek","@value":"schema:Thursday"},{"@type":"schema:DayOfWeek","@value":"schema:Tuesday"},{"@type":"schema:DayOfWeek","@value":"schema:Wednesday"}],"schema:opens":{"@type":"schema:Time","@value":"10:00:00"},"schema:validThrough":{"@type":"schema:Date","@value":"2021-12-31"},"schema:closes":{"@type":"schema:Time","@value":"18:00:00"}},"schema:isAccessibleForFree":{"@type":"schema:Boolean","@value":"false"},"schema:smokingAllowed":{"@type":"schema:Boolean","@value":"false"},"schema:url":{"@type":"schema:URL","@value":"http://www.alte-synagoge.erfurt.de"},"schema:availableLanguage":[{"@type":"thuecat:Language","@value":"thuecat:German"},{"@type":"thuecat:Language","@value":"thuecat:English"},{"@type":"thuecat:Language","@value":"thuecat:French"}],"schema:publicAccess":{"@type":"schema:Boolean","@value":"true"},"schema:paymentAccepted":[{"@type":"thuecat:PaymentAcceptedEnum","@value":"thuecat:CashPayment"},{"@type":"thuecat:PaymentAcceptedEnum","@value":"thuecat:EC"}],"schema:address":{"@id":"genid-28b33237f71b41e3ad54a99e1da769b9-b0","@type":["schema:Intangible","schema:PostalAddress","schema:StructuredValue","schema:Thing","schema:ContactPoint"],"schema:addressLocality":{"@language":"de","@value":"Erfurt"},"schema:addressCountry":{"@type":"thuecat:AddressCountry","@value":"thuecat:Germany"},"schema:postalCode":{"@language":"de","@value":"99084"},"schema:addressRegion":{"@type":"thuecat:AddressFederalState","@value":"thuecat:Thuringia"},"schema:telephone":{"@language":"de","@value":"+49 361 6551520"},"schema:email":{"@language":"de","@value":"altesynagoge@erfurt.de"},"schema:streetAddress":{"@language":"de","@value":"Waagegasse 8"},"schema:faxNumber":{"@language":"de","@value":"+49 361 6551669"},"thuecat:typOfAddress":{"@type":"thuecat:TypOfAddress","@value":"thuecat:HouseAddress"}},"schema:makesOffer":[{"@id":"genid-28b33237f71b41e3ad54a99e1da769b9-b5","@type":["schema:Intangible","schema:Thing","schema:Offer"],"schema:description":{"@language":"de","@value":"Immer samstags, um 11:15 Uhr findet eine öffentliche Führung durch das Museum statt. Dauer etwa 90 Minuten"},"schema:offeredBy":{"@id":"https://thuecat.org/resources/165868194223-zmqf"},"schema:name":{"@language":"de","@value":"Führungen"},"schema:priceSpecification":[{"@id":"genid-28b33237f71b41e3ad54a99e1da769b9-b6","@type":["schema:Intangible","schema:StructuredValue","schema:PriceSpecification","schema:Thing"],"schema:price":{"@type":"schema:Number","@value":"8"},"schema:name":{"@language":"de","@value":"Erwachsene"},"schema:priceCurrency":{"@type":"thuecat:Currency","@value":"thuecat:EUR"},"thuecat:calculationRule":{"@type":"thuecat:CalculationRule","@value":"thuecat:PerPerson"}},{"@id":"genid-28b33237f71b41e3ad54a99e1da769b9-b7","@type":["schema:Intangible","schema:StructuredValue","schema:PriceSpecification","schema:Thing"],"schema:description":{"@language":"de","@value":"als ermäßigt gelten schulpflichtige Kinder, Auszubildende, Studierende, Rentner/-innen, Menschen mit Behinderungen, Inhaber Sozialausweis der Landeshauptstadt Erfurt"},"schema:price":{"@type":"schema:Number","@value":"5"},"schema:name":{"@language":"de","@value":"Ermäßigt"},"schema:priceCurrency":{"@type":"thuecat:Currency","@value":"thuecat:EUR"},"thuecat:calculationRule":{"@type":"thuecat:CalculationRule","@value":"thuecat:PerPerson"}}],"thuecat:offerType":{"@type":"thuecat:OfferType","@value":"thuecat:GuidedTourOffer"}},{"@id":"genid-28b33237f71b41e3ad54a99e1da769b9-b8","@type":["schema:Intangible","schema:Thing","schema:Offer"],"schema:description":{"@language":"de","@value":"Schulklassen und Kitagruppen im Rahmen des Unterrichts: Eintritt frei\nAn jedem ersten Dienstag im Monat: Eintritt frei"},"schema:offeredBy":{"@id":"https://thuecat.org/resources/165868194223-zmqf"},"schema:name":{"@language":"de","@value":"Eintritt"},"schema:priceSpecification":[{"@id":"genid-28b33237f71b41e3ad54a99e1da769b9-b10","@type":["schema:Intangible","schema:StructuredValue","schema:PriceSpecification","schema:Thing"],"schema:description":{"@language":"de","@value":"als ermäßigt gelten schulpflichtige Kinder, Auszubildende, Studierende, Rentner/-innen, Menschen mit Behinderungen, Inhaber Sozialausweis der Landeshauptstadt Erfurt"},"schema:price":{"@type":"schema:Number","@value":"5"},"schema:name":{"@language":"de","@value":"Ermäßigt"},"schema:priceCurrency":{"@type":"thuecat:Currency","@value":"thuecat:EUR"},"thuecat:calculationRule":{"@type":"thuecat:CalculationRule","@value":"thuecat:PerPerson"}},{"@id":"genid-28b33237f71b41e3ad54a99e1da769b9-b11","@type":["schema:Intangible","schema:StructuredValue","schema:PriceSpecification","schema:Thing"],"schema:price":{"@type":"schema:Number","@value":"17"},"schema:name":{"@language":"de","@value":"Familienkarte"},"schema:priceCurrency":{"@type":"thuecat:Currency","@value":"thuecat:EUR"},"thuecat:calculationRule":{"@type":"thuecat:CalculationRule","@value":"thuecat:PerGroup"}},{"@id":"genid-28b33237f71b41e3ad54a99e1da769b9-b12","@type":["schema:Intangible","schema:StructuredValue","schema:PriceSpecification","schema:Thing"],"schema:price":{"@type":"schema:Number","@value":"14.90"},"schema:name":{"@language":"de","@value":"ErfurtCard"},"schema:priceCurrency":{"@type":"thuecat:Currency","@value":"thuecat:EUR"},"thuecat:calculationRule":{"@type":"thuecat:CalculationRule","@value":"thuecat:PerPackage"}},{"@id":"genid-28b33237f71b41e3ad54a99e1da769b9-b9","@type":["schema:Intangible","schema:StructuredValue","schema:PriceSpecification","schema:Thing"],"schema:price":{"@type":"schema:Number","@value":"8"},"schema:name":{"@language":"de","@value":"Erwachsene"},"schema:priceCurrency":{"@type":"thuecat:Currency","@value":"thuecat:EUR"},"thuecat:calculationRule":{"@type":"thuecat:CalculationRule","@value":"thuecat:PerPerson"}}],"thuecat:offerType":{"@type":"thuecat:OfferType","@value":"thuecat:EntryOffer"}}],"thuecat:exibitionObjekt":[{"@type":"thuecat:ExhibitionObject","@value":"thuecat:ReligiousHistoryExhibition"},{"@language":"de","@value":"Bau- und Nutzungsgeschichte der Alten Synagoge"},{"@language":"de","@value":"Erfurter Schatz"},{"@language":"de","@value":"Mittelalterliche Handschriften als Faksimile"}],"thuecat:museumService":{"@type":"thuecat:MuseumService","@value":"thuecat:MuseumShop"},"thuecat:contentResponsible":{"@id":"https://thuecat.org/resources/018132452787-ngbe"},"thuecat:monumentEnum":[{"@type":"thuecat:MonumentEnum","@value":"thuecat:ArchitecturalMonumentSingle"},{"@language":"de","@value":"Kulturdenkmal"}],"thuecat:digitalOffer":[{"@type":"thuecat:DigitalOffer","@value":"thuecat:AudioGuide"},{"@type":"thuecat:DigitalOffer","@value":"thuecat:VideoGuide"}],"thuecat:entrance":{"@type":"thuecat:Entrance","@value":"thuecat:IndoorActivities"},"thuecat:gastro":{"@type":"thuecat:GastroPoi","@value":"thuecat:ZeroGastronomy"},"thuecat:guidedTour":[{"@type":"thuecat:EnumGuidedTour","@value":"thuecat:GuidedTourOnlyWithRegistration"},{"@type":"thuecat:EnumGuidedTour","@value":"thuecat:GuidedTourRegistrationNotRequired"}],"thuecat:otherService":[{"@type":"thuecat:OtherService","@value":"thuecat:SeatingPossibilitiesRestArea"},{"@type":"thuecat:OtherService","@value":"thuecat:LockBoxes"},{"@type":"thuecat:OtherService","@value":"thuecat:SouvenirShop"},{"@type":"thuecat:OtherService","@value":"thuecat:BaggageStorage"}],"thuecat:photography":{"@type":"thuecat:Photography","@value":"thuecat:ZeroPhotography"},"thuecat:sanitation":[{"@type":"thuecat:Sanitation","@value":"thuecat:Toilets"},{"@type":"thuecat:Sanitation","@value":"thuecat:DisabledToilets"},{"@type":"thuecat:Sanitation","@value":"thuecat:NappyChangingArea"},{"@type":"thuecat:Sanitation","@value":"thuecat:FamilyAndChildFriendly"}],"thuecat:trafficInfrastructure":{"@type":"thuecat:TrafficInfrastructure","@value":"thuecat:ZeroSpecialTrafficInfrastructure"},"thuecat:distanceToPublicTransport":{"@id":"genid-28b33237f71b41e3ad54a99e1da769b9-b14","@type":["schema:Intangible","schema:QuantitativeValue","schema:StructuredValue","schema:Thing"],"schema:unitCode":{"@type":"thuecat:Unit","@value":"thuecat:MTR"},"schema:value":{"@type":"schema:Number","@value":"200"}},"thuecat:architecturalStyle":{"@type":"thuecat:ArchitecturalStyle","@value":"thuecat:GothicArt"},"thuecat:endOfConstruction":[{"@language":"de","@value":"12. Jh."},{"@language":"de","@value":"13. Jh."},{"@language":"de","@value":"19. Jh."},{"@language":"de","@value":"20. Jh."},{"@language":"de","@value":"14. Jh."},{"@language":"de","@value":"2009"}],"thuecat:startOfConstruction":[{"@language":"de","@value":"11. Jh."},{"@language":"en","@value":"11th century"}],"thuecat:openAirMuseum":{"@type":"schema:Boolean","@value":"false"}}]} diff --git a/Tests/Functional/Fixtures/Import/Guzzle/thuecat.org/resources/356133173991-cryw/GET_976c32c50e2a09718c35138281482010.txt b/Tests/Functional/Fixtures/Import/Guzzle/thuecat.org/resources/356133173991-cryw/GET_976c32c50e2a09718c35138281482010.txt new file mode 100644 index 0000000..0738272 --- /dev/null +++ b/Tests/Functional/Fixtures/Import/Guzzle/thuecat.org/resources/356133173991-cryw/GET_976c32c50e2a09718c35138281482010.txt @@ -0,0 +1,19 @@ +HTTP/1.1 200 OK +Date: Wed, 17 Feb 2021 08:02:03 GMT +Content-Type: application/ld+json; charset=utf-8 +Content-Length: 8246 +Connection: keep-alive +Set-Cookie: ahSession=3214d2dc9f40fe97b06822c2c25fd67baf623db4;path=/;expires=Sat, 20 Mar 2021 08:02:03 GMT;httpOnly=true; +Access-Control-Allow-Methods: HEAD, GET, POST, DELETE, OPTIONS +Access-Control-Allow-Headers: Authorization, Content-Type +Strict-Transport-Security: max-age=15724800; includeSubDomains +Access-Control-Allow-Credentials: true +X-Frame-Options: deny +X-XSS-Protection: 1; mode=block +X-Content-Type-Options: nosniff +Referrer-Policy: same-origin +Feature-Policy: microphone 'none'; camera 'none'; payment 'none' +Content-Security-Policy: default-src 'self'; script-src 'self' 'sha256-xfTbtWk8kVI65iLJs8LB3lWf2g0g10DS71pDdoutFHc='; style-src 'self' 'unsafe-inline' https://stackpath.bootstrapcdn.com; img-src 'self' data: blob: * +Access-Control-Allow-Origin: https://cdb.thuecat.org + +{"@context":{"schema":"http://schema.org/","dbo":"http://dbpedia.org/ontology/","dsv":"http://ontologies.sti-innsbruck.at/dsv/","foaf":"http://xmlns.com/foaf/0.1/","owl":"http://www.w3.org/2002/07/owl#","rdf":"http://www.w3.org/1999/02/22-rdf-syntax-ns#","rdfs":"http://www.w3.org/2000/01/rdf-schema#","sh":"http://www.w3.org/ns/shacl#","xsd":"http://www.w3.org/2001/XMLSchema#","ttgds":"https://thuecat.org/ontology/ttgds/1.0/","cdb":"https://thuecat.org/ontology/cdb/1.0/","dachkg":"https://thuecat.org/ontology/dachkg/1.0/","thuecat":"https://thuecat.org/ontology/thuecat/1.0/","epapp":"https://thuecat.org/ontology/epapp/1.0/"},"@graph":[{"@id":"https://thuecat.org/resources/356133173991-cryw","@type":["schema:Place","schema:Organization","schema:LocalBusiness","schema:Thing","schema:TouristAttraction","ttgds:OtherInfraStructure","thuecat:OtherPOI","thuecat:StrollingMile"],"schema:description":[{"@language":"de","@value":"Der Benediktsplatz befindet sich hinter dem Erfurter Rathaus am westlichen Zugang der Krämerbrücke. Von hier aus gelangt man nicht nur auf, sondern auch vor und hinter der Krämerbrücke. Außerdem verbindet der Benediktsplatz den Fischmarkt, den Wenigemarkt und die Michaelisstraße. \nAls Standort der Erfurt Tourist Information ist er häufig erste Anlaufstelle und Sammelpunkt für Besucher der Thüringer Landeshauptstadt.\nAuf dem zentralen Knotenpunkt Benediktsplatz kreuzen sich zudem der Radfernweg Thüringer Städtekette und der Gera-Radweg."},{"@language":"fr","@value":"La Benediktsplatz est située derrière l'hôtel de ville d'Erfurt, à l'entrée ouest du Krämerbrücke. De là, vous pouvez vous rendre non seulement sur, mais aussi devant et derrière le Krämerbrücke. La Benediktsplatz relie également le Fischmarkt, le Wenigemarkt et la Michaelisstraße. \nEn tant que siège de l'office du tourisme d'Erfurt, il est souvent le premier port d'escale et le point de rencontre des visiteurs de la capitale du Land de Thuringe.\nLa piste cyclable longue distance Thüringer Städtekette et la piste cyclable Gera se croisent également au carrefour central de la Benediktsplatz."},{"@language":"en","@value":"The Benediktsplatz is located behind the Erfurt city hall at the western entrance of the Krämerbrücke. From here you can get not only on, but also in front of and behind the Krämerbrücke. Benediktsplatz also connects the Fischmarkt, Wenigemarkt and Michaelisstraße. \nAs the location of Erfurt Tourist Information, it is often the first port of call and meeting point for visitors to the Thuringian state capital.\nThe long-distance cycle route Thüringer Städtekette and the Gera cycle route also intersect at the central Benediktsplatz junction."},{"@id":"genid-5e6f943aee4440a394cd43c2a16154da-b1","@type":["schema:Intangible","schema:Thing","schema:ComputerLanguage","thuecat:Html"],"schema:value":{"@language":"de","@value":"

Der Benediktsplatz befindet sich hinter dem Erfurter Rathaus am westlichen Zugang der Krämerbrücke. Von hier aus gelangt man nicht nur auf, sondern auch vor und hinter der Krämerbrücke. Außerdem verbindet der Benediktsplatz den Fischmarkt, den Wenigemarkt und die Michaelisstraße.

Als Standort der Erfurt Tourist Information ist er häufig erste Anlaufstelle und Sammelpunkt für Besucher der Thüringer Landeshauptstadt.

Auf dem zentralen Knotenpunkt Benediktsplatz kreuzen sich zudem der Radfernweg Thüringer Städtekette und der Gera-Radweg.

"}},{"@id":"genid-5e6f943aee4440a394cd43c2a16154da-b2","@type":["schema:Intangible","schema:Thing","schema:ComputerLanguage","thuecat:Html"],"schema:value":{"@language":"en","@value":"

The Benediktsplatz is located behind the Erfurt city hall at the western entrance of the Krämerbrücke. From here you can get not only on, but also in front of and behind the Krämerbrücke. Benediktsplatz also connects the Fischmarkt, Wenigemarkt and Michaelisstraße.

As the location of Erfurt Tourist Information, it is often the first port of call and meeting point for visitors to the Thuringian state capital.

The long-distance cycle route Thüringer Städtekette and the Gera cycle route also intersect at the central Benediktsplatz junction.

"}},{"@id":"genid-5e6f943aee4440a394cd43c2a16154da-b3","@type":["schema:Intangible","schema:Thing","schema:ComputerLanguage","thuecat:Html"],"schema:value":{"@language":"fr","@value":"

La Benediktsplatz est située derrière l'hôtel de ville d'Erfurt, à l'entrée ouest du Krämerbrücke. De là, vous pouvez vous rendre non seulement sur, mais aussi devant et derrière le Krämerbrücke. La Benediktsplatz relie également le Fischmarkt, le Wenigemarkt et la Michaelisstraße.

En tant que siège de l'office du tourisme d'Erfurt, il est souvent le premier port d'escale et le point de rencontre des visiteurs de la capitale du Land de Thuringe.

La piste cyclable longue distance Thüringer Städtekette et la piste cyclable Gera se croisent également au carrefour central de la Benediktsplatz.

"}}],"schema:name":{"@language":"de","@value":"Benediktsplatz Erfurt"},"schema:containedInPlace":{"@id":"https://thuecat.org/resources/043064193523-jcyt"},"schema:containsPlace":[{"@id":"https://thuecat.org/resources/333039283321-xxwg"},{"@id":"https://thuecat.org/resources/186583376407-xkwx"},{"@id":"https://thuecat.org/resources/297975882806-geen"}],"schema:photo":{"@id":"https://thuecat.org/resources/dms_6480118"},"schema:image":[{"@id":"https://thuecat.org/resources/dms_5311411"},{"@id":"https://thuecat.org/resources/dms_6233066"},{"@id":"https://thuecat.org/resources/dms_6480118"}],"schema:petsAllowed":{"@type":"schema:Boolean","@value":"true"},"schema:hasMap":{"@type":"schema:URL","@value":"https://www.google.de/maps/@50.9785325,11.0298036,20z"},"schema:geo":{"@id":"genid-5e6f943aee4440a394cd43c2a16154da-b4","@type":["schema:Intangible","schema:StructuredValue","schema:Thing","schema:GeoCoordinates"],"schema:longitude":{"@type":"schema:Number","@value":"11.029931019874105"},"schema:latitude":{"@type":"schema:Number","@value":"50.978601061243474"}},"schema:smokingAllowed":{"@type":"schema:Boolean","@value":"true"},"schema:address":{"@id":"genid-5e6f943aee4440a394cd43c2a16154da-b0","@type":["schema:Intangible","schema:PostalAddress","schema:StructuredValue","schema:Thing","schema:ContactPoint"],"schema:addressLocality":{"@language":"de","@value":"Erfurt"},"schema:addressCountry":{"@type":"thuecat:AddressCountry","@value":"thuecat:Germany"},"schema:postalCode":{"@language":"de","@value":"99084"},"schema:addressRegion":{"@type":"thuecat:AddressFederalState","@value":"thuecat:Thuringia"},"schema:streetAddress":{"@language":"de","@value":"Benediktsplatz"},"thuecat:typOfAddress":{"@type":"thuecat:TypOfAddress","@value":"thuecat:HouseAddress"}},"thuecat:contentResponsible":{"@id":"https://thuecat.org/resources/018132452787-ngbe"},"thuecat:gastro":[{"@type":"thuecat:GastroPoi","@value":"thuecat:TakeawayShop"},{"@type":"thuecat:GastroPoi","@value":"thuecat:Cafe"},{"@type":"thuecat:GastroPoi","@value":"thuecat:BarEnumMem"},{"@type":"thuecat:GastroPoi","@value":"thuecat:Restaurant"}],"thuecat:sanitation":{"@type":"thuecat:Sanitation","@value":"thuecat:ZeroSanitation"}}]} diff --git a/Tests/Functional/Fixtures/Import/Guzzle/thuecat.org/resources/396420044896-drzt/GET_e234b318dcfb8dfae8661f8c07530fa6.txt b/Tests/Functional/Fixtures/Import/Guzzle/thuecat.org/resources/396420044896-drzt/GET_e234b318dcfb8dfae8661f8c07530fa6.txt new file mode 100644 index 0000000..bba76b0 --- /dev/null +++ b/Tests/Functional/Fixtures/Import/Guzzle/thuecat.org/resources/396420044896-drzt/GET_e234b318dcfb8dfae8661f8c07530fa6.txt @@ -0,0 +1,19 @@ +HTTP/1.1 200 OK +Date: Wed, 17 Feb 2021 08:04:06 GMT +Content-Type: application/ld+json; charset=utf-8 +Content-Length: 10828 +Connection: keep-alive +Set-Cookie: ahSession=06f1bc392b6485385a5ad291337e404c45d21e40;path=/;expires=Sat, 20 Mar 2021 08:04:05 GMT;httpOnly=true; +Access-Control-Allow-Methods: HEAD, GET, POST, DELETE, OPTIONS +Access-Control-Allow-Headers: Authorization, Content-Type +Strict-Transport-Security: max-age=15724800; includeSubDomains +Access-Control-Allow-Credentials: true +X-Frame-Options: deny +X-XSS-Protection: 1; mode=block +X-Content-Type-Options: nosniff +Referrer-Policy: same-origin +Feature-Policy: microphone 'none'; camera 'none'; payment 'none' +Content-Security-Policy: default-src 'self'; script-src 'self' 'sha256-xfTbtWk8kVI65iLJs8LB3lWf2g0g10DS71pDdoutFHc='; style-src 'self' 'unsafe-inline' https://stackpath.bootstrapcdn.com; img-src 'self' data: blob: * +Access-Control-Allow-Origin: https://cdb.thuecat.org + +{"@context":{"schema":"http://schema.org/","dbo":"http://dbpedia.org/ontology/","dsv":"http://ontologies.sti-innsbruck.at/dsv/","foaf":"http://xmlns.com/foaf/0.1/","owl":"http://www.w3.org/2002/07/owl#","rdf":"http://www.w3.org/1999/02/22-rdf-syntax-ns#","rdfs":"http://www.w3.org/2000/01/rdf-schema#","sh":"http://www.w3.org/ns/shacl#","xsd":"http://www.w3.org/2001/XMLSchema#","ttgds":"https://thuecat.org/ontology/ttgds/1.0/","cdb":"https://thuecat.org/ontology/cdb/1.0/","dachkg":"https://thuecat.org/ontology/dachkg/1.0/","thuecat":"https://thuecat.org/ontology/thuecat/1.0/","epapp":"https://thuecat.org/ontology/epapp/1.0/"},"@graph":[{"@id":"https://thuecat.org/resources/396420044896-drzt","@type":["schema:Place","schema:Organization","schema:LocalBusiness","schema:CivicStructure","schema:Thing","schema:ParkingFacility","ttgds:OtherInfraStructure","thuecat:OtherPOI","thuecat:MultiStoreyCarPark"],"schema:description":[{"@language":"de","@value":"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."},{"@language":"fr","@value":"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."},{"@language":"en","@value":"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."},{"@id":"genid-2c9c8a1b44cc404ebe32e34cdbb87884-b1","@type":["schema:Intangible","schema:Thing","schema:ComputerLanguage","thuecat:Html"],"schema:value":{"@language":"de","@value":"

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.

"}},{"@id":"genid-2c9c8a1b44cc404ebe32e34cdbb87884-b2","@type":["schema:Intangible","schema:Thing","schema:ComputerLanguage","thuecat:Html"],"schema:value":{"@language":"en","@value":"

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.

"}},{"@id":"genid-2c9c8a1b44cc404ebe32e34cdbb87884-b3","@type":["schema:Intangible","schema:Thing","schema:ComputerLanguage","thuecat:Html"],"schema:value":{"@language":"fr","@value":"

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.

"}}],"schema:name":[{"@language":"de","@value":"Parkhaus Domplatz"},{"@language":"en","@value":"Car park Domplatz"},{"@language":"fr","@value":"Parking Domplatz"}],"schema:containedInPlace":{"@id":"https://thuecat.org/resources/508431710173-wwne"},"schema:photo":{"@id":"https://thuecat.org/resources/dms_6486108"},"schema:image":{"@id":"https://thuecat.org/resources/dms_6486108"},"schema:petsAllowed":{"@type":"schema:Boolean","@value":"true"},"schema:geo":{"@id":"genid-2c9c8a1b44cc404ebe32e34cdbb87884-b4","@type":["schema:Intangible","schema:StructuredValue","schema:Thing","schema:GeoCoordinates"],"schema:longitude":{"@type":"schema:Number","@value":"11.022127985954299"},"schema:latitude":{"@type":"schema:Number","@value":"50.977648905044"}},"schema:openingHoursSpecification":[{"@id":"genid-2c9c8a1b44cc404ebe32e34cdbb87884-b13","@type":["schema:Intangible","schema:StructuredValue","schema:Thing","schema:OpeningHoursSpecification"],"schema:dayOfWeek":[{"@type":"schema:DayOfWeek","@value":"schema:Saturday"},{"@type":"schema:DayOfWeek","@value":"schema:Friday"},{"@type":"schema:DayOfWeek","@value":"schema:Thursday"},{"@type":"schema:DayOfWeek","@value":"schema:Tuesday"},{"@type":"schema:DayOfWeek","@value":"schema:Monday"},{"@type":"schema:DayOfWeek","@value":"schema:Wednesday"}],"schema:opens":{"@type":"schema:Time","@value":"07:00:00"},"schema:closes":{"@type":"schema:Time","@value":"22:00:00"}},{"@id":"genid-2c9c8a1b44cc404ebe32e34cdbb87884-b14","@type":["schema:Intangible","schema:StructuredValue","schema:Thing","schema:OpeningHoursSpecification"],"schema:dayOfWeek":[{"@type":"schema:DayOfWeek","@value":"schema:Sunday"},{"@type":"schema:DayOfWeek","@value":"schema:PublicHolidays"}],"schema:opens":{"@type":"schema:Time","@value":"09:00:00"},"schema:closes":{"@type":"schema:Time","@value":"22:00:00"}}],"schema:smokingAllowed":{"@type":"schema:Boolean","@value":"false"},"schema:url":{"@type":"schema:URL","@value":"https://www.stadtwerke-erfurt.de/pb/swe/produkte+_+leistungen/parken/parkhaus+domplatz"},"schema:address":{"@id":"genid-2c9c8a1b44cc404ebe32e34cdbb87884-b0","@type":["schema:Intangible","schema:PostalAddress","schema:StructuredValue","schema:Thing","schema:ContactPoint"],"schema:addressLocality":{"@language":"de","@value":"Erfurt"},"schema:addressCountry":{"@type":"thuecat:AddressCountry","@value":"thuecat:Germany"},"schema:postalCode":{"@language":"de","@value":"99084"},"schema:addressRegion":{"@type":"thuecat:AddressFederalState","@value":"thuecat:Thuringia"},"schema:telephone":{"@language":"de","@value":"+49 361 5640"},"schema:email":{"@language":"de","@value":"info@stadtwerke-erfurt.de"},"schema:streetAddress":{"@language":"de","@value":"Bechtheimer Str. 1"},"thuecat:typOfAddress":{"@type":"thuecat:TypOfAddress","@value":"thuecat:HouseAddress"}},"schema:makesOffer":[{"@id":"genid-2c9c8a1b44cc404ebe32e34cdbb87884-b11","@type":["schema:Intangible","schema:Thing","schema:Offer"],"schema:offeredBy":{"@id":"https://thuecat.org/resources/396420044896-drzt"},"schema:availability":{"@type":"schema:ItemAvailability","@value":"schema:LimitedAvailability"},"schema:priceSpecification":{"@id":"genid-2c9c8a1b44cc404ebe32e34cdbb87884-b12","@type":["schema:Intangible","schema:StructuredValue","schema:PriceSpecification","schema:Thing"],"schema:price":{"@type":"schema:Number","@value":"35"},"schema:priceCurrency":{"@type":"thuecat:Currency","@value":"thuecat:EUR"},"thuecat:calculationRule":{"@type":"thuecat:CalculationRule","@value":"thuecat:PerCar"}},"thuecat:offerType":{"@type":"thuecat:OfferType","@value":"thuecat:ParkingFee"}},{"@id":"genid-2c9c8a1b44cc404ebe32e34cdbb87884-b5","@type":["schema:Intangible","schema:Thing","schema:Offer"],"schema:offeredBy":{"@id":"https://thuecat.org/resources/396420044896-drzt"},"schema:availability":{"@type":"schema:ItemAvailability","@value":"schema:LimitedAvailability"},"schema:priceSpecification":{"@id":"genid-2c9c8a1b44cc404ebe32e34cdbb87884-b6","@type":["schema:Intangible","schema:StructuredValue","schema:PriceSpecification","schema:Thing"],"schema:price":{"@type":"schema:Number","@value":"1.5"},"schema:priceCurrency":{"@type":"thuecat:Currency","@value":"thuecat:EUR"},"thuecat:calculationRule":{"@type":"thuecat:CalculationRule","@value":"thuecat:PerCar"}},"thuecat:offerType":{"@type":"thuecat:OfferType","@value":"thuecat:ParkingFee"}},{"@id":"genid-2c9c8a1b44cc404ebe32e34cdbb87884-b7","@type":["schema:Intangible","schema:Thing","schema:Offer"],"schema:offeredBy":{"@id":"https://thuecat.org/resources/396420044896-drzt"},"schema:availability":{"@type":"schema:ItemAvailability","@value":"schema:LimitedAvailability"},"schema:priceSpecification":{"@id":"genid-2c9c8a1b44cc404ebe32e34cdbb87884-b8","@type":["schema:Intangible","schema:StructuredValue","schema:PriceSpecification","schema:Thing"],"schema:price":{"@type":"schema:Number","@value":"10"},"schema:priceCurrency":{"@type":"thuecat:Currency","@value":"thuecat:EUR"},"thuecat:calculationRule":{"@type":"thuecat:CalculationRule","@value":"thuecat:PerCar"}},"thuecat:offerType":{"@type":"thuecat:OfferType","@value":"thuecat:ParkingFee"}},{"@id":"genid-2c9c8a1b44cc404ebe32e34cdbb87884-b9","@type":["schema:Intangible","schema:Thing","schema:Offer"],"schema:offeredBy":{"@id":"https://thuecat.org/resources/396420044896-drzt"},"schema:availability":{"@type":"schema:ItemAvailability","@value":"schema:LimitedAvailability"},"schema:priceSpecification":{"@id":"genid-2c9c8a1b44cc404ebe32e34cdbb87884-b10","@type":["schema:Intangible","schema:StructuredValue","schema:PriceSpecification","schema:Thing"],"schema:price":{"@type":"schema:Number","@value":"50"},"schema:priceCurrency":{"@type":"thuecat:Currency","@value":"thuecat:EUR"},"thuecat:calculationRule":{"@type":"thuecat:CalculationRule","@value":"thuecat:PerCar"}},"thuecat:offerType":{"@type":"thuecat:OfferType","@value":"thuecat:ParkingFee"}}],"thuecat:numberOfParkingSpace":{"@id":"genid-2c9c8a1b44cc404ebe32e34cdbb87884-b17","@type":["schema:Intangible","schema:QuantitativeValue","schema:StructuredValue","schema:Thing"],"schema:value":{"@type":"schema:Integer","@value":"300"},"schema:unitText":{"@type":"thuecat:TypeOfVehicle","@value":"thuecat:Car"}},"thuecat:contentResponsible":{"@id":"https://thuecat.org/resources/018132452787-ngbe"},"thuecat:managedBy":{"@id":"https://thuecat.org/resources/570107928040-rfze"},"thuecat:gastro":{"@type":"thuecat:GastroPoi","@value":"thuecat:ZeroGastronomy"},"thuecat:otherService":{"@type":"thuecat:OtherService","@value":"thuecat:ZeroOtherServiceEnumMem"},"thuecat:sanitation":{"@type":"thuecat:Sanitation","@value":"thuecat:ZeroSanitation"},"thuecat:trafficInfrastructure":{"@type":"thuecat:TrafficInfrastructure","@value":"thuecat:ElectricVehicleCarChargingStationEnumMem"},"thuecat:distanceToPublicTransport":{"@id":"genid-2c9c8a1b44cc404ebe32e34cdbb87884-b15","@type":["schema:Intangible","schema:QuantitativeValue","schema:StructuredValue","schema:Thing"],"schema:unitCode":{"@type":"thuecat:Unit","@value":"thuecat:MTR"},"schema:value":{"@type":"schema:Number","@value":"240"}},"thuecat:objectsNearBy":[{"@id":"https://thuecat.org/resources/908740175209-zbep"},{"@id":"https://thuecat.org/resources/835224016581-dara"},{"@id":"https://thuecat.org/resources/043064193523-jcyt"},{"@id":"https://thuecat.org/resources/363938447400-ammb"}],"thuecat:entryHeight":{"@id":"genid-2c9c8a1b44cc404ebe32e34cdbb87884-b16","@type":["schema:Intangible","schema:QuantitativeValue","schema:StructuredValue","schema:Thing"],"schema:unitCode":{"@type":"thuecat:Unit","@value":"thuecat:MTR"},"schema:value":{"@type":"schema:Number","@value":"2"}}}]} diff --git a/Tests/Functional/Fixtures/Import/Guzzle/thuecat.org/resources/440055527204-ocar/GET_ed2b49df916e1c2dba1a679b9866de31.txt b/Tests/Functional/Fixtures/Import/Guzzle/thuecat.org/resources/440055527204-ocar/GET_ed2b49df916e1c2dba1a679b9866de31.txt new file mode 100644 index 0000000..6c00e86 --- /dev/null +++ b/Tests/Functional/Fixtures/Import/Guzzle/thuecat.org/resources/440055527204-ocar/GET_ed2b49df916e1c2dba1a679b9866de31.txt @@ -0,0 +1,19 @@ +HTTP/1.1 200 OK +Date: Wed, 17 Feb 2021 08:04:06 GMT +Content-Type: application/ld+json; charset=utf-8 +Content-Length: 11716 +Connection: keep-alive +Set-Cookie: ahSession=06f1bc392b6485385a5ad291337e404c45d21e40;path=/;expires=Sat, 20 Mar 2021 08:04:05 GMT;httpOnly=true; +Access-Control-Allow-Methods: HEAD, GET, POST, DELETE, OPTIONS +Access-Control-Allow-Headers: Authorization, Content-Type +Strict-Transport-Security: max-age=15724800; includeSubDomains +Access-Control-Allow-Credentials: true +X-Frame-Options: deny +X-XSS-Protection: 1; mode=block +X-Content-Type-Options: nosniff +Referrer-Policy: same-origin +Feature-Policy: microphone 'none'; camera 'none'; payment 'none' +Content-Security-Policy: default-src 'self'; script-src 'self' 'sha256-xfTbtWk8kVI65iLJs8LB3lWf2g0g10DS71pDdoutFHc='; style-src 'self' 'unsafe-inline' https://stackpath.bootstrapcdn.com; img-src 'self' data: blob: * +Access-Control-Allow-Origin: https://cdb.thuecat.org + +{"@context":{"schema":"http://schema.org/","dbo":"http://dbpedia.org/ontology/","dsv":"http://ontologies.sti-innsbruck.at/dsv/","foaf":"http://xmlns.com/foaf/0.1/","owl":"http://www.w3.org/2002/07/owl#","rdf":"http://www.w3.org/1999/02/22-rdf-syntax-ns#","rdfs":"http://www.w3.org/2000/01/rdf-schema#","sh":"http://www.w3.org/ns/shacl#","xsd":"http://www.w3.org/2001/XMLSchema#","ttgds":"https://thuecat.org/ontology/ttgds/1.0/","cdb":"https://thuecat.org/ontology/cdb/1.0/","dachkg":"https://thuecat.org/ontology/dachkg/1.0/","thuecat":"https://thuecat.org/ontology/thuecat/1.0/","epapp":"https://thuecat.org/ontology/epapp/1.0/"},"@graph":[{"@id":"https://thuecat.org/resources/440055527204-ocar","@type":["schema:Place","schema:Organization","schema:LocalBusiness","schema:CivicStructure","schema:Thing","schema:TouristAttraction","schema:ParkingFacility","ttgds:OtherInfraStructure","thuecat:Building","thuecat:OtherPOI","thuecat:MultiStoreyCarPark","thuecat:TrafficBuilding"],"schema:description":[{"@language":"fr","@value":"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."},{"@language":"en","@value":"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."},{"@language":"de","@value":"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."},{"@id":"genid-9de58329a0684feaa8b9b5ea70621af8-b1","@type":["schema:Intangible","schema:Thing","schema:ComputerLanguage","thuecat:Html"],"schema:value":{"@language":"de","@value":"

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.

"}},{"@id":"genid-9de58329a0684feaa8b9b5ea70621af8-b2","@type":["schema:Intangible","schema:Thing","schema:ComputerLanguage","thuecat:Html"],"schema:value":{"@language":"en","@value":"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."}},{"@id":"genid-9de58329a0684feaa8b9b5ea70621af8-b3","@type":["schema:Intangible","schema:Thing","schema:ComputerLanguage","thuecat:Html"],"schema:value":{"@language":"fr","@value":"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."}}],"schema:name":[{"@language":"de","@value":"Q-Park Anger 1 Parkhaus"},{"@language":"en","@value":"Q-Park Anger 1 multi-storey car park"},{"@language":"fr","@value":"Q-Park Anger 1 parking à étages"}],"schema:containedInPlace":{"@id":"https://thuecat.org/resources/043064193523-jcyt"},"schema:photo":{"@id":"https://thuecat.org/resources/dms_5197164"},"schema:image":{"@id":"https://thuecat.org/resources/dms_5197164"},"schema:petsAllowed":{"@type":"schema:Boolean","@value":"true"},"schema:hasMap":{"@type":"schema:URL","@value":"https://www.google.de/maps/place/Q-Park+Anger+1+Parkhaus/@50.9777795,11.036599,18.5z/data=!4m12!1m6!3m5!1s0x47a47295932dd6c5:0x619ce72e7a54f805!2sPredigerkirche!8m2!3d50.976505!4d11.0289217!3m4!1s0x47a472bc3ecf3a5d:0x88cb2943674c2ea2!8m2!3d50.978002!4d11.0375074"},"schema:geo":{"@id":"genid-9de58329a0684feaa8b9b5ea70621af8-b4","@type":["schema:Intangible","schema:StructuredValue","schema:Thing","schema:GeoCoordinates"],"schema:longitude":{"@type":"schema:Number","@value":"11.037503264052475"},"schema:latitude":{"@type":"schema:Number","@value":"50.977999330565794"}},"schema:openingHoursSpecification":{"@id":"genid-9de58329a0684feaa8b9b5ea70621af8-b11","@type":["schema:Intangible","schema:StructuredValue","schema:Thing","schema:OpeningHoursSpecification"],"schema:validFrom":{"@type":"schema:Date","@value":"2020-12-01"},"schema:dayOfWeek":[{"@type":"schema:DayOfWeek","@value":"schema:Saturday"},{"@type":"schema:DayOfWeek","@value":"schema:Sunday"},{"@type":"schema:DayOfWeek","@value":"schema:Friday"},{"@type":"schema:DayOfWeek","@value":"schema:Thursday"},{"@type":"schema:DayOfWeek","@value":"schema:Tuesday"},{"@type":"schema:DayOfWeek","@value":"schema:Monday"},{"@type":"schema:DayOfWeek","@value":"schema:Wednesday"}],"schema:opens":{"@type":"schema:Time","@value":"05:30:00"},"schema:validThrough":{"@type":"schema:Date","@value":"2021-12-31"},"schema:closes":{"@type":"schema:Time","@value":"23:59:00"}},"schema:isAccessibleForFree":{"@type":"schema:Boolean","@value":"false"},"schema:smokingAllowed":{"@type":"schema:Boolean","@value":"false"},"schema:url":{"@type":"schema:URL","@value":"https://www.q-park.de/de-de/staedte/erfurt/anger-1/"},"schema:address":{"@id":"genid-9de58329a0684feaa8b9b5ea70621af8-b0","@type":["schema:Intangible","schema:PostalAddress","schema:StructuredValue","schema:Thing","schema:ContactPoint"],"schema:addressLocality":{"@language":"de","@value":"Erfurt"},"schema:addressCountry":{"@type":"thuecat:AddressCountry","@value":"thuecat:Germany"},"schema:postalCode":{"@language":"de","@value":"99084"},"schema:addressRegion":{"@type":"thuecat:AddressFederalState","@value":"thuecat:Thuringia"},"schema:telephone":{"@language":"de","@value":"+49 218 18190290"},"schema:email":{"@language":"de","@value":"servicecenter@q-park.de"},"schema:streetAddress":{"@language":"de","@value":"Anger 1"},"thuecat:typOfAddress":{"@type":"thuecat:TypOfAddress","@value":"thuecat:HouseAddress"}},"schema:makesOffer":[{"@id":"genid-9de58329a0684feaa8b9b5ea70621af8-b5","@type":["schema:Intangible","schema:Thing","schema:Offer"],"schema:offeredBy":{"@id":"https://thuecat.org/resources/440055527204-ocar"},"schema:priceSpecification":{"@id":"genid-9de58329a0684feaa8b9b5ea70621af8-b6","@type":["schema:Intangible","schema:StructuredValue","schema:PriceSpecification","schema:Thing"],"schema:price":{"@type":"schema:Number","@value":"2.2"},"schema:priceCurrency":{"@type":"thuecat:Currency","@value":"thuecat:EUR"},"thuecat:calculationRule":{"@type":"thuecat:CalculationRule","@value":"thuecat:PerCar"}},"thuecat:offerType":{"@type":"thuecat:OfferType","@value":"thuecat:ParkingFee"}},{"@id":"genid-9de58329a0684feaa8b9b5ea70621af8-b7","@type":["schema:Intangible","schema:Thing","schema:Offer"],"schema:offeredBy":{"@id":"https://thuecat.org/resources/440055527204-ocar"},"schema:priceSpecification":{"@id":"genid-9de58329a0684feaa8b9b5ea70621af8-b8","@type":["schema:Intangible","schema:StructuredValue","schema:PriceSpecification","schema:Thing"],"schema:price":{"@type":"schema:Number","@value":"1"},"schema:priceCurrency":{"@type":"thuecat:Currency","@value":"thuecat:EUR"},"thuecat:calculationRule":{"@type":"thuecat:CalculationRule","@value":"thuecat:PerCar"}},"thuecat:offerType":{"@type":"thuecat:OfferType","@value":"thuecat:ParkingFee"}},{"@id":"genid-9de58329a0684feaa8b9b5ea70621af8-b9","@type":["schema:Intangible","schema:Thing","schema:Offer"],"schema:offeredBy":{"@id":"https://thuecat.org/resources/440055527204-ocar"},"schema:priceSpecification":{"@id":"genid-9de58329a0684feaa8b9b5ea70621af8-b10","@type":["schema:Intangible","schema:StructuredValue","schema:PriceSpecification","schema:Thing"],"schema:price":{"@type":"schema:Number","@value":"13"},"schema:priceCurrency":{"@type":"thuecat:Currency","@value":"thuecat:EUR"},"thuecat:calculationRule":{"@type":"thuecat:CalculationRule","@value":"thuecat:PerCar"}},"thuecat:offerType":{"@type":"thuecat:OfferType","@value":"thuecat:ParkingFee"}}],"thuecat:numberOfParkingSpace":{"@id":"genid-9de58329a0684feaa8b9b5ea70621af8-b14","@type":["schema:Intangible","schema:QuantitativeValue","schema:StructuredValue","schema:Thing"],"schema:value":{"@type":"schema:Integer","@value":"716"},"schema:unitText":{"@type":"thuecat:TypeOfVehicle","@value":"thuecat:Car"}},"thuecat:contentResponsible":{"@id":"https://thuecat.org/resources/018132452787-ngbe"},"thuecat:gastro":{"@type":"thuecat:GastroPoi","@value":"thuecat:ZeroGastronomy"},"thuecat:otherService":{"@type":"thuecat:OtherService","@value":"thuecat:ZeroOtherServiceEnumMem"},"thuecat:sanitation":{"@type":"thuecat:Sanitation","@value":"thuecat:Toilets"},"thuecat:distanceToPublicTransport":{"@id":"genid-9de58329a0684feaa8b9b5ea70621af8-b12","@type":["schema:Intangible","schema:QuantitativeValue","schema:StructuredValue","schema:Thing"],"schema:unitCode":{"@type":"thuecat:Unit","@value":"thuecat:MTR"},"schema:value":{"@type":"schema:Number","@value":"120"}},"thuecat:objectsNearBy":[{"@id":"https://thuecat.org/resources/r_16573215-oapoi"},{"@id":"https://thuecat.org/resources/r_22031603-oapoi"},{"@id":"https://thuecat.org/resources/896842796891-acor"},{"@id":"https://thuecat.org/resources/691296454763-qdjy"}],"thuecat:entryHeight":{"@id":"genid-9de58329a0684feaa8b9b5ea70621af8-b13","@type":["schema:Intangible","schema:QuantitativeValue","schema:StructuredValue","schema:Thing"],"schema:unitCode":{"@type":"thuecat:Unit","@value":"thuecat:MTR"},"schema:value":{"@type":"schema:Number","@value":"2.1"}}}]} diff --git a/Tests/Functional/Fixtures/Import/Guzzle/thuecat.org/resources/497839263245-edbm/GET_68f53911ca843d0b5c0f792784fe3000.txt b/Tests/Functional/Fixtures/Import/Guzzle/thuecat.org/resources/497839263245-edbm/GET_68f53911ca843d0b5c0f792784fe3000.txt new file mode 100644 index 0000000..5a953c7 --- /dev/null +++ b/Tests/Functional/Fixtures/Import/Guzzle/thuecat.org/resources/497839263245-edbm/GET_68f53911ca843d0b5c0f792784fe3000.txt @@ -0,0 +1,19 @@ +HTTP/1.1 200 OK +Date: Wed, 17 Feb 2021 08:04:06 GMT +Content-Type: application/ld+json; charset=utf-8 +Content-Length: 11716 +Connection: keep-alive +Set-Cookie: ahSession=06f1bc392b6485385a5ad291337e404c45d21e40;path=/;expires=Sat, 20 Mar 2021 08:04:05 GMT;httpOnly=true; +Access-Control-Allow-Methods: HEAD, GET, POST, DELETE, OPTIONS +Access-Control-Allow-Headers: Authorization, Content-Type +Strict-Transport-Security: max-age=15724800; includeSubDomains +Access-Control-Allow-Credentials: true +X-Frame-Options: deny +X-XSS-Protection: 1; mode=block +X-Content-Type-Options: nosniff +Referrer-Policy: same-origin +Feature-Policy: microphone 'none'; camera 'none'; payment 'none' +Content-Security-Policy: default-src 'self'; script-src 'self' 'sha256-xfTbtWk8kVI65iLJs8LB3lWf2g0g10DS71pDdoutFHc='; style-src 'self' 'unsafe-inline' https://stackpath.bootstrapcdn.com; img-src 'self' data: blob: * +Access-Control-Allow-Origin: https://cdb.thuecat.org + +{"@context":{"schema":"http://schema.org/","dbo":"http://dbpedia.org/ontology/","dsv":"http://ontologies.sti-innsbruck.at/dsv/","foaf":"http://xmlns.com/foaf/0.1/","owl":"http://www.w3.org/2002/07/owl#","rdf":"http://www.w3.org/1999/02/22-rdf-syntax-ns#","rdfs":"http://www.w3.org/2000/01/rdf-schema#","sh":"http://www.w3.org/ns/shacl#","xsd":"http://www.w3.org/2001/XMLSchema#","ttgds":"https://thuecat.org/ontology/ttgds/1.0/","cdb":"https://thuecat.org/ontology/cdb/1.0/","dachkg":"https://thuecat.org/ontology/dachkg/1.0/","thuecat":"https://thuecat.org/ontology/thuecat/1.0/","epapp":"https://thuecat.org/ontology/epapp/1.0/"},"@graph":[{"@id":"https://thuecat.org/resources/497839263245-edbm","@type":["schema:Place","schema:Organization","schema:LocalBusiness","schema:Thing","schema:TouristAttraction","ttgds:OtherInfraStructure","thuecat:OtherPOI","thuecat:StrollingMile"],"schema:description":[{"@language":"de","@value":"Die Waagegasse mag zunächst unspektakulär erscheinen, ist aber eine bemerkenswert alte und für die Erfurter Geschichte sehr bedeutsame Straße. Denn hier wurden sämtliche Händler, die Erfurt passieren und/oder in Erfurt handeln wollten, durchgeführt. Die Straße ist genauso breit wie ein Fuhrwerk, sodass jeder einzeln durchgeschleust werden konnte. Jede Kutsche wurde hier gewogen, je nach Wert Steuern erhoben und die Ware wurde drei Tage in den heute noch sichtbaren Stapelhäusern gelagert.\nHeute spielt die Waagegasse vor allem als \"Schleichweg\" zwischen Michaelis- und Allerheiligenstraße, als Zugang zur Alten Synagoge und natürlich bei zahlreichen Stadtführungen eine Rolle."},{"@language":"fr","@value":"La Waagegasse peut sembler peu spectaculaire au premier abord, mais il s'agit d'une rue remarquablement ancienne et très importante pour l'histoire d'Erfurt. En effet, tous les marchands qui voulaient passer par Erfurt et/ou faire du commerce à Erfurt passaient par ici. La rue est aussi large qu'un carrosse, de sorte que l'on pouvait faire passer chacun d'eux individuellement. Chaque chariot était pesé ici, des taxes étaient prélevées en fonction de sa valeur et les marchandises étaient stockées pendant trois jours dans les maisons d'empilage qui sont encore visibles aujourd'hui.\nAujourd'hui, la Waagegasse joue surtout un rôle de \"chemin de traverse\" entre la Michaelisstrasse et l'Allerheiligenstrasse, d'accès à l'ancienne synagogue et, bien sûr, dans de nombreuses visites de la ville."},{"@language":"en","@value":"The Waagegasse may seem unspectacular at first, but it is a remarkably old and very significant street for Erfurt's history. This is because all merchants who wanted to pass through Erfurt and/or trade in Erfurt passed through here. The street is as wide as a carriage, so that each one could be passed through individually. Each carriage was weighed here, taxes were levied according to its value and the goods were stored for three days in the stacking houses that are still visible today.\nToday, the Waagegasse plays a role primarily as a \"sneak path\" between Michaelisstrasse and Allerheiligenstrasse, as access to the Old Synagogue and, of course, on numerous city tours."},{"@id":"genid-4205641db5894928b636fbc984941a62-b1","@type":["schema:Intangible","schema:Thing","schema:ComputerLanguage","thuecat:Html"],"schema:value":{"@language":"de","@value":"

Die Waagegasse mag zunächst unspektakulär erscheinen, ist aber eine bemerkenswert alte und für die Erfurter Geschichte sehr bedeutsame Straße. Denn hier wurden sämtliche Händler, die Erfurt passieren und/oder in Erfurt handeln wollten, durchgeführt. Die Straße ist genauso breit wie ein Fuhrwerk, sodass jeder einzeln durchgeschleust werden konnte. Jede Kutsche wurde hier gewogen, je nach Wert Steuern erhoben und die Ware wurde drei Tage in den heute noch sichtbaren Stapelhäusern gelagert.

Heute spielt die Waagegasse vor allem als \"Schleichweg\" zwischen Michaelis- und Allerheiligenstraße, als Zugang zur Alten Synagoge und natürlich bei zahlreichen Stadtführungen eine Rolle.

"}},{"@id":"genid-4205641db5894928b636fbc984941a62-b2","@type":["schema:Intangible","schema:Thing","schema:ComputerLanguage","thuecat:Html"],"schema:value":{"@language":"en","@value":"

The Waagegasse may seem unspectacular at first, but it is a remarkably old and very significant street for Erfurt's history. This is because all merchants who wanted to pass through Erfurt and/or trade in Erfurt passed through here. The street is as wide as a carriage, so that each one could be passed through individually. Each carriage was weighed here, taxes were levied according to its value and the goods were stored for three days in the stacking houses that are still visible today.

Today, the Waagegasse plays a role primarily as a \"sneak path\" between Michaelisstrasse and Allerheiligenstrasse, as access to the Old Synagogue and, of course, on numerous city tours.

"}},{"@id":"genid-4205641db5894928b636fbc984941a62-b3","@type":["schema:Intangible","schema:Thing","schema:ComputerLanguage","thuecat:Html"],"schema:value":{"@language":"fr","@value":"

La Waagegasse peut sembler peu spectaculaire au premier abord, mais il s'agit d'une rue remarquablement ancienne et très importante pour l'histoire d'Erfurt. En effet, tous les marchands qui voulaient passer par Erfurt et/ou faire du commerce à Erfurt passaient par ici. La rue est aussi large qu'un carrosse, de sorte que l'on pouvait faire passer chacun d'eux individuellement. Chaque chariot était pesé ici, des taxes étaient prélevées en fonction de sa valeur et les marchandises étaient stockées pendant trois jours dans les maisons d'empilage qui sont encore visibles aujourd'hui.

Aujourd'hui, la Waagegasse joue surtout un rôle de \"chemin de traverse\" entre la Michaelisstrasse et l'Allerheiligenstrasse, d'accès à l'ancienne synagogue et, bien sûr, dans de nombreuses visites de la ville.

"}}],"schema:name":{"@language":"de","@value":"Waagegasse Erfurt"},"schema:containedInPlace":{"@id":"https://thuecat.org/resources/043064193523-jcyt"},"schema:containsPlace":{"@id":"https://thuecat.org/resources/165868194223-zmqf"},"schema:photo":{"@id":"https://thuecat.org/resources/dms_5319686"},"schema:image":[{"@id":"https://thuecat.org/resources/dms_653435"},{"@id":"https://thuecat.org/resources/dms_653458"},{"@id":"https://thuecat.org/resources/dms_653546"},{"@id":"https://thuecat.org/resources/dms_653571"},{"@id":"https://thuecat.org/resources/dms_5319657"},{"@id":"https://thuecat.org/resources/dms_5319686"}],"schema:audience":[{"@id":"https://thuecat.org/resources/290287712606-zkwq"},{"@id":"https://thuecat.org/resources/312868368592-wnce"},{"@id":"https://thuecat.org/resources/301753337945-akzy"},{"@id":"https://thuecat.org/resources/304061111979-rmed"}],"schema:petsAllowed":{"@type":"schema:Boolean","@value":"true"},"schema:hasMap":{"@type":"schema:URL","@value":"https://www.google.de/maps/@50.9787007,11.0277439,21z"},"schema:geo":{"@id":"genid-4205641db5894928b636fbc984941a62-b4","@type":["schema:Intangible","schema:StructuredValue","schema:Thing","schema:GeoCoordinates"],"schema:longitude":{"@type":"schema:Number","@value":"11.027608736826844"},"schema:latitude":{"@type":"schema:Number","@value":"50.97868297541305"}},"schema:smokingAllowed":{"@type":"schema:Boolean","@value":"true"},"schema:address":{"@id":"genid-4205641db5894928b636fbc984941a62-b0","@type":["schema:Intangible","schema:PostalAddress","schema:StructuredValue","schema:Thing","schema:ContactPoint"],"schema:addressLocality":{"@language":"de","@value":"Erfurt"},"schema:addressCountry":{"@type":"thuecat:AddressCountry","@value":"thuecat:Germany"},"schema:postalCode":{"@language":"de","@value":"99084"},"schema:addressRegion":{"@type":"thuecat:AddressFederalState","@value":"thuecat:Thuringia"},"schema:streetAddress":{"@language":"de","@value":"Waagegasse"},"thuecat:typOfAddress":{"@type":"thuecat:TypOfAddress","@value":"thuecat:HouseAddress"}},"thuecat:contentResponsible":{"@id":"https://thuecat.org/resources/018132452787-ngbe"},"thuecat:gastro":[{"@type":"thuecat:GastroPoi","@value":"thuecat:BarEnumMem"},{"@type":"thuecat:GastroPoi","@value":"thuecat:Restaurant"}],"thuecat:sanitation":{"@type":"thuecat:Sanitation","@value":"thuecat:ZeroSanitation"}}]} diff --git a/Tests/Functional/Fixtures/Import/Guzzle/thuecat.org/resources/508431710173-wwne/GET_8a1f3581a2447dd37e646da1707ad9e7.txt b/Tests/Functional/Fixtures/Import/Guzzle/thuecat.org/resources/508431710173-wwne/GET_8a1f3581a2447dd37e646da1707ad9e7.txt new file mode 100644 index 0000000..b5b2b51 --- /dev/null +++ b/Tests/Functional/Fixtures/Import/Guzzle/thuecat.org/resources/508431710173-wwne/GET_8a1f3581a2447dd37e646da1707ad9e7.txt @@ -0,0 +1,19 @@ +HTTP/1.1 200 OK +Date: Wed, 17 Feb 2021 08:04:06 GMT +Content-Type: application/ld+json; charset=utf-8 +Content-Length: 11716 +Connection: keep-alive +Set-Cookie: ahSession=06f1bc392b6485385a5ad291337e404c45d21e40;path=/;expires=Sat, 20 Mar 2021 08:04:05 GMT;httpOnly=true; +Access-Control-Allow-Methods: HEAD, GET, POST, DELETE, OPTIONS +Access-Control-Allow-Headers: Authorization, Content-Type +Strict-Transport-Security: max-age=15724800; includeSubDomains +Access-Control-Allow-Credentials: true +X-Frame-Options: deny +X-XSS-Protection: 1; mode=block +X-Content-Type-Options: nosniff +Referrer-Policy: same-origin +Feature-Policy: microphone 'none'; camera 'none'; payment 'none' +Content-Security-Policy: default-src 'self'; script-src 'self' 'sha256-xfTbtWk8kVI65iLJs8LB3lWf2g0g10DS71pDdoutFHc='; style-src 'self' 'unsafe-inline' https://stackpath.bootstrapcdn.com; img-src 'self' data: blob: * +Access-Control-Allow-Origin: https://cdb.thuecat.org + +{"@context":{"schema":"http://schema.org/","dbo":"http://dbpedia.org/ontology/","dsv":"http://ontologies.sti-innsbruck.at/dsv/","foaf":"http://xmlns.com/foaf/0.1/","owl":"http://www.w3.org/2002/07/owl#","rdf":"http://www.w3.org/1999/02/22-rdf-syntax-ns#","rdfs":"http://www.w3.org/2000/01/rdf-schema#","sh":"http://www.w3.org/ns/shacl#","xsd":"http://www.w3.org/2001/XMLSchema#","ttgds":"https://thuecat.org/ontology/ttgds/1.0/","cdb":"https://thuecat.org/ontology/cdb/1.0/","dachkg":"https://thuecat.org/ontology/dachkg/1.0/","thuecat":"https://thuecat.org/ontology/thuecat/1.0/","epapp":"https://thuecat.org/ontology/epapp/1.0/"},"@graph":[{"@id":"https://thuecat.org/resources/508431710173-wwne","@type":["schema:Place","schema:Organization","schema:LocalBusiness","schema:Thing","schema:TouristAttraction","ttgds:OtherInfraStructure","thuecat:OtherPOI","thuecat:StrollingMile"],"schema:description":[{"@language":"de","@value":"Der Domplatz ist der wohl bekannteste Platz Erfurts, nicht zuletzt wegen des imposanten Ensembles aus dem Dom St. Marien und der St. Severikirche. Am Fuße des Petersbergs und am Rand der Altstadt gelegen, bietet er viel Platz für allerlei Feste und Veranstaltungen. \nMontag bis Samstag findet hier außerdem der Wochenmarkt statt.\nIm Osten und im Süden des Domplatzes laden eine Vielzahl Cafés und Restaurants zum Verweilen und Genießen ein."},{"@language":"fr","@value":"Avec pour toile de fond l’imposante cathédrale Notre-Dame et l’église Saint-Sévère, la place de la cathédrale vous attire avec ses charmants petits magasins et un large choix en terme de gastronomie.\nDes marchands de la région vous proposent chaque jour, de 7 à 14h, des produits frais comme des fruits et légumes, de la viande et des saucisses ainsi que de nombreuses gourmandises.\n"},{"@language":"en","@value":"Domplatz square is only a few seconds' walk from Kettenstrasse. Set against the majestic backdrop of the cathedral and the Church of St Severus, it boasts a host of attractive boutiques and a variety of restaurants and cafés. The square's daily market, which operates from 7am until 2pm sells fresh regional produce including fruit and vegetables, meat and sausage products and many other tasty treats.\nFrom Domplatz square, Marktstrasse - which follows the centuries-old trading route the Via Regia - leads you back towards the city centre."},{"@id":"genid-443f86d2acdc469dad4b3588d31d0c49-b1","@type":["schema:Intangible","schema:Thing","schema:ComputerLanguage","thuecat:Html"],"schema:value":{"@language":"de","@value":"

Der Domplatz ist der wohl bekannteste Platz Erfurts, nicht zuletzt wegen des imposanten Ensembles aus dem Dom St. Marien und der St. Severikirche. Am Fuße des Petersbergs und am Rand der Altstadt gelegen, bietet er viel Platz für allerlei Feste und Veranstaltungen.

Montag bis Samstag findet hier außerdem der Wochenmarkt statt.

Im Osten und im Süden des Domplatzes laden eine Vielzahl Cafés und Restaurants zum Verweilen und Genießen ein.

"}},{"@id":"genid-443f86d2acdc469dad4b3588d31d0c49-b2","@type":["schema:Intangible","schema:Thing","schema:ComputerLanguage","thuecat:Html"],"schema:value":{"@language":"fr","@value":"

Avec pour toile de fond l’imposante cathédrale Notre-Dame et l’église Saint-Sévère, la place de la cathédrale vous attire avec ses charmants petits magasins et un large choix en terme de gastronomie.

Des marchands de la région vous proposent chaque jour, de 7 à 14h, des produits frais comme des fruits et légumes, de la viande et des saucisses ainsi que de nombreuses gourmandises.

"}},{"@id":"genid-443f86d2acdc469dad4b3588d31d0c49-b3","@type":["schema:Intangible","schema:Thing","schema:ComputerLanguage","thuecat:Html"],"schema:value":{"@language":"en","@value":"

Domplatz square is only a few seconds' walk from Kettenstrasse. Set against the majestic backdrop of the cathedral and the Church of St Severus, it boasts a host of attractive boutiques and a variety of restaurants and cafés. The square's daily market, which operates from 7am until 2pm sells fresh regional produce including fruit and vegetables, meat and sausage products and many other tasty treats.

From Domplatz square, Marktstrasse - which follows the centuries-old trading route the Via Regia - leads you back towards the city centre.

"}}],"schema:name":[{"@language":"de","@value":"Domplatz Erfurt"},{"@language":"fr","@value":"Place de la cathédrale et rue commerçante"},{"@language":"en","@value":"Domplatz (Cathedral Square)"}],"schema:containedInPlace":{"@id":"https://thuecat.org/resources/043064193523-jcyt"},"schema:containsPlace":[{"@id":"https://thuecat.org/resources/396420044896-drzt"},{"@id":"https://thuecat.org/resources/835224016581-dara"},{"@id":"https://thuecat.org/resources/363938447400-ammb"},{"@id":"https://thuecat.org/resources/146945912069-xkhb"},{"@id":"https://thuecat.org/resources/772412525329-tjkf"},{"@id":"https://thuecat.org/resources/056407295912-gtoa"},{"@id":"https://thuecat.org/resources/173676937638-bjpa"},{"@id":"https://thuecat.org/resources/133118786105-nhtp"}],"schema:photo":{"@id":"https://thuecat.org/resources/dms_5319718"},"schema:image":[{"@id":"https://thuecat.org/resources/dms_5122508"},{"@id":"https://thuecat.org/resources/dms_5319718"},{"@id":"https://thuecat.org/resources/dms_5319755"},{"@id":"https://thuecat.org/resources/dms_5319964"}],"schema:petsAllowed":{"@type":"schema:Boolean","@value":"true"},"schema:hasMap":{"@type":"schema:URL","@value":"https://www.google.de/maps/@50.9767896,11.023818,18.25z"},"schema:geo":{"@id":"genid-443f86d2acdc469dad4b3588d31d0c49-b4","@type":["schema:Intangible","schema:StructuredValue","schema:Thing","schema:GeoCoordinates"],"schema:longitude":{"@type":"schema:Number","@value":"11.023886024076779"},"schema:latitude":{"@type":"schema:Number","@value":"50.97694183291915"}},"schema:smokingAllowed":{"@type":"schema:Boolean","@value":"true"},"schema:paymentAccepted":{"@language":"de","@value":"Unterscheidet sich je nach Geschäft."},"schema:address":{"@id":"genid-443f86d2acdc469dad4b3588d31d0c49-b0","@type":["schema:Intangible","schema:PostalAddress","schema:StructuredValue","schema:Thing","schema:ContactPoint"],"schema:addressLocality":{"@language":"de","@value":"Erfurt"},"schema:addressCountry":{"@type":"thuecat:AddressCountry","@value":"thuecat:Germany"},"schema:postalCode":{"@language":"de","@value":"99084"},"schema:addressRegion":{"@type":"thuecat:AddressFederalState","@value":"thuecat:Thuringia"},"schema:streetAddress":{"@language":"de","@value":"Domplatz"},"thuecat:typOfAddress":{"@type":"thuecat:TypOfAddress","@value":"thuecat:HouseAddress"}},"thuecat:contentResponsible":{"@id":"https://thuecat.org/resources/018132452787-ngbe"},"thuecat:gastro":[{"@type":"thuecat:GastroPoi","@value":"thuecat:TakeawayShop"},{"@type":"thuecat:GastroPoi","@value":"thuecat:Cafe"},{"@type":"thuecat:GastroPoi","@value":"thuecat:BarEnumMem"},{"@type":"thuecat:GastroPoi","@value":"thuecat:Restaurant"}],"thuecat:sanitation":{"@type":"thuecat:Sanitation","@value":"thuecat:Toilets"}}]} diff --git a/Tests/Functional/Fixtures/Import/Guzzle/thuecat.org/resources/573211638937-gmqb/GET_54e220a05e132d4644a58f33c065152d.txt b/Tests/Functional/Fixtures/Import/Guzzle/thuecat.org/resources/573211638937-gmqb/GET_54e220a05e132d4644a58f33c065152d.txt new file mode 100644 index 0000000..55b2693 --- /dev/null +++ b/Tests/Functional/Fixtures/Import/Guzzle/thuecat.org/resources/573211638937-gmqb/GET_54e220a05e132d4644a58f33c065152d.txt @@ -0,0 +1,19 @@ +HTTP/1.1 200 OK +Date: Wed, 17 Feb 2021 08:04:06 GMT +Content-Type: application/ld+json; charset=utf-8 +Content-Length: 11716 +Connection: keep-alive +Set-Cookie: ahSession=06f1bc392b6485385a5ad291337e404c45d21e40;path=/;expires=Sat, 20 Mar 2021 08:04:05 GMT;httpOnly=true; +Access-Control-Allow-Methods: HEAD, GET, POST, DELETE, OPTIONS +Access-Control-Allow-Headers: Authorization, Content-Type +Strict-Transport-Security: max-age=15724800; includeSubDomains +Access-Control-Allow-Credentials: true +X-Frame-Options: deny +X-XSS-Protection: 1; mode=block +X-Content-Type-Options: nosniff +Referrer-Policy: same-origin +Feature-Policy: microphone 'none'; camera 'none'; payment 'none' +Content-Security-Policy: default-src 'self'; script-src 'self' 'sha256-xfTbtWk8kVI65iLJs8LB3lWf2g0g10DS71pDdoutFHc='; style-src 'self' 'unsafe-inline' https://stackpath.bootstrapcdn.com; img-src 'self' data: blob: * +Access-Control-Allow-Origin: https://cdb.thuecat.org + +{"@context":{"schema":"http://schema.org/","dbo":"http://dbpedia.org/ontology/","dsv":"http://ontologies.sti-innsbruck.at/dsv/","foaf":"http://xmlns.com/foaf/0.1/","owl":"http://www.w3.org/2002/07/owl#","rdf":"http://www.w3.org/1999/02/22-rdf-syntax-ns#","rdfs":"http://www.w3.org/2000/01/rdf-schema#","sh":"http://www.w3.org/ns/shacl#","xsd":"http://www.w3.org/2001/XMLSchema#","ttgds":"https://thuecat.org/ontology/ttgds/1.0/","cdb":"https://thuecat.org/ontology/cdb/1.0/","dachkg":"https://thuecat.org/ontology/dachkg/1.0/","thuecat":"https://thuecat.org/ontology/thuecat/1.0/","epapp":"https://thuecat.org/ontology/epapp/1.0/"},"@graph":[{"@id":"https://thuecat.org/resources/573211638937-gmqb","@type":[],"schema:containsPlace":[{"@id":"https://thuecat.org/resources/932209179057-xqhd"},{"@id":"https://thuecat.org/resources/427978371125-hekp"}]}]} diff --git a/Tests/Functional/Fixtures/Import/Guzzle/thuecat.org/resources/dms_5197164/GET_84507add0ca543b4283a096d965d6b32.txt b/Tests/Functional/Fixtures/Import/Guzzle/thuecat.org/resources/dms_5197164/GET_84507add0ca543b4283a096d965d6b32.txt new file mode 100644 index 0000000..c643c70 --- /dev/null +++ b/Tests/Functional/Fixtures/Import/Guzzle/thuecat.org/resources/dms_5197164/GET_84507add0ca543b4283a096d965d6b32.txt @@ -0,0 +1,19 @@ +HTTP/1.1 200 OK +Date: Wed, 17 Feb 2021 08:04:06 GMT +Content-Type: application/ld+json; charset=utf-8 +Content-Length: 6991 +Connection: keep-alive +Set-Cookie: ahSession=40427ff59a969316c84fe78d7f913ec95d073d11;path=/;expires=Sat, 20 Mar 2021 08:04:06 GMT;httpOnly=true; +Access-Control-Allow-Methods: HEAD, GET, POST, DELETE, OPTIONS +Access-Control-Allow-Headers: Authorization, Content-Type +Strict-Transport-Security: max-age=15724800; includeSubDomains +Access-Control-Allow-Credentials: true +X-Frame-Options: deny +X-XSS-Protection: 1; mode=block +X-Content-Type-Options: nosniff +Referrer-Policy: same-origin +Feature-Policy: microphone 'none'; camera 'none'; payment 'none' +Content-Security-Policy: default-src 'self'; script-src 'self' 'sha256-xfTbtWk8kVI65iLJs8LB3lWf2g0g10DS71pDdoutFHc='; style-src 'self' 'unsafe-inline' https://stackpath.bootstrapcdn.com; img-src 'self' data: blob: * +Access-Control-Allow-Origin: https://cdb.thuecat.org + +{"@context":{"schema":"http://schema.org/","dbo":"http://dbpedia.org/ontology/","dsv":"http://ontologies.sti-innsbruck.at/dsv/","foaf":"http://xmlns.com/foaf/0.1/","owl":"http://www.w3.org/2002/07/owl#","rdf":"http://www.w3.org/1999/02/22-rdf-syntax-ns#","rdfs":"http://www.w3.org/2000/01/rdf-schema#","sh":"http://www.w3.org/ns/shacl#","xsd":"http://www.w3.org/2001/XMLSchema#","ttgds":"https://thuecat.org/ontology/ttgds/1.0/","cdb":"https://thuecat.org/ontology/cdb/1.0/","dachkg":"https://thuecat.org/ontology/dachkg/1.0/","thuecat":"https://thuecat.org/ontology/thuecat/1.0/","epapp":"https://thuecat.org/ontology/epapp/1.0/"},"@graph":[{"@id":"https://thuecat.org/resources/dms_5197164","@type":["schema:CreativeWork","schema:MediaObject","schema:Thing","schema:ImageObject","http://purl.org/dc/dcmitype/Image"],"schema:width":{"@type":"xsd:string","@value":"5621"},"schema:description":{"@language":"de","@value":"Straßenansicht des Parkhauses Q-Park am Kaufhaus Anger 1, schräg über den Juri-Gagarin-Ring"},"schema:sameAs":{"@type":"xsd:anyURI","@value":"https://wbk.thuecat.org"},"schema:identifier":{"@type":"schema:PropertyValue","@value":"5197164"},"schema:keywords":[{"@type":"xsd:string","@value":"Tag"},{"@type":"xsd:string","@value":"Gebäude / Architektur"},{"@type":"xsd:string","@value":"Vorder- / Frontallicht"},{"@type":"xsd:string","@value":"Seitenperspektive"},{"@type":"xsd:string","@value":"Erfurt"},{"@type":"xsd:string","@value":"Weitere Infrastruktur"},{"@type":"xsd:string","@value":"parken"},{"@type":"xsd:string","@value":"parkmoeglichkeit"}],"schema:name":{"@language":"de","@value":"Q-Park-Parkhaus-Anger1-Juri-Gagarin-Ring.JPG"},"schema:copyrightYear":{"@language":"de","@value":"2020"},"schema:height":{"@type":"xsd:string","@value":"3542"},"schema:copyrightHolder":{"@id":"https://thuecat.org/resources/018132452787-ngbe"},"schema:bitrate":{"@type":"xsd:string","@value":"8"},"schema:contentLocation":{"@id":"https://thuecat.org/resources/440055527204-ocar"},"schema:exifData":[{"@id":"genid-f77f9c8eeeda441687da6e30798e2a54-b0","@type":["schema:Intangible","schema:StructuredValue","schema:Thing","schema:PropertyValue"],"schema:name":{"@type":"xsd:string","@value":"tiff:Model"},"schema:value":{"@type":"xsd:string","@value":"ILCE-6000"}},{"@id":"genid-f77f9c8eeeda441687da6e30798e2a54-b1","@type":["schema:Intangible","schema:StructuredValue","schema:Thing","schema:PropertyValue"],"schema:name":{"@type":"xsd:string","@value":"exif:ExposureTime"},"schema:value":{"@type":"xsd:string","@value":"0.00625"}},{"@id":"genid-f77f9c8eeeda441687da6e30798e2a54-b10","@type":["schema:Intangible","schema:StructuredValue","schema:Thing","schema:PropertyValue"],"schema:name":{"@type":"xsd:string","@value":"tiff:SamplesPerPixel"},"schema:value":{"@type":"xsd:string","@value":"3"}},{"@id":"genid-f77f9c8eeeda441687da6e30798e2a54-b11","@type":["schema:Intangible","schema:StructuredValue","schema:Thing","schema:PropertyValue"],"schema:name":{"@type":"xsd:string","@value":"exif:IsoSpeedRatings"},"schema:value":{"@type":"xsd:string","@value":"100"}},{"@id":"genid-f77f9c8eeeda441687da6e30798e2a54-b12","@type":["schema:Intangible","schema:StructuredValue","schema:Thing","schema:PropertyValue"],"schema:name":{"@type":"xsd:string","@value":"tiff:YResolution"},"schema:value":{"@type":"xsd:string","@value":"350.0"}},{"@id":"genid-f77f9c8eeeda441687da6e30798e2a54-b13","@type":["schema:Intangible","schema:StructuredValue","schema:Thing","schema:PropertyValue"],"schema:name":{"@type":"xsd:string","@value":"tiff:Make"},"schema:value":{"@type":"xsd:string","@value":"SONY"}},{"@id":"genid-f77f9c8eeeda441687da6e30798e2a54-b2","@type":["schema:Intangible","schema:StructuredValue","schema:Thing","schema:PropertyValue"],"schema:name":{"@type":"xsd:string","@value":"exif:Flash"},"schema:value":{"@type":"xsd:string","@value":"false"}},{"@id":"genid-f77f9c8eeeda441687da6e30798e2a54-b3","@type":["schema:Intangible","schema:StructuredValue","schema:Thing","schema:PropertyValue"],"schema:name":{"@type":"xsd:string","@value":"exif:FocalLength"},"schema:value":{"@type":"xsd:string","@value":"16.0"}},{"@id":"genid-f77f9c8eeeda441687da6e30798e2a54-b4","@type":["schema:Intangible","schema:StructuredValue","schema:Thing","schema:PropertyValue"],"schema:name":{"@type":"xsd:string","@value":"exif:FNumber"},"schema:value":{"@type":"xsd:string","@value":"11.0"}},{"@id":"genid-f77f9c8eeeda441687da6e30798e2a54-b5","@type":["schema:Intangible","schema:StructuredValue","schema:Thing","schema:PropertyValue"],"schema:name":{"@type":"xsd:string","@value":"exif:DateTimeOriginal"},"schema:value":{"@type":"xsd:string","@value":"2016-04-17T23:30:49"}},{"@id":"genid-f77f9c8eeeda441687da6e30798e2a54-b6","@type":["schema:Intangible","schema:StructuredValue","schema:Thing","schema:PropertyValue"],"schema:name":{"@type":"xsd:string","@value":"tiff:XResolution"},"schema:value":{"@type":"xsd:string","@value":"350.0"}},{"@id":"genid-f77f9c8eeeda441687da6e30798e2a54-b7","@type":["schema:Intangible","schema:StructuredValue","schema:Thing","schema:PropertyValue"],"schema:name":{"@type":"xsd:string","@value":"tiff:Software"},"schema:value":{"@type":"xsd:string","@value":"GIMP 2.10.22"}},{"@id":"genid-f77f9c8eeeda441687da6e30798e2a54-b8","@type":["schema:Intangible","schema:StructuredValue","schema:Thing","schema:PropertyValue"],"schema:name":{"@type":"xsd:string","@value":"tiff:Orientation"},"schema:value":{"@type":"xsd:string","@value":"1"}},{"@id":"genid-f77f9c8eeeda441687da6e30798e2a54-b9","@type":["schema:Intangible","schema:StructuredValue","schema:Thing","schema:PropertyValue"],"schema:name":{"@type":"xsd:string","@value":"tiff:ResolutionUnit"},"schema:value":{"@type":"xsd:string","@value":"Inch"}}],"schema:author":{"@id":"https://thuecat.org/resources/018132452787-ngbe"},"schema:thumbnailUrl":{"@type":"xsd:string","@value":"https://cms.thuecat.org/o/adaptive-media/image/5197164/Thumbnail-300x300/image"},"schema:url":{"@type":"xsd:anyURI","@value":"https://cms.thuecat.org/o/adaptive-media/image/5197164/Preview-1280x0/image"},"schema:license":{"@language":"de","@value":"https://creativecommons.org/licenses/by/4.0/"},"thuecat:licenseAuthor":{"@language":"de","@value":""},"thuecat:licenseLocation":{"@language":"de","@value":""},"thuecat:licensePeriod":{"@language":"de","@value":""},"thuecat:licensePerson":{"@language":"de","@value":""}}]} diff --git a/Tests/Functional/Fixtures/Import/Guzzle/thuecat.org/resources/dms_6486108/GET_b54332e6fc5338f57621cba67faf4fd4.txt b/Tests/Functional/Fixtures/Import/Guzzle/thuecat.org/resources/dms_6486108/GET_b54332e6fc5338f57621cba67faf4fd4.txt new file mode 100644 index 0000000..84c4222 --- /dev/null +++ b/Tests/Functional/Fixtures/Import/Guzzle/thuecat.org/resources/dms_6486108/GET_b54332e6fc5338f57621cba67faf4fd4.txt @@ -0,0 +1,19 @@ +HTTP/1.1 200 OK +Date: Wed, 17 Feb 2021 08:04:06 GMT +Content-Type: application/ld+json; charset=utf-8 +Content-Length: 6991 +Connection: keep-alive +Set-Cookie: ahSession=40427ff59a969316c84fe78d7f913ec95d073d11;path=/;expires=Sat, 20 Mar 2021 08:04:06 GMT;httpOnly=true; +Access-Control-Allow-Methods: HEAD, GET, POST, DELETE, OPTIONS +Access-Control-Allow-Headers: Authorization, Content-Type +Strict-Transport-Security: max-age=15724800; includeSubDomains +Access-Control-Allow-Credentials: true +X-Frame-Options: deny +X-XSS-Protection: 1; mode=block +X-Content-Type-Options: nosniff +Referrer-Policy: same-origin +Feature-Policy: microphone 'none'; camera 'none'; payment 'none' +Content-Security-Policy: default-src 'self'; script-src 'self' 'sha256-xfTbtWk8kVI65iLJs8LB3lWf2g0g10DS71pDdoutFHc='; style-src 'self' 'unsafe-inline' https://stackpath.bootstrapcdn.com; img-src 'self' data: blob: * +Access-Control-Allow-Origin: https://cdb.thuecat.org + +{"@context":{"schema":"http://schema.org/","dbo":"http://dbpedia.org/ontology/","dsv":"http://ontologies.sti-innsbruck.at/dsv/","foaf":"http://xmlns.com/foaf/0.1/","owl":"http://www.w3.org/2002/07/owl#","rdf":"http://www.w3.org/1999/02/22-rdf-syntax-ns#","rdfs":"http://www.w3.org/2000/01/rdf-schema#","sh":"http://www.w3.org/ns/shacl#","xsd":"http://www.w3.org/2001/XMLSchema#","ttgds":"https://thuecat.org/ontology/ttgds/1.0/","cdb":"https://thuecat.org/ontology/cdb/1.0/","dachkg":"https://thuecat.org/ontology/dachkg/1.0/","thuecat":"https://thuecat.org/ontology/thuecat/1.0/","epapp":"https://thuecat.org/ontology/epapp/1.0/"},"@graph":[{"@id":"https://thuecat.org/resources/dms_6486108","@type":["schema:CreativeWork","schema:MediaObject","schema:Thing","schema:ImageObject","http://purl.org/dc/dcmitype/Image"],"schema:width":{"@type":"xsd:string","@value":"3648"},"schema:sameAs":{"@type":"xsd:anyURI","@value":"https://wbk.thuecat.org"},"schema:identifier":{"@type":"schema:PropertyValue","@value":"6486108"},"schema:keywords":[{"@type":"xsd:string","@value":"Tag"},{"@type":"xsd:string","@value":"Sommer"},{"@type":"xsd:string","@value":"Vorder- / Frontallicht"},{"@type":"xsd:string","@value":"Seitenperspektive"},{"@type":"xsd:string","@value":"Erfurt"},{"@type":"xsd:string","@value":"Weitere Infrastruktur"}],"schema:name":{"@language":"de","@value":"Erfurt-Parkhaus-Domplatz.jpg"},"schema:copyrightYear":{"@language":"de","@value":"2021"},"schema:height":{"@type":"xsd:string","@value":"2736"},"schema:copyrightHolder":{"@id":"https://thuecat.org/resources/018132452787-ngbe"},"schema:bitrate":{"@type":"xsd:string","@value":"8"},"schema:contentLocation":{"@id":"https://thuecat.org/resources/396420044896-drzt"},"schema:exifData":[{"@id":"genid-a253d47fa93342acb1b5f8da18de63b5-b0","@type":["schema:Intangible","schema:StructuredValue","schema:Thing","schema:PropertyValue"],"schema:name":{"@type":"xsd:string","@value":"tiff:Model"},"schema:value":{"@type":"xsd:string","@value":"DMC-FZ28"}},{"@id":"genid-a253d47fa93342acb1b5f8da18de63b5-b1","@type":["schema:Intangible","schema:StructuredValue","schema:Thing","schema:PropertyValue"],"schema:name":{"@type":"xsd:string","@value":"exif:ExposureTime"},"schema:value":{"@type":"xsd:string","@value":"0.002"}},{"@id":"genid-a253d47fa93342acb1b5f8da18de63b5-b10","@type":["schema:Intangible","schema:StructuredValue","schema:Thing","schema:PropertyValue"],"schema:name":{"@type":"xsd:string","@value":"exif:IsoSpeedRatings"},"schema:value":{"@type":"xsd:string","@value":"100"}},{"@id":"genid-a253d47fa93342acb1b5f8da18de63b5-b11","@type":["schema:Intangible","schema:StructuredValue","schema:Thing","schema:PropertyValue"],"schema:name":{"@type":"xsd:string","@value":"tiff:YResolution"},"schema:value":{"@type":"xsd:string","@value":"180.0"}},{"@id":"genid-a253d47fa93342acb1b5f8da18de63b5-b12","@type":["schema:Intangible","schema:StructuredValue","schema:Thing","schema:PropertyValue"],"schema:name":{"@type":"xsd:string","@value":"tiff:Make"},"schema:value":{"@type":"xsd:string","@value":"Panasonic"}},{"@id":"genid-a253d47fa93342acb1b5f8da18de63b5-b2","@type":["schema:Intangible","schema:StructuredValue","schema:Thing","schema:PropertyValue"],"schema:name":{"@type":"xsd:string","@value":"exif:Flash"},"schema:value":{"@type":"xsd:string","@value":"false"}},{"@id":"genid-a253d47fa93342acb1b5f8da18de63b5-b3","@type":["schema:Intangible","schema:StructuredValue","schema:Thing","schema:PropertyValue"],"schema:name":{"@type":"xsd:string","@value":"exif:FocalLength"},"schema:value":{"@type":"xsd:string","@value":"7.3"}},{"@id":"genid-a253d47fa93342acb1b5f8da18de63b5-b4","@type":["schema:Intangible","schema:StructuredValue","schema:Thing","schema:PropertyValue"],"schema:name":{"@type":"xsd:string","@value":"exif:FNumber"},"schema:value":{"@type":"xsd:string","@value":"5.6"}},{"@id":"genid-a253d47fa93342acb1b5f8da18de63b5-b5","@type":["schema:Intangible","schema:StructuredValue","schema:Thing","schema:PropertyValue"],"schema:name":{"@type":"xsd:string","@value":"exif:DateTimeOriginal"},"schema:value":{"@type":"xsd:string","@value":"2021-06-02T12:27:15"}},{"@id":"genid-a253d47fa93342acb1b5f8da18de63b5-b6","@type":["schema:Intangible","schema:StructuredValue","schema:Thing","schema:PropertyValue"],"schema:name":{"@type":"xsd:string","@value":"tiff:XResolution"},"schema:value":{"@type":"xsd:string","@value":"180.0"}},{"@id":"genid-a253d47fa93342acb1b5f8da18de63b5-b7","@type":["schema:Intangible","schema:StructuredValue","schema:Thing","schema:PropertyValue"],"schema:name":{"@type":"xsd:string","@value":"tiff:Software"},"schema:value":{"@type":"xsd:string","@value":"Ver.1.0 "}},{"@id":"genid-a253d47fa93342acb1b5f8da18de63b5-b8","@type":["schema:Intangible","schema:StructuredValue","schema:Thing","schema:PropertyValue"],"schema:name":{"@type":"xsd:string","@value":"tiff:Orientation"},"schema:value":{"@type":"xsd:string","@value":"1"}},{"@id":"genid-a253d47fa93342acb1b5f8da18de63b5-b9","@type":["schema:Intangible","schema:StructuredValue","schema:Thing","schema:PropertyValue"],"schema:name":{"@type":"xsd:string","@value":"tiff:ResolutionUnit"},"schema:value":{"@type":"xsd:string","@value":"Inch"}}],"schema:author":{"@id":"https://thuecat.org/resources/018132452787-ngbe"},"schema:thumbnailUrl":{"@type":"xsd:string","@value":"https://cms.thuecat.org/o/adaptive-media/image/6486108/Thumbnail-300x300/image"},"schema:url":{"@type":"xsd:anyURI","@value":"https://cms.thuecat.org/o/adaptive-media/image/6486108/Preview-1280x0/image"},"schema:license":{"@language":"de","@value":"https://creativecommons.org/licenses/by/4.0/"},"thuecat:licenseAuthor":{"@language":"de","@value":""},"thuecat:licenseLocation":{"@language":"de","@value":""},"thuecat:licensePeriod":{"@language":"de","@value":""},"thuecat:licensePerson":{"@language":"de","@value":""}}]} diff --git a/Tests/Functional/Fixtures/Import/ImportWithMultipleReferencesToSameObject.csv b/Tests/Functional/Fixtures/Import/ImportWithMultipleReferencesToSameObject.csv new file mode 100644 index 0000000..868d981 --- /dev/null +++ b/Tests/Functional/Fixtures/Import/ImportWithMultipleReferencesToSameObject.csv @@ -0,0 +1,33 @@ +"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.xml new file mode 100644 index 0000000..3d5e735 --- /dev/null +++ b/Tests/Functional/Fixtures/Import/ImportWithMultipleReferencesToSameObject.xml @@ -0,0 +1,85 @@ + + + + 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 + Attractions within Town Erfurt + static + + + + + + + 10 + + + + + + + + https://thuecat.org/resources/835224016581-dara + + + + + + + + + https://thuecat.org/resources/165868194223-zmqf + + + + 0 + + + + + + + + ]]> + + diff --git a/Tests/Functional/Fixtures/Import/ImportsSyncScopeResult.csv b/Tests/Functional/Fixtures/Import/ImportsSyncScope.csv similarity index 100% rename from Tests/Functional/Fixtures/Import/ImportsSyncScopeResult.csv rename to Tests/Functional/Fixtures/Import/ImportsSyncScope.csv diff --git a/Tests/Functional/Fixtures/Import/ImportsSyncScope.xml b/Tests/Functional/Fixtures/Import/ImportsSyncScope.xml index 25816f4..dfc6f48 100644 --- a/Tests/Functional/Fixtures/Import/ImportsSyncScope.xml +++ b/Tests/Functional/Fixtures/Import/ImportsSyncScope.xml @@ -74,18 +74,4 @@ 0 Erfurt - - - 1 - 10 - 1613400969 - 1613400969 - 1 - 0 - 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.0 1.1998 die Geschäftstätigkeit auf. - 0 - 0 - diff --git a/Tests/Functional/Fixtures/Import/ImportsTouristAttractionsWithRelations.csv b/Tests/Functional/Fixtures/Import/ImportsTouristAttractionsWithRelations.csv new file mode 100644 index 0000000..f6a5c06 --- /dev/null +++ b/Tests/Functional/Fixtures/Import/ImportsTouristAttractionsWithRelations.csv @@ -0,0 +1,35 @@ +"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","opening_hours","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" +,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"",""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"",""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""]}]",,,"Toilets,DisabledToilets","SeatingPossibilitiesRestArea,SouvenirShop",,"GothicArt","BicycleLockersEnumMem,BusParkCoachParkEnumMem",,"AugmentedReality","Fotogenehmigung für innen","false","true","true","German,English","350:MTR",1 +,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"",""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"",""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""]}]",,,"Toilets,DisabledToilets","SeatingPossibilitiesRestArea,SouvenirShop",,"GothicArt","BicycleLockersEnumMem,BusParkCoachParkEnumMem",,"AugmentedReality",,"false","true","true","German,English","350:MTR",1 +,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}}","[{""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""}]},{""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"",""copyrightYear"":2009,""license"":{""type"":""https:\/\/creativecommons.org\/licenses\/by\/4.0\/"",""author"":""F:\\Bilddatenbank\\Museen und Ausstellungen\\Alte Synagoge""}},{""mainImage"":false,""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"",""copyrightYear"":2009,""license"":{""type"":""https:\/\/creativecommons.org\/licenses\/by\/4.0\/"",""author"":""F:\\Bilddatenbank\\Museen und Ausstellungen\\Alte Synagoge""}}]","[{""opens"":""10:00:00"",""closes"":""18:00:00"",""from"":{""date"":""2021-03-01 00:00:00.000000"",""timezone_type"":3,""timezone"":""UTC""},""through"":{""date"":""2021-12-31 00:00:00.000000"",""timezone_type"":3,""timezone"":""UTC""},""daysOfWeek"":[""Saturday"",""Sunday"",""Friday"",""Thursday"",""Tuesday"",""Wednesday""]}]","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", +,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}}","[{""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""}]},{""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"",""copyrightYear"":2009,""license"":{""type"":""https:\/\/creativecommons.org\/licenses\/by\/4.0\/"",""author"":""F:\\Bilddatenbank\\Museen und Ausstellungen\\Alte Synagoge""}},{""mainImage"":false,""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"",""copyrightYear"":2009,""license"":{""type"":""https:\/\/creativecommons.org\/licenses\/by\/4.0\/"",""author"":""F:\\Bilddatenbank\\Museen und Ausstellungen\\Alte Synagoge""}}]","[{""opens"":""10:00:00"",""closes"":""18:00:00"",""from"":{""date"":""2021-03-01 00:00:00.000000"",""timezone_type"":3,""timezone"":""UTC""},""through"":{""date"":""2021-12-31 00:00:00.000000"",""timezone_type"":3,""timezone"":""UTC""},""daysOfWeek"":[""Saturday"",""Sunday"",""Friday"",""Thursday"",""Tuesday"",""Wednesday""]}]","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", +,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}}","[{""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""}]},{""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"",""copyrightYear"":2009,""license"":{""type"":""https:\/\/creativecommons.org\/licenses\/by\/4.0\/"",""author"":""F:\\Bilddatenbank\\Museen und Ausstellungen\\Alte Synagoge""}},{""mainImage"":false,""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"",""copyrightYear"":2009,""license"":{""type"":""https:\/\/creativecommons.org\/licenses\/by\/4.0\/"",""author"":""F:\\Bilddatenbank\\Museen und Ausstellungen\\Alte Synagoge""}}]","[{""opens"":""10:00:00"",""closes"":""18:00:00"",""from"":{""date"":""2021-03-01 00:00:00.000000"",""timezone_type"":3,""timezone"":""UTC""},""through"":{""date"":""2021-12-31 00:00:00.000000"",""timezone_type"":3,""timezone"":""UTC""},""daysOfWeek"":[""Saturday"",""Sunday"",""Friday"",""Thursday"",""Tuesday"",""Wednesday""]}]","Highlight",,"Toilets,DisabledToilets,NappyChangingArea,FamilyAndChildFriendly","SeatingPossibilitiesRestArea,LockBoxes,SouvenirShop,BaggageStorage","MuseumShop","GothicArt","ZeroSpecialTrafficInfrastructure","CashPayment,EC","AudioGuide,VideoGuide","ZeroPhotography",,"false","true","German,English,French","200:MTR", +,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"",""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"",""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-11.jpg"",""description"":""Kr\u00e4merbr\u00fccke in Erfurt"",""url"":""https:\/\/cms.thuecat.org\/o\/adaptive-media\/image\/134362\/Preview-1280x0\/image"",""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"",""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" +,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"",""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"",""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-11.jpg"",""description"":""Kr\u00e4merbr\u00fccke in Erfurt"",""url"":""https:\/\/cms.thuecat.org\/o\/adaptive-media\/image\/134362\/Preview-1280x0\/image"",""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"",""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" +,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"",""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"",""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-11.jpg"",""description"":""Kr\u00e4merbr\u00fccke in Erfurt"",""url"":""https:\/\/cms.thuecat.org\/o\/adaptive-media\/image\/134362\/Preview-1280x0\/image"",""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"",""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" +"tx_thuecat_parking_facility",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,"uid","pid","sys_language_uid","l18n_parent","l10n_source","l10n_state","remote_id","title","description","managed_by","address","offers","media","opening_hours","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}}","[{""title"":"""",""description"":"""",""prices"":[{""title"":"""",""description"":"""",""price"":35,""currency"":""EUR"",""rule"":""PerCar""}]},{""title"":"""",""description"":"""",""prices"":[{""title"":"""",""description"":"""",""price"":1.5,""currency"":""EUR"",""rule"":""PerCar""}]},{""title"":"""",""description"":"""",""prices"":[{""title"":"""",""description"":"""",""price"":10,""currency"":""EUR"",""rule"":""PerCar""}]},{""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"",""copyrightYear"":2021,""license"":{""type"":""https:\/\/creativecommons.org\/licenses\/by\/4.0\/"",""author"":""""}},{""mainImage"":false,""type"":""image"",""title"":""Erfurt-Parkhaus-Domplatz.jpg"",""description"":"""",""url"":""https:\/\/cms.thuecat.org\/o\/adaptive-media\/image\/6486108\/Preview-1280x0\/image"",""copyrightYear"":2021,""license"":{""type"":""https:\/\/creativecommons.org\/licenses\/by\/4.0\/"",""author"":""""}}]","[{""opens"":""07:00:00"",""closes"":""22:00:00"",""from"":"""",""through"":"""",""daysOfWeek"":[""Saturday"",""Friday"",""Thursday"",""Tuesday"",""Monday"",""Wednesday""]},{""opens"":""09:00:00"",""closes"":""22:00:00"",""from"":"""",""through"":"""",""daysOfWeek"":[""Sunday"",""PublicHolidays""]}]","ZeroSanitation","ZeroOtherServiceEnumMem","ElectricVehicleCarChargingStationEnumMem",,"240:MTR",,,,,,,,,,,, +,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}}","[{""title"":"""",""description"":"""",""prices"":[{""title"":"""",""description"":"""",""price"":35,""currency"":""EUR"",""rule"":""PerCar""}]},{""title"":"""",""description"":"""",""prices"":[{""title"":"""",""description"":"""",""price"":1.5,""currency"":""EUR"",""rule"":""PerCar""}]},{""title"":"""",""description"":"""",""prices"":[{""title"":"""",""description"":"""",""price"":10,""currency"":""EUR"",""rule"":""PerCar""}]},{""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"",""copyrightYear"":2021,""license"":{""type"":""https:\/\/creativecommons.org\/licenses\/by\/4.0\/"",""author"":""""}},{""mainImage"":false,""type"":""image"",""title"":""Erfurt-Parkhaus-Domplatz.jpg"",""description"":"""",""url"":""https:\/\/cms.thuecat.org\/o\/adaptive-media\/image\/6486108\/Preview-1280x0\/image"",""copyrightYear"":2021,""license"":{""type"":""https:\/\/creativecommons.org\/licenses\/by\/4.0\/"",""author"":""""}}]","[{""opens"":""07:00:00"",""closes"":""22:00:00"",""from"":"""",""through"":"""",""daysOfWeek"":[""Saturday"",""Friday"",""Thursday"",""Tuesday"",""Monday"",""Wednesday""]},{""opens"":""09:00:00"",""closes"":""22:00:00"",""from"":"""",""through"":"""",""daysOfWeek"":[""Sunday"",""PublicHolidays""]}]","ZeroSanitation","ZeroOtherServiceEnumMem","ElectricVehicleCarChargingStationEnumMem",,"240:MTR",,,,,,,,,,,, +,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}}","[{""title"":"""",""description"":"""",""prices"":[{""title"":"""",""description"":"""",""price"":35,""currency"":""EUR"",""rule"":""PerCar""}]},{""title"":"""",""description"":"""",""prices"":[{""title"":"""",""description"":"""",""price"":1.5,""currency"":""EUR"",""rule"":""PerCar""}]},{""title"":"""",""description"":"""",""prices"":[{""title"":"""",""description"":"""",""price"":10,""currency"":""EUR"",""rule"":""PerCar""}]},{""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"",""copyrightYear"":2021,""license"":{""type"":""https:\/\/creativecommons.org\/licenses\/by\/4.0\/"",""author"":""""}},{""mainImage"":false,""type"":""image"",""title"":""Erfurt-Parkhaus-Domplatz.jpg"",""description"":"""",""url"":""https:\/\/cms.thuecat.org\/o\/adaptive-media\/image\/6486108\/Preview-1280x0\/image"",""copyrightYear"":2021,""license"":{""type"":""https:\/\/creativecommons.org\/licenses\/by\/4.0\/"",""author"":""""}}]","[{""opens"":""07:00:00"",""closes"":""22:00:00"",""from"":"""",""through"":"""",""daysOfWeek"":[""Saturday"",""Friday"",""Thursday"",""Tuesday"",""Monday"",""Wednesday""]},{""opens"":""09:00:00"",""closes"":""22:00:00"",""from"":"""",""through"":"""",""daysOfWeek"":[""Sunday"",""PublicHolidays""]}]","ZeroSanitation","ZeroOtherServiceEnumMem","ElectricVehicleCarChargingStationEnumMem",,"240:MTR",,,,,,,,,,,, +,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}}","[{""title"":"""",""description"":"""",""prices"":[{""title"":"""",""description"":"""",""price"":2.2,""currency"":""EUR"",""rule"":""PerCar""}]},{""title"":"""",""description"":"""",""prices"":[{""title"":"""",""description"":"""",""price"":1,""currency"":""EUR"",""rule"":""PerCar""}]},{""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"",""copyrightYear"":2020,""license"":{""type"":""https:\/\/creativecommons.org\/licenses\/by\/4.0\/"",""author"":""""}},{""mainImage"":false,""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"",""copyrightYear"":2020,""license"":{""type"":""https:\/\/creativecommons.org\/licenses\/by\/4.0\/"",""author"":""""}}]","[{""opens"":""05:30:00"",""closes"":""23:59:00"",""from"":{""date"":""2020-12-01 00:00:00.000000"",""timezone_type"":3,""timezone"":""UTC""},""through"":{""date"":""2021-12-31 00:00:00.000000"",""timezone_type"":3,""timezone"":""UTC""},""daysOfWeek"":[""Saturday"",""Sunday"",""Friday"",""Thursday"",""Tuesday"",""Monday"",""Wednesday""]}]","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}}","[{""title"":"""",""description"":"""",""prices"":[{""title"":"""",""description"":"""",""price"":2.2,""currency"":""EUR"",""rule"":""PerCar""}]},{""title"":"""",""description"":"""",""prices"":[{""title"":"""",""description"":"""",""price"":1,""currency"":""EUR"",""rule"":""PerCar""}]},{""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"",""copyrightYear"":2020,""license"":{""type"":""https:\/\/creativecommons.org\/licenses\/by\/4.0\/"",""author"":""""}},{""mainImage"":false,""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"",""copyrightYear"":2020,""license"":{""type"":""https:\/\/creativecommons.org\/licenses\/by\/4.0\/"",""author"":""""}}]","[{""opens"":""05:30:00"",""closes"":""23:59:00"",""from"":{""date"":""2020-12-01 00:00:00.000000"",""timezone_type"":3,""timezone"":""UTC""},""through"":{""date"":""2021-12-31 00:00:00.000000"",""timezone_type"":3,""timezone"":""UTC""},""daysOfWeek"":[""Saturday"",""Sunday"",""Friday"",""Thursday"",""Tuesday"",""Monday"",""Wednesday""]}]","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}}","[{""title"":"""",""description"":"""",""prices"":[{""title"":"""",""description"":"""",""price"":2.2,""currency"":""EUR"",""rule"":""PerCar""}]},{""title"":"""",""description"":"""",""prices"":[{""title"":"""",""description"":"""",""price"":1,""currency"":""EUR"",""rule"":""PerCar""}]},{""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"",""copyrightYear"":2020,""license"":{""type"":""https:\/\/creativecommons.org\/licenses\/by\/4.0\/"",""author"":""""}},{""mainImage"":false,""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"",""copyrightYear"":2020,""license"":{""type"":""https:\/\/creativecommons.org\/licenses\/by\/4.0\/"",""author"":""""}}]","[{""opens"":""05:30:00"",""closes"":""23:59:00"",""from"":{""date"":""2020-12-01 00:00:00.000000"",""timezone_type"":3,""timezone"":""UTC""},""through"":{""date"":""2021-12-31 00:00:00.000000"",""timezone_type"":3,""timezone"":""UTC""},""daysOfWeek"":[""Saturday"",""Sunday"",""Friday"",""Thursday"",""Tuesday"",""Monday"",""Wednesday""]}]","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.xml index ad95c5f..7a7fecb 100644 --- a/Tests/Functional/Fixtures/Import/ImportsTouristAttractionsWithRelations.xml +++ b/Tests/Functional/Fixtures/Import/ImportsTouristAttractionsWithRelations.xml @@ -106,18 +106,4 @@ 0 Erfurt - - - 1 - 10 - 1613400969 - 1613400969 - 1 - 0 - 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.0 1.1998 die Geschäftstätigkeit auf. - 0 - 0 - diff --git a/Tests/Functional/Fixtures/Import/ImportsTouristAttractionsWithRelationsResult.csv b/Tests/Functional/Fixtures/Import/ImportsTouristAttractionsWithRelationsResult.csv deleted file mode 100644 index f62748a..0000000 --- a/Tests/Functional/Fixtures/Import/ImportsTouristAttractionsWithRelationsResult.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","media","opening_hours","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" -,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}}","[]","[{""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,""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""]}]",,,"Toilets,DisabledToilets","SeatingPossibilitiesRestArea,SouvenirShop",,"GothicArt","BicycleLockersEnumMem,BusParkCoachParkEnumMem",,"AugmentedReality","Fotogenehmigung für innen","false","true","true","German,English","350:MTR" -,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}}","[]","[{""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,""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""]}]",,,"Toilets,DisabledToilets","SeatingPossibilitiesRestArea,SouvenirShop",,"GothicArt","BicycleLockersEnumMem,BusParkCoachParkEnumMem",,"AugmentedReality",,"false","true","true","German,English","350:MTR" -,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}}","[{""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""}]},{""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"",""copyrightYear"":2009,""license"":{""type"":""https:\/\/creativecommons.org\/licenses\/by\/4.0\/"",""author"":""F:\\Bilddatenbank\\Museen und Ausstellungen\\Alte Synagoge""}},{""mainImage"":false,""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"",""copyrightYear"":2009,""license"":{""type"":""https:\/\/creativecommons.org\/licenses\/by\/4.0\/"",""author"":""F:\\Bilddatenbank\\Museen und Ausstellungen\\Alte Synagoge""}}]","[{""opens"":""10:00:00"",""closes"":""18:00:00"",""from"":{""date"":""2021-03-01 00:00:00.000000"",""timezone_type"":3,""timezone"":""UTC""},""through"":{""date"":""2021-12-31 00:00:00.000000"",""timezone_type"":3,""timezone"":""UTC""},""daysOfWeek"":[""Saturday"",""Sunday"",""Friday"",""Thursday"",""Tuesday"",""Wednesday""]}]","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" -,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}}","[{""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""}]},{""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"",""copyrightYear"":2009,""license"":{""type"":""https:\/\/creativecommons.org\/licenses\/by\/4.0\/"",""author"":""F:\\Bilddatenbank\\Museen und Ausstellungen\\Alte Synagoge""}},{""mainImage"":false,""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"",""copyrightYear"":2009,""license"":{""type"":""https:\/\/creativecommons.org\/licenses\/by\/4.0\/"",""author"":""F:\\Bilddatenbank\\Museen und Ausstellungen\\Alte Synagoge""}}]","[{""opens"":""10:00:00"",""closes"":""18:00:00"",""from"":{""date"":""2021-03-01 00:00:00.000000"",""timezone_type"":3,""timezone"":""UTC""},""through"":{""date"":""2021-12-31 00:00:00.000000"",""timezone_type"":3,""timezone"":""UTC""},""daysOfWeek"":[""Saturday"",""Sunday"",""Friday"",""Thursday"",""Tuesday"",""Wednesday""]}]","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" -,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}}","[{""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""}]},{""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"",""copyrightYear"":2009,""license"":{""type"":""https:\/\/creativecommons.org\/licenses\/by\/4.0\/"",""author"":""F:\\Bilddatenbank\\Museen und Ausstellungen\\Alte Synagoge""}},{""mainImage"":false,""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"",""copyrightYear"":2009,""license"":{""type"":""https:\/\/creativecommons.org\/licenses\/by\/4.0\/"",""author"":""F:\\Bilddatenbank\\Museen und Ausstellungen\\Alte Synagoge""}}]","[{""opens"":""10:00:00"",""closes"":""18:00:00"",""from"":{""date"":""2021-03-01 00:00:00.000000"",""timezone_type"":3,""timezone"":""UTC""},""through"":{""date"":""2021-12-31 00:00:00.000000"",""timezone_type"":3,""timezone"":""UTC""},""daysOfWeek"":[""Saturday"",""Sunday"",""Friday"",""Thursday"",""Tuesday"",""Wednesday""]}]","Highlight",,"Toilets,DisabledToilets,NappyChangingArea,FamilyAndChildFriendly","SeatingPossibilitiesRestArea,LockBoxes,SouvenirShop,BaggageStorage","MuseumShop","GothicArt","ZeroSpecialTrafficInfrastructure","CashPayment,EC","AudioGuide,VideoGuide","ZeroPhotography",,"false","true","German,English,French","200:MTR" -,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}}","[]","[{""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"",""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"",""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-11.jpg"",""description"":""Kr\u00e4merbr\u00fccke in Erfurt"",""url"":""https:\/\/cms.thuecat.org\/o\/adaptive-media\/image\/134362\/Preview-1280x0\/image"",""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"",""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" -,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}}","[]","[{""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"",""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"",""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-11.jpg"",""description"":""Kr\u00e4merbr\u00fccke in Erfurt"",""url"":""https:\/\/cms.thuecat.org\/o\/adaptive-media\/image\/134362\/Preview-1280x0\/image"",""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"",""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" -,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}}","[]","[{""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"",""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"",""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-11.jpg"",""description"":""Kr\u00e4merbr\u00fccke in Erfurt"",""url"":""https:\/\/cms.thuecat.org\/o\/adaptive-media\/image\/134362\/Preview-1280x0\/image"",""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"",""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" diff --git a/Tests/Functional/Fixtures/Import/ImportsTouristInformationWithRelation.csv b/Tests/Functional/Fixtures/Import/ImportsTouristInformationWithRelation.csv new file mode 100644 index 0000000..8e13dd4 --- /dev/null +++ b/Tests/Functional/Fixtures/Import/ImportsTouristInformationWithRelation.csv @@ -0,0 +1,9 @@ +"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.xml b/Tests/Functional/Fixtures/Import/ImportsTouristInformationWithRelation.xml index 64083ac..853f080 100644 --- a/Tests/Functional/Fixtures/Import/ImportsTouristInformationWithRelation.xml +++ b/Tests/Functional/Fixtures/Import/ImportsTouristInformationWithRelation.xml @@ -73,31 +73,4 @@ ]]> - - - 1 - 10 - 1613401129 - 1613401129 - 1 - 0 - https://thuecat.org/resources/043064193523-jcyt - 1 - 0 - Erfurt - - - - 1 - 10 - 1613400969 - 1613400969 - 1 - 0 - 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.0 1.1998 die Geschäftstätigkeit auf. - 0 - 0 - diff --git a/Tests/Functional/Fixtures/Import/ImportsTouristInformationWithRelationResult.csv b/Tests/Functional/Fixtures/Import/ImportsTouristInformationWithRelationResult.csv deleted file mode 100644 index 5ce51f8..0000000 --- a/Tests/Functional/Fixtures/Import/ImportsTouristInformationWithRelationResult.csv +++ /dev/null @@ -1,3 +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 diff --git a/Tests/Functional/Fixtures/Import/ImportsTown.csv b/Tests/Functional/Fixtures/Import/ImportsTown.csv index dd41e83..ad43804 100644 --- a/Tests/Functional/Fixtures/Import/ImportsTown.csv +++ b/Tests/Functional/Fixtures/Import/ImportsTown.csv @@ -1,3 +1,6 @@ -tx_thuecat_town +"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,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.csv b/Tests/Functional/Fixtures/Import/ImportsTownWithRelation.csv index b03c8e9..ad43804 100644 --- a/Tests/Functional/Fixtures/Import/ImportsTownWithRelation.csv +++ b/Tests/Functional/Fixtures/Import/ImportsTownWithRelation.csv @@ -1,3 +1,6 @@ -tx_thuecat_town +"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.xml b/Tests/Functional/Fixtures/Import/ImportsTownWithRelation.xml index 2aae09a..1920bf9 100644 --- a/Tests/Functional/Fixtures/Import/ImportsTownWithRelation.xml +++ b/Tests/Functional/Fixtures/Import/ImportsTownWithRelation.xml @@ -77,14 +77,11 @@ 1 10 - 1613400969 - 1613400969 + 1613400587 + 1613400558 1 0 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.0 1.1998 die Geschäftstätigkeit auf. - 0 - 0 + Old title diff --git a/Tests/Functional/FrontendTest.php b/Tests/Functional/FrontendTest.php index eb20551..6b99a9b 100644 --- a/Tests/Functional/FrontendTest.php +++ b/Tests/Functional/FrontendTest.php @@ -183,6 +183,18 @@ class FrontendTest extends FunctionalTestCase self::assertStringNotContainsString('Deutsch', (string)$result->getBody()); self::assertStringNotContainsString('Englisch', (string)$result->getBody()); self::assertStringNotContainsString('Französisch', (string)$result->getBody()); + + self::assertStringContainsString('Parkhäuser in der Nähe', (string)$result->getBody()); + self::assertStringContainsString('Parkhaus Domplatz', (string)$result->getBody()); + self::assertStringContainsString('Bechtheimer Str. 1', (string)$result->getBody()); + self::assertStringContainsString('99084 Erfurt', (string)$result->getBody()); + self::assertStringContainsString('info@stadtwerke-erfurt.de', (string)$result->getBody()); + self::assertStringContainsString('+49 361 5640', (string)$result->getBody()); + self::assertStringContainsString('Q-Park Anger 1 Parkhaus', (string)$result->getBody()); + self::assertStringContainsString('Anger 1', (string)$result->getBody()); + self::assertStringContainsString('99084 Erfurt', (string)$result->getBody()); + self::assertStringContainsString('servicecenter@q-park.de', (string)$result->getBody()); + self::assertStringContainsString('+49 218 18190290', (string)$result->getBody()); } /** diff --git a/Tests/Functional/ImportTest.php b/Tests/Functional/ImportTest.php index a2ea7da..ad98d1d 100644 --- a/Tests/Functional/ImportTest.php +++ b/Tests/Functional/ImportTest.php @@ -148,21 +148,6 @@ class ImportTest extends TestCase $extbaseBootstrap = $this->getContainer()->get(Bootstrap::class); $extbaseBootstrap->handleBackendRequest($serverRequest->reveal()); - self::assertCount( - 1, - $this->getAllRecords('tx_thuecat_organisation'), - 'Did not create expected number of organisations.' - ); - self::assertCount( - 1, - $this->getAllRecords('tx_thuecat_import_log'), - 'Did not create expected number of import logs.' - ); - self::assertCount( - 1, - $this->getAllRecords('tx_thuecat_import_log_entry'), - 'Did not create expected number of import log entries.' - ); $this->assertCSVDataSet('EXT:thuecat/Tests/Functional/Fixtures/Import/ImportsFreshOrganization.csv'); } @@ -210,9 +195,6 @@ class ImportTest extends TestCase $extbaseBootstrap = $this->getContainer()->get(Bootstrap::class); $extbaseBootstrap->handleBackendRequest($serverRequest->reveal()); - $towns = $this->getAllRecords('tx_thuecat_town'); - self::assertCount(1, $towns); - $this->assertCSVDataSet('EXT:thuecat/Tests/Functional/Fixtures/Import/ImportsTown.csv'); } @@ -228,9 +210,6 @@ class ImportTest extends TestCase $extbaseBootstrap = $this->getContainer()->get(Bootstrap::class); $extbaseBootstrap->handleBackendRequest($serverRequest->reveal()); - $towns = $this->getAllRecords('tx_thuecat_town'); - self::assertCount(1, $towns); - $this->assertCSVDataSet('EXT:thuecat/Tests/Functional/Fixtures/Import/ImportsTownWithRelation.csv'); } @@ -246,10 +225,7 @@ class ImportTest extends TestCase $extbaseBootstrap = $this->getContainer()->get(Bootstrap::class); $extbaseBootstrap->handleBackendRequest($serverRequest->reveal()); - $touristAttractions = $this->getAllRecords('tx_thuecat_tourist_attraction'); - self::assertCount(8, $touristAttractions); - - $this->assertCSVDataSet('EXT:thuecat/Tests/Functional/Fixtures/Import/ImportsTouristAttractionsWithRelationsResult.csv'); + $this->assertCSVDataSet('EXT:thuecat/Tests/Functional/Fixtures/Import/ImportsTouristAttractionsWithRelations.csv'); } /** @@ -264,10 +240,7 @@ class ImportTest extends TestCase $extbaseBootstrap = $this->getContainer()->get(Bootstrap::class); $extbaseBootstrap->handleBackendRequest($serverRequest->reveal()); - $touristInformation = $this->getAllRecords('tx_thuecat_tourist_information'); - self::assertCount(1, $touristInformation); - - $this->assertCSVDataSet('EXT:thuecat/Tests/Functional/Fixtures/Import/ImportsTouristInformationWithRelationResult.csv'); + $this->assertCSVDataSet('EXT:thuecat/Tests/Functional/Fixtures/Import/ImportsTouristInformationWithRelation.csv'); } /** @@ -282,10 +255,23 @@ class ImportTest extends TestCase $extbaseBootstrap = $this->getContainer()->get(Bootstrap::class); $extbaseBootstrap->handleBackendRequest($serverRequest->reveal()); - $touristAttractions = $this->getAllRecords('tx_thuecat_tourist_attraction'); - self::assertCount(8, $touristAttractions); + $this->assertCSVDataSet('EXT:thuecat/Tests/Functional/Fixtures/Import/ImportsSyncScope.csv'); + } - $this->assertCSVDataSet('EXT:thuecat/Tests/Functional/Fixtures/Import/ImportsSyncScopeResult.csv'); + /** + * @test + * @testdox Referencing the same thing multiple times only adds it once. + */ + public function importWithMultipleReferencesToSameObject(): void + { + $this->importDataSet(__DIR__ . '/Fixtures/Import/ImportWithMultipleReferencesToSameObject.xml'); + + $serverRequest = $this->getServerRequest(); + + $extbaseBootstrap = $this->getContainer()->get(Bootstrap::class); + $extbaseBootstrap->handleBackendRequest($serverRequest->reveal()); + + $this->assertCSVDataSet('EXT:thuecat/Tests/Functional/Fixtures/Import/ImportWithMultipleReferencesToSameObject.csv'); } /** diff --git a/Tests/Unit/Domain/Import/ImportTest.php b/Tests/Unit/Domain/Import/ImportTest.php new file mode 100644 index 0000000..4dac290 --- /dev/null +++ b/Tests/Unit/Domain/Import/ImportTest.php @@ -0,0 +1,217 @@ + + * + * 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; + +use Prophecy\PhpUnit\ProphecyTrait; +use WerkraumMedia\ThueCat\Domain\Import\Import; +use PHPUnit\Framework\TestCase; +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 +{ + use ProphecyTrait; + + /** + * @test + */ + public function canBeCreated(): void + { + $subject = new Import(); + + self::assertInstanceOf( + Import::class, + $subject + ); + } + + /** + * @test + */ + public function canStart(): void + { + $configuration = $this->prophesize(ImportConfiguration::class); + $subject = new Import(); + $subject->start($configuration->reveal()); + + self::assertSame( + $configuration->reveal(), + $subject->getConfiguration() + ); + self::assertInstanceOf( + ImportLog::class, + $subject->getLog() + ); + } + + /** + * @test + */ + public function canEndAfterStart(): void + { + $configuration = $this->prophesize(ImportConfiguration::class); + $subject = new Import(); + $subject->start($configuration->reveal()); + $subject->end(); + + self::assertSame( + $configuration->reveal(), + $subject->getConfiguration() + ); + self::assertInstanceOf( + ImportLog::class, + $subject->getLog() + ); + } + + /** + * @test + */ + public function isDoneAfterStartAndEnd(): void + { + $configuration = $this->prophesize(ImportConfiguration::class); + $subject = new Import(); + $subject->start($configuration->reveal()); + $subject->end(); + + self::assertTrue($subject->done()); + } + + /** + * @test + */ + public function isNotDoneAfterJustStartWithoutEnd(): void + { + $configuration = $this->prophesize(ImportConfiguration::class); + $subject = new Import(); + $subject->start($configuration->reveal()); + + self::assertFalse($subject->done()); + } + + /** + * @test + */ + public function nestedStartReturnsExpectedConfiguration(): void + { + $configuration1 = $this->prophesize(ImportConfiguration::class); + $subject = new Import(); + $subject->start($configuration1->reveal()); + + $configuration2 = $this->prophesize(ImportConfiguration::class); + $subject->start($configuration2->reveal()); + + self::assertSame( + $configuration2->reveal(), + $subject->getConfiguration() + ); + } + + /** + * @test + */ + public function nestedStartReturnsExpectedLog(): void + { + $configuration1 = $this->prophesize(ImportConfiguration::class); + $subject = new Import(); + $subject->start($configuration1->reveal()); + + $log1 = $subject->getLog(); + self::assertInstanceOf( + ImportLog::class, + $log1 + ); + + $configuration2 = $this->prophesize(ImportConfiguration::class); + $subject->start($configuration2->reveal()); + + $log2 = $subject->getLog(); + self::assertInstanceOf( + ImportLog::class, + $log2 + ); + + self::assertNotSame( + $log1, + $log2 + ); + } + + /** + * @test + */ + public function nestedImportMergesLog(): void + { + $configuration1 = $this->prophesize(ImportConfiguration::class); + $subject = new Import(); + $subject->start($configuration1->reveal()); + + $log1 = $subject->getLog(); + + $configuration2 = $this->prophesize(ImportConfiguration::class); + $subject->start($configuration2->reveal()); + $importLogEntry = $this->prophesize(ImportLogEntry::class); + $subject->getLog()->addEntry($importLogEntry->reveal()); + $subject->end(); + + self::assertSame( + $log1, + $subject->getLog() + ); + + self::assertSame( + [ + $importLogEntry->reveal() + ], + $log1->getEntries()->toArray() + ); + } + + /** + * @test + */ + public function nestedImportReturnsHandledForRemoteId(): void + { + $configuration1 = $this->prophesize(ImportConfiguration::class); + $subject = new Import(); + $subject->start($configuration1->reveal()); + + $configuration2 = $this->prophesize(ImportConfiguration::class); + $subject->start($configuration2->reveal()); + $importLogEntry = $this->prophesize(ImportLogEntry::class); + $importLogEntry->getRemoteId()->willReturn('https://example.com/remote-id'); + $subject->getLog()->addEntry($importLogEntry->reveal()); + $subject->end(); + + $configuration3 = $this->prophesize(ImportConfiguration::class); + $subject->start($configuration3->reveal()); + self::assertTrue( + $subject->handledRemoteId('https://example.com/remote-id') + ); + } +} diff --git a/ext_tables.sql b/ext_tables.sql index 0a6c927..c70aa7f 100644 --- a/ext_tables.sql +++ b/ext_tables.sql @@ -50,6 +50,7 @@ CREATE TABLE tx_thuecat_tourist_attraction ( remote_id varchar(255) DEFAULT '' NOT NULL, managed_by int(11) unsigned DEFAULT '0' NOT NULL, town int(11) unsigned DEFAULT '0' NOT NULL, + parking_facility_near_by varchar(255) DEFAULT '' NOT NULL, title varchar(255) DEFAULT '' NOT NULL, description text DEFAULT '' NOT NULL, opening_hours text DEFAULT '' NOT NULL, @@ -72,3 +73,20 @@ CREATE TABLE tx_thuecat_tourist_attraction ( available_languages text DEFAULT '' NOT NULL, distance_to_public_transport text DEFAULT '' NOT NULL, ); + +CREATE TABLE tx_thuecat_parking_facility ( + remote_id varchar(255) DEFAULT '' NOT NULL, + managed_by int(11) unsigned DEFAULT '0' NOT NULL, + town int(11) unsigned DEFAULT '0' NOT NULL, + title varchar(255) DEFAULT '' NOT NULL, + description text DEFAULT '' NOT NULL, + opening_hours text DEFAULT '' NOT NULL, + address text DEFAULT '' NOT NULL, + media text DEFAULT '' NOT NULL, + offers text DEFAULT '' NOT NULL, + sanitation text DEFAULT '' NOT NULL, + other_service text DEFAULT '' NOT NULL, + traffic_infrastructure text DEFAULT '' NOT NULL, + payment_accepted text DEFAULT '' NOT NULL, + distance_to_public_transport text DEFAULT '' NOT NULL, +); diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 597c2b1..ebb719a 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -1,7 +1,12 @@ parameters: ignoreErrors: - - message: "#^Parameter \\#1 \\$function of function call_user_func expects callable\\(\\)\\: mixed, array\\(string\\|null, 'getSupportedTypes'\\) given\\.$#" + message: "#^Parameter \\#1 \\$function of function call_user_func expects callable\\(\\)\\: mixed, array\\(string, 'getPriority'\\) given\\.$#" + count: 1 + path: Classes/DependencyInjection/EntityPass.php + + - + message: "#^Parameter \\#1 \\$function of function call_user_func expects callable\\(\\)\\: mixed, array\\(string, 'getSupportedTypes'\\) given\\.$#" count: 1 path: Classes/DependencyInjection/EntityPass.php @@ -15,6 +20,16 @@ parameters: count: 1 path: Classes/Domain/Model/Backend/ImportLog.php + - + message: "#^Property WerkraumMedia\\\\ThueCat\\\\Domain\\\\Model\\\\Frontend\\\\Place\\:\\:\\$parkingFacilityNearBy \\(iterable\\&TYPO3\\\\CMS\\\\Extbase\\\\Persistence\\\\ObjectStorage\\) does not accept TYPO3\\\\CMS\\\\Extbase\\\\Persistence\\\\ObjectStorage\\.$#" + count: 1 + path: Classes/Domain/Model/Frontend/Place.php + + - + message: "#^Method WerkraumMedia\\\\ThueCat\\\\Domain\\\\Repository\\\\Backend\\\\ParkingFacilityRepository\\:\\:findByEntity\\(\\) should return TYPO3\\\\CMS\\\\Extbase\\\\Persistence\\\\QueryResultInterface\\|null but returns array\\|TYPO3\\\\CMS\\\\Extbase\\\\Persistence\\\\QueryResultInterface\\.$#" + count: 1 + path: Classes/Domain/Repository/Backend/ParkingFacilityRepository.php + - message: "#^Cannot call method getFirst\\(\\) on array\\|TYPO3\\\\CMS\\\\Extbase\\\\Persistence\\\\QueryResultInterface\\.$#" count: 1 @@ -35,3 +50,8 @@ parameters: count: 1 path: Classes/Frontend/DataProcessing/ResolveEntities.php + - + message: "#^Cannot call method format\\(\\) on DateTimeImmutable\\|null\\.$#" + count: 4 + path: Tests/Functional/Import/EntityMapping/PlaceInfosTest.php +