vendor/ibexa/admin-ui/src/lib/Form/Processor/ContentType/ContentTypeFormProcessor.php line 108

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. namespace Ibexa\AdminUi\Form\Processor\ContentType;
  7. use Ibexa\ContentForms\Event\FormActionEvent;
  8. use Ibexa\Contracts\AdminUi\Event\FormEvents;
  9. use Ibexa\Contracts\Core\Repository\ContentTypeService;
  10. use Ibexa\Contracts\Core\Repository\Values\ContentType\ContentTypeDraft;
  11. use Ibexa\Contracts\Core\Repository\Values\ContentType\FieldDefinition;
  12. use Ibexa\Contracts\Core\Repository\Values\ContentType\FieldDefinitionCreateStruct;
  13. use Ibexa\Core\Base\Exceptions\InvalidArgumentException;
  14. use Ibexa\Core\Helper\FieldsGroups\FieldsGroupsList;
  15. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  16. use Symfony\Component\HttpFoundation\RedirectResponse;
  17. use Symfony\Component\Routing\RouterInterface;
  18. class ContentTypeFormProcessor implements EventSubscriberInterface
  19. {
  20.     /**
  21.      * @var \Ibexa\Contracts\Core\Repository\ContentTypeService
  22.      */
  23.     private $contentTypeService;
  24.     /**
  25.      * @var \Symfony\Component\Routing\RouterInterface
  26.      */
  27.     private $router;
  28.     /**
  29.      * @var array
  30.      */
  31.     private $options;
  32.     /**
  33.      * @var \Ibexa\Core\Helper\FieldsGroups\FieldsGroupsList
  34.      */
  35.     private $groupsList;
  36.     public function __construct(
  37.         ContentTypeService $contentTypeService,
  38.         RouterInterface $router,
  39.         array $options = []
  40.     ) {
  41.         $this->contentTypeService $contentTypeService;
  42.         $this->router $router;
  43.         $this->setOptions($options);
  44.     }
  45.     public function setGroupsList(FieldsGroupsList $groupsList)
  46.     {
  47.         $this->groupsList $groupsList;
  48.     }
  49.     public function setOptions(array $options = [])
  50.     {
  51.         $this->options $options + ['redirectRouteAfterPublish' => null];
  52.     }
  53.     public static function getSubscribedEvents()
  54.     {
  55.         return [
  56.             FormEvents::CONTENT_TYPE_UPDATE => 'processDefaultAction',
  57.             FormEvents::CONTENT_TYPE_ADD_FIELD_DEFINITION => 'processAddFieldDefinition',
  58.             FormEvents::CONTENT_TYPE_REMOVE_FIELD_DEFINITION => 'processRemoveFieldDefinition',
  59.             FormEvents::CONTENT_TYPE_PUBLISH => 'processPublishContentType',
  60.             FormEvents::CONTENT_TYPE_PUBLISH_AND_EDIT => 'processPublishAndEditContentType',
  61.             FormEvents::CONTENT_TYPE_REMOVE_DRAFT => 'processRemoveContentTypeDraft',
  62.         ];
  63.     }
  64.     public function processDefaultAction(FormActionEvent $event)
  65.     {
  66.         // Don't update anything if we just want to cancel the draft.
  67.         if ($event->getClickedButton() === 'removeDraft') {
  68.             return;
  69.         }
  70.         // Always update FieldDefinitions and ContentTypeDraft
  71.         /** @var \Ibexa\AdminUi\Form\Data\ContentTypeData $contentTypeData */
  72.         $contentTypeData $event->getData();
  73.         $contentTypeDraft $contentTypeData->contentTypeDraft;
  74.         foreach ($contentTypeData->getFlatFieldDefinitionsData() as $fieldDefData) {
  75.             $this->contentTypeService->updateFieldDefinition($contentTypeDraft$fieldDefData->fieldDefinition$fieldDefData);
  76.         }
  77.         // Update enabled FieldDefinitions and remove disabled.
  78.         foreach ($contentTypeData->getFlatMetaFieldDefinitionsData() as $fieldDefData) {
  79.             if ($fieldDefData->enabled) {
  80.                 $this->contentTypeService->updateFieldDefinition(
  81.                     $contentTypeDraft,
  82.                     $fieldDefData->fieldDefinition,
  83.                     $fieldDefData
  84.                 );
  85.             } else {
  86.                 $this->contentTypeService->removeFieldDefinition($contentTypeDraft$fieldDefData->fieldDefinition);
  87.             }
  88.         }
  89.         $contentTypeData->sortFieldDefinitions();
  90.         $this->contentTypeService->updateContentTypeDraft($contentTypeDraft$contentTypeData);
  91.     }
  92.     public function processAddFieldDefinition(FormActionEvent $event)
  93.     {
  94.         // Reload the draft, to make sure we include any changes made in the current form submit
  95.         $contentTypeDraft $this->contentTypeService->loadContentTypeDraft($event->getData()->contentTypeDraft->id);
  96.         $fieldTypeIdentifier $event->getForm()->get('fieldTypeSelection')->getData();
  97.         $targetLanguageCode $event->getForm()->getConfig()->getOption('languageCode');
  98.         if ($contentTypeDraft->mainLanguageCode !== $targetLanguageCode) {
  99.             throw new InvalidArgumentException(
  100.                 'languageCode',
  101.                 'Field definitions can only be added to the main language translation'
  102.             );
  103.         }
  104.         $maxFieldPos 0;
  105.         foreach ($contentTypeDraft->fieldDefinitions as $existingFieldDef) {
  106.             if ($existingFieldDef->position $maxFieldPos) {
  107.                 $maxFieldPos $existingFieldDef->position;
  108.             }
  109.         }
  110.         $fieldDefCreateStruct = new FieldDefinitionCreateStruct([
  111.             'fieldTypeIdentifier' => $fieldTypeIdentifier,
  112.             'identifier' => $this->resolveNewFieldDefinitionIdentifier(
  113.                 $contentTypeDraft,
  114.                 $maxFieldPos,
  115.                 $fieldTypeIdentifier
  116.             ),
  117.             'names' => [$event->getOption('languageCode') => 'New FieldDefinition'],
  118.             'position' => $maxFieldPos 1,
  119.         ]);
  120.         if (isset($this->groupsList)) {
  121.             $fieldDefCreateStruct->fieldGroup $this->groupsList->getDefaultGroup();
  122.         }
  123.         $this->contentTypeService->addFieldDefinition($contentTypeDraft$fieldDefCreateStruct);
  124.     }
  125.     public function processRemoveFieldDefinition(FormActionEvent $event)
  126.     {
  127.         /** @var \Ibexa\Contracts\Core\Repository\Values\ContentType\ContentTypeDraft $contentTypeDraft */
  128.         $contentTypeDraft $event->getData()->contentTypeDraft;
  129.         // Accessing FieldDefinition user selection through the form and not the data,
  130.         // as "selected" is not a property of FieldDefinitionData.
  131.         /** @var \Symfony\Component\Form\FormInterface $fieldDefForm */
  132.         foreach ($event->getForm()->get('fieldDefinitionsData') as $fieldDefForm) {
  133.             if ($fieldDefForm->get('selected')->getData() === true) {
  134.                 $this->contentTypeService->removeFieldDefinition($contentTypeDraft$fieldDefForm->getData()->fieldDefinition);
  135.             }
  136.         }
  137.     }
  138.     public function processPublishContentType(FormActionEvent $event)
  139.     {
  140.         $contentTypeDraft $event->getData()->contentTypeDraft;
  141.         $this->contentTypeService->publishContentTypeDraft($contentTypeDraft);
  142.         if (isset($this->options['redirectRouteAfterPublish'])) {
  143.             $event->setResponse(
  144.                 new RedirectResponse($this->router->generate($this->options['redirectRouteAfterPublish']))
  145.             );
  146.         }
  147.     }
  148.     public function processPublishAndEditContentType(FormActionEvent $event): void
  149.     {
  150.         $eventData $event->getData();
  151.         /** @var \Ibexa\Contracts\Core\Repository\Values\ContentType\ContentTypeDraft $contentTypeDraft */
  152.         $contentTypeDraft $eventData->contentTypeDraft;
  153.         $languageCode $eventData->languageCode;
  154.         $this->contentTypeService->publishContentTypeDraft($contentTypeDraft);
  155.         $contentType $this->contentTypeService->loadContentType($contentTypeDraft->id, [$languageCode]);
  156.         $this->contentTypeService->createContentTypeDraft($contentType);
  157.     }
  158.     public function processRemoveContentTypeDraft(FormActionEvent $event)
  159.     {
  160.         $contentTypeDraft $event->getData()->contentTypeDraft;
  161.         $this->contentTypeService->deleteContentType($contentTypeDraft);
  162.         if (isset($this->options['redirectRouteAfterPublish'])) {
  163.             $event->setResponse(
  164.                 new RedirectResponse($this->router->generate($this->options['redirectRouteAfterPublish']))
  165.             );
  166.         }
  167.     }
  168.     /**
  169.      * Resolves unique field definition identifier.
  170.      *
  171.      * @param \Ibexa\Contracts\Core\Repository\Values\ContentType\ContentTypeDraft $contentTypeDraft
  172.      * @param int $startIndex
  173.      * @param string $fieldTypeIdentifier
  174.      *
  175.      * @return string
  176.      */
  177.     private function resolveNewFieldDefinitionIdentifier(
  178.         ContentTypeDraft $contentTypeDraft,
  179.         int $startIndex,
  180.         string $fieldTypeIdentifier
  181.     ): string {
  182.         $fieldDefinitionIdentifiers $contentTypeDraft
  183.             ->getFieldDefinitions()
  184.             ->map(static function (FieldDefinition $fieldDefinition): string {
  185.                 return $fieldDefinition->identifier;
  186.             });
  187.         do {
  188.             $fieldDefinitionIdentifier sprintf('new_%s_%d'$fieldTypeIdentifier, ++$startIndex);
  189.         } while (in_array($fieldDefinitionIdentifier$fieldDefinitionIdentifierstrue));
  190.         return $fieldDefinitionIdentifier;
  191.     }
  192. }
  193. class_alias(ContentTypeFormProcessor::class, 'EzSystems\EzPlatformAdminUi\Form\Processor\ContentType\ContentTypeFormProcessor');