Skip to content

Commit 7a567aa

Browse files
committed
[Validator] do not guess getter method names
1 parent 6699928 commit 7a567aa

13 files changed

+69
-31
lines changed

src/Symfony/Component/Validator/Mapping/ClassMetadata.php

+8-6
Original file line numberDiff line numberDiff line change
@@ -299,15 +299,16 @@ public function addPropertyConstraints($property, array $constraints)
299299
* The name of the getter is assumed to be the name of the property with an
300300
* uppercased first letter and either the prefix "get" or "is".
301301
*
302-
* @param string $property The name of the property
303-
* @param Constraint $constraint The constraint
302+
* @param string $property The name of the property
303+
* @param Constraint $constraint The constraint
304+
* @param string|null $method The method that is called to retrieve the value being validated (null for auto-detection)
304305
*
305306
* @return $this
306307
*/
307-
public function addGetterConstraint($property, Constraint $constraint)
308+
public function addGetterConstraint($property, Constraint $constraint, $method = null)
308309
{
309310
if (!isset($this->getters[$property])) {
310-
$this->getters[$property] = new GetterMetadata($this->getClassName(), $property);
311+
$this->getters[$property] = new GetterMetadata($this->getClassName(), $property, $method);
311312

312313
$this->addPropertyMetadata($this->getters[$property]);
313314
}
@@ -322,13 +323,14 @@ public function addGetterConstraint($property, Constraint $constraint)
322323
/**
323324
* @param string $property
324325
* @param Constraint[] $constraints
326+
* @param string|null $method The method that is called to retrieve the value being validated (null for auto-detection)
325327
*
326328
* @return $this
327329
*/
328-
public function addGetterConstraints($property, array $constraints)
330+
public function addGetterConstraints($property, array $constraints, $method = null)
329331
{
330332
foreach ($constraints as $constraint) {
331-
$this->addGetterConstraint($property, $constraint);
333+
$this->addGetterConstraint($property, $constraint, $method);
332334
}
333335

334336
return $this;

src/Symfony/Component/Validator/Mapping/GetterMetadata.php

+19-14
Original file line numberDiff line numberDiff line change
@@ -35,25 +35,30 @@ class GetterMetadata extends MemberMetadata
3535
/**
3636
* Constructor.
3737
*
38-
* @param string $class The class the getter is defined on
39-
* @param string $property The property which the getter returns
38+
* @param string $class The class the getter is defined on
39+
* @param string $property The property which the getter returns
40+
* @param string|null $method The method that is called to retrieve the value being validated (null for auto-detection)
4041
*
4142
* @throws ValidatorException
4243
*/
43-
public function __construct($class, $property)
44+
public function __construct($class, $property, $method = null)
4445
{
45-
$getMethod = 'get'.ucfirst($property);
46-
$isMethod = 'is'.ucfirst($property);
47-
$hasMethod = 'has'.ucfirst($property);
46+
if (null === $method) {
47+
$getMethod = 'get'.ucfirst($property);
48+
$isMethod = 'is'.ucfirst($property);
49+
$hasMethod = 'has'.ucfirst($property);
4850

49-
if (method_exists($class, $getMethod)) {
50-
$method = $getMethod;
51-
} elseif (method_exists($class, $isMethod)) {
52-
$method = $isMethod;
53-
} elseif (method_exists($class, $hasMethod)) {
54-
$method = $hasMethod;
55-
} else {
56-
throw new ValidatorException(sprintf('Neither of these methods exist in class %s: %s, %s, %s', $class, $getMethod, $isMethod, $hasMethod));
51+
if (method_exists($class, $getMethod)) {
52+
$method = $getMethod;
53+
} elseif (method_exists($class, $isMethod)) {
54+
$method = $isMethod;
55+
} elseif (method_exists($class, $hasMethod)) {
56+
$method = $hasMethod;
57+
} else {
58+
throw new ValidatorException(sprintf('Neither of these methods exist in class %s: %s, %s, %s', $class, $getMethod, $isMethod, $hasMethod));
59+
}
60+
} elseif (!method_exists($class, $method)) {
61+
throw new ValidatorException(sprintf('The %s() method does not exist in class %s.', $method, $class));
5762
}
5863

5964
parent::__construct($class, $method, $property);

src/Symfony/Component/Validator/Mapping/Loader/AnnotationLoader.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ public function loadClassMetadata(ClassMetadata $metadata)
7979
$metadata->addConstraint($constraint);
8080
} elseif ($constraint instanceof Constraint) {
8181
if (preg_match('/^(get|is|has)(.+)$/i', $method->name, $matches)) {
82-
$metadata->addGetterConstraint(lcfirst($matches[2]), $constraint);
82+
$metadata->addGetterConstraint(lcfirst($matches[2]), $constraint, $matches[0]);
8383
} else {
8484
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));
8585
}

src/Symfony/Component/Validator/Mapping/Loader/XmlFileLoader.php

+7-1
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,13 @@ private function loadClassMetadataFromXml(ClassMetadata $metadata, \SimpleXMLEle
206206

207207
foreach ($classDescription->getter as $getter) {
208208
foreach ($this->parseConstraints($getter->constraint) as $constraint) {
209-
$metadata->addGetterConstraint((string) $getter['property'], $constraint);
209+
$method = null;
210+
211+
if ((string) $getter['method']) {
212+
$method = (string) $getter['method'];
213+
}
214+
215+
$metadata->addGetterConstraint((string) $getter['property'], $constraint, $method);
210216
}
211217
}
212218
}

src/Symfony/Component/Validator/Mapping/Loader/YamlFileLoader.php

+11-2
Original file line numberDiff line numberDiff line change
@@ -166,10 +166,19 @@ private function loadClassMetadataFromYaml(ClassMetadata $metadata, array $class
166166
}
167167

168168
if (isset($classDescription['getters']) && is_array($classDescription['getters'])) {
169-
foreach ($classDescription['getters'] as $getter => $constraints) {
169+
foreach ($classDescription['getters'] as $getter => $properties) {
170+
$method = null;
171+
172+
if (isset($properties['constraints'])) {
173+
$constraints = $properties['constraints'];
174+
$method = isset($properties['method']) ? $properties['method'] : null;
175+
} else {
176+
$constraints = $properties;
177+
}
178+
170179
if (null !== $constraints) {
171180
foreach ($this->parseNodes($constraints) as $constraint) {
172-
$metadata->addGetterConstraint($getter, $constraint);
181+
$metadata->addGetterConstraint($getter, $constraint, $method);
173182
}
174183
}
175184
}

src/Symfony/Component/Validator/Mapping/Loader/schema/dic/constraint-mapping/constraint-mapping-1.0.xsd

+1
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@
105105
<xsd:element name="constraint" type="constraint" maxOccurs="unbounded" />
106106
</xsd:sequence>
107107
<xsd:attribute name="property" type="xsd:string" use="required" />
108+
<xsd:attribute name="method" type="xsd:string" />
108109
</xsd:complexType>
109110

110111
<xsd:complexType name="constraint" mixed="true">

src/Symfony/Component/Validator/Tests/Fixtures/Entity.php

+4
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,10 @@ public function getLastName()
6363
return $this->lastName;
6464
}
6565

66+
public function getValid()
67+
{
68+
}
69+
6670
/**
6771
* @Assert\IsTrue
6872
*/

src/Symfony/Component/Validator/Tests/Mapping/GetterMetadataTest.php

+10-1
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ public function testGetPropertyValueFromOverriddenPublicGetter()
4747
public function testGetPropertyValueFromIsser()
4848
{
4949
$entity = new Entity();
50-
$metadata = new GetterMetadata(self::CLASSNAME, 'valid');
50+
$metadata = new GetterMetadata(self::CLASSNAME, 'valid', 'isValid');
5151

5252
$this->assertEquals('valid', $metadata->getPropertyValue($entity));
5353
}
@@ -59,4 +59,13 @@ public function testGetPropertyValueFromHasser()
5959

6060
$this->assertEquals('permissions', $metadata->getPropertyValue($entity));
6161
}
62+
63+
/**
64+
* @expectedException \Symfony\Component\Validator\Exception\ValidatorException
65+
* @expectedExceptionMessage The hasLastName() method does not exist in class Symfony\Component\Validator\Tests\Fixtures\Entity.
66+
*/
67+
public function testUndefinedMethodNameThrowsException()
68+
{
69+
new GetterMetadata(self::CLASSNAME, 'lastName', 'hasLastName');
70+
}
6271
}

src/Symfony/Component/Validator/Tests/Mapping/Loader/AnnotationLoaderTest.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ public function testLoadClassMetadata()
6868
'choices' => array('A', 'B'),
6969
)));
7070
$expected->addGetterConstraint('lastName', new NotNull());
71-
$expected->addGetterConstraint('valid', new IsTrue());
71+
$expected->addGetterConstraint('valid', new IsTrue(), 'isValid');
7272
$expected->addGetterConstraint('permissions', new IsTrue());
7373

