setOpeningDate($dateOpening ?? new DateTime('now')); $this->participations = new ArrayCollection(); $this->scopes = new ArrayCollection(); $this->socialIssues = new ArrayCollection(); $this->comments = new ArrayCollection(); $this->works = new ArrayCollection(); $this->resources = new ArrayCollection(); } /** * Return an array with open participations sorted by household * [ * [ * "household" => Household x, * "members" => [ * Participation y , Participation z, ... * ] * ], * ]. */ public function actualParticipationsByHousehold(): array { $participations = $this->getOpenParticipations()->toArray(); $households = []; foreach ($participations as $p) { $households[] = $p->getPerson()->getCurrentHousehold(); } $households = array_unique($households, SORT_REGULAR); $array = []; foreach ($households as $household) { $members = []; foreach ($participations as $p) { if ($p->getPerson()->getCurrentHousehold() === $household) { $members[] = array_shift($participations); } else { $participations[] = array_shift($participations); } } $array[] = ['household' => $household, 'members' => $members]; } return $array; } public function addComment(Comment $comment): self { $this->comments[] = $comment; $comment->setAccompanyingPeriod($this); return $this; } public function addPerson(?Person $person = null): self { if (null !== $person) { $this->createParticipationFor($person); } return $this; } public function addResource(Resource $resource): self { $resource->setAccompanyingPeriod($this); $this->resources[] = $resource; return $this; } public function addScope(Scope $scope): self { if (!$this->scopes->contains($scope)) { $this->scopes[] = $scope; } return $this; } public function addSocialIssue(SocialIssue $socialIssue): self { if (!$this->socialIssues->contains($socialIssue)) { $this->socialIssues[] = $socialIssue; } return $this; } public function addWork(AccompanyingPeriodWork $work): self { $this->works[] = $work; $work->setAccompanyingPeriod($this); return $this; } /** * If the period can be reopened. * * This function test if the period is closed and if the period is the last * for the given person */ public function canBeReOpened(Person $person): bool { if ($this->isOpen() === true) { return false; } $participation = $this->getOpenParticipationContainsPerson($person); if (null === $participation) { return false; } $periods = $participation->getPerson()->getAccompanyingPeriodsOrdered(); return end($periods) === $this; } /** * Close a participation for a person. * * Search for the person's participation and set the end date at * 'now'. * * @param mixed $person * * @return void */ public function closeParticipationFor($person): ?AccompanyingPeriodParticipation { $participation = $this->getOpenParticipationContainsPerson($person); if ($participation instanceof AccompanyingPeriodParticipation) { $participation->setEndDate(new DateTimeImmutable('now')); } return $participation; } /** * Return true if the accompanying period contains a person. * * **Note**: this participation can be opened or not. */ public function containsPerson(Person $person): bool { return $this->getParticipationsContainsPerson($person)->count() > 0; } /** * Open a new participation for a person. */ public function createParticipationFor(Person $person): AccompanyingPeriodParticipation { $participation = new AccompanyingPeriodParticipation($this, $person); $this->participations[] = $participation; return $participation; } public function getAddressLocation(): ?Address { return $this->addressLocation; } /** * Get a list of person which have an adresse available for a valid location. * * @return Collection|Person[] */ public function getAvailablePersonLocation(): Collection { return $this->getOpenParticipations() ->filter(static function (AccompanyingPeriodParticipation $p) { return $p->getPerson()->hasCurrentHouseholdAddress(); }) ->map(static function (AccompanyingPeriodParticipation $p) { return $p->getPerson(); }); } public function getCenter(): ?Center { if (count($this->getPersons()) === 0) { return null; } return $this->getPersons()->first()->getCenter(); } public function getCenters(): ?iterable { foreach ($this->getPersons() as $person) { if (!in_array($person->getCenter(), $centers ?? [], true) && null !== $person->getCenter()) { $centers[] = $person->getCenter(); } } return $centers ?? null; } /** * Get closingDate. * * @return DateTime */ public function getClosingDate(): ?DateTime { return $this->closingDate; } public function getClosingMotive(): ?ClosingMotive { return $this->closingMotive; } /** * @Groups({"read"}) */ public function getComments(): Collection { return $this->comments->filter(function (Comment $c) { return $c !== $this->initialComment; }); } public function getCreatedAt(): ?DateTime { return $this->createdAt; } public function getCreatedBy(): ?User { return $this->createdBy; } /** * @Groups({"docgen:read"}) */ public function getCurrentParticipations(): Collection { return $this->getOpenParticipations(); } public function getGroupSequence() { if ($this->getStep() === self::STEP_DRAFT) { return [[self::STEP_DRAFT]]; } if ($this->getStep() === self::STEP_CONFIRMED) { return [[self::STEP_DRAFT, self::STEP_CONFIRMED]]; } throw new LogicException('no validation group permitted with this step'); } /** * Get id. * * @return int */ public function getId(): ?int { return $this->id; } /** * @Groups({"read"}) */ public function getInitialComment(): ?Comment { return $this->initialComment; } public function getIntensity(): ?string { return $this->intensity; } /** * Get the location, taking precedence into account. * * @Groups({"read"}) */ public function getLocation(?DateTimeImmutable $at = null): ?Address { if ($this->getPersonLocation() instanceof Person) { return $this->getPersonLocation()->getCurrentPersonAddress(); } return $this->getAddressLocation(); } /** * Get where the location is. * * @Groups({"read"}) */ public function getLocationStatus(): string { if ($this->getPersonLocation() instanceof Person) { return 'person'; } if ($this->getAddressLocation() instanceof Address) { return 'address'; } return 'none'; } /** * Get openingDate. * * @return DateTime */ public function getOpeningDate(): ?DateTime { return $this->openingDate; } /** * Get the opened participation containing a person. * * "Open" means that the closed date is NULL */ public function getOpenParticipationContainsPerson(Person $person): ?AccompanyingPeriodParticipation { $collection = $this ->getParticipationsContainsPerson($person) ->filter( static function (AccompanyingPeriodParticipation $participation): bool { return null === $participation->getEndDate(); } ); return $collection->count() > 0 ? $collection->first() : null; } public function getOpenParticipations(): Collection { return $this ->getParticipations() ->filter( static function (AccompanyingPeriodParticipation $participation): bool { return null === $participation->getEndDate(); } ); } public function getOrigin(): ?Origin { return $this->origin; } /** * Get Participations Collection. */ public function getParticipations(): Collection { return $this->participations; } /** * Get the participation containing a person. */ public function getParticipationsContainsPerson(Person $person): Collection { return $this ->getParticipations() ->filter( static function (AccompanyingPeriodParticipation $participation) use ($person): bool { return $participation->getPerson() === $person; } ); } /** * @Groups({"read"}) */ public function getPersonLocation(): ?Person { return $this->personLocation; } /** * Get a list of all persons which are participating to this course. * * @psalm-return Collection */ public function getPersons(): Collection { return $this ->participations ->map( static function (AccompanyingPeriodParticipation $participation): Person { return $participation->getPerson(); } ); } /** * @return Collection|SocialAction[] All the descendant social actions of all * the descendants of the entity */ public function getRecursiveSocialActions(): Collection { $recursiveSocialActions = new ArrayCollection(); foreach ($this->socialIssues as $socialIssue) { foreach ($socialIssue->getRecursiveSocialActions() as $descendant) { if (!$recursiveSocialActions->contains($descendant)) { $recursiveSocialActions->add($descendant); } } } return $recursiveSocialActions; } /** * @return Collection|SocialIssues[] All social issues and their descendants */ public function getRecursiveSocialIssues(): Collection { $recursiveSocialIssues = new ArrayCollection(); foreach ($this->socialIssues as $socialIssue) { foreach ($socialIssue->getDescendantsWithThis() as $descendant) { if (!$recursiveSocialIssues->contains($descendant)) { $recursiveSocialIssues->add($descendant); } } } return $recursiveSocialIssues; } public function getRemark(): string { return $this->remark; } /** * @return Person|ThirdParty * @Groups({"read"}) */ public function getRequestor() { return $this->requestorPerson ?? $this->requestorThirdParty; } public function getRequestorPerson(): ?Person { return $this->requestorPerson; } public function getRequestorThirdParty(): ?ThirdParty { return $this->requestorThirdParty; } public function getResources(): Collection { return $this->resources; } /** * @return Collection|iterable */ public function getScopes(): Collection { return $this->scopes; } public function getSocialIssues(): Collection { return $this->socialIssues; } public function getStep(): ?string { return $this->step; } public function getUser(): ?User { return $this->user; } /** * @return AccompanyingPeriodWork[] */ public function getWorks(): Collection { return $this->works; } /** * Returns true if the closing date is after the opening date. */ public function isClosingAfterOpening(): bool { if (null === $this->getClosingDate()) { return false; } $diff = $this->getOpeningDate()->diff($this->getClosingDate()); if (0 === $diff->invert) { return true; } return false; } public function isConfidential(): bool { return $this->confidential; } /** * Validation function. */ public function isDateConsistent(ExecutionContextInterface $context) { if ($this->isOpen()) { return; } if (!$this->isClosingAfterOpening()) { $context->buildViolation('The date of closing is before the date of opening') ->atPath('dateClosing') ->addViolation(); } } public function isEmergency(): bool { return $this->emergency; } public function isOpen(): bool { if ($this->getOpeningDate() > new DateTimeImmutable('now')) { return false; } if ($this->getClosingDate() === null) { return true; } return false; } public function isRequestorAnonymous(): bool { return $this->requestorAnonymous; } public function removeComment(Comment $comment): void { $comment->setAccompanyingPeriod(null); $this->comments->removeElement($comment); } /** * Remove Participation. */ public function removeParticipation(AccompanyingPeriodParticipation $participation) { $participation->setAccompanyingPeriod(null); } /** * Remove Person. */ public function removePerson(Person $person): self { $this->closeParticipationFor($person); return $this; } public function removeResource(Resource $resource): void { $resource->setAccompanyingPeriod(null); $this->resources->removeElement($resource); } public function removeScope(Scope $scope): void { $this->scopes->removeElement($scope); } public function removeSocialIssue(SocialIssue $socialIssue): void { $this->socialIssues->removeElement($socialIssue); } public function removeWork(AccompanyingPeriodWork $work): self { $this->work->removeElement($work); $work->setAccompanyingPeriod(null); return $this; } public function reOpen(): void { $this->setClosingDate(null); $this->setClosingMotive(null); } /** * @Groups({"write"}) */ public function setAddressLocation(?Address $addressLocation = null): self { $this->addressLocation = $addressLocation; return $this; } /** * Set closingDate. * * For closing a Person file, you should use Person::setClosed instead. * * @param mixed $closingDate * * @return AccompanyingPeriod */ public function setClosingDate($closingDate) { $this->closingDate = $closingDate; return $this; } public function setClosingMotive(?ClosingMotive $closingMotive = null): self { $this->closingMotive = $closingMotive; return $this; } public function setConfidential(bool $confidential): self { $this->confidential = $confidential; return $this; } public function setCreatedAt(DateTimeInterface $datetime): self { $this->createdAt = $datetime; return $this; } public function setCreatedBy(User $createdBy): self { $this->createdBy = $createdBy; return $this; } public function setEmergency(bool $emergency): self { $this->emergency = $emergency; return $this; } /** * @Groups({"write"}) */ public function setInitialComment(?Comment $comment = null): self { if (null !== $this->initialComment) { $this->removeComment($this->initialComment); } if ($comment instanceof Comment) { $this->addComment($comment); } $this->initialComment = $comment; return $this; } public function setIntensity(string $intensity): self { $this->intensity = $intensity; return $this; } /** * Set openingDate. * * @param mixed $openingDate * * @return AccompanyingPeriod */ public function setOpeningDate($openingDate) { $this->openingDate = $openingDate; return $this; } public function setOrigin(Origin $origin): self { $this->origin = $origin; return $this; } /** * @Groups({"write"}) */ public function setPersonLocation(?Person $person = null): self { $this->personLocation = $person; return $this; } public function setRemark(?string $remark = null): self { $this->remark = (string) $remark; return $this; } /** * Set a requestor. * * The requestor is either an instance of ThirdParty, or an * instance of Person * * @param $requestor Person|ThirdParty * @throw UnexpectedValueException if the requestor is not a Person or ThirdParty * @Groups({"write"}) */ public function setRequestor($requestor): self { if ($requestor instanceof Person) { $this->setRequestorThirdParty(null); $this->setRequestorPerson($requestor); } elseif ($requestor instanceof ThirdParty) { $this->setRequestorThirdParty($requestor); $this->setRequestorPerson(null); } elseif (null === $requestor) { $this->setRequestorPerson(null); $this->setRequestorThirdParty(null); } else { throw new UnexpectedValueException('requestor is not an instance of Person or ThirdParty'); } return $this; } public function setRequestorAnonymous(bool $requestorAnonymous): self { $this->requestorAnonymous = $requestorAnonymous; return $this; } public function setStep(string $step): self { $this->step = $step; return $this; } public function setUpdatedAt(DateTimeInterface $datetime): self { $this->updatedAt = $datetime; return $this; } public function setUpdatedBy(User $user): self { $this->updatedBy = $user; return $this; } public function setUser(User $user): self { $this->user = $user; return $this; } private function setRequestorPerson(?Person $requestorPerson = null): self { $this->requestorPerson = $requestorPerson; return $this; } private function setRequestorThirdParty(?ThirdParty $requestorThirdParty = null): self { $this->requestorThirdParty = $requestorThirdParty; return $this; } }