Skip to content

Commit a610dbe

Browse files
committed
Merge branch '2.3'
* 2.3: (24 commits) Add german translation for several validators (Greater/Equal/Less) No Entity Manager defined exception fixed CS [Acl] Fix for issue #9433 [Validator] fix docblock typos [DependencyInjection] removed the unused Reference and Parameter classes use statements from the compiled container class Removed useless check if self::$trustProxies is set Fix mistake in translation's service definition. if handler_id is identical to null fix CS fix Fixed ModelChoiceList tests in Propel1 bridge. [AclProvider] Fix incorrect behaviour when partial results returned from cache Check if the pipe array is empty before calling stream_select() [Intl] fixed datetime test as described in #9455 bumped Symfony version to 2.3.8 updated VERSION for 2.3.7 updated CHANGELOG for 2.3.7 re-factor Propel1 ModelChoiceList [Form] Added method Form::getClickedButton() to remove memory leak in FormValidator [Locale] fixed the failing test described in #9455 ... Conflicts: src/Symfony/Bridge/Propel1/Form/ChoiceList/ModelChoiceList.php src/Symfony/Bridge/Propel1/Tests/Fixtures/ItemQuery.php src/Symfony/Bridge/Propel1/Tests/Form/ChoiceList/ModelChoiceListTest.php src/Symfony/Bridge/Propel1/Tests/Propel1TestCase.php src/Symfony/Component/Form/Tests/CompoundFormTest.php src/Symfony/Component/HttpKernel/Kernel.php src/Symfony/Component/Process/Process.php
2 parents bba9ff5 + f8c8990 commit a610dbe

File tree

6 files changed

+133
-57
lines changed

6 files changed

+133
-57
lines changed