7474
// load reflection class so that the comparison passes
@@ -138,7 +138,7 @@ public function testLoadClassMetadataAndMerge()
138138
'choices' => array('A', 'B'),
139139
)));
140140
$expected->addGetterConstraint('lastName', new NotNull());
141-
$expected->addGetterConstraint('valid', new IsTrue());
141+
$expected->addGetterConstraint('valid', new IsTrue(), 'isValid');
142142
$expected->addGetterConstraint('permissions', new IsTrue());
143143

144144
// load reflection class so that the comparison passes

src/Symfony/Component/Validator/Tests/Mapping/Loader/XmlFileLoaderTest.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ public function testLoadClassMetadata()
7373
'choices' => array('A', 'B'),
7474
)));
7575
$expected->addGetterConstraint('lastName', new NotNull());
76-
$expected->addGetterConstraint('valid', new IsTrue());
76+
$expected->addGetterConstraint('valid', new IsTrue(), 'isValid');
7777
$expected->addGetterConstraint('permissions', new IsTrue());
7878

7979
$this->assertEquals($expected, $metadata);

src/Symfony/Component/Validator/Tests/Mapping/Loader/YamlFileLoaderTest.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ public function testLoadClassMetadata()
117117
'choices' => array('A', 'B'),
118118
)));
119119
$expected->addGetterConstraint('lastName', new NotNull());
120-
$expected->addGetterConstraint('valid', new IsTrue());
120+
$expected->addGetterConstraint('valid', new IsTrue(), 'isValid');
121121
$expected->addGetterConstraint('permissions', new IsTrue());
122122

123123
$this->assertEquals($expected, $metadata);

src/Symfony/Component/Validator/Tests/Mapping/Loader/constraint-mapping.xml

+1-1
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@
107107
<getter property="lastName">
108108
<constraint name="NotNull" />
109109
</getter>
110-
<getter property="valid">
110+
<getter property="valid" method="isValid">
111111
<constraint name="IsTrue" />
112112
</getter>
113113
<getter property="permissions">

src/Symfony/Component/Validator/Tests/Mapping/Loader/constraint-mapping.yml

+3-1
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,9 @@ Symfony\Component\Validator\Tests\Fixtures\Entity:
5454
lastName:
5555
- NotNull: ~
5656
valid:
57-
- "IsTrue": ~
57+
method: isValid
58+
constraints:
59+
- "IsTrue": ~
5860
permissions:
5961
- "IsTrue": ~
6062

0 commit comments

Comments
 (0)