diff --git a/Tests/Validator/BirthdateValidatorTest.php b/Tests/Validator/BirthdateValidatorTest.php new file mode 100644 index 000000000..94f1347a5 --- /dev/null +++ b/Tests/Validator/BirthdateValidatorTest.php @@ -0,0 +1,112 @@ + + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +namespace Chill\PersonBundle\Tests\Validator; + +use Chill\PersonBundle\Validator\Constraints\BirthdateValidator; +use Chill\PersonBundle\Validator\Constraints\Birthdate; +use Prophecy\Argument; +use Prophecy\Prophet; + +/** + * Test the behaviour of BirthdayValidator + * + * @author Julien Fastré + */ +class BirthdateValidatorTest extends \PHPUnit_Framework_TestCase +{ + /** + * A prophecy for \Symfony\Component\Validator\Context\ExecutionContextInterface + * + * Will reveal \Symfony\Component\Validator\Context\ExecutionContextInterface + */ + private $context; + + private $prophet; + + /** + * + * @var Birthdate + */ + private $constraint; + + public function setUp() + { + $this->prophet = new Prophet; + + $constraintViolationBuilder = $this->prophet->prophesize(); + $constraintViolationBuilder->willImplement('Symfony\Component\Validator\Violation\ConstraintViolationBuilderInterface'); + + $constraintViolationBuilder->setParameter(Argument::any(), Argument::any()) + ->willReturn($constraintViolationBuilder->reveal()); + $constraintViolationBuilder->addViolation() + ->willReturn($constraintViolationBuilder->reveal()); + + $this->context = $this->prophet->prophesize(); + $this->context->willImplement('Symfony\Component\Validator\Context\ExecutionContextInterface'); + $this->context->buildViolation(Argument::type('string')) + ->willReturn($constraintViolationBuilder->reveal()); + + $this->constraint = new Birthdate(); + } + + public function testValidBirthDate() + { + + $date = new \DateTime('2015-01-01'); + + $birthdateValidator = new BirthdateValidator(); + $birthdateValidator->initialize($this->context->reveal()); + + $birthdateValidator->validate($date, $this->constraint); + + $this->context->buildViolation(Argument::any())->shouldNotHaveBeenCalled(); + } + + public function testInvalidBirthDate() + { + $date = new \DateTime('tomorrow'); + + $birthdateValidator = new BirthdateValidator(); + $birthdateValidator->initialize($this->context->reveal()); + + $birthdateValidator->validate($date, $this->constraint); + + $this->context->buildViolation(Argument::type('string'))->shouldHaveBeenCalled(); + } + + public function testInvalidBirthDateWithParameter() + { + $date = (new \DateTime('today'))->sub(new \DateInterval('P1M')); + + $birthdateValidator = new BirthdateValidator('P1Y'); + $birthdateValidator->initialize($this->context->reveal()); + + $birthdateValidator->validate($date, $this->constraint); + + $this->context->buildViolation(Argument::type('string'))->shouldHaveBeenCalled(); + } + + public function tearDown() + { + $this->prophet->checkPredictions(); + } + + +} diff --git a/Validator/Constraints/Birthdate.php b/Validator/Constraints/Birthdate.php new file mode 100644 index 000000000..35ad118df --- /dev/null +++ b/Validator/Constraints/Birthdate.php @@ -0,0 +1,37 @@ + + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +namespace Chill\PersonBundle\Validator\Constraints; + +use Symfony\Component\Validator\Constraint; + +/** + * Create a constraint on birth date: the birthdate after today are not allowed. + * + * It is possible to add a delay before today, expressed as described in + * interval_spec : http://php.net/manual/en/dateinterval.construct.php + * (this interval_spec itself is based on ISO8601 : + * https://en.wikipedia.org/wiki/ISO_8601#Durations) + * + * @author Julien Fastré + */ +class Birthdate extends Constraint +{ + public $message = "The birthdate must be before %date%"; +} diff --git a/Validator/Constraints/BirthdateValidator.php b/Validator/Constraints/BirthdateValidator.php new file mode 100644 index 000000000..5f65c3ed7 --- /dev/null +++ b/Validator/Constraints/BirthdateValidator.php @@ -0,0 +1,70 @@ + + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +namespace Chill\PersonBundle\Validator\Constraints; + +use Symfony\Component\Validator\Constraint; +use Symfony\Component\Validator\ConstraintValidator; + +/** + * + * + * @author Julien Fastré + */ +class BirthdateValidator extends ConstraintValidator +{ + private $interval_spec = null; + + public function __construct($interval_spec = null) + { + $this->interval_spec = $interval_spec; + } + + public function validate($value, Constraint $constraint) + { + if (!$value instanceof \DateTime) { + throw new \LogicException('The input should a be a \DateTime interface,' + . (is_object($value) ? get_class($value) : gettype($value))); + } + + $limitDate = $this->getLimitDate(); + + if ($limitDate < $value) { + $this->context->buildViolation($constraint->message) + ->setParameter('%date%', $value->format(\DateTime::ATOM)) + ->addViolation(); + } + + } + + /** + * + * @return \DateTime + */ + private function getLimitDate() + { + if ($this->interval_spec !== NULL) { + $interval = new \DateInterval($this->interval_spec); + return (new \DateTime('now'))->sub($interval); + } else { + return (new \DateTime('now')); + } + } + +}