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

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.      */
  38.     public function __construct($name$dataClassEventDispatcherInterface $dispatcherFormFactoryInterface $factory, array $options = [])
  39.     {
  40.         parent::__construct($name$dataClass$dispatcher$options);
  41.         $this->setFormFactory($factory);
  42.     }
  43.     /**
  44.      * {@inheritdoc}
  45.      */
  46.     public function add($child$type null, array $options = [])
  47.     {
  48.         if ($this->locked) {
  49.             throw new BadMethodCallException('FormBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.');
  50.         }
  51.         if ($child instanceof FormBuilderInterface) {
  52.             $this->children[$child->getName()] = $child;
  53.             // In case an unresolved child with the same name exists
  54.             unset($this->unresolvedChildren[$child->getName()]);
  55.             return $this;
  56.         }
  57.         if (!\is_string($child) && !\is_int($child)) {
  58.             throw new UnexpectedTypeException($child'string or Symfony\Component\Form\FormBuilderInterface');
  59.         }
  60.         if (null !== $type && !\is_string($type) && !$type instanceof FormTypeInterface) {
  61.             throw new UnexpectedTypeException($type'string or Symfony\Component\Form\FormTypeInterface');
  62.         }
  63.         // Add to "children" to maintain order
  64.         $this->children[$child] = null;
  65.         $this->unresolvedChildren[$child] = [$type$options];
  66.         return $this;
  67.     }
  68.     /**
  69.      * {@inheritdoc}
  70.      */
  71.     public function create($name$type null, array $options = [])
  72.     {
  73.         if ($this->locked) {
  74.             throw new BadMethodCallException('FormBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.');
  75.         }
  76.         if (null === $type && null === $this->getDataClass()) {
  77.             $type 'Symfony\Component\Form\Extension\Core\Type\TextType';
  78.         }
  79.         if (null !== $type) {
  80.             return $this->getFormFactory()->createNamedBuilder($name$typenull$options);
  81.         }
  82.         return $this->getFormFactory()->createBuilderForProperty($this->getDataClass(), $namenull$options);
  83.     }
  84.     /**
  85.      * {@inheritdoc}
  86.      */
  87.     public function get($name)
  88.     {
  89.         if ($this->locked) {
  90.             throw new BadMethodCallException('FormBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.');
  91.         }
  92.         if (isset($this->unresolvedChildren[$name])) {
  93.             return $this->resolveChild($name);
  94.         }
  95.         if (isset($this->children[$name])) {
  96.             return $this->children[$name];
  97.         }
  98.         throw new InvalidArgumentException(sprintf('The child with the name "%s" does not exist.'$name));
  99.     }
  100.     /**
  101.      * {@inheritdoc}
  102.      */
  103.     public function remove($name)
  104.     {
  105.         if ($this->locked) {
  106.             throw new BadMethodCallException('FormBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.');
  107.         }
  108.         unset($this->unresolvedChildren[$name], $this->children[$name]);
  109.         return $this;
  110.     }
  111.     /**
  112.      * {@inheritdoc}
  113.      */
  114.     public function has($name)
  115.     {
  116.         if ($this->locked) {
  117.             throw new BadMethodCallException('FormBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.');
  118.         }
  119.         return isset($this->unresolvedChildren[$name]) || isset($this->children[$name]);
  120.     }
  121.     /**
  122.      * {@inheritdoc}
  123.      */
  124.     public function all()
  125.     {
  126.         if ($this->locked) {
  127.             throw new BadMethodCallException('FormBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.');
  128.         }
  129.         $this->resolveChildren();
  130.         return $this->children;
  131.     }
  132.     /**
  133.      * {@inheritdoc}
  134.      */
  135.     public function count()
  136.     {
  137.         if ($this->locked) {
  138.             throw new BadMethodCallException('FormBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.');
  139.         }
  140.         return \count($this->children);
  141.     }
  142.     /**
  143.      * {@inheritdoc}
  144.      */
  145.     public function getFormConfig()
  146.     {
  147.         /** @var $config self */
  148.         $config parent::getFormConfig();
  149.         $config->children = [];
  150.         $config->unresolvedChildren = [];
  151.         return $config;
  152.     }
  153.     /**
  154.      * {@inheritdoc}
  155.      */
  156.     public function getForm()
  157.     {
  158.         if ($this->locked) {
  159.             throw new BadMethodCallException('FormBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.');
  160.         }
  161.         $this->resolveChildren();
  162.         $form = new Form($this->getFormConfig());
  163.         foreach ($this->children as $child) {
  164.             // Automatic initialization is only supported on root forms
  165.             $form->add($child->setAutoInitialize(false)->getForm());
  166.         }
  167.         if ($this->getAutoInitialize()) {
  168.             // Automatically initialize the form if it is configured so
  169.             $form->initialize();
  170.         }
  171.         return $form;
  172.     }
  173.     /**
  174.      * {@inheritdoc}
  175.      *
  176.      * @return FormBuilderInterface[]|\Traversable
  177.      */
  178.     public function getIterator()
  179.     {
  180.         if ($this->locked) {
  181.             throw new BadMethodCallException('FormBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.');
  182.         }
  183.         return new \ArrayIterator($this->all());
  184.     }
  185.     /**
  186.      * Converts an unresolved child into a {@link FormBuilder} instance.
  187.      *
  188.      * @param string $name The name of the unresolved child
  189.      *
  190.      * @return self The created instance
  191.      */
  192.     private function resolveChild($name)
  193.     {
  194.         list($type$options) = $this->unresolvedChildren[$name];
  195.         unset($this->unresolvedChildren[$name]);
  196.         return $this->children[$name] = $this->create($name$type$options);
  197.     }
  198.     /**
  199.      * Converts all unresolved children into {@link FormBuilder} instances.
  200.      */
  201.     private function resolveChildren()
  202.     {
  203.         foreach ($this->unresolvedChildren as $name => $info) {
  204.             $this->children[$name] = $this->create($name$info[0], $info[1]);
  205.         }
  206.         $this->unresolvedChildren = [];
  207.     }
  208. }