Uploaded image for project: 'Ibexa IBX'
  1. Ibexa IBX
  2. IBX-6345

AbstractTaxonomyIdentifierValidator::doValidate() returns incorrect return type structure

    XMLWordPrintable

Details

    • Yes

    Description

      The documentation for \Ibexa\Contracts\Core\Repository\Validator\ContentValidator::validate() states :

           * @return array Grouped validation errors by field definition and language code, in format:
           *           $returnValue[string|int $fieldDefinitionId][string $languageCode] = $fieldErrors;
      

      However, \Ibexa\Taxonomy\Repository\Content\Validator\AbstractTaxonomyIdentifierValidator::doValidate() doesn't do that, and this causes Ibexa\Taxonomy\Repository\Content\Validator\ContentCreateStructValidator and Ibexa\Taxonomy\Repository\Content\Validator\ContentUpdateStructValidator to return validation errors with wrong structure.

      Steps to reproduce :

      src/Controller/TestController.php
      <?PHP
      
      declare(strict_types=1);
      
      namespace App\Controller;
      
      use Ibexa\Contracts\Core\Repository\Repository;
      use Ibexa\Contracts\Taxonomy\Service\TaxonomyServiceInterface;
      use Ibexa\Core\Base\Exceptions\ContentFieldValidationException;
      use Ibexa\Core\FieldType\TextLine\Value as TextLineValue;
      use Ibexa\Taxonomy\FieldType\TaxonomyEntry\Value as TaxonomyEntryValue;
      use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
      use Symfony\Component\HttpFoundation\Response;
      use Symfony\Component\Routing\Annotation\Route;
      
      final class TestController extends AbstractController
      {
          public function __construct(
              private readonly Repository $repository,
              private readonly TaxonomyServiceInterface $taxonomyService,
          ) {}
      
          #[Route('/taxtest')]
          public function test(): Response
          {
              $this->repository->sudo(
                  function (Repository $repository) {
                      $identifier = "Test";
                      $contentService = $repository->getContentService();
      
                      $contentType = $repository->getContentTypeService()->loadContentTypeByIdentifier('tag');
                      $contentCreateStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
      
                      $contentCreateStruct->setField('name', new TextLineValue($identifier));
                      $contentCreateStruct->setField('identifier', new TextLineValue(strtolower($identifier)));
                      $contentCreateStruct->setField('parent', new TaxonomyEntryValue(
                          $this->taxonomyService->loadRootEntry('tags'),
                      ));
      
                      $locationCreateStruct = $repository->getLocationService()->newLocationCreateStruct(59);
                      $contentService->publishVersion($contentService->createContent($contentCreateStruct, [$locationCreateStruct])->versionInfo);
      
                      $contentCreateStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB');
      
                      $contentCreateStruct->setField('name', new TextLineValue(''));
                      $contentCreateStruct->setField('identifier', new TextLineValue(strtolower($identifier)));
                      $contentCreateStruct->setField('parent', new TaxonomyEntryValue(
                          $this->taxonomyService->loadRootEntry('tags'),
                      ));
      
                      try {
                          $locationCreateStruct = $repository->getLocationService()->newLocationCreateStruct(59);
                          $contentService->publishVersion($contentService->createContent($contentCreateStruct, [$locationCreateStruct])->versionInfo);
                      } catch (ContentFieldValidationException $e) {
                          dump($e->getFieldErrors());
                      }
                  }
              );
      
              return new Response("<html><body>Done</body></html>");
          }
      }
      

      The code above will first create two tags with same identifier. The second time, the tag will be created with two validations errors and you can see the structure is not consistent.
      It will look like this:

      array:2 [▼
        190 => array:1 [▼
          "eng-GB" => Ibexa\Core\FieldType\ValidationError {#5685 ▼
            #singular: "Value for required field definition '%identifier%' with language '%languageCode%' is empty"
            #plural: null
            #values: array:2 [▶]
            #target: "empty"
          }
        ]
        0 => Ibexa\Core\FieldType\ValidationError {#5680 ▼
          #singular: "Taxonomy Entry with identifier "{{ identifier }}" already exists in "{{ taxonomy }}" taxonomy tree. Please use unique identifier."
          #plural: null
          #values: array:2 [▶]
          #target: null
        }
      ]
      

      Designs

        Attachments

          Activity

            People

              Unassigned Unassigned
              vidar.langseid@ibexa.co Vidar Langseid
              Votes:
              0 Vote for this issue
              Watchers:
              3 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved: