vendor/symfony/symfony/src/Symfony/Component/Form/FormBuilder.php line 202

Open in your IDE?
  1. <?php
  2. /*
  3.  * This file is part of the Symfony package.
  4.  *
  5.  * (c) Fabien Potencier <fabien@symfony.com>
  6.  *
  7.  * For the full copyright and license information, please view the LICENSE
  8.  * file that was distributed with this source code.
  9.  */
  10. namespace Symfony\Component\Form;
  11. use Symfony\Component\EventDispatcher\EventDispatcherInterface;
  12. use Symfony\Component\Form\Exception\BadMethodCallException;
  13. use Symfony\Component\Form\Exception\InvalidArgumentException;
  14. use Symfony\Component\Form\Exception\UnexpectedTypeException;
  15. /**
  16.  * A builder for creating {@link Form} instances.
  17.  *
  18.  * @author Bernhard Schussek <bschussek@gmail.com>
  19.  */
  20. class FormBuilder extends FormConfigBuilder implements \IteratorAggregateFormBuilderInterface
  21. {
  22.     /**
  23.      * The children of the form builder.
  24.      *
  25.      * @var FormBuilderInterface[]
  26.      */
  27.     private $children = [];
  28.     /**
  29.      * The data of children who haven't been converted to form builders yet.
  30.      *
  31.      * @var array
  32.      */
  33.     private $unresolvedChildren = [];
  34.     /**
  35.      * @param string                   $name
  36.      * @param string|null              $dataClass
  37.      * @param EventDispatcherInterface $dispatcher
  38.      * @param FormFactoryInterface     $factory
  39.      * @param array                    $options
  40.      */
  41.     public function __construct($name$dataClassEventDispatcherInterface $dispatcherFormFactoryInterface $factory, array $options = [])
  42.     {
  43.         parent::__construct($name$dataClass$dispatcher$options);
  44.         $this->setFormFactory($factory);
  45.     }
  46.     /**
  47.      * {@inheritdoc}
  48.      */
  49.     public function add($child$type null, array $options = [])
  50.     {
  51.         if ($this->locked) {
  52.             throw new BadMethodCallException('FormBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.');
  53.         }
  54.         if ($child instanceof FormBuilderInterface) {
  55.             $this->children[$child->getName()] = $child;
  56.             // In case an unresolved child with the same name exists
  57.             unset($this->unresolvedChildren[$child->getName()]);
  58.             return $this;
  59.         }
  60.         if (!\is_string($child) && !\is_int($child)) {
  61.             throw new UnexpectedTypeException($child'string, integer or Symfony\Component\Form\FormBuilderInterface');
  62.         }
  63.         if (null !== $type && !\is_string($type) && !$type instanceof FormTypeInterface) {
  64.             throw new UnexpectedTypeException($type'string or Symfony\Component\Form\FormTypeInterface');
  65.         }
  66.         // Add to "children" to maintain order
  67.         $this->children[$child] = null;
  68.         $this->unresolvedChildren[$child] = [$type$options];
  69.         return $this;
  70.     }
  71.     /**
  72.      * {@inheritdoc}
  73.      */
  74.     public function create($name$type null, array $options = [])
  75.     {
  76.         if ($this->locked) {
  77.             throw new BadMethodCallException('FormBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.');
  78.         }
  79.         if (null === $type && null === $this->getDataClass()) {
  80.             $type 'Symfony\Component\Form\Extension\Core\Type\TextType';
  81.         }
  82.         if (null !== $type) {
  83.             return $this->getFormFactory()->createNamedBuilder($name$typenull$options);
  84.         }
  85.         return $this->getFormFactory()->createBuilderForProperty($this->getDataClass(), $namenull$options);
  86.     }
  87.     /**
  88.      * {@inheritdoc}
  89.      */
  90.     public function get($name)
  91.     {
  92.         if ($this->locked) {
  93.             throw new BadMethodCallException('FormBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.');
  94.         }
  95.         if (isset($this->unresolvedChildren[$name])) {
  96.             return $this->resolveChild($name);
  97.         }
  98.         if (isset($this->children[$name])) {
  99.             return $this->children[$name];
  100.         }
  101.         throw new InvalidArgumentException(sprintf('The child with the name "%s" does not exist.'$name));
  102.     }
  103.     /**
  104.      * {@inheritdoc}
  105.      */
  106.     public function remove($name)
  107.     {
  108.         if ($this->locked) {
  109.             throw new BadMethodCallException('FormBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.');
  110.         }
  111.         unset($this->unresolvedChildren[$name], $this->children[$name]);
  112.         return $this;
  113.     }
  114.     /**
  115.      * {@inheritdoc}
  116.      */
  117.     public function has($name)
  118.     {
  119.         if ($this->locked) {
  120.             throw new BadMethodCallException('FormBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.');
  121.         }
  122.         return isset($this->unresolvedChildren[$name]) || isset($this->children[$name]);
  123.     }
  124.     /**
  125.      * {@inheritdoc}
  126.      */
  127.     public function all()
  128.     {
  129.         if ($this->locked) {
  130.             throw new BadMethodCallException('FormBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.');
  131.         }
  132.         $this->resolveChildren();
  133.         return $this->children;
  134.     }
  135.     /**
  136.      * {@inheritdoc}
  137.      */
  138.     public function count()
  139.     {
  140.         if ($this->locked) {
  141.             throw new BadMethodCallException('FormBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.');
  142.         }
  143.         return \count($this->children);
  144.     }
  145.     /**
  146.      * {@inheritdoc}
  147.      */
  148.     public function getFormConfig()
  149.     {
  150.         /** @var $config self */
  151.         $config parent::getFormConfig();
  152.         $config->children = [];
  153.         $config->unresolvedChildren = [];
  154.         return $config;
  155.     }
  156.     /**
  157.      * {@inheritdoc}
  158.      */
  159.     public function getForm()
  160.     {
  161.         if ($this->locked) {
  162.             throw new BadMethodCallException('FormBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.');
  163.         }
  164.         $this->resolveChildren();
  165.         $form = new Form($this->getFormConfig());
  166.         foreach ($this->children as $child) {
  167.             // Automatic initialization is only supported on root forms
  168.             $form->add($child->setAutoInitialize(false)->getForm());
  169.         }
  170.         if ($this->getAutoInitialize()) {
  171.             // Automatically initialize the form if it is configured so
  172.             $form->initialize();
  173.         }
  174.         return $form;
  175.     }
  176.     /**
  177.      * {@inheritdoc}
  178.      *
  179.      * @return FormBuilderInterface[]|\Traversable
  180.      */
  181.     public function getIterator()
  182.     {
  183.         if ($this->locked) {
  184.             throw new BadMethodCallException('FormBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.');
  185.         }
  186.         return new \ArrayIterator($this->all());
  187.     }
  188.     /**
  189.      * Converts an unresolved child into a {@link FormBuilder} instance.
  190.      *
  191.      * @param string $name The name of the unresolved child
  192.      *
  193.      * @return self The created instance
  194.      */
  195.     private function resolveChild($name)
  196.     {
  197.         list($type$options) = $this->unresolvedChildren[$name];
  198.         unset($this->unresolvedChildren[$name]);
  199.         return $this->children[$name] = $this->create($name$type$options);
  200.     }
  201.     /**
  202.      * Converts all unresolved children into {@link FormBuilder} instances.
  203.      */
  204.     private function resolveChildren()
  205.     {
  206.         foreach ($this->unresolvedChildren as $name => $info) {
  207.             $this->children[$name] = $this->create($name$info[0], $info[1]);
  208.         }
  209.         $this->unresolvedChildren = [];
  210.     }
  211. }