vendor/sulu/form-bundle/Form/Type/DynamicFormType.php line 27

Open in your IDE?
  1. <?php
  2. /*
  3.  * This file is part of Sulu.
  4.  *
  5.  * (c) Sulu GmbH
  6.  *
  7.  * This source file is subject to the MIT license that is bundled
  8.  * with this source code in the file LICENSE.
  9.  */
  10. namespace Sulu\Bundle\FormBundle\Form\Type;
  11. use Sulu\Bundle\FormBundle\Dynamic\Checksum;
  12. use Sulu\Bundle\FormBundle\Dynamic\FormFieldTypePool;
  13. use Sulu\Bundle\FormBundle\Entity\Dynamic;
  14. use Sulu\Bundle\FormBundle\Entity\Form;
  15. use Sulu\Bundle\FormBundle\Exception\FormNotFoundException;
  16. use Symfony\Component\Form\AbstractType;
  17. use Symfony\Component\Form\Extension\Core\Type\EmailType;
  18. use Symfony\Component\Form\Extension\Core\Type\HiddenType;
  19. use Symfony\Component\Form\Extension\Core\Type\SubmitType;
  20. use Symfony\Component\Form\FormBuilderInterface;
  21. use Symfony\Component\OptionsResolver\OptionsResolver;
  22. use Symfony\Component\Validator\Constraints\NotBlank;
  23. class DynamicFormType extends AbstractType
  24. {
  25.     /**
  26.      * @var FormFieldTypePool
  27.      */
  28.     private $typePool;
  29.     /**
  30.      * @var Checksum
  31.      */
  32.     private $checksum;
  33.     /**
  34.      * @var string|null
  35.      */
  36.     private $honeyPotField;
  37.     /**
  38.      * DynamicFormType constructor.
  39.      */
  40.     public function __construct(
  41.         FormFieldTypePool $typePool,
  42.         Checksum $checksum,
  43.         ?string $honeyPotField null
  44.     ) {
  45.         $this->typePool $typePool;
  46.         $this->checksum $checksum;
  47.         $this->honeyPotField $honeyPotField;
  48.     }
  49.     /**
  50.      * @return void
  51.      */
  52.     public function buildForm(FormBuilderInterface $builder, array $options)
  53.     {
  54.         /** @var Form $formEntity */
  55.         $formEntity $options['formEntity'];
  56.         /** @var string $locale */
  57.         $locale $options['locale'];
  58.         /** @var string $type */
  59.         $type $options['type'];
  60.         /** @var string $typeId */
  61.         $typeId $options['typeId'];
  62.         /** @var string $name */
  63.         $name $options['name'];
  64.         if (!$translation $formEntity->getTranslation($locale)) {
  65.             throw new FormNotFoundException($formEntity->getId(), $locale);
  66.         }
  67.         $currentWidthValue 0;
  68.         $fields $formEntity->getFields();
  69.         foreach ($fields as $key => $field) {
  70.             $fieldTranslation $field->getTranslation($locale);
  71.             if (!$fieldTranslation) {
  72.                 continue;
  73.             }
  74.             $options = [
  75.                 'constraints' => [],
  76.                 'attr' => [],
  77.                 'translation_domain' => false,
  78.                 'property_path' => 'data[' $field->getKey() . ']',
  79.             ];
  80.             $title $fieldTranslation->getTitle();
  81.             $placeholder $fieldTranslation->getPlaceholder();
  82.             $width $field->getWidth() ?: 'full';
  83.             $nextField null;
  84.             $nextWidth 'full';
  85.             if (isset($fields[$key 1])) {
  86.                 $nextWidth $fields[$key 1]->getWidth();
  87.             }
  88.             $lastWidth $this->getLastWidth($currentWidthValue$width$nextWidth);
  89.             $options['label'] = $title ?: false;
  90.             $options['required'] = $field->getRequired();
  91.             $options['attr']['width'] = $width;
  92.             $options['attr']['widthNumber'] = $this->getItemWidthNumber($width);
  93.             $options['attr']['lastWidth'] = $lastWidth;
  94.             if ($placeholder) {
  95.                 $options['attr']['placeholder'] = $placeholder;
  96.             }
  97.             // required
  98.             if ($field->getRequired()) {
  99.                 $options['constraints'][] = new NotBlank();
  100.             }
  101.             $this->typePool->get($field->getType())->build($builder$field$locale$options);
  102.         }
  103.         // Add hidden locale. (de, en, ...)
  104.         $builder->add('locale'HiddenType::class, [
  105.             'data' => $locale,
  106.             'mapped' => false,
  107.         ]);
  108.         // Add hidden type field. (page, article, event, blog, ...)
  109.         $builder->add('type'HiddenType::class, [
  110.             'data' => $type,
  111.             'mapped' => false,
  112.         ]);
  113.         // Add hidden typeId field. (UUID, Database id, ...)
  114.         $builder->add('typeId'HiddenType::class, [
  115.             'data' => $typeId,
  116.             'mapped' => false,
  117.         ]);
  118.         // Add hidden formId. (id, uuid,…)
  119.         $builder->add('formId'HiddenType::class, [
  120.             'data' => $formEntity->getId(),
  121.             'mapped' => false,
  122.         ]);
  123.         // Add hidden formName field. (Name of "form_select"-content-type.)
  124.         $builder->add('formName'HiddenType::class, [
  125.             'data' => $name,
  126.             'mapped' => false,
  127.         ]);
  128.         // Add hidden formName field. (Name of "form_select"-content-type.)
  129.         $checksum $this->checksum->get($type$typeId$formEntity->getId(), $name);
  130.         $builder->add('checksum'HiddenType::class, [
  131.             'data' => $checksum,
  132.             'mapped' => false,
  133.         ]);
  134.         if ($this->honeyPotField) {
  135.             $builder->add(
  136.                 \str_replace(' ''_'\strtolower($this->honeyPotField)),
  137.                 EmailType::class,
  138.                 [
  139.                     'label' => $this->honeyPotField,
  140.                     'mapped' => false,
  141.                     'block_prefix' => 'honeypot',
  142.                     'required' => false,
  143.                 ]
  144.             );
  145.         }
  146.         // Add submit button.
  147.         $builder->add(
  148.             'submit',
  149.             SubmitType::class,
  150.             [
  151.                 'label' => $translation->getSubmitLabel(),
  152.                 'translation_domain' => false,
  153.                 'attr' => [
  154.                     'width' => 'full',
  155.                     'widthNumber' => $this->getItemWidthNumber('full'),
  156.                     'lastWidth' => true,
  157.                 ],
  158.             ]
  159.         );
  160.     }
  161.     /**
  162.      * @return void
  163.      */
  164.     public function configureOptions(OptionsResolver $resolver)
  165.     {
  166.         $defaults = [];
  167.         $defaults['csrf_protection'] = true;
  168.         $defaults['csrf_field_name'] = '_token';
  169.         $defaults['data_class'] = Dynamic::class;
  170.         $resolver->setDefaults($defaults);
  171.         $resolver->setRequired('locale');
  172.         $resolver->setRequired('type');
  173.         $resolver->setRequired('typeId');
  174.         $resolver->setRequired('name');
  175.         $resolver->setRequired('formEntity');
  176.     }
  177.     public function getBlockPrefix()
  178.     {
  179.         return 'dynamic';
  180.     }
  181.     private function getItemWidthNumber(string $width): int
  182.     {
  183.         switch ($width) {
  184.             case 'one-sixth':
  185.                 $itemWidth 2;
  186.                 break;
  187.             case 'five-sixths':
  188.                 $itemWidth 10;
  189.                 break;
  190.             case 'one-quarter':
  191.                 $itemWidth 3;
  192.                 break;
  193.             case 'three-quarters':
  194.                 $itemWidth 9;
  195.                 break;
  196.             case 'one-third':
  197.                 $itemWidth 4;
  198.                 break;
  199.             case 'two-thirds':
  200.                 $itemWidth 8;
  201.                 break;
  202.             case 'half':
  203.                 $itemWidth 6;
  204.                 break;
  205.             case 'full':
  206.                 $itemWidth 12;
  207.                 break;
  208.             default:
  209.                 $itemWidth 12;
  210.         }
  211.         return $itemWidth;
  212.     }
  213.     private function getLastWidth(int &$currentWidthValuestring $widthstring $nextWidth): bool
  214.     {
  215.         $widthNumber $this->getItemWidthNumber($width);
  216.         $nextWidthNumber $this->getItemWidthNumber($nextWidth);
  217.         $currentWidthValue += $widthNumber;
  218.         if (== $currentWidthValue 12) {
  219.             return true;
  220.         }
  221.         // if next item has no space in current row the current item is last
  222.         if (($currentWidthValue 12) + $nextWidthNumber 12) {
  223.             $currentWidthValue += 12 $currentWidthValue 12;
  224.             return true;
  225.         }
  226.         return false;
  227.     }
  228. }