diff --git a/src/lib/Form/Type/Extension/EventSubscriber/ModifyFieldDefinitionFieldsSubscriber.php b/src/lib/Form/Type/Extension/EventSubscriber/ModifyFieldDefinitionFieldsSubscriber.php index 935cc70fd6..88f5d8c7d9 100644 --- a/src/lib/Form/Type/Extension/EventSubscriber/ModifyFieldDefinitionFieldsSubscriber.php +++ b/src/lib/Form/Type/Extension/EventSubscriber/ModifyFieldDefinitionFieldsSubscriber.php @@ -8,28 +8,44 @@ namespace Ibexa\AdminUi\Form\Type\Extension\EventSubscriber; +use Ibexa\AdminUi\Form\Data\FieldDefinitionData; use Ibexa\AdminUi\Form\Type\FieldDefinition\FieldDefinitionType; +use Ibexa\Contracts\Core\Repository\Values\ContentType\ContentTypeDraft; +use Ibexa\Contracts\Core\Specification\SpecificationInterface; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\Form\FormEvent; use Symfony\Component\Form\FormEvents; +use Symfony\Component\Form\FormInterface; /** - * Modifies CT editing form by rebuilding field definition list with custom options on given field type. + * Rebuilds specific field definitions in the Content Type editing form with custom options for a given field type and set of field identifiers. */ final class ModifyFieldDefinitionFieldsSubscriber implements EventSubscriberInterface { - private string $fieldTypeIdentifier; + private ?string $fieldTypeIdentifier; + + /** @var string[] */ + private array $fieldIdentifiers; /** @var array */ private array $modifiedOptions; + private ?SpecificationInterface $contentTypeSpecification; + /** * @param array $modifiedOptions + * @param array $fieldIdentifiers */ - public function __construct(string $fieldTypeIdentifier, array $modifiedOptions) - { + public function __construct( + ?string $fieldTypeIdentifier, + array $modifiedOptions, + array $fieldIdentifiers = [], + ?SpecificationInterface $contentTypeSpecification = null + ) { $this->fieldTypeIdentifier = $fieldTypeIdentifier; $this->modifiedOptions = $modifiedOptions; + $this->fieldIdentifiers = $fieldIdentifiers; + $this->contentTypeSpecification = $contentTypeSpecification; } public static function getSubscribedEvents(): array @@ -45,30 +61,75 @@ public function onPreSetData(FormEvent $event): void $data = $event->getData(); $form = $event->getForm(); - if (null === $data) { + if (empty($data)) { + return; + } + + if (!$this->isApplicableToContentTypeDraft($this->getContentTypeDraft($data))) { return; } - foreach ($data as $fieldTypeIdentifier => $fieldTypeData) { - if ($this->fieldTypeIdentifier !== $fieldTypeData->fieldDefinition->fieldTypeIdentifier) { + foreach ($data as $fieldIdentifier => $fieldTypeData) { + if (!$form->has($fieldIdentifier)) { continue; } - if (!$form->has($fieldTypeIdentifier)) { - return; + if (!$this->acceptsFieldDefinition($fieldTypeData, $fieldIdentifier)) { + continue; } - $baseFieldForm = $form->get($fieldTypeIdentifier); - $baseFieldFormName = $baseFieldForm->getName(); + $this->rebuildFieldForm($form, $fieldIdentifier); + } + } - $form->remove($baseFieldFormName); + private function isApplicableToContentTypeDraft(?ContentTypeDraft $contentTypeDraft): bool + { + if ($this->contentTypeSpecification === null) { + return true; + } - $options = array_merge( - $baseFieldForm->getConfig()->getOptions(), - $this->modifiedOptions - ); + if ($contentTypeDraft === null) { + return false; + } - $form->add($baseFieldFormName, FieldDefinitionType::class, $options); + return $this->contentTypeSpecification->isSatisfiedBy($contentTypeDraft); + } + + /** + * @param array $data + */ + private function getContentTypeDraft(array $data): ?ContentTypeDraft + { + $firstField = reset($data); + if ($firstField instanceof FieldDefinitionData && isset($firstField->contentTypeData)) { + return $firstField->contentTypeData->contentTypeDraft ?? null; } + + return null; + } + + private function acceptsFieldDefinition(FieldDefinitionData $field, string $identifier): bool + { + $matchesType = $this->fieldTypeIdentifier === $field->fieldDefinition->fieldTypeIdentifier; + $matchesIdentifier = in_array($identifier, $this->fieldIdentifiers, true); + + return $matchesType || $matchesIdentifier; + } + + /** + * @param \Symfony\Component\Form\FormInterface<\Ibexa\AdminUi\Form\Data\FieldDefinitionData[]> $form + */ + private function rebuildFieldForm(FormInterface $form, string $name): void + { + $baseFieldForm = $form->get($name); + $baseFieldFormName = $baseFieldForm->getName(); + + $options = array_merge( + $baseFieldForm->getConfig()->getOptions(), + $this->modifiedOptions + ); + + $form->remove($baseFieldFormName); + $form->add($baseFieldFormName, FieldDefinitionType::class, $options); } } diff --git a/src/lib/Form/Type/Extension/ModifyFieldDefinitionsCollectionTypeExtension.php b/src/lib/Form/Type/Extension/ModifyFieldDefinitionsCollectionTypeExtension.php index 78b7bb606c..524ac14709 100644 --- a/src/lib/Form/Type/Extension/ModifyFieldDefinitionsCollectionTypeExtension.php +++ b/src/lib/Form/Type/Extension/ModifyFieldDefinitionsCollectionTypeExtension.php @@ -10,6 +10,7 @@ use Ibexa\AdminUi\Form\Type\ContentType\FieldDefinitionsCollectionType; use Ibexa\AdminUi\Form\Type\Extension\EventSubscriber\ModifyFieldDefinitionFieldsSubscriber; +use Ibexa\Contracts\Core\Specification\SpecificationInterface; use Symfony\Component\Form\AbstractTypeExtension; use Symfony\Component\Form\FormBuilderInterface; @@ -20,24 +21,40 @@ */ final class ModifyFieldDefinitionsCollectionTypeExtension extends AbstractTypeExtension { - private string $fieldTypeIdentifier; + private ?string $fieldTypeIdentifier; + + /** @var string[] */ + private array $fieldIdentifiers; /** @var array */ private array $modifiedOptions; + private ?SpecificationInterface $contentTypeSpecification; + /** - * @param string $fieldTypeIdentifier * @param array $modifiedOptions + * @param array $fieldIdentifiers */ - public function __construct(string $fieldTypeIdentifier, array $modifiedOptions) - { + public function __construct( + ?string $fieldTypeIdentifier, + array $modifiedOptions, + array $fieldIdentifiers = [], + ?SpecificationInterface $contentTypeSpecification = null + ) { $this->fieldTypeIdentifier = $fieldTypeIdentifier; + $this->fieldIdentifiers = $fieldIdentifiers; $this->modifiedOptions = $modifiedOptions; + $this->contentTypeSpecification = $contentTypeSpecification; } public function buildForm(FormBuilderInterface $builder, array $options): void { - $subscriber = new ModifyFieldDefinitionFieldsSubscriber($this->fieldTypeIdentifier, $this->modifiedOptions); + $subscriber = new ModifyFieldDefinitionFieldsSubscriber( + $this->fieldTypeIdentifier, + $this->modifiedOptions, + $this->fieldIdentifiers, + $this->contentTypeSpecification + ); foreach ($builder->all() as $fieldTypeGroup) { $fieldTypeGroup->addEventSubscriber($subscriber);