create max holder validator

This commit is contained in:
Julien Fastré 2021-06-11 17:03:48 +02:00
parent 4fd6d38187
commit ecc8b929ca
4 changed files with 142 additions and 2 deletions

View File

@ -98,6 +98,18 @@ class Household
return $this->members;
}
public function getMembersHolder(): Collection
{
$criteria = new Criteria();
$expr = Criteria::expr();
$criteria->where(
$expr->eq('holder', true)
);
return $this->getMembers()->matching($criteria);
}
public function getCurrentMembers(?\DateTimeImmutable $now = null): Collection
{
$criteria = new Criteria();

View File

@ -0,0 +1,76 @@
<?php
namespace Chill\PersonBundle\Tests\Validator\Household;
use Chill\PersonBundle\Entity\Household\HouseholdMember;
use Chill\PersonBundle\Entity\Household\Position;
use Chill\PersonBundle\Entity\Household\Household;
use Chill\PersonBundle\Validator\Constraints\Household\MaxHolderValidator;
use Chill\PersonBundle\Validator\Constraints\Household\MaxHolder;
use Symfony\Component\Validator\Test\ConstraintValidatorTestCase;
class MaxHolderValidatorTest extends ConstraintValidatorTestCase
{
/**
* @dataProvider provideInvalidHousehold
*/
public function testHouseholdInvalid(Household $household, $parameters)
{
$constraint = $this->getConstraint();
$this->validator->validate($household, $constraint);
$this->buildViolation('msg')
->setParameters($parameters)
->assertRaised()
;
}
protected function getConstraint()
{
return new MaxHolder([
'message' => 'msg',
'messageInfinity' => 'msgInfinity'
]);
}
public function provideInvalidHousehold()
{
$household = new Household();
$position = (new Position())
->setAllowHolder(true);
$household
->addMember(
(new HouseholdMember())
->setHolder(true)
->setStartDate(new \DateTimeImmutable('2010-01-01'))
->setEndDate(new \DateTimeImmutable('2010-12-01'))
)
->addMember(
(new HouseholdMember())
->setHolder(true)
->setStartDate(new \DateTimeImmutable('2010-06-01'))
->setEndDate(new \DateTimeImmutable('2010-07-01'))
)
->addMember(
(new HouseholdMember())
->setHolder(true)
->setStartDate(new \DateTimeImmutable('2010-01-01'))
->setEndDate(new \DateTimeImmutable('2010-12-01'))
)
;
yield [
$household,
[
'start' => '01-06-2010',
'end' => '01-07-2010'
]
];
}
protected function createValidator()
{
return new MaxHolderValidator();
}
}

View File

@ -0,0 +1,13 @@
<?php
namespace Chill\PersonBundle\Validator\Constraints\Household;
use Symfony\Component\Validator\Constraint;
class MaxHolder extends Constraint
{
public $message = 'household.max_holder_overflowed';
public $messageInfinity = 'household.max_holder_overflowed_infinity';
}

View File

@ -2,7 +2,46 @@
namespace Chill\PersonBundle\Validator\Constraints\Household;
class MaxHolderValidator
use Chill\MainBundle\Util\DateRangeCovering;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
use Symfony\Component\Validator\Exception\UnexpectedValueException;
class MaxHolderValidator extends ConstraintValidator
{
private const MAX_HOLDERS = 2;
public function validate($household, Constraint $constraint)
{
$holders = $household->getMembersHolder();
if ($holders->count() <= self::MAX_HOLDERS) {
return;
}
$covers = new DateRangeCovering(self::MAX_HOLDERS,
$holders[0]->getStartDate()->getTimezone());
foreach ($holders as $key => $member) {
$covers->add($member->getStartDate(), $member->getEndDate(), $key);
}
$covers->compute();
if ($covers->hasIntersections()) {
foreach ($covers->getIntersections() as list($start, $end, $ids)) {
$msg = $end === null ? $constraint->messageEndInfinite :
$constraint->message;
$this->context->buildViolation($msg)
->setParameters([
'start' => $start->format('d-m-Y'), // TODO fix when MessageParameter works with timezone
'end' => $end === null ? null : $end->format('d-m-Y')
])
->addViolation();
}
}
}
}