Merge branch '2.3'

* 2.3:
  [HttpFoundation] fixed format duplication in Request
  [Form] Fixed FormValidator::findClickedButton() not to be called exponentially
This commit is contained in:
Fabien Potencier 2013-09-10 22:45:14 +02:00
commit ddee0db00f
4 changed files with 91 additions and 7 deletions

View File

@ -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');

View File

@ -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);
}
}

View File

@ -411,9 +411,8 @@ class Request
$dup->method = null;
$dup->format = null;
if (!$dup->get('_format')) {
// we set the request format to null if the current request is not known
$dup->setRequestFormat($this->getRequestFormat(null));
if (!$dup->get('_format') && $this->get('_format')) {
$dup->attributes->set('_format', $this->get('_format'));
}
return $dup;

View File

@ -250,9 +250,6 @@ class RequestTest extends \PHPUnit_Framework_TestCase
$this->assertEquals('foo=bar', $request->getQueryString());
}
/**
* @covers Symfony\Component\HttpFoundation\Request::duplicate
*/
public function testDuplicate()
{
$request = new Request(array('foo' => 'bar'), array('foo' => 'bar'), array('foo' => 'bar'), array(), array(), array('HTTP_FOO' => 'bar'));
@ -271,6 +268,15 @@ class RequestTest extends \PHPUnit_Framework_TestCase
$this->assertEquals(array('foo' => array('foobar')), $dup->headers->all(), '->duplicate() overrides the HTTP header if provided');
}
public function testDuplicateWithFormat()
{
$request = new Request(array(), array(), array('_format' => 'json'));
$dup = $request->duplicate();
$this->assertEquals('json', $dup->getRequestFormat());
$this->assertEquals('json', $dup->attributes->get('_format'));
}
/**
* @covers Symfony\Component\HttpFoundation\Request::getFormat
* @covers Symfony\Component\HttpFoundation\Request::setFormat