diff --git a/src/Symfony/Component/Form/Exception/CircularReferenceException.php b/src/Symfony/Component/Form/Exception/CircularReferenceException.php new file mode 100644 index 0000000000..629044965e --- /dev/null +++ b/src/Symfony/Component/Form/Exception/CircularReferenceException.php @@ -0,0 +1,22 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Exception; + +use Symfony\Component\Form\FormTypeInterface; + +class CircularReferenceException extends FormException +{ + public function __construct(FormTypeInterface $type, $code = 0, $previous = null) + { + parent::__construct(sprintf('Circular reference detected in the "%s" type (defined in class "%s").', $type->getName(), get_class($type)), $code, $previous); + } +} diff --git a/src/Symfony/Component/Form/FormBuilder.php b/src/Symfony/Component/Form/FormBuilder.php index fe0c1032b9..aebbbd3c45 100644 --- a/src/Symfony/Component/Form/FormBuilder.php +++ b/src/Symfony/Component/Form/FormBuilder.php @@ -13,6 +13,7 @@ namespace Symfony\Component\Form; use Symfony\Component\Form\Exception\FormException; use Symfony\Component\Form\Exception\UnexpectedTypeException; +use Symfony\Component\Form\Exception\CircularReferenceException; use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\EventDispatcher\EventSubscriberInterface; @@ -110,6 +111,8 @@ class FormBuilder */ private $emptyData = ''; + private $currentLoadingType; + /** * Constructor. * @@ -538,6 +541,10 @@ class FormBuilder throw new UnexpectedTypeException($type, 'string or Symfony\Component\Form\FormTypeInterface'); } + if ($this->currentLoadingType && ($type instanceof FormTypeInterface ? $type->getName() : $type) == $this->currentLoadingType) { + throw new CircularReferenceException(is_string($type) ? $this->getFormFactory()->getType($type) : $type); + } + $this->children[$child] = array( 'type' => $type, 'options' => $options, @@ -655,6 +662,11 @@ class FormBuilder return $instance; } + public function setCurrentLoadingType($type) + { + $this->currentLoadingType = $type; + } + /** * Returns the event dispatcher. * diff --git a/src/Symfony/Component/Form/FormFactory.php b/src/Symfony/Component/Form/FormFactory.php index 64d35b3b73..8df3939c7d 100644 --- a/src/Symfony/Component/Form/FormFactory.php +++ b/src/Symfony/Component/Form/FormFactory.php @@ -269,6 +269,7 @@ class FormFactory implements FormFactoryInterface } $builder->setTypes($types); + $builder->setCurrentLoadingType($type->getName()); foreach ($types as $type) { $type->buildForm($builder, $options); @@ -277,6 +278,7 @@ class FormFactory implements FormFactoryInterface $typeExtension->buildForm($builder, $options); } } + $builder->setCurrentLoadingType(null); return $builder; }