405 lines
9.6 KiB
PHP

<?php
declare(strict_types=1);
/*
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\PersonBundle\Entity\SocialWork;
use DateInterval;
use DateTimeInterface;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Serializer\Annotation as Serializer;
/**
* @ORM\Entity
* @ORM\Table(name="chill_person_social_action")
* @Serializer\DiscriminatorMap(
* typeProperty="type",
* mapping={
* "social_work_social_action": SocialAction::class
* }
* )
*/
class SocialAction
{
/**
* @ORM\OneToMany(targetEntity=SocialAction::class, mappedBy="parent")
*/
private $children;
/**
* @ORM\Column(type="dateinterval", nullable=true)
*/
private $defaultNotificationDelay;
/**
* @ORM\Column(type="datetime", nullable=true)
*/
private $desactivationDate;
/**
* @ORM\ManyToMany(targetEntity=Evaluation::class, inversedBy="socialActions")
* @ORM\JoinTable(name="chill_person_social_work_evaluation_action")
*/
private Collection $evaluations;
/**
* @ORM\ManyToMany(targetEntity=Goal::class, inversedBy="socialActions")
* @ORM\JoinTable(name="chill_person_social_action_goal")
*/
private $goals;
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
*/
private ?int $id = null;
/**
* @ORM\ManyToOne(targetEntity=SocialIssue::class, inversedBy="socialActions")
*/
private $issue;
/**
* @ORM\Column(type="float", name="ordering", options={"default": 0.0})
*/
private float $ordering = 0.0;
/**
* @ORM\ManyToOne(targetEntity=SocialAction::class, inversedBy="children")
*/
private $parent;
/**
* @ORM\ManyToMany(targetEntity=Result::class, inversedBy="socialActions")
* @ORM\JoinTable(name="chill_person_social_action_result")
*/
private $results;
/**
* @ORM\Column(type="json")
*/
private $title = [];
public function __construct()
{
$this->children = new ArrayCollection();
$this->goals = new ArrayCollection();
$this->results = new ArrayCollection();
$this->evaluations = new ArrayCollection();
}
public function addChild(self $child): self
{
if (!$this->children->contains($child)) {
$this->children[] = $child;
$child->setParent($this)->setIssue($this->getIssue());
}
return $this;
}
public function addEvaluation(Evaluation $evaluation): self
{
if (!$this->evaluations->contains($evaluation)) {
$this->evaluations[] = $evaluation;
$evaluation->addSocialAction($this);
}
return $this;
}
public function addGoal(Goal $goal): self
{
if (!$this->goals->contains($goal)) {
$this->goals[] = $goal;
}
return $this;
}
public function addResult(Result $result): self
{
if (!$this->results->contains($result)) {
$this->results[] = $result;
}
return $this;
}
/**
* In a SocialIssues's collection, find the elements which are an ancestor of
* other elements.
*
* The difference of the given list (thus, the elements which are **not** kept
* in the returned collection) are the most-grand-child elements of the list.
*
* Removing those elements of the Collection (which is not done by this method)
* will ensure that only the most descendent elements are present in the collection,
* (any ancestor of another element are present).
*
* @param Collection|SocialAction[] $socialActions
*
* @return Collection|SocialAction[] a list with the elements of the given list which are parent of other elements in the given list
*/
public static function findAncestorSocialActions(Collection $socialActions): Collection
{
$ancestors = new ArrayCollection();
foreach ($socialActions as $candidateChild) {
if ($ancestors->contains($candidateChild)) {
continue;
}
foreach ($socialActions as $candidateParent) {
if ($ancestors->contains($candidateParent)) {
continue;
}
if ($candidateChild->isDescendantOf($candidateParent)) {
$ancestors->add($candidateParent);
}
}
}
return $ancestors;
}
/**
* @return Collection|self[]
*/
public function getChildren(): Collection
{
return $this->children;
}
public function getDefaultNotificationDelay(): ?DateInterval
{
return $this->defaultNotificationDelay;
}
public function getDesactivationDate(): ?DateTimeInterface
{
return $this->desactivationDate;
}
/**
* @return Collection|self[] All the descendants (children, children of children, ...)
*/
public function getDescendants(): Collection
{
$descendants = new ArrayCollection();
foreach ($this->getChildren() as $child) {
if (!$descendants->contains($child)) {
$descendants->add($child);
foreach ($child->getDescendants() as $descendantsOfChild) {
if (!$descendants->contains($descendantsOfChild)) {
$descendants->add($descendantsOfChild);
}
}
}
}
return $descendants;
}
/**
* @return Collection|self[] All the descendants including the current entity (this)
*/
public function getDescendantsWithThis(): Collection
{
$descendants = $this->getDescendants();
if (!$descendants->contains($this)) {
$descendants->add($this);
}
return $descendants;
}
/**
* @param Collection|SocialAction[] $socialActions
*/
public static function getDescendantsWithThisForActions($socialActions): Collection
{
$unique = [];
foreach ($socialActions as $action) {
foreach ($action->getDescendantsWithThis() as $child) {
$unique[spl_object_hash($child)] = $child;
}
}
return new ArrayCollection(array_values($unique));
}
public function getEvaluations(): Collection
{
return $this->evaluations;
}
/**
* @return Collection|Goal[]
*/
public function getGoals(): Collection
{
return $this->goals;
}
public function getId(): ?int
{
return $this->id;
}
public function getIssue(): ?SocialIssue
{
return $this->issue;
}
public function getOrdering(): float
{
return $this->ordering;
}
public function getParent(): ?self
{
return $this->parent;
}
/**
* @return Collection|Result[]
*/
public function getResults(): Collection
{
return $this->results;
}
public function getTitle(): array
{
return $this->title;
}
public function hasChildren(): bool
{
return 0 < $this->getChildren()->count();
}
public function hasParent(): bool
{
return $this->getParent() instanceof self;
}
/**
* Recursive method which return true if the current $action
* is a descendant of the $action given in parameter.
*/
public function isDescendantOf(SocialAction $action): bool
{
if (!$this->hasParent()) {
return false;
}
if ($this->getParent() === $action) {
return true;
}
return $this->getParent()->isDescendantOf($action);
}
public function removeChild(self $child): self
{
if ($this->children->removeElement($child)) {
// set the owning side to null (unless already changed)
if ($child->getParent() === $this) {
$child->setParent(null);
}
}
return $this;
}
public function removeEvaluation(Evaluation $evaluation): self
{
$this->evaluations->removeElement($evaluation);
$evaluation->removeSocialAction($this);
return $this;
}
public function removeGoal(Goal $goal): self
{
$this->goals->removeElement($goal);
return $this;
}
public function removeResult(Result $result): self
{
$this->results->removeElement($result);
return $this;
}
public function setDefaultNotificationDelay(DateInterval $defaultNotificationDelay): self
{
$this->defaultNotificationDelay = $defaultNotificationDelay;
return $this;
}
public function setDesactivationDate(?DateTimeInterface $desactivationDate): self
{
$this->desactivationDate = $desactivationDate;
return $this;
}
public function setIssue(?SocialIssue $issue): self
{
$this->issue = $issue;
foreach ($this->getChildren() as $child) {
$child->setIssue($issue);
}
return $this;
}
public function setOrdering(float $ordering): SocialAction
{
$this->ordering = $ordering;
return $this;
}
/**
* @internal use $parent->addChild() instead (@see{self::addChild()})
*/
public function setParent(?self $parent): self
{
$this->parent = $parent;
$parent->addChild($this);
return $this;
}
public function setTitle(array $title): self
{
$this->title = $title;
return $this;
}
}