vendor/ibexa/taxonomy/src/lib/Event/Subscriber/ContentEditCustomValidationSubscriber.php line 59

Open in your IDE?
  1. <?php
  2. /**
  3.  * @copyright Copyright (C) Ibexa AS. All rights reserved.
  4.  * @license For full copyright and license information view LICENSE file distributed with this source code.
  5.  */
  6. declare(strict_types=1);
  7. namespace Ibexa\Taxonomy\Event\Subscriber;
  8. use Ibexa\ContentForms\Event\ContentCreateFieldOptionsEvent;
  9. use Ibexa\ContentForms\Event\ContentFormEvents;
  10. use Ibexa\ContentForms\Event\ContentUpdateFieldOptionsEvent;
  11. use Ibexa\Contracts\ContentForms\Data\Content\FieldData;
  12. use Ibexa\Contracts\Core\Repository\Values\ContentType\ContentType;
  13. use Ibexa\Taxonomy\Exception\TaxonomyNotFoundException;
  14. use Ibexa\Taxonomy\Form\Type\Validation\Constraint\Nested;
  15. use Ibexa\Taxonomy\Form\Type\Validation\Constraint\UniqueIdentifier;
  16. use Ibexa\Taxonomy\Service\TaxonomyConfiguration;
  17. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  18. use Symfony\Component\Validator\Constraints\Length;
  19. use Symfony\Component\Validator\Constraints\NotBlank;
  20. /**
  21.  * Adds custom validators to Taxonomy fields in Content update/create form.
  22.  *
  23.  * @internal
  24.  */
  25. final class ContentEditCustomValidationSubscriber implements EventSubscriberInterface
  26. {
  27.     private const MAX_IDENTIFIER_LENGTH 190;
  28.     private const MAX_NAME_LENGTH 255;
  29.     private TaxonomyConfiguration $taxonomyConfiguration;
  30.     public function __construct(
  31.         TaxonomyConfiguration $taxonomyConfiguration
  32.     ) {
  33.         $this->taxonomyConfiguration $taxonomyConfiguration;
  34.     }
  35.     public static function getSubscribedEvents(): array
  36.     {
  37.         return [
  38.             ContentFormEvents::CONTENT_EDIT_FIELD_OPTIONS => 'onEditFieldOptions',
  39.             ContentFormEvents::CONTENT_CREATE_FIELD_OPTIONS => 'onCreateFieldOptions',
  40.         ];
  41.     }
  42.     public function onEditFieldOptions(ContentUpdateFieldOptionsEvent $event): void
  43.     {
  44.         $contentType $event->getContent()->getContentType();
  45.         $event->setOptions(
  46.             $this->attachValidator($contentType$event->getFieldData(), $event->getOptions())
  47.         );
  48.     }
  49.     public function onCreateFieldOptions(ContentCreateFieldOptionsEvent $event): void
  50.     {
  51.         $contentType $event->getContentCreateStruct()->contentType;
  52.         $event->setOptions(
  53.             $this->attachValidator($contentType$event->getFieldData(), $event->getOptions())
  54.         );
  55.     }
  56.     /**
  57.      * @param array<string, mixed> $options
  58.      *
  59.      * @return array<string, mixed>
  60.      */
  61.     private function attachValidator(ContentType $contentTypeFieldData $fieldData, array $options): array
  62.     {
  63.         try {
  64.             $taxonomy $this->taxonomyConfiguration->getTaxonomyForContentType($contentType);
  65.             $fieldMappings $this->taxonomyConfiguration->getFieldMappings($taxonomy);
  66.         } catch (TaxonomyNotFoundException $e) {
  67.             return $options;
  68.         }
  69.         if ($fieldData->fieldDefinition->identifier === $fieldMappings['identifier']) {
  70.             return $this->doAttachValidatorToIdentifier($options$taxonomy);
  71.         }
  72.         if ($fieldData->fieldDefinition->identifier === $fieldMappings['name']) {
  73.             return $this->doAttachValidatorToName($options);
  74.         }
  75.         return $options;
  76.     }
  77.     /**
  78.      * @param array<string, mixed> $options
  79.      *
  80.      * @return array<string, mixed>
  81.      */
  82.     private function doAttachValidatorToName(array $options): array
  83.     {
  84.         $options['constraints'] = array_merge(
  85.             $options['constraints'] ?? [],
  86.             [
  87.                 $this->createNestedConstraints(
  88.                     [
  89.                         new NotBlank(),
  90.                         new Length(['max' => self::MAX_NAME_LENGTH]),
  91.                     ]
  92.                 ),
  93.             ]
  94.         );
  95.         $options['error_mapping'] = array_merge(
  96.             $options['error_mapping'] ?? [],
  97.             ['.' => 'value']
  98.         );
  99.         return $options;
  100.     }
  101.     /**
  102.      * @param array<string, mixed> $options
  103.      *
  104.      * @return array<string, mixed>
  105.      */
  106.     private function doAttachValidatorToIdentifier(array $optionsstring $taxonomy): array
  107.     {
  108.         $options['constraints'] = array_merge(
  109.             $options['constraints'] ?? [],
  110.             [
  111.                 $this->createNestedConstraints(
  112.                     [
  113.                         new NotBlank(),
  114.                         new Length(['max' => self::MAX_IDENTIFIER_LENGTH]),
  115.                     ]
  116.                 ),
  117.                 new UniqueIdentifier(['taxonomy' => $taxonomy]),
  118.             ]
  119.         );
  120.         $options['error_mapping'] = array_merge(
  121.             $options['error_mapping'] ?? [],
  122.             ['.' => 'value']
  123.         );
  124.         return $options;
  125.     }
  126.     /**
  127.      * @param \Symfony\Component\Validator\Constraint[] $constraints
  128.      *
  129.      * @return \Ibexa\Taxonomy\Form\Type\Validation\Constraint\Nested
  130.      */
  131.     private function createNestedConstraints(array $constraints): Nested
  132.     {
  133.         return new Nested(
  134.             static function (?FieldData $value): ?string {
  135.                 if ($value === null || $value->value === null) {
  136.                     return null;
  137.                 }
  138.                 return $value->value->text;
  139.             },
  140.             $constraints
  141.         );
  142.     }
  143. }