[Form] Fixed FormValidator::findClickedButton() not to be called exponentially
This commit is contained in:
parent
a672bba5cb
commit
b65a51519d
@ -22,6 +22,11 @@ use Symfony\Component\Validator\ConstraintValidator;
|
||||
*/
|
||||
class FormValidator extends ConstraintValidator
|
||||
{
|
||||
/**
|
||||
* @var \SplObjectStorage
|
||||
*/
|
||||
private static $clickedButtons;
|
||||
|
||||
/**
|
||||
* @var ServerParams
|
||||
*/
|
||||
@ -47,6 +52,16 @@ class FormValidator extends ConstraintValidator
|
||||
return;
|
||||
}
|
||||
|
||||
if (null === static::$clickedButtons) {
|
||||
static::$clickedButtons = new \SplObjectStorage();
|
||||
}
|
||||
|
||||
// If the form was previously validated, remove it from the cache in
|
||||
// case the clicked button has changed
|
||||
if (static::$clickedButtons->contains($form)) {
|
||||
static::$clickedButtons->detach($form);
|
||||
}
|
||||
|
||||
/* @var FormInterface $form */
|
||||
$config = $form->getConfig();
|
||||
|
||||
@ -172,7 +187,17 @@ class FormValidator extends ConstraintValidator
|
||||
*/
|
||||
private static function getValidationGroups(FormInterface $form)
|
||||
{
|
||||
$button = self::findClickedButton($form->getRoot());
|
||||
$root = $form->getRoot();
|
||||
|
||||
// Determine the clicked button of the complete form tree
|
||||
if (!static::$clickedButtons->contains($root)) {
|
||||
// Only call findClickedButton() once to prevent an exponential
|
||||
// runtime
|
||||
// https://github.com/symfony/symfony/issues/8317
|
||||
static::$clickedButtons->attach($root, self::findClickedButton($root));
|
||||
}
|
||||
|
||||
$button = static::$clickedButtons->offsetGet($root);
|
||||
|
||||
if (null !== $button) {
|
||||
$groups = $button->getConfig()->getOption('validation_groups');
|
||||
|
@ -0,0 +1,54 @@
|
||||
<?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\Tests\Extension\Validator\Constraints;
|
||||
|
||||
use Symfony\Component\Form\Extension\Validator\ValidatorExtension;
|
||||
use Symfony\Component\Form\Test\FormPerformanceTestCase;
|
||||
use Symfony\Component\Validator\Validation;
|
||||
|
||||
/**
|
||||
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||
*/
|
||||
class FormValidatorPerformanceTest extends FormPerformanceTestCase
|
||||
{
|
||||
protected function getExtensions()
|
||||
{
|
||||
return array(
|
||||
new ValidatorExtension(Validation::createValidator()),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* findClickedButton() used to have an exponential number of calls
|
||||
*
|
||||
* @group benchmark
|
||||
*/
|
||||
public function testValidationPerformance()
|
||||
{
|
||||
$this->setMaxRunningTime(1);
|
||||
|
||||
$builder = $this->factory->createBuilder('form');
|
||||
|
||||
for ($i = 0; $i < 100; ++$i) {
|
||||
$builder->add($i, 'form');
|
||||
|
||||
$builder->get($i)
|
||||
->add('a')
|
||||
->add('b')
|
||||
->add('c');
|
||||
}
|
||||
|
||||
$form = $builder->getForm();
|
||||
|
||||
$form->submit(null);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user