ButtonBuilder.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ class ButtonBuilder implements \IteratorAggregate, FormBuilderInterface
6060
*
6161
* @throws InvalidArgumentException If the name is empty.
6262
*/
63-
public function __construct($name, array $options)
63+
public function __construct($name, array $options = array())
6464
{
6565
if (empty($name) && 0 != $name) {
6666
throw new InvalidArgumentException('Buttons cannot have empty names.');

Extension/Validator/Constraints/FormValidator.php

Lines changed: 6 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,6 @@
2222
*/
2323
class FormValidator extends ConstraintValidator
2424
{
25-
/**
26-
* @var \SplObjectStorage
27-
*/
28-
private static $clickedButtons;
29-
3025
/**
3126
* @var ServerParams
3227
*/
@@ -52,16 +47,6 @@ public function validate($form, Constraint $constraint)
5247
return;
5348
}
5449

55-
if (null === static::$clickedButtons) {
56-
static::$clickedButtons = new \SplObjectStorage();
57-
}
58-
59-
// If the form was previously validated, remove it from the cache in
60-
// case the clicked button has changed
61-
if (static::$clickedButtons->contains($form)) {
62-
static::$clickedButtons->detach($form);
63-
}
64-
6550
/* @var FormInterface $form */
6651
$config = $form->getConfig();
6752

@@ -187,20 +172,15 @@ private static function allowDataWalking(FormInterface $form)
187172
*/
188173
private static function getValidationGroups(FormInterface $form)
189174
{
190-
$root = $form->getRoot();
191-
192175
// Determine the clicked button of the complete form tree
193-
if (!static::$clickedButtons->contains($root)) {
194-
// Only call findClickedButton() once to prevent an exponential
195-
// runtime
196-
// https://github.com/symfony/symfony/issues/8317
197-
static::$clickedButtons->attach($root, self::findClickedButton($root));
198-
}
176+
$clickedButton = null;
199177

200-
$button = static::$clickedButtons->offsetGet($root);
178+
if (method_exists($form, 'getClickedButton')) {
179+
$clickedButton = $form->getClickedButton();
180+
}
201181

202-
if (null !== $button) {
203-
$groups = $button->getConfig()->getOption('validation_groups');
182+
if (null !== $clickedButton) {
183+
$groups = $clickedButton->getConfig()->getOption('validation_groups');
204184

205185
if (null !== $groups) {
206186
return self::resolveValidationGroups($groups, $form);
@@ -220,28 +200,6 @@ private static function getValidationGroups(FormInterface $form)
220200
return array(Constraint::DEFAULT_GROUP);
221201
}
222202

223-
/**
224-
* Extracts a clicked button from a form tree, if one exists.
225-
*
226-
* @param FormInterface $form The root form.
227-
*
228-
* @return ClickableInterface|null The clicked button or null.
229-
*/
230-
private static function findClickedButton(FormInterface $form)
231-
{
232-
if ($form instanceof ClickableInterface && $form->isClicked()) {
233-
return $form;
234-
}
235-
236-
foreach ($form as $child) {
237-
if (null !== ($button = self::findClickedButton($child))) {
238-
return $button;
239-
}
240-
}
241-
242-
return null;
243-
}
244-
245203
/**
246204
* Post-processes the validation groups option for a given form.
247205
*

Form.php

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,12 @@ class Form implements \IteratorAggregate, FormInterface
9090
*/
9191
private $submitted = false;
9292

93+
/**
94+
* The button that was used to submit the form
95+
* @var Button
96+
*/
97+
private $clickedButton;
98+
9399
/**
94100
* The form data in model format
95101
* @var mixed
@@ -553,6 +559,20 @@ public function submit($submittedData, $clearMissing = true)
553559
if (array_key_exists($name, $submittedData) || $clearMissing) {
554560
$child->submit(isset($submittedData[$name]) ? $submittedData[$name] : null, $clearMissing);
555561
unset($submittedData[$name]);
562+
563+
if (null !== $this->clickedButton) {
564+
continue;
565+
}
566+
567+
if ($child instanceof ClickableInterface && $child->isClicked()) {
568+
$this->clickedButton = $child;
569+
570+
continue;
571+
}
572+
573+
if (method_exists($child, 'getClickedButton') && null !== $child->getClickedButton()) {
574+
$this->clickedButton = $child->getClickedButton();
575+
}
556576
}
557577
}
558578

@@ -732,6 +752,25 @@ public function isValid()
732752
return true;
733753
}
734754

755+
/**
756+
* Returns the button that was used to submit the form.
757+
*
758+
* @return Button|null The clicked button or NULL if the form was not
759+
* submitted
760+
*/
761+
public function getClickedButton()
762+
{
763+
if ($this->clickedButton) {
764+
return $this->clickedButton;
765+
}
766+
767+
if ($this->parent && method_exists($this->parent, 'getClickedButton')) {
768+
return $this->parent->getClickedButton();
769+
}
770+
771+
return null;
772+
}
773+
735774
/**
736775
* {@inheritdoc}
737776
*/

Tests/CompoundFormTest.php

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,11 @@
1313

1414
use Symfony\Component\Form\Extension\Core\DataMapper\PropertyPathMapper;
1515
use Symfony\Component\Form\Extension\HttpFoundation\HttpFoundationRequestHandler;
16+
use Symfony\Component\Form\FormBuilder;
1617
use Symfony\Component\Form\FormError;
1718
use Symfony\Component\Form\Forms;
1819
use Symfony\Component\Form\FormView;
20+
use Symfony\Component\Form\SubmitButtonBuilder;
1921
use Symfony\Component\HttpFoundation\Request;
2022
use Symfony\Component\HttpFoundation\File\UploadedFile;
2123
use Symfony\Component\Form\Tests\Fixtures\FixedDataTransformer;
@@ -880,6 +882,88 @@ public function testCreateViewWithChildren()
880882
$this->assertSame($view, $this->form->createView());
881883
}
882884

885+
public function testNoClickedButtonBeforeSubmission()
886+
{
887+
$this->assertNull($this->form->getClickedButton());
888+
}
889+
890+
public function testNoClickedButton()
891+
{
892+
$button = $this->getMockBuilder('Symfony\Component\Form\SubmitButton')
893+
->setConstructorArgs(array(new SubmitButtonBuilder('submit')))
894+
->setMethods(array('isClicked'))
895+
->getMock();
896+
897+
$button->expects($this->any())
898+
->method('isClicked')
899+
->will($this->returnValue(false));
900+
901+
$parentForm = $this->getBuilder('parent')->getForm();
902+
$nestedForm = $this->getBuilder('nested')->getForm();
903+
904+
$this->form->setParent($parentForm);
905+
$this->form->add($button);
906+
$this->form->add($nestedForm);
907+
$this->form->submit(array());
908+
909+
$this->assertNull($this->form->getClickedButton());
910+
}
911+
912+
public function testClickedButton()
913+
{
914+
$button = $this->getMockBuilder('Symfony\Component\Form\SubmitButton')
915+
->setConstructorArgs(array(new SubmitButtonBuilder('submit')))
916+
->setMethods(array('isClicked'))
917+
->getMock();
918+
919+
$button->expects($this->any())
920+
->method('isClicked')
921+
->will($this->returnValue(true));
922+
923+
$this->form->add($button);
924+
$this->form->submit(array());
925+
926+
$this->assertSame($button, $this->form->getClickedButton());
927+
}
928+
929+
public function testClickedButtonFromNestedForm()
930+
{
931+
$button = $this->getBuilder('submit')->getForm();
932+
933+
$nestedForm = $this->getMockBuilder('Symfony\Component\Form\Form')
934+
->setConstructorArgs(array($this->getBuilder('nested')))
935+
->setMethods(array('getClickedButton'))
936+
->getMock();
937+
938+
$nestedForm->expects($this->any())
939+
->method('getClickedButton')
940+
->will($this->returnValue($button));
941+
942+
$this->form->add($nestedForm);
943+
$this->form->submit(array());
944+
945+
$this->assertSame($button, $this->form->getClickedButton());
946+
}
947+
948+
public function testClickedButtonFromParentForm()
949+
{
950+
$button = $this->getBuilder('submit')->getForm();
951+
952+
$parentForm = $this->getMockBuilder('Symfony\Component\Form\Form')
953+
->setConstructorArgs(array($this->getBuilder('parent')))
954+
->setMethods(array('getClickedButton'))
955+
->getMock();
956+
957+
$parentForm->expects($this->any())
958+
->method('getClickedButton')
959+
->will($this->returnValue($button));
960+
961+
$this->form->setParent($parentForm);
962+
$this->form->submit(array());
963+
964+
$this->assertSame($button, $this->form->getClickedButton());
965+
}
966+
883967
protected function createForm()
884968
{
885969
return $this->getBuilder()

Tests/Extension/Validator/Constraints/FormValidatorPerformanceTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ public function testValidationPerformance()
3838

3939
$builder = $this->factory->createBuilder('form');
4040

41-
for ($i = 0; $i < 100; ++$i) {
41+
for ($i = 0; $i < 40; ++$i) {
4242
$builder->add($i, 'form');
4343

4444
$builder->get($i)

Tests/Extension/Validator/Constraints/FormValidatorTest.php

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -426,11 +426,11 @@ public function testUseValidationGroupOfClickedButton()
426426
));
427427

428428
$parent->add($form);
429-
$parent->add($this->getClickedSubmitButton('submit', array(
429+
$parent->add($this->getSubmitButton('submit', array(
430430
'validation_groups' => 'button_group',
431431
)));
432432

433-
$form->setData($object);
433+
$parent->submit(array('name' => $object, 'submit' => ''));
434434

435435
$context->expects($this->once())
436436
->method('validate')
@@ -729,11 +729,6 @@ private function getSubmitButton($name = 'name', array $options = array())
729729
return $builder->getForm();
730730
}
731731

732-
private function getClickedSubmitButton($name = 'name', array $options = array())
733-
{
734-
return $this->getSubmitButton($name, $options)->submit('');
735-
}
736-
737732
/**
738733
* @return \PHPUnit_Framework_MockObject_MockObject
739734
*/

0 commit comments

Comments
 (0)