bug #21115 [Validator] do not guess getter method names (xabbuh)
This PR was merged into the 2.7 branch.
Discussion
----------
[Validator] do not guess getter method names
| Q | A
| ------------- | ---
| Branch? | 2.7
| Bug fix? | yes
| New feature? | no
| BC breaks? | no
| Deprecations? | no
| Tests pass? | yes
| Fixed tickets | #5219, #18700
| License | MIT
| Doc PR | TODO
Commits
-------
bd3a90a0c3
[Validator] do not guess getter method names
This commit is contained in:
commit
eb0ffaaee7
@ -299,8 +299,9 @@ class ClassMetadata extends ElementMetadata implements ClassMetadataInterface
|
|||||||
* The name of the getter is assumed to be the name of the property with an
|
* The name of the getter is assumed to be the name of the property with an
|
||||||
* uppercased first letter and either the prefix "get" or "is".
|
* uppercased first letter and either the prefix "get" or "is".
|
||||||
*
|
*
|
||||||
* @param string $property The name of the property
|
* @param string $property The name of the property
|
||||||
* @param Constraint $constraint The constraint
|
* @param Constraint $constraint The constraint
|
||||||
|
* @param string|null $method The method that is called to retrieve the value being validated (null for auto-detection)
|
||||||
*
|
*
|
||||||
* @return $this
|
* @return $this
|
||||||
*/
|
*/
|
||||||
@ -319,6 +320,30 @@ class ClassMetadata extends ElementMetadata implements ClassMetadataInterface
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a constraint to the getter of the given property.
|
||||||
|
*
|
||||||
|
* @param string $property The name of the property
|
||||||
|
* @param string $method The name of the getter method
|
||||||
|
* @param Constraint $constraint The constraint
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function addGetterMethodConstraint($property, $method, Constraint $constraint)
|
||||||
|
{
|
||||||
|
if (!isset($this->getters[$property])) {
|
||||||
|
$this->getters[$property] = new GetterMetadata($this->getClassName(), $property, $method);
|
||||||
|
|
||||||
|
$this->addPropertyMetadata($this->getters[$property]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$constraint->addImplicitGroupName($this->getDefaultGroup());
|
||||||
|
|
||||||
|
$this->getters[$property]->addConstraint($constraint);
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $property
|
* @param string $property
|
||||||
* @param Constraint[] $constraints
|
* @param Constraint[] $constraints
|
||||||
@ -334,6 +359,22 @@ class ClassMetadata extends ElementMetadata implements ClassMetadataInterface
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $property
|
||||||
|
* @param string $method
|
||||||
|
* @param Constraint[] $constraints
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function addGetterMethodConstraints($property, $method, array $constraints)
|
||||||
|
{
|
||||||
|
foreach ($constraints as $constraint) {
|
||||||
|
$this->addGetterMethodConstraint($property, $method, $constraint);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Merges the constraints of the given metadata into this object.
|
* Merges the constraints of the given metadata into this object.
|
||||||
*
|
*
|
||||||
|
@ -35,25 +35,30 @@ class GetterMetadata extends MemberMetadata
|
|||||||
/**
|
/**
|
||||||
* Constructor.
|
* Constructor.
|
||||||
*
|
*
|
||||||
* @param string $class The class the getter is defined on
|
* @param string $class The class the getter is defined on
|
||||||
* @param string $property The property which the getter returns
|
* @param string $property The property which the getter returns
|
||||||
|
* @param string|null $method The method that is called to retrieve the value being validated (null for auto-detection)
|
||||||
*
|
*
|
||||||
* @throws ValidatorException
|
* @throws ValidatorException
|
||||||
*/
|
*/
|
||||||
public function __construct($class, $property)
|
public function __construct($class, $property, $method = null)
|
||||||
{
|
{
|
||||||
$getMethod = 'get'.ucfirst($property);
|
if (null === $method) {
|
||||||
$isMethod = 'is'.ucfirst($property);
|
$getMethod = 'get'.ucfirst($property);
|
||||||
$hasMethod = 'has'.ucfirst($property);
|
$isMethod = 'is'.ucfirst($property);
|
||||||
|
$hasMethod = 'has'.ucfirst($property);
|
||||||
|
|
||||||
if (method_exists($class, $getMethod)) {
|
if (method_exists($class, $getMethod)) {
|
||||||
$method = $getMethod;
|
$method = $getMethod;
|
||||||
} elseif (method_exists($class, $isMethod)) {
|
} elseif (method_exists($class, $isMethod)) {
|
||||||
$method = $isMethod;
|
$method = $isMethod;
|
||||||
} elseif (method_exists($class, $hasMethod)) {
|
} elseif (method_exists($class, $hasMethod)) {
|
||||||
$method = $hasMethod;
|
$method = $hasMethod;
|
||||||
} else {
|
} else {
|
||||||
throw new ValidatorException(sprintf('Neither of these methods exist in class %s: %s, %s, %s', $class, $getMethod, $isMethod, $hasMethod));
|
throw new ValidatorException(sprintf('Neither of these methods exist in class %s: %s, %s, %s', $class, $getMethod, $isMethod, $hasMethod));
|
||||||
|
}
|
||||||
|
} elseif (!method_exists($class, $method)) {
|
||||||
|
throw new ValidatorException(sprintf('The %s() method does not exist in class %s.', $method, $class));
|
||||||
}
|
}
|
||||||
|
|
||||||
parent::__construct($class, $method, $property);
|
parent::__construct($class, $method, $property);
|
||||||
|
@ -79,7 +79,7 @@ class AnnotationLoader implements LoaderInterface
|
|||||||
$metadata->addConstraint($constraint);
|
$metadata->addConstraint($constraint);
|
||||||
} elseif ($constraint instanceof Constraint) {
|
} elseif ($constraint instanceof Constraint) {
|
||||||
if (preg_match('/^(get|is|has)(.+)$/i', $method->name, $matches)) {
|
if (preg_match('/^(get|is|has)(.+)$/i', $method->name, $matches)) {
|
||||||
$metadata->addGetterConstraint(lcfirst($matches[2]), $constraint);
|
$metadata->addGetterMethodConstraint(lcfirst($matches[2]), $matches[0], $constraint);
|
||||||
} else {
|
} else {
|
||||||
throw new MappingException(sprintf('The constraint on "%s::%s" cannot be added. Constraints can only be added on methods beginning with "get", "is" or "has".', $className, $method->name));
|
throw new MappingException(sprintf('The constraint on "%s::%s" cannot be added. Constraints can only be added on methods beginning with "get", "is" or "has".', $className, $method->name));
|
||||||
}
|
}
|
||||||
|
@ -63,6 +63,10 @@ class Entity extends EntityParent implements EntityInterfaceB
|
|||||||
return $this->lastName;
|
return $this->lastName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getValid()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Assert\IsTrue
|
* @Assert\IsTrue
|
||||||
*/
|
*/
|
||||||
|
@ -48,7 +48,7 @@ class GetterMetadataTest extends TestCase
|
|||||||
public function testGetPropertyValueFromIsser()
|
public function testGetPropertyValueFromIsser()
|
||||||
{
|
{
|
||||||
$entity = new Entity();
|
$entity = new Entity();
|
||||||
$metadata = new GetterMetadata(self::CLASSNAME, 'valid');
|
$metadata = new GetterMetadata(self::CLASSNAME, 'valid', 'isValid');
|
||||||
|
|
||||||
$this->assertEquals('valid', $metadata->getPropertyValue($entity));
|
$this->assertEquals('valid', $metadata->getPropertyValue($entity));
|
||||||
}
|
}
|
||||||
@ -60,4 +60,13 @@ class GetterMetadataTest extends TestCase
|
|||||||
|
|
||||||
$this->assertEquals('permissions', $metadata->getPropertyValue($entity));
|
$this->assertEquals('permissions', $metadata->getPropertyValue($entity));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @expectedException \Symfony\Component\Validator\Exception\ValidatorException
|
||||||
|
* @expectedExceptionMessage The hasLastName() method does not exist in class Symfony\Component\Validator\Tests\Fixtures\Entity.
|
||||||
|
*/
|
||||||
|
public function testUndefinedMethodNameThrowsException()
|
||||||
|
{
|
||||||
|
new GetterMetadata(self::CLASSNAME, 'lastName', 'hasLastName');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -69,7 +69,7 @@ class AnnotationLoaderTest extends TestCase
|
|||||||
'choices' => array('A', 'B'),
|
'choices' => array('A', 'B'),
|
||||||
)));
|
)));
|
||||||
$expected->addGetterConstraint('lastName', new NotNull());
|
$expected->addGetterConstraint('lastName', new NotNull());
|
||||||
$expected->addGetterConstraint('valid', new IsTrue());
|
$expected->addGetterMethodConstraint('valid', 'isValid', new IsTrue());
|
||||||
$expected->addGetterConstraint('permissions', new IsTrue());
|
$expected->addGetterConstraint('permissions', new IsTrue());
|
||||||
|
|
||||||
// load reflection class so that the comparison passes
|
// load reflection class so that the comparison passes
|
||||||
@ -139,7 +139,7 @@ class AnnotationLoaderTest extends TestCase
|
|||||||
'choices' => array('A', 'B'),
|
'choices' => array('A', 'B'),
|
||||||
)));
|
)));
|
||||||
$expected->addGetterConstraint('lastName', new NotNull());
|
$expected->addGetterConstraint('lastName', new NotNull());
|
||||||
$expected->addGetterConstraint('valid', new IsTrue());
|
$expected->addGetterMethodConstraint('valid', 'isValid', new IsTrue());
|
||||||
$expected->addGetterConstraint('permissions', new IsTrue());
|
$expected->addGetterConstraint('permissions', new IsTrue());
|
||||||
|
|
||||||
// load reflection class so that the comparison passes
|
// load reflection class so that the comparison passes
|
||||||
|
Reference in New Issue
Block a user