Skip to content

Instantly share code, notes, and snippets.

@pylebecq
Created July 5, 2012 13:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pylebecq/3053790 to your computer and use it in GitHub Desktop.
Save pylebecq/3053790 to your computer and use it in GitHub Desktop.
[Symfony2][2.0] A validator which trigger validation constraints only if an entity has some values in its properties. All properties of the entity must have a getter or must be public, otherwise the PropertyPath will throw an exception.
<?php
namespace Sensio\Bundle\FakeBundle\Entity;
use Sensio\Component\Validator\Constraints\ValidateIfNeeded;
use Symfony\Component\Validator\Constraints as Assert;
/**
* FakeEntity.
*
* @ValidateIfNeeded()
*/
class FakeEntity
{
/**
* @Assert\NotBlank(groups={"ValidateIfNeeded"})
*/
public $a;
/**
* @Assert\NotBlank(groups={"ValidateIfNeeded"})
*/
protected $b;
/**
* @Assert\NotBlank(groups={"ValidateIfNeeded"})
*/
private $c;
public function getB()
{
return $this->b;
}
public function setB($b)
{
$this->b = $b;
}
public function getC()
{
return $this->c;
}
public function setC($c)
{
$this->c = $c;
}
}
validator.constraint.validate_if_needed:
class: Sensio\Component\Validator\Constraints\ValidateIfNeededValidator
arguments: [@validator]
tags:
- { name: validator.constraint_validator, alias: validate_if_needed }
<?php
namespace Sensio\Component\Validator\Constraints;
use Symfony\Component\Validator\Constraint;
/**
* Constraint for the Validate if needed validator
*
* @Annotation
* @author Pierre-Yves LEBECQ <py.lebecq@gmail.com>
*/
class ValidateIfNeeded extends Constraint
{
/**
* {@inheritDoc}
*/
public function getTargets()
{
return self::CLASS_CONSTRAINT;
}
/**
* {@inheritDoc}
*/
public function validatedBy()
{
return 'validate_if_needed';
}
}
<?php
namespace Sensio\Component\Validator\Constraints;
use Symfony\Component\Validator\ValidatorInterface;
use Symfony\Component\Form\Util\PropertyPath;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
/**
* Validates an entity only if it seems to contains some values.
*
* @author Pierre-Yves LEBECQ <py.lebecq@gmail.com>
*/
class ValidateIfNeededValidator extends ConstraintValidator
{
/** @var ValidatorInterface */
private $validator;
public function __construct(ValidatorInterface $validator)
{
$this->validator = $validator;
}
/**
* {@inheritDoc}
*/
public function isValid($value, Constraint $constraint)
{
if (null === $value) {
return true;
}
if (!is_object($value)) {
throw new UnexpectedTypeException($value, 'object');
}
$hasSomeData = false;
$reflectionClass = new \ReflectionClass($value);
$properties = $reflectionClass->getProperties();
foreach ($properties as $property) {
$propertyPath = new PropertyPath($property->getName());
$propertyValue = $propertyPath->getValue($value);
if (null !== $propertyValue) {
$hasSomeData = true;
}
}
if (!$hasSomeData) {
return true;
}
$walker = $this->context->getGraphWalker();
$propertyPath = $this->context->getPropertyPath();
$metadata = $this->validator->getMetadataFactory()->getClassMetadata(get_class($value));
$walker->walkObject($metadata, $value, 'ValidateIfNeeded', $propertyPath);
$this->context->setPropertyPath($propertyPath); // Reset property path modified by the $walker->walkObject() call
return true;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment