src/EventSubscriber/SpecificFieldsAwareFormTypeEventSubscriber.php line 127

Open in your IDE?
  1. <?php
  2. namespace App\EventSubscriber;
  3. use ApiPlatform\Core\DataProvider\CollectionDataProviderInterface;
  4. use ApiPlatform\Core\DataProvider\ContextAwareCollectionDataProviderInterface;
  5. use ApiPlatform\Core\Exception\ResourceClassNotSupportedException;
  6. use App\Form\SpecificField\SpecificFieldBuilder;
  7. use App\Form\Type\AbstractViewOrderAwareType;
  8. use App\Model\Field\Field;
  9. use App\Model\FieldType\FieldType;
  10. use App\Model\SpecificField\SpecificField;
  11. use App\Model\SpecificFieldsAwareInterface;
  12. use App\Security\User;
  13. use App\V4\Model\SpecificField\SpecificField as SpecificFieldV4;
  14. use LogicException;
  15. use ReflectionClass;
  16. use ReflectionException;
  17. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  18. use Symfony\Component\Form\Event\PostSubmitEvent;
  19. use Symfony\Component\Form\Event\PreSetDataEvent;
  20. use Symfony\Component\Form\FormEvents;
  21. use Symfony\Component\Security\Core\Security;
  22. class SpecificFieldsAwareFormTypeEventSubscriber implements EventSubscriberInterface
  23. {
  24.     /**
  25.      * @var ContextAwareCollectionDataProviderInterface
  26.      */
  27.     private $collectionDataProvider;
  28.     /**
  29.      * @var SpecificFieldBuilder
  30.      */
  31.     private $specificFieldBuilder;
  32.     /**
  33.      * @var Security
  34.      */
  35.     private $security;
  36.     /**
  37.      * @var Field[]
  38.      */
  39.     private $fields = [];
  40.     /**
  41.      * @param CollectionDataProviderInterface $collectionDataProvider
  42.      * @param SpecificFieldBuilder            $specificFieldBuilder
  43.      * @param Security                        $security
  44.      */
  45.     public function __construct(
  46.         CollectionDataProviderInterface $collectionDataProvider,
  47.         SpecificFieldBuilder $specificFieldBuilder,
  48.         Security $security
  49.     ) {
  50.         $this->collectionDataProvider $collectionDataProvider;
  51.         $this->specificFieldBuilder $specificFieldBuilder;
  52.         $this->security $security;
  53.     }
  54.     /**
  55.      * @return array
  56.      */
  57.     public static function getSubscribedEvents(): array
  58.     {
  59.         return [
  60.             FormEvents::PRE_SET_DATA => 'onPreSetData',
  61.             FormEvents::POST_SUBMIT => 'onPostSubmit',
  62.         ];
  63.     }
  64.     /**
  65.      * @param PreSetDataEvent $event
  66.      *
  67.      * @return bool
  68.      */
  69.     public function supports(PreSetDataEvent $event): bool
  70.     {
  71.         return $event->getForm()->getConfig()->getType()->getInnerType() instanceof AbstractViewOrderAwareType;
  72.     }
  73.     /**
  74.      * @param PreSetDataEvent $event
  75.      *
  76.      * @return void
  77.      *
  78.      * @throws LogicException
  79.      * @throws ResourceClassNotSupportedException
  80.      * @throws ReflectionException
  81.      */
  82.     public function onPreSetData(PreSetDataEvent $event): void
  83.     {
  84.         if (!$this->supports($event)) {
  85.             throw new LogicException(sprintf('%s should not be used with %s as it does not extends %s'__CLASS__get_class($event->getForm()->getConfig()->getType()->getInnerType()), AbstractViewOrderAwareType::class));
  86.         }
  87.         $entity $event->getForm()->getConfig()->getOption(AbstractViewOrderAwareType::FORM_CONFIG_SPECIFIC_FIELD_ENTITY);
  88.         $entityShortName = (new ReflectionClass($entity))->getShortName();
  89.         if (!isset($this->fields[$entityShortName])) {
  90.             $this->fields[$entityShortName] = $this->collectionDataProvider->getCollection(Field::class, null, [
  91.                 'filters' => [
  92.                     'entity' => $entityShortName,
  93.                 ],
  94.             ]);
  95.         }
  96.         /** @var Field $field */
  97.         foreach ($this->fields[$entityShortName] as $field) {
  98.             foreach ($this->specificFieldBuilder->getSpecificFieldTypeBuilders() as $specificFieldTypeBuilder) {
  99.                 if ($specificFieldTypeBuilder->supports($field)) {
  100.                     $specificFieldTypeBuilder->build($event->getForm(), $event->getData(), $field);
  101.                     continue 2;
  102.                 }
  103.             }
  104.             throw new LogicException(sprintf('Unable to build specific field %s (%s)'$field->getId(), $field->getName()));
  105.         }
  106.     }
  107.     /**
  108.      * @param PostSubmitEvent $event
  109.      *
  110.      * @return void
  111.      */
  112.     public function onPostSubmit(PostSubmitEvent $event): void
  113.     {
  114.         $entity $event->getData();
  115.         if (!$entity instanceof SpecificFieldsAwareInterface) {
  116.             return;
  117.         }
  118.         foreach ($event->getForm()->all() as $formChild) {
  119.             if (!str_starts_with($formChild->getName(), 'sf_')) {
  120.                 continue;
  121.             }
  122.             $fieldId str_replace('sf_'''$formChild->getName());
  123.             $specificField $entity->getSpecificFieldByFieldId($fieldId);
  124.             if (!$specificField instanceof SpecificField && !$specificField instanceof SpecificFieldV4) {
  125.                 /** @var User $user */
  126.                 $user $this->security->getUser();
  127.                 /** @var SpecificFieldV4|SpecificField $specificField */
  128.                 $specificFieldClass $entity::SPECIFIC_FIELD_CLASS_NAME;
  129.                 $specificField = new $specificFieldClass();
  130.                 $specificField->setFieldId($fieldId);
  131.                 $specificField->setCustomerId($user->getCustomerId());
  132.                 $specificField->setFieldType(
  133.                     $formChild->getConfig()->getOption('choices'false) && !$formChild->getConfig()->getOption('multiple'false)
  134.                         ? FieldType::FIELD_TYPE_CHOICE
  135.                         null
  136.                 );
  137.                 $entity->addSpecificField($specificField);
  138.             }
  139.             $specificField->setValue(is_array($formChild->getViewData()) ? implode(','$formChild->getViewData()) : $formChild->getViewData());
  140.         }
  141.     }
  142. }