From 651fc17fd90ae217cb7638912445b9ba318d9389 Mon Sep 17 00:00:00 2001 From: Daniel Siepmann Date: Wed, 30 Aug 2023 14:14:51 +0200 Subject: [PATCH] Respect possible arrays in accessibility certification (#114) --- .../Entity/AccessibilityCertification.php | 48 +- Classes/Domain/Import/EntityMapper.php | 11 +- .../CustomAnnotationExtractor.php | 375 +++++++++ Documentation/Changelog/2.1.0.rst | 3 + ...tion-with-accessibility-specification.json | 54 ++ ...e6edc-rfa-accessibility-specification.json | 767 ++++++++++++++++++ ...tractionWithAccessibilitySpecification.csv | 4 + ...tractionWithAccessibilitySpecification.xml | 76 ++ ...nWithAccessibilitySpecificationEnglish.txt | 1 + ...onWithAccessibilitySpecificationGerman.txt | 1 + Tests/Functional/ImportTest.php | 20 + ecs.php | 1 + phpstan-baseline.neon | 4 +- phpstan.neon | 1 + 14 files changed, 1354 insertions(+), 12 deletions(-) create mode 100644 Classes/Domain/Import/EntityMapper/CustomAnnotationExtractor.php create mode 100644 Tests/Functional/Fixtures/Import/Guzzle/thuecat.org/resources/attraction-with-accessibility-specification.json create mode 100644 Tests/Functional/Fixtures/Import/Guzzle/thuecat.org/resources/e_331baf4eeda4453db920dde62f7e6edc-rfa-accessibility-specification.json create mode 100644 Tests/Functional/Fixtures/Import/ImportsTouristAttractionWithAccessibilitySpecification.csv create mode 100644 Tests/Functional/Fixtures/Import/ImportsTouristAttractionWithAccessibilitySpecification.xml create mode 100644 Tests/Functional/Fixtures/Import/ImportsTouristAttractionWithAccessibilitySpecificationEnglish.txt create mode 100644 Tests/Functional/Fixtures/Import/ImportsTouristAttractionWithAccessibilitySpecificationGerman.txt diff --git a/Classes/Domain/Import/Entity/AccessibilityCertification.php b/Classes/Domain/Import/Entity/AccessibilityCertification.php index 8550551..16f790d 100644 --- a/Classes/Domain/Import/Entity/AccessibilityCertification.php +++ b/Classes/Domain/Import/Entity/AccessibilityCertification.php @@ -109,65 +109,97 @@ class AccessibilityCertification implements MapsToType /** * @internal for mapping via Symfony component. + * @param string|array $accessibilityCertificationStatus */ - public function setAccessibilityCertificationStatus(string $accessibilityCertificationStatus): void + public function setAccessibilityCertificationStatus($accessibilityCertificationStatus): void { + if (is_array($accessibilityCertificationStatus)) { + $accessibilityCertificationStatus = $accessibilityCertificationStatus['value'] ?? ''; + } $this->accessibilityCertificationStatus = PropertyValues::removePrefixFromEntry($accessibilityCertificationStatus); } /** * @internal for mapping via Symfony component. + * @param string|array $certificationAccessibilityDeaf */ - public function setCertificationAccessibilityDeaf(string $certificationAccessibilityDeaf): void + public function setCertificationAccessibilityDeaf($certificationAccessibilityDeaf): void { + if (is_array($certificationAccessibilityDeaf)) { + $certificationAccessibilityDeaf = $certificationAccessibilityDeaf['value'] ?? ''; + } $this->certificationAccessibilityDeaf = PropertyValues::removePrefixFromEntry($certificationAccessibilityDeaf); } /** * @internal for mapping via Symfony component. + * @param string|array $certificationAccessibilityMental */ - public function setCertificationAccessibilityMental(string $certificationAccessibilityMental): void + public function setCertificationAccessibilityMental($certificationAccessibilityMental): void { + if (is_array($certificationAccessibilityMental)) { + $certificationAccessibilityMental = $certificationAccessibilityMental['value'] ?? ''; + } $this->certificationAccessibilityMental = PropertyValues::removePrefixFromEntry($certificationAccessibilityMental); } /** * @internal for mapping via Symfony component. + * @param string|array $certificationAccessibilityPartiallyDeaf */ - public function setCertificationAccessibilityPartiallyDeaf(string $certificationAccessibilityPartiallyDeaf): void + public function setCertificationAccessibilityPartiallyDeaf($certificationAccessibilityPartiallyDeaf): void { + if (is_array($certificationAccessibilityPartiallyDeaf)) { + $certificationAccessibilityPartiallyDeaf = $certificationAccessibilityPartiallyDeaf['value'] ?? ''; + } $this->certificationAccessibilityPartiallyDeaf = PropertyValues::removePrefixFromEntry($certificationAccessibilityPartiallyDeaf); } /** * @internal for mapping via Symfony component. + * @param string|array $certificationAccessibilityPartiallyVisual */ - public function setCertificationAccessibilityPartiallyVisual(string $certificationAccessibilityPartiallyVisual): void + public function setCertificationAccessibilityPartiallyVisual($certificationAccessibilityPartiallyVisual): void { + if (is_array($certificationAccessibilityPartiallyVisual)) { + $certificationAccessibilityPartiallyVisual = $certificationAccessibilityPartiallyVisual['value'] ?? ''; + } $this->certificationAccessibilityPartiallyVisual = PropertyValues::removePrefixFromEntry($certificationAccessibilityPartiallyVisual); } /** * @internal for mapping via Symfony component. + * @param string|array $certificationAccessibilityVisual */ - public function setCertificationAccessibilityVisual(string $certificationAccessibilityVisual): void + public function setCertificationAccessibilityVisual($certificationAccessibilityVisual): void { + if (is_array($certificationAccessibilityVisual)) { + $certificationAccessibilityVisual = $certificationAccessibilityVisual['value'] ?? ''; + } $this->certificationAccessibilityVisual = PropertyValues::removePrefixFromEntry($certificationAccessibilityVisual); } /** * @internal for mapping via Symfony component. + * @param string|array $certificationAccessibilityWalking */ - public function setCertificationAccessibilityWalking(string $certificationAccessibilityWalking): void + public function setCertificationAccessibilityWalking($certificationAccessibilityWalking): void { + if (is_array($certificationAccessibilityWalking)) { + $certificationAccessibilityWalking = $certificationAccessibilityWalking['value'] ?? ''; + } $this->certificationAccessibilityWalking = PropertyValues::removePrefixFromEntry($certificationAccessibilityWalking); } /** * @internal for mapping via Symfony component. + * @param string|array $certificationAccessibilityWheelchair */ - public function setCertificationAccessibilityWheelchair(string $certificationAccessibilityWheelchair): void + public function setCertificationAccessibilityWheelchair($certificationAccessibilityWheelchair): void { + if (is_array($certificationAccessibilityWheelchair)) { + $certificationAccessibilityWheelchair = $certificationAccessibilityWheelchair['value'] ?? ''; + } $this->certificationAccessibilityWheelchair = PropertyValues::removePrefixFromEntry($certificationAccessibilityWheelchair); } diff --git a/Classes/Domain/Import/EntityMapper.php b/Classes/Domain/Import/EntityMapper.php index 9fc63e5..d82fed2 100644 --- a/Classes/Domain/Import/EntityMapper.php +++ b/Classes/Domain/Import/EntityMapper.php @@ -31,6 +31,7 @@ use Symfony\Component\Serializer\Normalizer\DateTimeNormalizer; use Symfony\Component\Serializer\Normalizer\ObjectNormalizer; use Symfony\Component\Serializer\Serializer; use WerkraumMedia\ThueCat\Domain\Import\EntityMapper\ArrayDenormalizer; +use WerkraumMedia\ThueCat\Domain\Import\EntityMapper\CustomAnnotationExtractor; use WerkraumMedia\ThueCat\Domain\Import\EntityMapper\JsonDecode; use WerkraumMedia\ThueCat\Domain\Import\EntityMapper\MappingException; @@ -70,16 +71,22 @@ class EntityMapper null, null, // We enforce following behaviour: - // 1. Try to fetch info via reflection (e.g. by methods or property) - // 2. Use php doc as fallback + // 1. Try our own extractor to check for annotations on setter method. + // 2. Try to fetch info via reflection (e.g. by methods or property) + // 3. Use php doc as fallback // We do this because of: // Most of the time we can just use the TypeHint of setter or add/remove for collections // Sometimes we have to deal with multiple types (e.g. string and array) // We then can have a different property name and no type hint, reflection will fail // But we can use PHPDoc to define all supported + // And we can overrule the symfony behaviour first of all with our own extractor taking precedence. + // + // The reflection will first check mutator, then getter followed from properties. + // The phpdoc will first check the property itself. new PropertyInfoExtractor( [], [ + new CustomAnnotationExtractor(), new ReflectionExtractor(), new PhpDocExtractor(), ] diff --git a/Classes/Domain/Import/EntityMapper/CustomAnnotationExtractor.php b/Classes/Domain/Import/EntityMapper/CustomAnnotationExtractor.php new file mode 100644 index 0000000..282d0ec --- /dev/null +++ b/Classes/Domain/Import/EntityMapper/CustomAnnotationExtractor.php @@ -0,0 +1,375 @@ + + * + * 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; + +use LogicException; +use phpDocumentor\Reflection\DocBlock; +use phpDocumentor\Reflection\DocBlockFactory; +use phpDocumentor\Reflection\DocBlockFactoryInterface; +use phpDocumentor\Reflection\DocBlock\Tags\InvalidTag; +use phpDocumentor\Reflection\Types\Context; +use phpDocumentor\Reflection\Types\ContextFactory; +use Symfony\Component\PropertyInfo\Extractor\ConstructorArgumentTypeExtractorInterface; +use Symfony\Component\PropertyInfo\Extractor\ReflectionExtractor; +use Symfony\Component\PropertyInfo\PropertyDescriptionExtractorInterface; +use Symfony\Component\PropertyInfo\PropertyTypeExtractorInterface; +use Symfony\Component\PropertyInfo\Type; +use Symfony\Component\PropertyInfo\Util\PhpDocTypeHelper; + +/** + * A copy of symfonies own PhpDocExtractor class. + * We only alter the order within getDocBlock() to execute checks in same order as the ReflectionExtractor. + * That way we can check PhpDoc of mutators first. + * + * Make updating the file contents easier by keeping the original file contents as close as possible. + */ +class CustomAnnotationExtractor implements PropertyDescriptionExtractorInterface, PropertyTypeExtractorInterface, ConstructorArgumentTypeExtractorInterface +{ + public const PROPERTY = 0; + public const ACCESSOR = 1; + public const MUTATOR = 2; + + /** + * @var array + */ + private $docBlocks = []; + + /** + * @var Context[] + */ + private $contexts = []; + + private $docBlockFactory; + private $contextFactory; + private $phpDocTypeHelper; + private $mutatorPrefixes; + private $accessorPrefixes; + private $arrayMutatorPrefixes; + + /** + * @param string[]|null $mutatorPrefixes + * @param string[]|null $accessorPrefixes + * @param string[]|null $arrayMutatorPrefixes + */ + public function __construct(DocBlockFactoryInterface $docBlockFactory = null, array $mutatorPrefixes = null, array $accessorPrefixes = null, array $arrayMutatorPrefixes = null) + { + if (!class_exists(DocBlockFactory::class)) { + throw new \LogicException(sprintf('Unable to use the "%s" class as the "phpdocumentor/reflection-docblock" package is not installed. Try running composer require "phpdocumentor/reflection-docblock".', __CLASS__)); + } + + $this->docBlockFactory = $docBlockFactory ?: DocBlockFactory::createInstance(); + $this->contextFactory = new ContextFactory(); + $this->phpDocTypeHelper = new PhpDocTypeHelper(); + $this->mutatorPrefixes = $mutatorPrefixes ?? ReflectionExtractor::$defaultMutatorPrefixes; + $this->accessorPrefixes = $accessorPrefixes ?? ReflectionExtractor::$defaultAccessorPrefixes; + $this->arrayMutatorPrefixes = $arrayMutatorPrefixes ?? ReflectionExtractor::$defaultArrayMutatorPrefixes; + } + + /** + * {@inheritdoc} + */ + public function getShortDescription(string $class, string $property, array $context = []): ?string + { + /** @var $docBlock DocBlock */ + [$docBlock] = $this->getDocBlock($class, $property); + if (!$docBlock) { + return null; + } + + $shortDescription = $docBlock->getSummary(); + + if (!empty($shortDescription)) { + return $shortDescription; + } + + foreach ($docBlock->getTagsByName('var') as $var) { + if ($var && !$var instanceof InvalidTag) { + $varDescription = $var->getDescription()->render(); + + if (!empty($varDescription)) { + return $varDescription; + } + } + } + + return null; + } + + /** + * {@inheritdoc} + */ + public function getLongDescription(string $class, string $property, array $context = []): ?string + { + /** @var $docBlock DocBlock */ + [$docBlock] = $this->getDocBlock($class, $property); + if (!$docBlock) { + return null; + } + + $contents = $docBlock->getDescription()->render(); + + return '' === $contents ? null : $contents; + } + + /** + * {@inheritdoc} + */ + public function getTypes(string $class, string $property, array $context = []): ?array + { + /** @var $docBlock DocBlock */ + [$docBlock, $source, $prefix] = $this->getDocBlock($class, $property); + if (!$docBlock) { + return null; + } + + switch ($source) { + case self::PROPERTY: + $tag = 'var'; + break; + + case self::ACCESSOR: + $tag = 'return'; + break; + + case self::MUTATOR: + $tag = 'param'; + break; + } + + $parentClass = null; + $types = []; + /** @var DocBlock\Tags\Var_|DocBlock\Tags\Return_|DocBlock\Tags\Param $tag */ + foreach ($docBlock->getTagsByName($tag) as $tag) { + if ($tag && !$tag instanceof InvalidTag && null !== $tag->getType()) { + foreach ($this->phpDocTypeHelper->getTypes($tag->getType()) as $type) { + switch ($type->getClassName()) { + case 'self': + case 'static': + $resolvedClass = $class; + break; + + case 'parent': + if (false !== $resolvedClass = $parentClass ?? $parentClass = get_parent_class($class)) { + break; + } + // no break + + default: + $types[] = $type; + continue 2; + } + + $types[] = new Type(Type::BUILTIN_TYPE_OBJECT, $type->isNullable(), $resolvedClass, $type->isCollection(), $type->getCollectionKeyTypes(), $type->getCollectionValueTypes()); + } + } + } + + if (!isset($types[0])) { + return null; + } + + if (!\in_array($prefix, $this->arrayMutatorPrefixes)) { + return $types; + } + + return [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), $types[0])]; + } + + /** + * {@inheritdoc} + */ + public function getTypesFromConstructor(string $class, string $property): ?array + { + $docBlock = $this->getDocBlockFromConstructor($class, $property); + + if (!$docBlock) { + return null; + } + + $types = []; + /** @var DocBlock\Tags\Var_|DocBlock\Tags\Return_|DocBlock\Tags\Param $tag */ + foreach ($docBlock->getTagsByName('param') as $tag) { + if ($tag && null !== $tag->getType()) { + $types[] = $this->phpDocTypeHelper->getTypes($tag->getType()); + } + } + + if (!isset($types[0]) || [] === $types[0]) { + return null; + } + + return array_merge([], ...$types); + } + + private function getDocBlockFromConstructor(string $class, string $property): ?DocBlock + { + try { + $reflectionClass = new \ReflectionClass($class); + } catch (\ReflectionException $e) { + return null; + } + $reflectionConstructor = $reflectionClass->getConstructor(); + if (!$reflectionConstructor) { + return null; + } + + try { + $docBlock = $this->docBlockFactory->create($reflectionConstructor, $this->contextFactory->createFromReflector($reflectionConstructor)); + + return $this->filterDocBlockParams($docBlock, $property); + } catch (\InvalidArgumentException $e) { + return null; + } + } + + private function filterDocBlockParams(DocBlock $docBlock, string $allowedParam): DocBlock + { + $tags = array_values(array_filter($docBlock->getTagsByName('param'), function ($tag) use ($allowedParam) { + return $tag instanceof DocBlock\Tags\Param && $allowedParam === $tag->getVariableName(); + })); + + return new DocBlock($docBlock->getSummary(), $docBlock->getDescription(), $tags, $docBlock->getContext(), + $docBlock->getLocation(), $docBlock->isTemplateStart(), $docBlock->isTemplateEnd()); + } + + /** + * @return array{DocBlock|null, int|null, string|null} + */ + private function getDocBlock(string $class, string $property): array + { + $propertyHash = sprintf('%s::%s', $class, $property); + + if (isset($this->docBlocks[$propertyHash])) { + return $this->docBlocks[$propertyHash]; + } + + $ucFirstProperty = ucfirst($property); + + switch (true) { + case [$docBlock, $prefix] = $this->getDocBlockFromMethod($class, $ucFirstProperty, self::MUTATOR): + $data = [$docBlock, self::MUTATOR, $prefix]; + break; + + case [$docBlock] = $this->getDocBlockFromMethod($class, $ucFirstProperty, self::ACCESSOR): + $data = [$docBlock, self::ACCESSOR, null]; + break; + + case $docBlock = $this->getDocBlockFromProperty($class, $property): + $data = [$docBlock, self::PROPERTY, null]; + break; + + default: + $data = [null, null, null]; + } + + return $this->docBlocks[$propertyHash] = $data; + } + + private function getDocBlockFromProperty(string $class, string $property): ?DocBlock + { + // Use a ReflectionProperty instead of $class to get the parent class if applicable + try { + $reflectionProperty = new \ReflectionProperty($class, $property); + } catch (\ReflectionException $e) { + return null; + } + + $reflector = $reflectionProperty->getDeclaringClass(); + + foreach ($reflector->getTraits() as $trait) { + if ($trait->hasProperty($property)) { + return $this->getDocBlockFromProperty($trait->getName(), $property); + } + } + + try { + return $this->docBlockFactory->create($reflectionProperty, $this->createFromReflector($reflector)); + } catch (\InvalidArgumentException|\RuntimeException $e) { + return null; + } + } + + /** + * @return array{DocBlock, string}|null + */ + private function getDocBlockFromMethod(string $class, string $ucFirstProperty, int $type): ?array + { + $prefixes = self::ACCESSOR === $type ? $this->accessorPrefixes : $this->mutatorPrefixes; + $prefix = null; + + foreach ($prefixes as $prefix) { + $methodName = $prefix.$ucFirstProperty; + + try { + $reflectionMethod = new \ReflectionMethod($class, $methodName); + if ($reflectionMethod->isStatic()) { + continue; + } + + if ( + (self::ACCESSOR === $type && 0 === $reflectionMethod->getNumberOfRequiredParameters()) || + (self::MUTATOR === $type && $reflectionMethod->getNumberOfParameters() >= 1) + ) { + break; + } + } catch (\ReflectionException $e) { + // Try the next prefix if the method doesn't exist + } + } + + if (!isset($reflectionMethod)) { + return null; + } + + $reflector = $reflectionMethod->getDeclaringClass(); + + foreach ($reflector->getTraits() as $trait) { + if ($trait->hasMethod($methodName)) { + return $this->getDocBlockFromMethod($trait->getName(), $ucFirstProperty, $type); + } + } + + try { + return [$this->docBlockFactory->create($reflectionMethod, $this->createFromReflector($reflector)), $prefix]; + } catch (\InvalidArgumentException|\RuntimeException $e) { + return null; + } + } + + /** + * Prevents a lot of redundant calls to ContextFactory::createForNamespace(). + */ + private function createFromReflector(\ReflectionClass $reflector): Context + { + $cacheKey = $reflector->getNamespaceName().':'.$reflector->getFileName(); + + if (isset($this->contexts[$cacheKey])) { + return $this->contexts[$cacheKey]; + } + + $this->contexts[$cacheKey] = $this->contextFactory->createFromReflector($reflector); + + return $this->contexts[$cacheKey]; + } +} diff --git a/Documentation/Changelog/2.1.0.rst b/Documentation/Changelog/2.1.0.rst index 810ff31..5720da7 100644 --- a/Documentation/Changelog/2.1.0.rst +++ b/Documentation/Changelog/2.1.0.rst @@ -34,6 +34,9 @@ Fixes The logging is now adjusted to only log errors. The file will be checked for each test that does not expect errors to happen. +* Handle incoming array instead of string for ``AccessibilityCertification``. + That prevents mapping exceptions for objects containing the corresponding certification with more info than a single value. + Tasks ----- diff --git a/Tests/Functional/Fixtures/Import/Guzzle/thuecat.org/resources/attraction-with-accessibility-specification.json b/Tests/Functional/Fixtures/Import/Guzzle/thuecat.org/resources/attraction-with-accessibility-specification.json new file mode 100644 index 0000000..a3d1e5c --- /dev/null +++ b/Tests/Functional/Fixtures/Import/Guzzle/thuecat.org/resources/attraction-with-accessibility-specification.json @@ -0,0 +1,54 @@ +{ + "@context": { + "cdb": "https://thuecat.org/ontology/cdb/1.0/", + "dachkg": "https://thuecat.org/ontology/dachkg/1.0/", + "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#", + "schema": "http://schema.org/", + "sh": "http://www.w3.org/ns/shacl#", + "thuecat": "https://thuecat.org/ontology/thuecat/1.0/", + "ttgds": "https://thuecat.org/ontology/ttgds/1.0/", + "xsd": "http://www.w3.org/2001/XMLSchema#" + }, + "@graph": [ + { + "@id": "https://thuecat.org/resources/attraction-with-accessibility-specification", + "@type": [ + "schema:Place", + "schema:Thing", + "schema:TouristAttraction", + "ttgds:PointOfInterest" + ], + "schema:availableLanguage": [ + { + "@type": "thuecat:Language", + "@value": "thuecat:German" + }, + { + "@type": "thuecat:Language", + "@value": "thuecat:English" + } + ], + "schema:name": [ + { + "@language": "de", + "@value": "Attraktion mit accessibility specification" + }, + { + "@language": "en", + "@value": "Attraction with accessibility specification" + } + ], + "thuecat:contentResponsible": { + "@id": "https://thuecat.org/resources/018132452787-ngbe" + }, + "thuecat:accessibilitySpecification": { + "@id": "https://thuecat.org/resources/e_331baf4eeda4453db920dde62f7e6edc-rfa-accessibility-specification.json" + } + } + ] +} diff --git a/Tests/Functional/Fixtures/Import/Guzzle/thuecat.org/resources/e_331baf4eeda4453db920dde62f7e6edc-rfa-accessibility-specification.json b/Tests/Functional/Fixtures/Import/Guzzle/thuecat.org/resources/e_331baf4eeda4453db920dde62f7e6edc-rfa-accessibility-specification.json new file mode 100644 index 0000000..1fa0756 --- /dev/null +++ b/Tests/Functional/Fixtures/Import/Guzzle/thuecat.org/resources/e_331baf4eeda4453db920dde62f7e6edc-rfa-accessibility-specification.json @@ -0,0 +1,767 @@ +{ + "@context": { + "cdb": "https://thuecat.org/ontology/cdb/1.0/", + "dbo": "http://dbpedia.org/ontology/", + "dsv": "http://ontologies.sti-innsbruck.at/dsv/", + "epapp": "https://thuecat.org/ontology/epapp/1.0/", + "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#", + "schema": "http://schema.org/", + "sh": "http://www.w3.org/ns/shacl#", + "thuecat": "https://thuecat.org/ontology/thuecat/1.0/", + "ttgds": "https://thuecat.org/ontology/ttgds/1.0/", + "xsd": "http://www.w3.org/2001/XMLSchema#" + }, + "@graph": [ + { + "@id": "https://thuecat.org/resources/e_331baf4eeda4453db920dde62f7e6edc-rfa-accessibility-specification", + "@type": [ + "schema:Thing", + "schema:Intangible", + "thuecat:AccessibilitySpecification", + "ttgds:AccessibilitySpecification" + ], + "schema:name": [ + { + "@language": "en", + "@value": "Attraction with accessibility specification" + }, + { + "@language": "de", + "@value": "Attraktion mit accessibility specification" + } + ], + "thuecat:accessibilityCertification": { + "@id": "genid-9d018924d60a4c65b2f8aabc404b7eeb955032-b0", + "@type": [ + "schema:Thing", + "schema:Intangible", + "thuecat:AccessibilityCertification" + ], + "schema:image": [ + { + "@id": "genid-9d018924d60a4c65b2f8aabc404b7eeb955032-b1", + "@type": [ + "schema:Thing", + "schema:CreativeWork", + "schema:MediaObject", + "schema:ImageObject", + "http://purl.org/dc/dcmitype/Image" + ], + "schema:inLanguage": { + "@type": "http://www.w3.org/2001/XMLSchema#string", + "@value": "de" + }, + "schema:url": { + "@type": "http://schema.org/URL", + "@value": "https://partner-api.reisen-fuer-alle.de/barrierefrei/assets/icons/certificates/certified_accessibility_de.svg" + } + }, + { + "@id": "genid-9d018924d60a4c65b2f8aabc404b7eeb955032-b2", + "@type": [ + "schema:Thing", + "schema:CreativeWork", + "schema:MediaObject", + "schema:ImageObject", + "http://purl.org/dc/dcmitype/Image" + ], + "schema:inLanguage": { + "@type": "http://www.w3.org/2001/XMLSchema#string", + "@value": "en" + }, + "schema:url": { + "@type": "http://schema.org/URL", + "@value": "https://partner-api.reisen-fuer-alle.de/barrierefrei/assets/icons/certificates/certified_accessibility_en.svg" + } + } + ], + "schema:logo": [ + { + "@id": "genid-9d018924d60a4c65b2f8aabc404b7eeb955032-b1", + "@type": [ + "schema:Thing", + "schema:CreativeWork", + "schema:MediaObject", + "schema:ImageObject", + "http://purl.org/dc/dcmitype/Image" + ], + "schema:inLanguage": { + "@type": "http://www.w3.org/2001/XMLSchema#string", + "@value": "de" + }, + "schema:url": { + "@type": "http://schema.org/URL", + "@value": "https://partner-api.reisen-fuer-alle.de/barrierefrei/assets/icons/certificates/certified_accessibility_de.svg" + } + }, + { + "@id": "genid-9d018924d60a4c65b2f8aabc404b7eeb955032-b2", + "@type": [ + "schema:Thing", + "schema:CreativeWork", + "schema:MediaObject", + "schema:ImageObject", + "http://purl.org/dc/dcmitype/Image" + ], + "schema:inLanguage": { + "@type": "http://www.w3.org/2001/XMLSchema#string", + "@value": "en" + }, + "schema:url": { + "@type": "http://schema.org/URL", + "@value": "https://partner-api.reisen-fuer-alle.de/barrierefrei/assets/icons/certificates/certified_accessibility_en.svg" + } + } + ], + "schema:validFrom": { + "@type": "xsd:string", + "@value": "2023-03-01" + }, + "schema:validThrough": { + "@type": "xsd:string", + "@value": "2026-02-28" + }, + "thuecat:accessibilityCertificationStatus": { + "@type": "thuecat:AccessibilityCertificationStatus", + "@value": "thuecat:AccessibilityChecked" + }, + "thuecat:certificationAccessibilityDeaf": { + "@id": "genid-9d018924d60a4c65b2f8aabc404b7eeb955032-b3", + "@type": [ + "schema:Thing", + "schema:Intangible", + "schema:StructuredValue", + "schema:PropertyValue" + ], + "schema:value": { + "@type": "thuecat:CertificationLevel", + "@value": "thuecat:None" + } + }, + "thuecat:certificationAccessibilityMental": { + "@id": "genid-9d018924d60a4c65b2f8aabc404b7eeb955032-b4", + "@type": [ + "schema:Thing", + "schema:Intangible", + "schema:StructuredValue", + "schema:PropertyValue" + ], + "schema:value": { + "@type": "thuecat:CertificationLevel", + "@value": "thuecat:None" + } + }, + "thuecat:certificationAccessibilityPartiallyDeaf": { + "@id": "genid-9d018924d60a4c65b2f8aabc404b7eeb955032-b5", + "@type": [ + "schema:Thing", + "schema:Intangible", + "schema:StructuredValue", + "schema:PropertyValue" + ], + "schema:image": { + "@type": "schema:URL", + "@value": "https://partner-api.reisen-fuer-alle.de/barrierefrei/assets/icons/certificates/partially_deaf.svg" + }, + "schema:logo": { + "@type": "schema:URL", + "@value": "https://partner-api.reisen-fuer-alle.de/barrierefrei/assets/icons/certificates/partially_deaf.svg" + }, + "schema:value": { + "@type": "thuecat:CertificationLevel", + "@value": "thuecat:Full" + } + }, + "thuecat:certificationAccessibilityPartiallyVisual": { + "@id": "genid-9d018924d60a4c65b2f8aabc404b7eeb955032-b6", + "@type": [ + "schema:Thing", + "schema:Intangible", + "schema:StructuredValue", + "schema:PropertyValue" + ], + "schema:image": { + "@type": "schema:URL", + "@value": "https://partner-api.reisen-fuer-alle.de/barrierefrei/assets/icons/certificates/partially_visual_info.svg" + }, + "schema:logo": { + "@type": "schema:URL", + "@value": "https://partner-api.reisen-fuer-alle.de/barrierefrei/assets/icons/certificates/partially_visual_info.svg" + }, + "schema:value": { + "@type": "thuecat:CertificationLevel", + "@value": "thuecat:Info" + } + }, + "thuecat:certificationAccessibilityVisual": { + "@id": "genid-9d018924d60a4c65b2f8aabc404b7eeb955032-b7", + "@type": [ + "schema:Thing", + "schema:Intangible", + "schema:StructuredValue", + "schema:PropertyValue" + ], + "schema:image": { + "@type": "schema:URL", + "@value": "https://partner-api.reisen-fuer-alle.de/barrierefrei/assets/icons/certificates/visual_info.svg" + }, + "schema:logo": { + "@type": "schema:URL", + "@value": "https://partner-api.reisen-fuer-alle.de/barrierefrei/assets/icons/certificates/visual_info.svg" + }, + "schema:value": { + "@type": "thuecat:CertificationLevel", + "@value": "thuecat:Info" + } + }, + "thuecat:certificationAccessibilityWalking": { + "@id": "genid-9d018924d60a4c65b2f8aabc404b7eeb955032-b8", + "@type": [ + "schema:Thing", + "schema:Intangible", + "schema:StructuredValue", + "schema:PropertyValue" + ], + "schema:image": { + "@type": "schema:URL", + "@value": "https://partner-api.reisen-fuer-alle.de/barrierefrei/assets/icons/certificates/walking.svg" + }, + "schema:logo": { + "@type": "schema:URL", + "@value": "https://partner-api.reisen-fuer-alle.de/barrierefrei/assets/icons/certificates/walking.svg" + }, + "schema:value": { + "@type": "thuecat:CertificationLevel", + "@value": "thuecat:Full" + } + }, + "thuecat:certificationAccessibilityWheelchair": { + "@id": "genid-9d018924d60a4c65b2f8aabc404b7eeb955032-b9", + "@type": [ + "schema:Thing", + "schema:Intangible", + "schema:StructuredValue", + "schema:PropertyValue" + ], + "schema:image": { + "@type": "schema:URL", + "@value": "https://partner-api.reisen-fuer-alle.de/barrierefrei/assets/icons/certificates/wheelchair.svg" + }, + "schema:logo": { + "@type": "schema:URL", + "@value": "https://partner-api.reisen-fuer-alle.de/barrierefrei/assets/icons/certificates/wheelchair.svg" + }, + "schema:value": { + "@type": "thuecat:CertificationLevel", + "@value": "thuecat:Full" + } + } + }, + "thuecat:accessibilitySearchCriteria": [ + { + "@type": "thuecat:facilityAccessibilityWalking", + "@value": "thuecat:AllRoomsStepFreeAccess" + }, + { + "@type": "thuecat:facilityAccessibilityVisual", + "@value": "thuecat:AssistanceDogsWelcome" + }, + { + "@type": "thuecat:facilityAccessibilityWalking", + "@value": "thuecat:EightyCMWidthPassageWays" + }, + { + "@type": "thuecat:facilityAccessibilityWalking", + "@value": "thuecat:HingedGrabRailToilet" + }, + { + "@type": "thuecat:facilityAccessibilityWalking", + "@value": "thuecat:LateralAccessibleToilet" + }, + { + "@type": "thuecat:facilityAccessibilityWalking", + "@value": "thuecat:ParkingPeopleWithDisabilities" + }, + { + "@type": "thuecat:facilityAccessibilityWalking", + "@value": "thuecat:SeventyCMWidthPassageWays" + }, + { + "@type": "thuecat:facilityAccessibilityWalking", + "@value": "thuecat:StepFreeAccess" + }, + { + "@type": "thuecat:facilityAccessibilityWalking", + "@value": "thuecat:ToiletsPeopleWithDisabilities" + }, + { + "@type": "thuecat:facilityAccessibilityWalking", + "@value": "thuecat:NinetyCMWidthPassageWays" + }, + { + "@type": "thuecat:facilityAccessibilityVisual", + "@value": "thuecat:VisuallyContrastingStepEdges" + }, + { + "@type": "thuecat:facilityAccessibilityDeaf", + "@value": "thuecat:AudioInductionLoop" + } + ], + "thuecat:shortDescriptionAccessibilityAllGenerations": [ + { + "@language": "de", + "@value": "Einige \nHinweise zur Barrierefreiheit haben wir nachfolgend zusammengestellt. Detaillierte Angaben finden Sie im Pr\u00fcfbericht. \nParkm\u00f6glichkeiten im Parkhaus am Domplatz. \nIn 150 m Entfernung befindet sich die Bushaltestelle auf dem Petersberg. Die Stra\u00dfenbahnhaltestelle Domplatz (Linie 2, 3, 6) ist etwa 800 Meter entfernt. Zum Petersberg f\u00fchrt ein Panoramaweg von 600 m L\u00e4nge und max. 6 % Steigung sowie ein Aufzug. Die Rampe vom Domplatz zum Panoramaweg hat eine maximale Neigung von 6 % und eine Gesamtl\u00e4nge von 24 m (Zwischenpodeste vorhanden). Die Aufzugkabine vom Panoramaweg zur Zitadelle ist 160 cm x 240 cm gro\u00df. \nDie Wege zum Eingang sind leicht begeh- und befahrbar und haben eine maximale L\u00e4ngsneigung von 6 %. \nDer Eingang ist visuell kontrastreich gestaltet.\nDas Geb\u00e4ude ist stufenlos zug\u00e4nglich.\nAlle f\u00fcr den Gast nutzbaren und erhobenen R\u00e4ume und Einrichtungen sind stufenlos oder \u00fcber Aufz\u00fcge oder eine Rampe zug\u00e4nglich. Die Aufzugkabine im Geb\u00e4ude ist 110 cm x 220 cm gro\u00df. Ein abgehender Notruf in den Aufz\u00fcgen wird akustisch best\u00e4tigt. Alternativ sind Treppen vorhanden. Treppen im Geb\u00e4ude weisen mindestens an der ersten und letzten Stufe visuell kontrastreiche Kanten auf, die Treppen vom Domplatz zur Zitadelle auf dem Petersberg jedoch nicht. Treppen haben beidseitigen Handlauf.\nAlle f\u00fcr den Gast nutzbaren und erhobenen T\u00fcren/Durchg\u00e4nge sind mindestens 90 cm breit. Es gibt Glast\u00fcren ohne Sicherheitsmarkierungen. \nAlle erhobenen und f\u00fcr den Gast nutzbaren Bereiche sind gut, d.h. hell und blendfrei, ausgeleuchtet.\nEs gibt eine induktive H\u00f6ranlage.\nDie Exponate sind allgemein gut ausgeleuchtet. Die Informationen zu den Exponaten werden schriftlich vermittelt und sind visuell kontrastreich gestaltet. Es gibt teilweise akustische und fotorealistische Informationen zu den Exponaten.\n\u00d6ffentliche Toiletten vorhanden.\nEs werden F\u00fchrungen f\u00fcr Menschen mit Gehbehinderung angeboten. Die gesamte Route der F\u00fchrung ist stufenlos befahrbar. Es stehen mobile oder feste Sitzgelegenheiten zur Verf\u00fcgung, die w\u00e4hrend der F\u00fchrung benutzt werden k\u00f6nnen. F\u00fcr Menschen mit H\u00f6rbehinderung werden F\u00fchrungen mit FM-Anlagen erm\u00f6glicht (z.B. Kopfh\u00f6rer, Halsringschleifen). Es werden F\u00fchrungen f\u00fcr Menschen mit Sehbehinderung und blinde Menschen angeboten. W\u00e4hrend der F\u00fchrungen werden Exponate zum Tasten integriert. F\u00fcr alle F\u00fchrungen ist eine Voranmeldung notwendig.\n" + }, + { + "@language": "en", + "@value": "We have compiled some information on accessibility below. Detailed information can be found in the test report. \nParking is available in the parking garage on Domplatz. \nThe bus stop on Petersberg is 150 meters away. The Domplatz streetcar stop (lines 2, 3, 6) is about 800 meters away. A panoramic path 600 meters long with a maximum gradient of 6% and an elevator lead to the Petersberg. The ramp from Domplatz to the Panoramaweg has a maximum incline of 6% and a total length of 24 meters (intermediate landings available). The elevator cabin from the Panoramaweg to the Zitadelle is 160 cm x 240 cm. \nThe paths to the entrance are easy to walk and drive on and have a maximum longitudinal slope of 6%. \nThe entrance is visually contrasting.\nThe building is accessible without steps.\nAll rooms and facilities that can be used and elevated for guests are accessible without steps or via elevators or a ramp. The elevator cabin in the building is 110 cm x 220 cm. An outgoing emergency call in the elevators is confirmed acoustically. Alternatively, stairs are available. Stairs in the building have visually contrasting edges at least on the first and last steps, but the stairs from Domplatz to the Zitadelle on Petersberg do not. Stairs have handrails on both sides.\nAll doors/passages that can be used by guests and are raised are at least 90 cm wide. There are glass doors without safety markings. \nAll raised and usable areas for the guest are well lit, i.e. bright and glare-free.\nThere is an inductive hearing system.\nExhibits are generally well lit. Exhibit information is provided in writing and is visually contrasting. There is partial audio and photorealistic information about the exhibits.\nPublic restrooms available.\nGuided tours are available for people with walking disabilities. The entire tour route is accessible without steps. Mobile or fixed seating is available for use during the tour. Guided tours with FM equipment are made possible for people with hearing disabilities (e.g. headphones, neck ring loops). Guided tours are provided for people with visual impairments and blind people. Touch exhibits will be integrated during the tours. Pre-registration is required for all tours.\n" + }, + { + "@id": "genid-9d018924d60a4c65b2f8aabc404b7eeb955032-b10", + "@type": [ + "schema:Thing", + "schema:Intangible", + "schema:ComputerLanguage", + "thuecat:Html" + ], + "schema:value": { + "@language": "de", + "@value": "

 Einige Hinweise zur Barrierefreiheit haben wir nachfolgend zusammengestellt. Detaillierte Angaben finden Sie im Pr\u00fcfbericht. 

\n" + } + }, + { + "@id": "genid-9d018924d60a4c65b2f8aabc404b7eeb955032-b11", + "@type": [ + "schema:Thing", + "schema:Intangible", + "schema:ComputerLanguage", + "thuecat:Html" + ], + "schema:value": { + "@language": "en", + "@value": "

We have compiled some information on accessibility below. Detailed information can be found in the test report. 

\n" + } + } + ], + "thuecat:shortDescriptionAccessibilityDeaf": [ + { + "@language": "en", + "@value": "All areas relevant for testing meet the quality criteria of the label \"\nAccessibility certified - accessible for people with hearing impairment\".\nSome \ninformation on accessibility are listed below. For detailed information please see the evaluation report. \nThe alarm is clearly visible at the counter and in the WCs.\nThere is an audio induction loop system. \nAn outgoing emergency call in the elevators is confirmed acoustically. Alternatively, stairs are available.\nInformation about the exhibits is provided in writing. There is partial audio and photorealistic information about the exhibits.\nGuided tours are available for people with hearing disabilities, but not for deaf people. Advance reservations are required.\nGuided tours with FM systems (e.g. headphones, neck loops) are available for people with hearing impairments. \n" + }, + { + "@language": "de", + "@value": "Alle pr\u00fcfrelevanten Bereiche erf\u00fcllen die Qualit\u00e4tskriterien der Kennzeichnung \u201e\nBarrierefreiheit gepr\u00fcft \u2013 barrierefrei f\u00fcr Menschen mit H\u00f6rbehinderung\u201c.\nEinige \nHinweise zur Barrierefreiheit haben wir nachfolgend zusammengestellt. Detaillierte Angaben finden Sie im Pr\u00fcfbericht.\nDer Alarm ist am Tresen und in den WCs optisch deutlich wahrnehmbar.\nEs gibt eine induktive H\u00f6ranlage.\nEin abgehender Notruf in den Aufz\u00fcgen wird akustisch best\u00e4tigt. Alternativ sind Treppen vorhanden.\nDie Informationen zu den Exponaten werden schriftlich vermittelt. Es gibt teilweise akustische und fotorealistische Informationen zu den Exponaten.\nEs werden F\u00fchrungen f\u00fcr Menschen mit H\u00f6rbehinderung angeboten, jedoch nicht f\u00fcr geh\u00f6rlose Menschen. Es ist eine Voranmeldung notwendig.\nEs werden f\u00fcr Menschen mit H\u00f6rbehinderung F\u00fchrungen mit FM-Anlagen erm\u00f6glicht (z.B. Kopfh\u00f6rer, Halsringschleifen).\n" + }, + { + "@id": "genid-9d018924d60a4c65b2f8aabc404b7eeb955032-b12", + "@type": [ + "schema:Thing", + "schema:Intangible", + "schema:ComputerLanguage", + "thuecat:Html" + ], + "schema:value": { + "@language": "de", + "@value": "

Alle pr\u00fcfrelevanten Bereiche erf\u00fcllen die Qualit\u00e4tskriterien der Kennzeichnung \u201eBarrierefreiheit gepr\u00fcft \u2013 barrierefrei f\u00fcr Menschen mit H\u00f6rbehinderung\u201c.

\n

Einige Hinweise zur Barrierefreiheit haben wir nachfolgend zusammengestellt. Detaillierte Angaben finden Sie im Pr\u00fcfbericht.

\n" + } + }, + { + "@id": "genid-9d018924d60a4c65b2f8aabc404b7eeb955032-b13", + "@type": [ + "schema:Thing", + "schema:Intangible", + "schema:ComputerLanguage", + "thuecat:Html" + ], + "schema:value": { + "@language": "en", + "@value": "

All areas relevant for testing meet the quality criteria of the label \"Accessibility certified - accessible for people with hearing impairment\".

\n

Some information on accessibility are listed below. For detailed information please see the evaluation report. 

\n" + } + } + ], + "thuecat:shortDescriptionAccessibilityMental": [ + { + "@language": "de", + "@value": "Einige \nHinweise zur Barrierefreiheit haben wir nachfolgend zusammengestellt. Detaillierte Angaben finden Sie im Pr\u00fcfbericht.\nName bzw. Logo des Betriebs sind von au\u00dfen klar erkennbar.\nDie Ziele der Wege sind in Sichtweite oder es sind Wegezeichen in st\u00e4ndig sichtbarem Abstand vorhanden.\nInformationen zu den Exponaten werden teilweise in Leichter Sprache bereitgestellt.\nEs werden F\u00fchrungen f\u00fcr Menschen mit kognitiven Beeintr\u00e4chtigungen angeboten. Es ist eine Voranmeldung notwendig.\nDie F\u00fchrung f\u00fcr Menschen mit kognitiven Beeintr\u00e4chtigungen angeboten.\n" + }, + { + "@language": "en", + "@value": "Some \ninformation on accessibility are listed below. For detailed information please see the evaluation report. \nThe name or logo of the operation is clearly visible from the outside.\nThe destinations of the paths are within sight or there are path signs at a constantly visible distance.\nInformation about exhibits is provided in plain language in some cases.\nGuided tours are provided for people with cognitive impairments. Advance registration is required.\nThe guided tour for people with cognitive impairments offered.\n" + }, + { + "@id": "genid-9d018924d60a4c65b2f8aabc404b7eeb955032-b14", + "@type": [ + "schema:Thing", + "schema:Intangible", + "schema:ComputerLanguage", + "thuecat:Html" + ], + "schema:value": { + "@language": "de", + "@value": "

Einige Hinweise zur Barrierefreiheit haben wir nachfolgend zusammengestellt. Detaillierte Angaben finden Sie im Pr\u00fcfbericht.

\n" + } + }, + { + "@id": "genid-9d018924d60a4c65b2f8aabc404b7eeb955032-b15", + "@type": [ + "schema:Thing", + "schema:Intangible", + "schema:ComputerLanguage", + "thuecat:Html" + ], + "schema:value": { + "@language": "en", + "@value": "

Some information on accessibility are listed below. For detailed information please see the evaluation report.   

\n" + } + } + ], + "thuecat:shortDescriptionAccessibilityVisual": [ + { + "@language": "en", + "@value": "All areas relevant for testing meet the quality criteria of the label \"\nAccessibility certified - partially accessible for people with visual impairments and blind people\".\nSome \ninformation on accessibility are listed below. For detailed information please see the evaluation report. \nAssistance dogs may be brought into all relevant areas/rooms.\nThe entrance is visually contrasting.\nThere are glass doors without security markings. \nAll raised areas that can be used by the guest are well lit, i.e. bright and glare-free.\nThere are visually contrasting and tactile floor indicators in the entrance area.\nSignage is designed in easy-to-read, high-contrast lettering.\nAn outgoing emergency call in the elevators is confirmed acoustically. In the elevator in the visitor center, the stop position is announced by voice. The elevator from Domplatz to the Citadel has only 2 floors. The controls in both elevators are visually contrasting and tactilely detectable.\nStairs in the building have visually contrasting edges at least on the first and last steps, but the stairs from Domplatz to the Citadel on Petersberg do not.\nStairs have handrails on both sides.\nExhibits are generally well lit. \nInformation about the exhibits is predominantly provided in writing and is visually contrasting. There is some audio information about the exhibits. \nGuided tours are offered for people with visual impairments and blind people. Advance reservations are required.\nDuring the tours, exhibits are integrated for touching.\n" + }, + { + "@language": "de", + "@value": "Alle pr\u00fcfrelevanten Bereiche erf\u00fcllen die Qualit\u00e4tskriterien der Kennzeichnung \u201e\nBarrierefreiheit gepr\u00fcft \u2013 teilweise barrierefrei f\u00fcr Menschen mit Sehbehinderung und f\u00fcr blinde Menschen\u201c.\nEinige \nHinweise zur Barrierefreiheit haben wir nachfolgend zusammengestellt. Detaillierte Angaben finden Sie im Pr\u00fcfbericht.\nAssistenzhunde d\u00fcrfen in alle relevanten Bereiche/R\u00e4ume mitgebracht werden.\nDer Eingang ist visuell kontrastreich gestaltet.\nEs gibt Glast\u00fcren ohne Sicherheitsmarkierungen. \nAlle erhobenen und f\u00fcr den Gast nutzbaren Bereiche sind gut, d.h. hell und blendfrei, ausgeleuchtet.\nIm Eingangsbereich sind visuell kontrastreiche und taktil erfassbare Bodenindikatoren vorhanden.\nDie Beschilderung ist in gut lesbarer und kontrastreicher Schrift gestaltet.\nEin abgehender Notruf in den Aufz\u00fcgen wird akustisch best\u00e4tigt. Im Aufzug im Besucherzentrum wird die Halteposition durch Sprache angesagt. Der Aufzug vom Domplatz zur Zitadelle f\u00fchrt \u00fcber nur 2 Etagen. Die Bedienelemente in beiden Aufz\u00fcgen sind visuell kontrastreich gestaltet und taktil erfassbar.\nTreppen im Geb\u00e4ude weisen mindestens an der ersten und letzten Stufe visuell kontrastreiche Kanten auf, die Treppen vom Domplatz zur Zitadelle auf dem Petersberg jedoch nicht.\nTreppen haben beidseitigen Handlauf.\nDie Exponate sind allgemein gut ausgeleuchtet. \nDie Informationen zu den Exponaten werden \u00fcberwiegend schriftlich vermittelt und sind visuell kontrastreich gestaltet. Es gibt teilweise akustische Informationen zu den Exponaten. \nEs werden F\u00fchrungen f\u00fcr Menschen mit Sehbehinderung und blinde Menschen angeboten. Es ist eine Voranmeldung notwendig.\nW\u00e4hrend der F\u00fchrungen werden Exponate zum Tasten integriert. \n" + }, + { + "@id": "genid-9d018924d60a4c65b2f8aabc404b7eeb955032-b16", + "@type": [ + "schema:Thing", + "schema:Intangible", + "schema:ComputerLanguage", + "thuecat:Html" + ], + "schema:value": { + "@language": "de", + "@value": "

Alle pr\u00fcfrelevanten Bereiche erf\u00fcllen die Qualit\u00e4tskriterien der Kennzeichnung \u201eBarrierefreiheit gepr\u00fcft \u2013 teilweise barrierefrei f\u00fcr Menschen mit Sehbehinderung und f\u00fcr blinde Menschen\u201c.

\n

Einige Hinweise zur Barrierefreiheit haben wir nachfolgend zusammengestellt. Detaillierte Angaben finden Sie im Pr\u00fcfbericht.

\n" + } + }, + { + "@id": "genid-9d018924d60a4c65b2f8aabc404b7eeb955032-b17", + "@type": [ + "schema:Thing", + "schema:Intangible", + "schema:ComputerLanguage", + "thuecat:Html" + ], + "schema:value": { + "@language": "en", + "@value": "

All areas relevant for testing meet the quality criteria of the label \"Accessibility certified - partially accessible for people with visual impairments and blind people\".

\n

Some information on accessibility are listed below. For detailed information please see the evaluation report. 

\n" + } + } + ], + "thuecat:shortDescriptionAccessibilityWalking": [ + { + "@language": "en", + "@value": "All areas relevant for testing meet the quality criteria of the label \"\nAccessibility certified - accessible for people with walking disabilities and wheelchair users\".\nSome \ninformation on accessibility are listed below. For detailed information please see the evaluation report. \nThere are three marked parking spaces for people with disabilities (parking space size: 350 cm x 500 cm, 100 m distance from the entrance). \nThe bus stop on Petersberg is 150 m away. The streetcar stop Domplatz (line 2, 3, 6) is about 800 m away. You can get to the citadel from Domplatz via the panorama path and an elevator. \nThe paths to the entrance are easy to walk and drive on and have a maximum longitudinal gradient of 6%. \nThe building is accessible without steps.\nAll rooms and facilities that can be used and elevated for guests are accessible without steps or via elevators or a ramp.\nThe elevator cabin in the building is 110 cm x 220 cm. \nThe elevator cabin from the panoramic path to the citadel is 160 cm x 240 cm. \nThe ramp from the cathedral square to the Panoramaweg has a maximum slope of 6% and a total length of 24 m (intermediate landings available).\nAll doors/passages that can be used by guests and are raised are at least 90 cm wide.\nThe cash counter is 73 cm high at the lowest point. \nThe exhibits are predominantly visible while seated. Exhibit information is predominantly legible while seated. \nGuided tours are available for people with walking disabilities and wheelchair users. Advance reservations are required.\nMobile or fixed seating is available for people with walking disabilities to use during the tour.\nThe entire route of the guided tour is step-free for wheelchair users.\nPublic toilet for people with disabilities (basement)\nThe manoeuvring spaces are: \nin front of/behind the door, in front of the WC and in front of the washbasin at least 150 cm x 150 cm;\nto the left and right of the WC at least 90 cm x 70 cm. \nGrab rails are provided to the left and right of the WC. The grab rails are flipped up.\nThe sink is wheelchair compatible. \nThe mirror can be viewed while standing or sitting.\nThere is an alarm trigger.\n" + }, + { + "@language": "de", + "@value": "Alle pr\u00fcfrelevanten Bereiche erf\u00fcllen die Qualit\u00e4tskriterien der Kennzeichnung \n\"Barrierefreiheit gepr\u00fcft - barrierefrei f\u00fcr Menschen mit Gehbehinderung und Rollstuhlfahrer\".\nEinige \nHinweise zur Barrierefreiheit haben wir nachfolgend zusammengestellt. Detaillierte Angaben finden Sie im Pr\u00fcfbericht. \nEs sind drei gekennzeichnete Parkpl\u00e4tze f\u00fcr Menschen mit Behinderung vorhanden (Stellplatzgr\u00f6\u00dfe: 350 cm x 500 cm, 100 m Entfernung zum Eingang). \nIn 150 m Entfernung befindet sich die Bushaltestelle auf dem Petersberg. Die Stra\u00dfenbahnhaltestelle Domplatz (Linie 2, 3, 6) ist etwa 800 m entfernt. Zur Zitadelle gelangt man vom Domplatz \u00fcber den Panoramaweg und einen Aufzug. \nDie Wege zum Eingang sind leicht begeh- und befahrbar und haben eine maximale L\u00e4ngsneigung von 6 %. \nDas Geb\u00e4ude ist stufenlos zug\u00e4nglich.\nAlle f\u00fcr den Gast nutzbaren und erhobenen R\u00e4ume und Einrichtungen sind stufenlos oder \u00fcber Aufz\u00fcge oder eine Rampe zug\u00e4nglich.\nDie Aufzugkabine im Geb\u00e4ude ist 110 cm x 220 cm gro\u00df. \nDie Aufzugkabine vom Panoramaweg zur Zitadelle ist 160 cm x 240 cm gro\u00df. \nDie Rampe vom Domplatz zum Panoramaweg hat eine maximale Neigung von 6 % und eine Gesamtl\u00e4nge von 24 m (Zwischenpodeste vorhanden).\nAlle f\u00fcr den Gast nutzbaren und erhobenen T\u00fcren/Durchg\u00e4nge sind mindestens 90 cm breit.\nDer Kassentresen ist an der niedrigsten Stelle 73 cm hoch. \nDie Exponate sind \u00fcberwiegend im Sitzen sichtbar. Die Informationen zu den Exponaten sind \u00fcberwiegend im Sitzen lesbar. \nEs werden F\u00fchrungen f\u00fcr Menschen mit Gehbehinderung und Rollstuhlfahrer angeboten. Es ist eine Voranmeldung notwendig.\nEs stehen f\u00fcr Menschen mit Gehbehinderung mobile oder feste Sitzgelegenheiten zur Verf\u00fcgung, die w\u00e4hrend der F\u00fchrung benutzt werden k\u00f6nnen.\nDie gesamte Route der F\u00fchrung ist f\u00fcr Rollstuhlfahrer stufenlos befahrbar.\n\u00d6ffentliches WC f\u00fcr Menschen mit Behinderung (Untergeschoss)\nDie Bewegungsfl\u00e4chen betragen:\nvor/hinter der T\u00fcr, vor dem WC und vor dem Waschbecken mindestens 150 cm x 150 cm;\nlinks und rechts neben dem WC mindestens 90 cm x 70 cm. \nEs sind links und rechts vom WC Haltegriffe vorhanden. Die Haltegriffe sind hochklappbar.\nDas Waschbecken ist unterfahrbar.\nDer Spiegel ist im Stehen und Sitzen einsehbar.\nEs ist ein Alarmausl\u00f6ser vorhanden.\n" + }, + { + "@id": "genid-9d018924d60a4c65b2f8aabc404b7eeb955032-b18", + "@type": [ + "schema:Thing", + "schema:Intangible", + "schema:ComputerLanguage", + "thuecat:Html" + ], + "schema:value": { + "@language": "de", + "@value": "

Alle pr\u00fcfrelevanten Bereiche erf\u00fcllen die Qualit\u00e4tskriterien der Kennzeichnung \"Barrierefreiheit gepr\u00fcft - barrierefrei f\u00fcr Menschen mit Gehbehinderung und Rollstuhlfahrer\".

\n

Einige Hinweise zur Barrierefreiheit haben wir nachfolgend zusammengestellt. Detaillierte Angaben finden Sie im Pr\u00fcfbericht. 

\n\n

\u00d6ffentliches WC f\u00fcr Menschen mit Behinderung (Untergeschoss)

\n" + } + }, + { + "@id": "genid-9d018924d60a4c65b2f8aabc404b7eeb955032-b19", + "@type": [ + "schema:Thing", + "schema:Intangible", + "schema:ComputerLanguage", + "thuecat:Html" + ], + "schema:value": { + "@language": "en", + "@value": "

All areas relevant for testing meet the quality criteria of the label \"Accessibility certified - accessible for people with walking disabilities and wheelchair users\".

\n

Some information on accessibility are listed below. For detailed information please see the evaluation report. 

\n\n

Public toilet for people with disabilities (basement)

\n" + } + } + ], + "thuecat:urlDescriptionAccessibilityAllGenerations": [ + { + "@id": "genid-9d018924d60a4c65b2f8aabc404b7eeb955032-b20", + "@type": [ + "schema:Thing", + "schema:CreativeWork", + "schema:DigitalDocument" + ], + "schema:inLanguage": { + "@type": "xsd:string", + "@value": "de" + }, + "schema:url": { + "@type": "schema:URL", + "@value": "https://partner-api.reisen-fuer-alle.de/bfdbpdfs/service_provider/6594/Generationen_Kommandantenhaus__Ausstellung_und_Besucherzentrum.pdf" + } + }, + { + "@id": "genid-9d018924d60a4c65b2f8aabc404b7eeb955032-b21", + "@type": [ + "schema:Thing", + "schema:CreativeWork", + "schema:DigitalDocument" + ], + "schema:inLanguage": { + "@type": "xsd:string", + "@value": "en" + }, + "schema:url": { + "@type": "schema:URL", + "@value": "https://partner-api.reisen-fuer-alle.de/bfdbpdfs/service_provider/6594/Generations_Commandants_house_-_exhibition_and_visitor_center.pdf" + } + } + ], + "thuecat:urlDescriptionAccessibilityAllergic": [ + { + "@id": "genid-9d018924d60a4c65b2f8aabc404b7eeb955032-b22", + "@type": [ + "schema:Thing", + "schema:CreativeWork", + "schema:DigitalDocument" + ], + "schema:inLanguage": { + "@type": "xsd:string", + "@value": "de" + }, + "schema:url": { + "@type": "schema:URL", + "@value": "https://partner-api.reisen-fuer-alle.de/bfdbpdfs/service_provider/6594/Allergien_Kommandantenhaus__Ausstellung_und_Besucherzentrum.pdf" + } + }, + { + "@id": "genid-9d018924d60a4c65b2f8aabc404b7eeb955032-b23", + "@type": [ + "schema:Thing", + "schema:CreativeWork", + "schema:DigitalDocument" + ], + "schema:inLanguage": { + "@type": "xsd:string", + "@value": "en" + }, + "schema:url": { + "@type": "schema:URL", + "@value": "https://partner-api.reisen-fuer-alle.de/bfdbpdfs/service_provider/6594/Allergic_Commandants_house_-_exhibition_and_visitor_center.pdf" + } + } + ], + "thuecat:urlDescriptionAccessibilityDeaf": [ + { + "@id": "genid-9d018924d60a4c65b2f8aabc404b7eeb955032-b24", + "@type": [ + "schema:Thing", + "schema:CreativeWork", + "schema:DigitalDocument" + ], + "schema:inLanguage": { + "@type": "xsd:string", + "@value": "de" + }, + "schema:url": { + "@type": "schema:URL", + "@value": "https://partner-api.reisen-fuer-alle.de/bfdbpdfs/service_provider/6594/Hoeren_Kommandantenhaus__Ausstellung_und_Besucherzentrum.pdf" + } + }, + { + "@id": "genid-9d018924d60a4c65b2f8aabc404b7eeb955032-b25", + "@type": [ + "schema:Thing", + "schema:CreativeWork", + "schema:DigitalDocument" + ], + "schema:inLanguage": { + "@type": "xsd:string", + "@value": "en" + }, + "schema:url": { + "@type": "schema:URL", + "@value": "https://partner-api.reisen-fuer-alle.de/bfdbpdfs/service_provider/6594/Deaf_Commandants_house_-_exhibition_and_visitor_center.pdf" + } + } + ], + "thuecat:urlDescriptionAccessibilityMental": [ + { + "@id": "genid-9d018924d60a4c65b2f8aabc404b7eeb955032-b26", + "@type": [ + "schema:Thing", + "schema:CreativeWork", + "schema:DigitalDocument" + ], + "schema:inLanguage": { + "@type": "xsd:string", + "@value": "de" + }, + "schema:url": { + "@type": "schema:URL", + "@value": "https://partner-api.reisen-fuer-alle.de/bfdbpdfs/service_provider/6594/Kognitiv_Kommandantenhaus__Ausstellung_und_Besucherzentrum.pdf" + } + }, + { + "@id": "genid-9d018924d60a4c65b2f8aabc404b7eeb955032-b27", + "@type": [ + "schema:Thing", + "schema:CreativeWork", + "schema:DigitalDocument" + ], + "schema:inLanguage": { + "@type": "xsd:string", + "@value": "en" + }, + "schema:url": { + "@type": "schema:URL", + "@value": "https://partner-api.reisen-fuer-alle.de/bfdbpdfs/service_provider/6594/Mental_Commandants_house_-_exhibition_and_visitor_center.pdf" + } + } + ], + "thuecat:urlDescriptionAccessibilitySummary": [ + { + "@id": "genid-9d018924d60a4c65b2f8aabc404b7eeb955032-b28", + "@type": [ + "schema:Thing", + "schema:CreativeWork", + "schema:DigitalDocument" + ], + "schema:inLanguage": { + "@type": "xsd:string", + "@value": "de" + }, + "schema:url": { + "@type": "schema:URL", + "@value": "https://partner-api.reisen-fuer-alle.de/bfdbpdfs/service_provider/6594/Kurzbericht_Kommandantenhaus_Ausstellung_und_Besucherzentrum_PA-13326-2022_de.pdf" + } + }, + { + "@id": "genid-9d018924d60a4c65b2f8aabc404b7eeb955032-b29", + "@type": [ + "schema:Thing", + "schema:CreativeWork", + "schema:DigitalDocument" + ], + "schema:inLanguage": { + "@type": "xsd:string", + "@value": "en" + }, + "schema:url": { + "@type": "schema:URL", + "@value": "https://partner-api.reisen-fuer-alle.de/bfdbpdfs/service_provider/6594/Short_Report_Commandant_s_house_-_exhibition_and_visitor_center_PA-13326-2022_en.pdf" + } + } + ], + "thuecat:urlDescriptionAccessibilityVisual": [ + { + "@id": "genid-9d018924d60a4c65b2f8aabc404b7eeb955032-b30", + "@type": [ + "schema:Thing", + "schema:CreativeWork", + "schema:DigitalDocument" + ], + "schema:inLanguage": { + "@type": "xsd:string", + "@value": "de" + }, + "schema:url": { + "@type": "schema:URL", + "@value": "https://partner-api.reisen-fuer-alle.de/bfdbpdfs/service_provider/6594/Sehen_Kommandantenhaus__Ausstellung_und_Besucherzentrum.pdf" + } + }, + { + "@id": "genid-9d018924d60a4c65b2f8aabc404b7eeb955032-b31", + "@type": [ + "schema:Thing", + "schema:CreativeWork", + "schema:DigitalDocument" + ], + "schema:inLanguage": { + "@type": "xsd:string", + "@value": "en" + }, + "schema:url": { + "@type": "schema:URL", + "@value": "https://partner-api.reisen-fuer-alle.de/bfdbpdfs/service_provider/6594/Visual_Commandants_house_-_exhibition_and_visitor_center.pdf" + } + } + ], + "thuecat:urlDescriptionAccessibilityWalking": [ + { + "@id": "genid-9d018924d60a4c65b2f8aabc404b7eeb955032-b32", + "@type": [ + "schema:Thing", + "schema:CreativeWork", + "schema:DigitalDocument" + ], + "schema:inLanguage": { + "@type": "xsd:string", + "@value": "de" + }, + "schema:url": { + "@type": "schema:URL", + "@value": "https://partner-api.reisen-fuer-alle.de/bfdbpdfs/service_provider/6594/Gehen_Kommandantenhaus__Ausstellung_und_Besucherzentrum.pdf" + } + }, + { + "@id": "genid-9d018924d60a4c65b2f8aabc404b7eeb955032-b33", + "@type": [ + "schema:Thing", + "schema:CreativeWork", + "schema:DigitalDocument" + ], + "schema:inLanguage": { + "@type": "xsd:string", + "@value": "en" + }, + "schema:url": { + "@type": "schema:URL", + "@value": "https://partner-api.reisen-fuer-alle.de/bfdbpdfs/service_provider/6594/Walking_Commandants_house_-_exhibition_and_visitor_center.pdf" + } + } + ], + "thuecat:urlDescriptionAccessibilityWheelchair": [ + { + "@id": "genid-9d018924d60a4c65b2f8aabc404b7eeb955032-b34", + "@type": [ + "schema:Thing", + "schema:CreativeWork", + "schema:DigitalDocument" + ], + "schema:inLanguage": { + "@type": "xsd:string", + "@value": "de" + }, + "schema:url": { + "@type": "schema:URL", + "@value": "https://partner-api.reisen-fuer-alle.de/bfdbpdfs/service_provider/6594/Rollstuhl_Kommandantenhaus__Ausstellung_und_Besucherzentrum.pdf" + } + }, + { + "@id": "genid-9d018924d60a4c65b2f8aabc404b7eeb955032-b35", + "@type": [ + "schema:Thing", + "schema:CreativeWork", + "schema:DigitalDocument" + ], + "schema:inLanguage": { + "@type": "xsd:string", + "@value": "en" + }, + "schema:url": { + "@type": "schema:URL", + "@value": "https://partner-api.reisen-fuer-alle.de/bfdbpdfs/service_provider/6594/Wheelchair_Commandants_house_-_exhibition_and_visitor_center.pdf" + } + } + ] + } + ] +} diff --git a/Tests/Functional/Fixtures/Import/ImportsTouristAttractionWithAccessibilitySpecification.csv b/Tests/Functional/Fixtures/Import/ImportsTouristAttractionWithAccessibilitySpecification.csv new file mode 100644 index 0000000..4e41dfc --- /dev/null +++ b/Tests/Functional/Fixtures/Import/ImportsTouristAttractionWithAccessibilitySpecification.csv @@ -0,0 +1,4 @@ +"tx_thuecat_tourist_attraction",,,,,,,, +,"uid","pid","sys_language_uid","l18n_parent","l10n_source","remote_id","title" +,1,10,0,0,0,"https://thuecat.org/resources/attraction-with-accessibility-specification","Attraktion mit accessibility specification" +,2,10,1,1,1,"https://thuecat.org/resources/attraction-with-accessibility-specification","Attraction with accessibility specification" diff --git a/Tests/Functional/Fixtures/Import/ImportsTouristAttractionWithAccessibilitySpecification.xml b/Tests/Functional/Fixtures/Import/ImportsTouristAttractionWithAccessibilitySpecification.xml new file mode 100644 index 0000000..0754c1b --- /dev/null +++ b/Tests/Functional/Fixtures/Import/ImportsTouristAttractionWithAccessibilitySpecification.xml @@ -0,0 +1,76 @@ + + + + 1 + 0 + 1613400587 + 1613400558 + 1 + 4 + Rootpage + 1 + + + 10 + 1 + 1613400587 + 1613400558 + 1 + 254 + Storage folder + + + + 1 + 0 + English + en-us-gb + en + + + + 2 + 0 + French + fr + fr + + + + 1 + 0 + 1613400587 + 1613400558 + 1 + 0 + Tourist Attraction + static + + + + + + + 10 + + + + + + + + https://thuecat.org/resources/attraction-with-accessibility-certification + + + + 0 + + + + + + + + ]]> + + diff --git a/Tests/Functional/Fixtures/Import/ImportsTouristAttractionWithAccessibilitySpecificationEnglish.txt b/Tests/Functional/Fixtures/Import/ImportsTouristAttractionWithAccessibilitySpecificationEnglish.txt new file mode 100644 index 0000000..2c51a86 --- /dev/null +++ b/Tests/Functional/Fixtures/Import/ImportsTouristAttractionWithAccessibilitySpecificationEnglish.txt @@ -0,0 +1 @@ +{"accessibilityCertificationStatus":"AccessibilityChecked","certificationAccessibilityDeaf":"None","certificationAccessibilityMental":"None","certificationAccessibilityPartiallyDeaf":"Full","certificationAccessibilityPartiallyVisual":"Info","certificationAccessibilityVisual":"Info","certificationAccessibilityWalking":"Full","certificationAccessibilityWheelchair":"Full","accessibilitySearchCriteria":{"facilityAccessibilityWalking":["AllRoomsStepFreeAccess","EightyCMWidthPassageWays","HingedGrabRailToilet","LateralAccessibleToilet","ParkingPeopleWithDisabilities","SeventyCMWidthPassageWays","StepFreeAccess","ToiletsPeopleWithDisabilities","NinetyCMWidthPassageWays"],"facilityAccessibilityVisual":["AssistanceDogsWelcome","VisuallyContrastingStepEdges"],"facilityAccessibilityDeaf":["AudioInductionLoop"]},"shortDescriptionAccessibilityAllGenerations":"We have compiled some information on accessibility below. Detailed information can be found in the test report. \nParking is available in the parking garage on Domplatz. \nThe bus stop on Petersberg is 150 meters away. The Domplatz streetcar stop (lines 2, 3, 6) is about 800 meters away. A panoramic path 600 meters long with a maximum gradient of 6% and an elevator lead to the Petersberg. The ramp from Domplatz to the Panoramaweg has a maximum incline of 6% and a total length of 24 meters (intermediate landings available). The elevator cabin from the Panoramaweg to the Zitadelle is 160 cm x 240 cm. \nThe paths to the entrance are easy to walk and drive on and have a maximum longitudinal slope of 6%. \nThe entrance is visually contrasting.\nThe building is accessible without steps.\nAll rooms and facilities that can be used and elevated for guests are accessible without steps or via elevators or a ramp. The elevator cabin in the building is 110 cm x 220 cm. An outgoing emergency call in the elevators is confirmed acoustically. Alternatively, stairs are available. Stairs in the building have visually contrasting edges at least on the first and last steps, but the stairs from Domplatz to the Zitadelle on Petersberg do not. Stairs have handrails on both sides.\nAll doors\/passages that can be used by guests and are raised are at least 90 cm wide. There are glass doors without safety markings. \nAll raised and usable areas for the guest are well lit, i.e. bright and glare-free.\nThere is an inductive hearing system.\nExhibits are generally well lit. Exhibit information is provided in writing and is visually contrasting. There is partial audio and photorealistic information about the exhibits.\nPublic restrooms available.\nGuided tours are available for people with walking disabilities. The entire tour route is accessible without steps. Mobile or fixed seating is available for use during the tour. Guided tours with FM equipment are made possible for people with hearing disabilities (e.g. headphones, neck ring loops). Guided tours are provided for people with visual impairments and blind people. Touch exhibits will be integrated during the tours. Pre-registration is required for all tours.\n","shortDescriptionAccessibilityDeaf":"All areas relevant for testing meet the quality criteria of the label \"\nAccessibility certified - accessible for people with hearing impairment\".\nSome \ninformation on accessibility are listed below. For detailed information please see the evaluation report. \nThe alarm is clearly visible at the counter and in the WCs.\nThere is an audio induction loop system. \nAn outgoing emergency call in the elevators is confirmed acoustically. Alternatively, stairs are available.\nInformation about the exhibits is provided in writing. There is partial audio and photorealistic information about the exhibits.\nGuided tours are available for people with hearing disabilities, but not for deaf people. Advance reservations are required.\nGuided tours with FM systems (e.g. headphones, neck loops) are available for people with hearing impairments. \n","shortDescriptionAccessibilityMental":"Some \ninformation on accessibility are listed below. For detailed information please see the evaluation report. \nThe name or logo of the operation is clearly visible from the outside.\nThe destinations of the paths are within sight or there are path signs at a constantly visible distance.\nInformation about exhibits is provided in plain language in some cases.\nGuided tours are provided for people with cognitive impairments. Advance registration is required.\nThe guided tour for people with cognitive impairments offered.\n","shortDescriptionAccessibilityVisual":"All areas relevant for testing meet the quality criteria of the label \"\nAccessibility certified - partially accessible for people with visual impairments and blind people\".\nSome \ninformation on accessibility are listed below. For detailed information please see the evaluation report. \nAssistance dogs may be brought into all relevant areas\/rooms.\nThe entrance is visually contrasting.\nThere are glass doors without security markings. \nAll raised areas that can be used by the guest are well lit, i.e. bright and glare-free.\nThere are visually contrasting and tactile floor indicators in the entrance area.\nSignage is designed in easy-to-read, high-contrast lettering.\nAn outgoing emergency call in the elevators is confirmed acoustically. In the elevator in the visitor center, the stop position is announced by voice. The elevator from Domplatz to the Citadel has only 2 floors. The controls in both elevators are visually contrasting and tactilely detectable.\nStairs in the building have visually contrasting edges at least on the first and last steps, but the stairs from Domplatz to the Citadel on Petersberg do not.\nStairs have handrails on both sides.\nExhibits are generally well lit. \nInformation about the exhibits is predominantly provided in writing and is visually contrasting. There is some audio information about the exhibits. \nGuided tours are offered for people with visual impairments and blind people. Advance reservations are required.\nDuring the tours, exhibits are integrated for touching.\n","shortDescriptionAccessibilityWalking":"All areas relevant for testing meet the quality criteria of the label \"\nAccessibility certified - accessible for people with walking disabilities and wheelchair users\".\nSome \ninformation on accessibility are listed below. For detailed information please see the evaluation report. \nThere are three marked parking spaces for people with disabilities (parking space size: 350 cm x 500 cm, 100 m distance from the entrance). \nThe bus stop on Petersberg is 150 m away. The streetcar stop Domplatz (line 2, 3, 6) is about 800 m away. You can get to the citadel from Domplatz via the panorama path and an elevator. \nThe paths to the entrance are easy to walk and drive on and have a maximum longitudinal gradient of 6%. \nThe building is accessible without steps.\nAll rooms and facilities that can be used and elevated for guests are accessible without steps or via elevators or a ramp.\nThe elevator cabin in the building is 110 cm x 220 cm. \nThe elevator cabin from the panoramic path to the citadel is 160 cm x 240 cm. \nThe ramp from the cathedral square to the Panoramaweg has a maximum slope of 6% and a total length of 24 m (intermediate landings available).\nAll doors\/passages that can be used by guests and are raised are at least 90 cm wide.\nThe cash counter is 73 cm high at the lowest point. \nThe exhibits are predominantly visible while seated. Exhibit information is predominantly legible while seated. \nGuided tours are available for people with walking disabilities and wheelchair users. Advance reservations are required.\nMobile or fixed seating is available for people with walking disabilities to use during the tour.\nThe entire route of the guided tour is step-free for wheelchair users.\nPublic toilet for people with disabilities (basement)\nThe manoeuvring spaces are: \nin front of\/behind the door, in front of the WC and in front of the washbasin at least 150 cm x 150 cm;\nto the left and right of the WC at least 90 cm x 70 cm. \nGrab rails are provided to the left and right of the WC. The grab rails are flipped up.\nThe sink is wheelchair compatible. \nThe mirror can be viewed while standing or sitting.\nThere is an alarm trigger.\n"} diff --git a/Tests/Functional/Fixtures/Import/ImportsTouristAttractionWithAccessibilitySpecificationGerman.txt b/Tests/Functional/Fixtures/Import/ImportsTouristAttractionWithAccessibilitySpecificationGerman.txt new file mode 100644 index 0000000..626ed94 --- /dev/null +++ b/Tests/Functional/Fixtures/Import/ImportsTouristAttractionWithAccessibilitySpecificationGerman.txt @@ -0,0 +1 @@ +{"accessibilityCertificationStatus":"AccessibilityChecked","certificationAccessibilityDeaf":"None","certificationAccessibilityMental":"None","certificationAccessibilityPartiallyDeaf":"Full","certificationAccessibilityPartiallyVisual":"Info","certificationAccessibilityVisual":"Info","certificationAccessibilityWalking":"Full","certificationAccessibilityWheelchair":"Full","accessibilitySearchCriteria":{"facilityAccessibilityWalking":["AllRoomsStepFreeAccess","EightyCMWidthPassageWays","HingedGrabRailToilet","LateralAccessibleToilet","ParkingPeopleWithDisabilities","SeventyCMWidthPassageWays","StepFreeAccess","ToiletsPeopleWithDisabilities","NinetyCMWidthPassageWays"],"facilityAccessibilityVisual":["AssistanceDogsWelcome","VisuallyContrastingStepEdges"],"facilityAccessibilityDeaf":["AudioInductionLoop"]},"shortDescriptionAccessibilityAllGenerations":"Einige \nHinweise zur Barrierefreiheit haben wir nachfolgend zusammengestellt. Detaillierte Angaben finden Sie im Pr\u00fcfbericht. \nParkm\u00f6glichkeiten im Parkhaus am Domplatz. \nIn 150 m Entfernung befindet sich die Bushaltestelle auf dem Petersberg. Die Stra\u00dfenbahnhaltestelle Domplatz (Linie 2, 3, 6) ist etwa 800 Meter entfernt. Zum Petersberg f\u00fchrt ein Panoramaweg von 600 m L\u00e4nge und max. 6 % Steigung sowie ein Aufzug. Die Rampe vom Domplatz zum Panoramaweg hat eine maximale Neigung von 6 % und eine Gesamtl\u00e4nge von 24 m (Zwischenpodeste vorhanden). Die Aufzugkabine vom Panoramaweg zur Zitadelle ist 160 cm x 240 cm gro\u00df. \nDie Wege zum Eingang sind leicht begeh- und befahrbar und haben eine maximale L\u00e4ngsneigung von 6 %. \nDer Eingang ist visuell kontrastreich gestaltet.\nDas Geb\u00e4ude ist stufenlos zug\u00e4nglich.\nAlle f\u00fcr den Gast nutzbaren und erhobenen R\u00e4ume und Einrichtungen sind stufenlos oder \u00fcber Aufz\u00fcge oder eine Rampe zug\u00e4nglich. Die Aufzugkabine im Geb\u00e4ude ist 110 cm x 220 cm gro\u00df. Ein abgehender Notruf in den Aufz\u00fcgen wird akustisch best\u00e4tigt. Alternativ sind Treppen vorhanden. Treppen im Geb\u00e4ude weisen mindestens an der ersten und letzten Stufe visuell kontrastreiche Kanten auf, die Treppen vom Domplatz zur Zitadelle auf dem Petersberg jedoch nicht. Treppen haben beidseitigen Handlauf.\nAlle f\u00fcr den Gast nutzbaren und erhobenen T\u00fcren\/Durchg\u00e4nge sind mindestens 90 cm breit. Es gibt Glast\u00fcren ohne Sicherheitsmarkierungen. \nAlle erhobenen und f\u00fcr den Gast nutzbaren Bereiche sind gut, d.h. hell und blendfrei, ausgeleuchtet.\nEs gibt eine induktive H\u00f6ranlage.\nDie Exponate sind allgemein gut ausgeleuchtet. Die Informationen zu den Exponaten werden schriftlich vermittelt und sind visuell kontrastreich gestaltet. Es gibt teilweise akustische und fotorealistische Informationen zu den Exponaten.\n\u00d6ffentliche Toiletten vorhanden.\nEs werden F\u00fchrungen f\u00fcr Menschen mit Gehbehinderung angeboten. Die gesamte Route der F\u00fchrung ist stufenlos befahrbar. Es stehen mobile oder feste Sitzgelegenheiten zur Verf\u00fcgung, die w\u00e4hrend der F\u00fchrung benutzt werden k\u00f6nnen. F\u00fcr Menschen mit H\u00f6rbehinderung werden F\u00fchrungen mit FM-Anlagen erm\u00f6glicht (z.B. Kopfh\u00f6rer, Halsringschleifen). Es werden F\u00fchrungen f\u00fcr Menschen mit Sehbehinderung und blinde Menschen angeboten. W\u00e4hrend der F\u00fchrungen werden Exponate zum Tasten integriert. F\u00fcr alle F\u00fchrungen ist eine Voranmeldung notwendig.\n","shortDescriptionAccessibilityDeaf":"Alle pr\u00fcfrelevanten Bereiche erf\u00fcllen die Qualit\u00e4tskriterien der Kennzeichnung \u201e\nBarrierefreiheit gepr\u00fcft \u2013 barrierefrei f\u00fcr Menschen mit H\u00f6rbehinderung\u201c.\nEinige \nHinweise zur Barrierefreiheit haben wir nachfolgend zusammengestellt. Detaillierte Angaben finden Sie im Pr\u00fcfbericht.\nDer Alarm ist am Tresen und in den WCs optisch deutlich wahrnehmbar.\nEs gibt eine induktive H\u00f6ranlage.\nEin abgehender Notruf in den Aufz\u00fcgen wird akustisch best\u00e4tigt. Alternativ sind Treppen vorhanden.\nDie Informationen zu den Exponaten werden schriftlich vermittelt. Es gibt teilweise akustische und fotorealistische Informationen zu den Exponaten.\nEs werden F\u00fchrungen f\u00fcr Menschen mit H\u00f6rbehinderung angeboten, jedoch nicht f\u00fcr geh\u00f6rlose Menschen. Es ist eine Voranmeldung notwendig.\nEs werden f\u00fcr Menschen mit H\u00f6rbehinderung F\u00fchrungen mit FM-Anlagen erm\u00f6glicht (z.B. Kopfh\u00f6rer, Halsringschleifen).\n","shortDescriptionAccessibilityMental":"Einige \nHinweise zur Barrierefreiheit haben wir nachfolgend zusammengestellt. Detaillierte Angaben finden Sie im Pr\u00fcfbericht.\nName bzw. Logo des Betriebs sind von au\u00dfen klar erkennbar.\nDie Ziele der Wege sind in Sichtweite oder es sind Wegezeichen in st\u00e4ndig sichtbarem Abstand vorhanden.\nInformationen zu den Exponaten werden teilweise in Leichter Sprache bereitgestellt.\nEs werden F\u00fchrungen f\u00fcr Menschen mit kognitiven Beeintr\u00e4chtigungen angeboten. Es ist eine Voranmeldung notwendig.\nDie F\u00fchrung f\u00fcr Menschen mit kognitiven Beeintr\u00e4chtigungen angeboten.\n","shortDescriptionAccessibilityVisual":"Alle pr\u00fcfrelevanten Bereiche erf\u00fcllen die Qualit\u00e4tskriterien der Kennzeichnung \u201e\nBarrierefreiheit gepr\u00fcft \u2013 teilweise barrierefrei f\u00fcr Menschen mit Sehbehinderung und f\u00fcr blinde Menschen\u201c.\nEinige \nHinweise zur Barrierefreiheit haben wir nachfolgend zusammengestellt. Detaillierte Angaben finden Sie im Pr\u00fcfbericht.\nAssistenzhunde d\u00fcrfen in alle relevanten Bereiche\/R\u00e4ume mitgebracht werden.\nDer Eingang ist visuell kontrastreich gestaltet.\nEs gibt Glast\u00fcren ohne Sicherheitsmarkierungen. \nAlle erhobenen und f\u00fcr den Gast nutzbaren Bereiche sind gut, d.h. hell und blendfrei, ausgeleuchtet.\nIm Eingangsbereich sind visuell kontrastreiche und taktil erfassbare Bodenindikatoren vorhanden.\nDie Beschilderung ist in gut lesbarer und kontrastreicher Schrift gestaltet.\nEin abgehender Notruf in den Aufz\u00fcgen wird akustisch best\u00e4tigt. Im Aufzug im Besucherzentrum wird die Halteposition durch Sprache angesagt. Der Aufzug vom Domplatz zur Zitadelle f\u00fchrt \u00fcber nur 2 Etagen. Die Bedienelemente in beiden Aufz\u00fcgen sind visuell kontrastreich gestaltet und taktil erfassbar.\nTreppen im Geb\u00e4ude weisen mindestens an der ersten und letzten Stufe visuell kontrastreiche Kanten auf, die Treppen vom Domplatz zur Zitadelle auf dem Petersberg jedoch nicht.\nTreppen haben beidseitigen Handlauf.\nDie Exponate sind allgemein gut ausgeleuchtet. \nDie Informationen zu den Exponaten werden \u00fcberwiegend schriftlich vermittelt und sind visuell kontrastreich gestaltet. Es gibt teilweise akustische Informationen zu den Exponaten. \nEs werden F\u00fchrungen f\u00fcr Menschen mit Sehbehinderung und blinde Menschen angeboten. Es ist eine Voranmeldung notwendig.\nW\u00e4hrend der F\u00fchrungen werden Exponate zum Tasten integriert. \n","shortDescriptionAccessibilityWalking":"Alle pr\u00fcfrelevanten Bereiche erf\u00fcllen die Qualit\u00e4tskriterien der Kennzeichnung \n\"Barrierefreiheit gepr\u00fcft - barrierefrei f\u00fcr Menschen mit Gehbehinderung und Rollstuhlfahrer\".\nEinige \nHinweise zur Barrierefreiheit haben wir nachfolgend zusammengestellt. Detaillierte Angaben finden Sie im Pr\u00fcfbericht. \nEs sind drei gekennzeichnete Parkpl\u00e4tze f\u00fcr Menschen mit Behinderung vorhanden (Stellplatzgr\u00f6\u00dfe: 350 cm x 500 cm, 100 m Entfernung zum Eingang). \nIn 150 m Entfernung befindet sich die Bushaltestelle auf dem Petersberg. Die Stra\u00dfenbahnhaltestelle Domplatz (Linie 2, 3, 6) ist etwa 800 m entfernt. Zur Zitadelle gelangt man vom Domplatz \u00fcber den Panoramaweg und einen Aufzug. \nDie Wege zum Eingang sind leicht begeh- und befahrbar und haben eine maximale L\u00e4ngsneigung von 6 %. \nDas Geb\u00e4ude ist stufenlos zug\u00e4nglich.\nAlle f\u00fcr den Gast nutzbaren und erhobenen R\u00e4ume und Einrichtungen sind stufenlos oder \u00fcber Aufz\u00fcge oder eine Rampe zug\u00e4nglich.\nDie Aufzugkabine im Geb\u00e4ude ist 110 cm x 220 cm gro\u00df. \nDie Aufzugkabine vom Panoramaweg zur Zitadelle ist 160 cm x 240 cm gro\u00df. \nDie Rampe vom Domplatz zum Panoramaweg hat eine maximale Neigung von 6 % und eine Gesamtl\u00e4nge von 24 m (Zwischenpodeste vorhanden).\nAlle f\u00fcr den Gast nutzbaren und erhobenen T\u00fcren\/Durchg\u00e4nge sind mindestens 90 cm breit.\nDer Kassentresen ist an der niedrigsten Stelle 73 cm hoch. \nDie Exponate sind \u00fcberwiegend im Sitzen sichtbar. Die Informationen zu den Exponaten sind \u00fcberwiegend im Sitzen lesbar. \nEs werden F\u00fchrungen f\u00fcr Menschen mit Gehbehinderung und Rollstuhlfahrer angeboten. Es ist eine Voranmeldung notwendig.\nEs stehen f\u00fcr Menschen mit Gehbehinderung mobile oder feste Sitzgelegenheiten zur Verf\u00fcgung, die w\u00e4hrend der F\u00fchrung benutzt werden k\u00f6nnen.\nDie gesamte Route der F\u00fchrung ist f\u00fcr Rollstuhlfahrer stufenlos befahrbar.\n\u00d6ffentliches WC f\u00fcr Menschen mit Behinderung (Untergeschoss)\nDie Bewegungsfl\u00e4chen betragen:\nvor\/hinter der T\u00fcr, vor dem WC und vor dem Waschbecken mindestens 150 cm x 150 cm;\nlinks und rechts neben dem WC mindestens 90 cm x 70 cm. \nEs sind links und rechts vom WC Haltegriffe vorhanden. Die Haltegriffe sind hochklappbar.\nDas Waschbecken ist unterfahrbar.\nDer Spiegel ist im Stehen und Sitzen einsehbar.\nEs ist ein Alarmausl\u00f6ser vorhanden.\n"} diff --git a/Tests/Functional/ImportTest.php b/Tests/Functional/ImportTest.php index 2887eac..2a570f2 100644 --- a/Tests/Functional/ImportTest.php +++ b/Tests/Functional/ImportTest.php @@ -384,4 +384,24 @@ class ImportTest extends AbstractImportTest $this->assertCSVDataSet('EXT:thuecat/Tests/Functional/Fixtures/Import/ImportsTouristAttractionWithMedia.csv'); } + + /** + * @test + */ + public function importsTouristAttractionWithAccessibilitySpecification(): void + { + $this->importDataSet(__DIR__ . '/Fixtures/Import/ImportsTouristAttractionWithAccessibilitySpecification.xml'); + + GuzzleClientFaker::appendResponseFromFile(__DIR__ . '/Fixtures/Import/Guzzle/thuecat.org/resources/attraction-with-accessibility-specification.json'); + GuzzleClientFaker::appendResponseFromFile(__DIR__ . '/Fixtures/Import/Guzzle/thuecat.org/resources/018132452787-ngbe.json'); + GuzzleClientFaker::appendResponseFromFile(__DIR__ . '/Fixtures/Import/Guzzle/thuecat.org/resources/e_331baf4eeda4453db920dde62f7e6edc-rfa-accessibility-specification.json'); + + $configuration = $this->get(ImportConfigurationRepository::class)->findByUid(1); + $this->get(Importer::class)->importConfiguration($configuration); + + $this->assertCSVDataSet('EXT:thuecat/Tests/Functional/Fixtures/Import/ImportsTouristAttractionWithAccessibilitySpecification.csv'); + $records = $this->getAllRecords('tx_thuecat_tourist_attraction'); + self::assertStringEqualsFile(__DIR__ . '/Fixtures/Import/ImportsTouristAttractionWithAccessibilitySpecificationGerman.txt', $records[0]['accessibility_specification'] . PHP_EOL); + self::assertStringEqualsFile(__DIR__ . '/Fixtures/Import/ImportsTouristAttractionWithAccessibilitySpecificationEnglish.txt', $records[1]['accessibility_specification'] . PHP_EOL); + } } diff --git a/ecs.php b/ecs.php index d6a0589..2307d86 100644 --- a/ecs.php +++ b/ecs.php @@ -33,6 +33,7 @@ return static function (ContainerConfigurator $containerConfigurator): void { ]); $parameters->set(Option::SKIP, [ + __DIR__ . '/Classes/Domain/Import/EntityMapper/CustomAnnotationExtractor.php', DeclareStrictTypesFixer::class => [ __DIR__ . '/Configuration/', __DIR__ . '/ext_emconf.php', diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 6e87eb7..c20fe08 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -326,12 +326,12 @@ parameters: - message: "#^Cannot call method findByUid\\(\\) on mixed\\.$#" - count: 13 + count: 14 path: Tests/Functional/ImportTest.php - message: "#^Cannot call method importConfiguration\\(\\) on mixed\\.$#" - count: 13 + count: 14 path: Tests/Functional/ImportTest.php - diff --git a/phpstan.neon b/phpstan.neon index ca2e558..5df3728 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -8,6 +8,7 @@ parameters: - Tests excludePaths: - Tests/Acceptance/Support/_generated/ + - Classes/Domain/Import/EntityMapper/CustomAnnotationExtractor.php checkMissingIterableValueType: false reportUnmatchedIgnoredErrors: false checkGenericClassInNonGenericObjectType: false