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

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