Sfoglia il codice sorgente

[Form] added a circular reference safeguard for form type

Fabien Potencier 14 anni fa
parent
commit
ea93e4cafa

+ 22 - 0
src/Symfony/Component/Form/Exception/CircularReferenceException.php

@@ -0,0 +1,22 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * 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);
+    }
+}

+ 12 - 0
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.
      *

+ 2 - 0
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;
     }