diff --git a/src/Symfony/Component/Form/Form.php b/src/Symfony/Component/Form/Form.php index 54b9b39ebd..87cd15bf47 100644 --- a/src/Symfony/Component/Form/Form.php +++ b/src/Symfony/Component/Form/Form.php @@ -408,6 +408,10 @@ class Form implements \IteratorAggregate, FormInterface } if (!$this->defaultDataSet) { + if ($this->lockSetData) { + throw new RuntimeException('A cycle was detected. Listeners to the PRE_SET_DATA event must not call getData() if the form data has not already been set. You should call getData() on the FormEvent object instead.'); + } + $this->setData($this->config->getData()); } @@ -428,6 +432,10 @@ class Form implements \IteratorAggregate, FormInterface } if (!$this->defaultDataSet) { + if ($this->lockSetData) { + throw new RuntimeException('A cycle was detected. Listeners to the PRE_SET_DATA event must not call getNormData() if the form data has not already been set.'); + } + $this->setData($this->config->getData()); } @@ -448,6 +456,10 @@ class Form implements \IteratorAggregate, FormInterface } if (!$this->defaultDataSet) { + if ($this->lockSetData) { + throw new RuntimeException('A cycle was detected. Listeners to the PRE_SET_DATA event must not call getViewData() if the form data has not already been set.'); + } + $this->setData($this->config->getData()); } diff --git a/src/Symfony/Component/Form/Tests/SimpleFormTest.php b/src/Symfony/Component/Form/Tests/SimpleFormTest.php index 6223d3b39f..62c94c7490 100644 --- a/src/Symfony/Component/Form/Tests/SimpleFormTest.php +++ b/src/Symfony/Component/Form/Tests/SimpleFormTest.php @@ -903,6 +903,7 @@ class SimpleFormTest extends AbstractFormTest /** * @expectedException \Symfony\Component\Form\Exception\RuntimeException + * @expectedExceptionMessage A cycle was detected. Listeners to the PRE_SET_DATA event must not call setData(). You should call setData() on the FormEvent object instead. */ public function testSetDataCannotInvokeItself() { @@ -1084,6 +1085,51 @@ class SimpleFormTest extends AbstractFormTest $fooType->setDefaultOptions($resolver); } + /** + * @expectedException \Symfony\Component\Form\Exception\RuntimeException + * @expectedExceptionMessage A cycle was detected. Listeners to the PRE_SET_DATA event must not call getData() if the form data has not already been set. You should call getData() on the FormEvent object instead. + */ + public function testCannotCallGetDataInPreSetDataListenerIfDataHasNotAlreadyBeenSet() + { + $config = new FormConfigBuilder('name', 'stdClass', $this->dispatcher); + $config->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) { + $event->getForm()->getData(); + }); + $form = new Form($config); + + $form->setData('foo'); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\RuntimeException + * @expectedExceptionMessage A cycle was detected. Listeners to the PRE_SET_DATA event must not call getNormData() if the form data has not already been set. + */ + public function testCannotCallGetNormDataInPreSetDataListener() + { + $config = new FormConfigBuilder('name', 'stdClass', $this->dispatcher); + $config->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) { + $event->getForm()->getNormData(); + }); + $form = new Form($config); + + $form->setData('foo'); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\RuntimeException + * @expectedExceptionMessage A cycle was detected. Listeners to the PRE_SET_DATA event must not call getViewData() if the form data has not already been set. + */ + public function testCannotCallGetViewDataInPreSetDataListener() + { + $config = new FormConfigBuilder('name', 'stdClass', $this->dispatcher); + $config->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) { + $event->getForm()->getViewData(); + }); + $form = new Form($config); + + $form->setData('foo'); + } + protected function createForm() { return $this->getBuilder()->getForm();