bug #12004 [Form] Fixed ValidatorTypeGuesser to guess properties without constraints not to be required (webmozart)

This PR was merged into the 2.3 branch.

Discussion
----------

[Form] Fixed ValidatorTypeGuesser to guess properties without constraints not to be required

| Q             | A
| ------------- | ---
| Bug fix?      | yes
| New feature?  | no
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | #6645
| License       | MIT
| Doc PR        | -

Consider the following entity:

```php
class Author
{
    /**
     * @Assert\NotBlank
     */
    private $name;

    private $age;
}
```

Right now, the "required" HTML attribute is set for both fields (since the default value of the "required" option is true). IMO this is wrong.

With this fix, the ValidatorTypeGuesser guesses `false` for the "required" option unless a NotNull/NotBlank constraint is present.

Commits
-------

fd77b09 [Form] Fixed ValidatorTypeGuesser to guess properties without constraints not to be required
This commit is contained in:
Fabien Potencier 2014-09-24 14:19:03 +02:00
commit bc8ee6f497
3 changed files with 90 additions and 27 deletions

View File

@ -1,9 +1,8 @@
CHANGELOG
=========
2.3.0
------
-----
* deprecated FormPerformanceTestCase and FormIntegrationTestCase in the Symfony\Component\Form\Tests namespace and moved them to the Symfony\Component\Form\Test namespace
* deprecated TypeTestCase in the Symfony\Component\Form\Tests\Extension\Core\Type namespace and moved it to the Symfony\Component\Form\Test namespace

View File

@ -276,10 +276,10 @@ class ValidatorTypeGuesser implements FormTypeGuesserInterface
}
}
}
}
if (null !== $defaultValue) {
$guesses[] = new ValueGuess($defaultValue, Guess::LOW_CONFIDENCE);
}
if (null !== $defaultValue) {
$guesses[] = new ValueGuess($defaultValue, Guess::LOW_CONFIDENCE);
}
return Guess::getBestGuess($guesses);

View File

