Merge branch '3.2'

* 3.2:
  [Serializer] Removed duplicate operation in camelcase denormalization
  [Validator] do not guess getter method names
This commit is contained in:
Fabien Potencier 2017-02-19 16:48:52 -08:00
commit 5037c2adbd
7 changed files with 80 additions and 21 deletions

View File

@ -76,7 +76,7 @@ class CamelCaseToSnakeCaseNameConverter implements NameConverterInterface
}
if (null === $this->attributes || in_array($camelCasedName, $this->attributes)) {
return $this->lowerCamelCase ? lcfirst($camelCasedName) : $camelCasedName;
return $camelCasedName;
}
return $propertyName;

View File

@ -257,8 +257,9 @@ class ClassMetadata extends GenericMetadata implements ClassMetadataInterface
* 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".
*
* @param string $property The name of the property
* @param Constraint $constraint The constraint
* @param string $property The name of the property
* @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
*/
@ -277,6 +278,30 @@ class ClassMetadata extends GenericMetadata implements ClassMetadataInterface
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 Constraint[] $constraints
@ -292,6 +317,22 @@ class ClassMetadata extends GenericMetadata implements ClassMetadataInterface
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.
*

View File

@ -35,25 +35,30 @@ class GetterMetadata extends MemberMetadata
/**
* Constructor.
*
* @param string $class The class the getter is defined on
* @param string $property The property which the getter returns
* @param string $class The class the getter is defined on
* @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
*/
public function __construct($class, $property)
public function __construct($class, $property, $method = null)
{
$getMethod = 'get'.ucfirst($property);
$isMethod = 'is'.ucfirst($property);
$hasMethod = 'has'.ucfirst($property);
if (null === $method) {
$getMethod = 'get'.ucfirst($property);
$isMethod = 'is'.ucfirst($property);
$hasMethod = 'has'.ucfirst($property);
if (method_exists($class, $getMethod)) {
$method = $getMethod;
} elseif (method_exists($class, $isMethod)) {
$method = $isMethod;
} elseif (method_exists($class, $hasMethod)) {
$method = $hasMethod;
} else {
throw new ValidatorException(sprintf('Neither of these methods exist in class %s: %s, %s, %s', $class, $getMethod, $isMethod, $hasMethod));
if (method_exists($class, $getMethod)) {
$method = $getMethod;
} elseif (method_exists($class, $isMethod)) {
$method = $isMethod;
} elseif (method_exists($class, $hasMethod)) {
$method = $hasMethod;
} else {
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);

View File

@ -78,7 +78,7 @@ class AnnotationLoader implements LoaderInterface
$metadata->addConstraint($constraint);
} elseif ($constraint instanceof Constraint) {
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 {
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));
}

View File

@ -71,6 +71,10 @@ class Entity extends EntityParent implements EntityInterfaceB
return $this->lastName;
}
public function getValid()
{
}
/**
* @Assert\IsTrue
*/

View File

@ -48,7 +48,7 @@ class GetterMetadataTest extends TestCase
public function testGetPropertyValueFromIsser()
{
$entity = new Entity();
$metadata = new GetterMetadata(self::CLASSNAME, 'valid');
$metadata = new GetterMetadata(self::CLASSNAME, 'valid', 'isValid');
$this->assertEquals('valid', $metadata->getPropertyValue($entity));
}
@ -60,4 +60,13 @@ class GetterMetadataTest extends TestCase
$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');
}
}

View File

@ -72,7 +72,7 @@ class AnnotationLoaderTest extends TestCase
$expected->addPropertyConstraint('childA', new Valid());
$expected->addPropertyConstraint('childB', new Valid());
$expected->addGetterConstraint('lastName', new NotNull());
$expected->addGetterConstraint('valid', new IsTrue());
$expected->addGetterMethodConstraint('valid', 'isValid', new IsTrue());
$expected->addGetterConstraint('permissions', new IsTrue());
// load reflection class so that the comparison passes
@ -144,7 +144,7 @@ class AnnotationLoaderTest extends TestCase
$expected->addPropertyConstraint('childA', new Valid());
$expected->addPropertyConstraint('childB', new Valid());
$expected->addGetterConstraint('lastName', new NotNull());
$expected->addGetterConstraint('valid', new IsTrue());
$expected->addGetterMethodConstraint('valid', 'isValid', new IsTrue());
$expected->addGetterConstraint('permissions', new IsTrue());
// load reflection class so that the comparison passes