SocialAction::class])] #[ORM\Entity] #[ORM\Table(name: 'chill_person_social_action')] class SocialAction { /** * @var Collection */ #[ORM\OneToMany(targetEntity: SocialAction::class, mappedBy: 'parent')] private Collection $children; #[ORM\Column(type: \Doctrine\DBAL\Types\Types::DATEINTERVAL, nullable: true)] private ?\DateInterval $defaultNotificationDelay = null; #[ORM\Column(type: \Doctrine\DBAL\Types\Types::DATETIME_MUTABLE, nullable: true)] private ?\DateTimeInterface $desactivationDate = null; /** * @var Collection */ #[ORM\ManyToMany(targetEntity: Evaluation::class, inversedBy: 'socialActions')] #[ORM\JoinTable(name: 'chill_person_social_work_evaluation_action')] private Collection $evaluations; /** * @var Collection */ #[ORM\ManyToMany(targetEntity: Goal::class, inversedBy: 'socialActions')] #[ORM\JoinTable(name: 'chill_person_social_action_goal')] private Collection $goals; #[ORM\Id] #[ORM\GeneratedValue] #[ORM\Column(type: \Doctrine\DBAL\Types\Types::INTEGER)] private ?int $id = null; #[ORM\ManyToOne(targetEntity: SocialIssue::class, inversedBy: 'socialActions')] private ?SocialIssue $issue = null; #[ORM\Column(type: \Doctrine\DBAL\Types\Types::FLOAT, name: 'ordering', options: ['default' => '0.0'])] private float $ordering = 0.0; #[ORM\ManyToOne(targetEntity: SocialAction::class, inversedBy: 'children')] private ?SocialAction $parent = null; /** * @var Collection */ #[ORM\ManyToMany(targetEntity: Result::class, inversedBy: 'socialActions')] #[ORM\JoinTable(name: 'chill_person_social_action_result')] private Collection $results; #[ORM\Column(type: \Doctrine\DBAL\Types\Types::JSON)] private array $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(array|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(array|Collection $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 isDesactivated(\DateTime $atDate): bool { if (null !== $this->desactivationDate && $this->desactivationDate < $atDate) { return true; } if ($this->hasParent()) { return $this->parent->isDesactivated($atDate); } return false; } 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; } public static function filterRemoveDeactivatedActions(array|ReadableCollection $actions, \DateTime $comparisonDate): array|ReadableCollection { $filterFn = fn (SocialAction $socialAction) => !$socialAction->isDesactivated($comparisonDate); return match ($actions instanceof ReadableCollection) { true => $actions->filter($filterFn), false => array_filter($actions, $filterFn) }; } }