@ -13,32 +13,91 @@ namespace Symfony\Component\Form\Tests\Extension\Validator;
use Symfony\Component\Form\Extension\Validator\ValidatorTypeGuesser;
use Symfony\Component\Form\Guess\Guess;
use Symfony\Component\Form\Guess\ValueGuess;
use Symfony\Component\Validator\Constraints\Email;
use Symfony\Component\Validator\Constraints\Length;
use Symfony\Component\Validator\Constraints\NotBlank;
use Symfony\Component\Validator\Constraints\NotNull;
use Symfony\Component\Validator\Constraints\Range;
use Symfony\Component\Validator\Constraints\True;
use Symfony\Component\Validator\Constraints\Type;
use Symfony\Component\Validator\Mapping\ClassMetadata;
/**
* @author franek <franek@chicour.net>
*/
* @author franek <franek@chicour.net>
* @author Bernhard Schussek <bschussek@gmail.com>
*/
class ValidatorTypeGuesserTest extends \PHPUnit_Framework_TestCase
{
private $typeGuesser;
const TEST_CLASS = 'Symfony\Component\Form\Tests\Extension\Validator\ValidatorTypeGuesserTest_TestClass';
public function setUp()
const TEST_PROPERTY = 'property';
/**
* @var ValidatorTypeGuesser
*/
private $guesser;
/**
* @var ClassMetadata
*/
private $metadata;
/**
* @var \PHPUnit_Framework_MockObject_MockObject
*/
private $metadataFactory;
protected function setUp()
{
if (!class_exists('Symfony\Component\Validator\Constraint')) {
$this->markTestSkipped('The "Validator" component is not available');
}
$metadataFactory = $this->getMock('Symfony\Component\Validator\MetadataFactoryInterface');
$this->metadata = new ClassMetadata(self::TEST_CLASS);
$this->metadataFactory = $this->getMock('Symfony\Component\Validator\MetadataFactoryInterface');
$this->metadataFactory->expects($this->any())
->method('getMetadataFor')
->with(self::TEST_CLASS)
->will($this->returnValue($this->metadata));
$this->guesser = new ValidatorTypeGuesser($this->metadataFactory);
}
$this->typeGuesser = new ValidatorTypeGuesser($metadataFactory);
public function guessRequiredProvider()
{
return array(
array(new NotNull(), new ValueGuess(true, Guess::HIGH_CONFIDENCE)),
array(new NotBlank(), new ValueGuess(true, Guess::HIGH_CONFIDENCE)),
array(new True(), new ValueGuess(true, Guess::HIGH_CONFIDENCE)),
array(new Length(10), new ValueGuess(false, Guess::LOW_CONFIDENCE)),
array(new Range(array('min' => 1, 'max' => 20)), new ValueGuess(false, Guess::LOW_CONFIDENCE)),
);
}
/**
* @dataProvider guessRequiredProvider
*/
public function testGuessRequired($constraint, $guess)
{
// add distracting constraint
$this->metadata->addPropertyConstraint(self::TEST_PROPERTY, new Email());
// add constraint under test
$this->metadata->addPropertyConstraint(self::TEST_PROPERTY, $constraint);
$this->assertEquals($guess, $this->guesser->guessRequired(self::TEST_CLASS, self::TEST_PROPERTY));
}
public function testGuessRequiredReturnsFalseForUnmappedProperties()
{
$this->assertEquals(new ValueGuess(false, Guess::LOW_CONFIDENCE), $this->guesser->guessRequired(self::TEST_CLASS, self::TEST_PROPERTY));
}
public function testGuessMaxLengthForConstraintWithMaxValue()
{
$constraint = new Length(array('max' => '2'));
$result = $this->typeGuesser->guessMaxLengthForConstraint($constraint);
$result = $this->guesser->guessMaxLengthForConstraint($constraint);
$this->assertInstanceOf('Symfony\Component\Form\Guess\ValueGuess', $result);
$this->assertEquals(2, $result->getValue());
$this->assertEquals(Guess::HIGH_CONFIDENCE, $result->getConfidence());
@ -48,24 +107,11 @@ class ValidatorTypeGuesserTest extends \PHPUnit_Framework_TestCase
{
$constraint = new Length(array('min' => '2'));
$result = $this->typeGuesser->guessMaxLengthForConstraint($constraint);
$result = $this->guesser->guessMaxLengthForConstraint($constraint);
$this->assertNull($result);
}
/**
* @dataProvider dataProviderTestGuessMaxLengthForConstraintWithType
*/
public function testGuessMaxLengthForConstraintWithType($type)
{
$constraint = new Type($type);
$result = $this->typeGuesser->guessMaxLengthForConstraint($constraint);
$this->assertInstanceOf('Symfony\Component\Form\Guess\ValueGuess', $result);
$this->assertEquals(null, $result->getValue());
$this->assertEquals(Guess::MEDIUM_CONFIDENCE, $result->getConfidence());
}
public static function dataProviderTestGuessMaxLengthForConstraintWithType()
public function maxLengthTypeProvider()
{
return array (
array('double'),
@ -74,4 +120,22 @@ class ValidatorTypeGuesserTest extends \PHPUnit_Framework_TestCase
array('real'),
);
}
/**
* @dataProvider maxLengthTypeProvider
*/
public function testGuessMaxLengthForConstraintWithType($type)
{
$constraint = new Type($type);
$result = $this->guesser->guessMaxLengthForConstraint($constraint);
$this->assertInstanceOf('Symfony\Component\Form\Guess\ValueGuess', $result);
$this->assertNull($result->getValue());
$this->assertEquals(Guess::MEDIUM_CONFIDENCE, $result->getConfidence());
}
}
class ValidatorTypeGuesserTest_TestClass
{
private $property;
}