128 lines
3.6 KiB
PHP

<?php
namespace Chill\PersonBundle\Household;
use Symfony\Component\Validator\ConstraintViolationListInterface;
use Symfony\Component\Validator\ConstraintViolationList;
use Doctrine\Common\Collections\Criteria;
use Chill\PersonBundle\Entity\Household\HouseholdMember;
use Chill\PersonBundle\Entity\Household\Position;
use Chill\PersonBundle\Entity\Household\Household;
use Chill\PersonBundle\Entity\Person;
use Symfony\Component\Validator\Validator\ValidatorInterface;
class MembersEditor
{
private ValidatorInterface $validator;
private ?Household $household = null;
private array $persistables = [];
private array $membershipsAffected = [];
public const VALIDATION_GROUP = 'household_memberships';
public function __construct(ValidatorInterface $validator, ?Household $household)
{
$this->validator = $validator;
$this->household = $household;
}
public function addMovement(\DateTimeImmutable $date, Person $person, Position $position, ?bool $holder = false, ?string $comment = null): self
{
if (NULL === $this->household) {
throw new \LogicException("You must define a household first");
}
$membership = (new HouseholdMember())
->setStartDate($date)
->setPerson($person)
->setPosition($position)
->setHolder($holder)
->setComment($comment)
;
$this->household->addMember($membership);
if ($position->getShareHousehold()) {
foreach ($person->getHouseholdParticipationsShareHousehold() as $participation) {
if ($participation === $membership) {
continue;
}
if ($participation->getStartDate() > $membership->getStartDate()) {
continue;
}
if ($participation->getEndDate() === NULL || $participation->getEndDate() > $date) {
$participation->setEndDate($date);
$this->membershipsAffected[] = $participation;
}
}
}
$this->membershipsAffected[] = $membership;
$this->persistables[] = $membership;
return $this;
}
public function leaveMovement(
\DateTimeImmutable $date,
Person $person
): self {
$criteria = new Criteria();
$expr = Criteria::expr();
$criteria->where(
$expr->andX(
$expr->lt('startDate', $date),
$expr->isNull('endDate', $date)
)
);
$participations = $person->getHouseholdParticipations()
->matching($criteria)
;
foreach ($participations as $participation) {
$participation->setEndDate($date);
$this->membershipsAffected[] = $participation;
}
return $this;
}
public function validate(): ConstraintViolationListInterface
{
if ($this->hasHousehold()) {
$list = $this->validator
->validate($this->getHousehold(), null, [ self::VALIDATION_GROUP ]);
} else {
$list = new ConstraintViolationList();
}
foreach ($this->membershipsAffected as $m) {
$list->addAll($this->validator->validate($m, null, [ self::VALIDATION_GROUP ]));
}
return $list;
}
public function getPersistable(): array
{
return $this->persistables;
}
public function getHousehold(): ?Household
{
return $this->household;
}
public function hasHousehold(): bool
{
return $this->household !== null;
}
}