379 lines
9.3 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 Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Serializer\Annotation\DiscriminatorMap;
use Symfony\Component\Serializer\Annotation\Groups;
/**
* @ORM\Entity
*
* @ORM\Table(name="chill_person_social_issue")
*
* @DiscriminatorMap(typeProperty="type", mapping={
* "social_issue": SocialIssue::class
* })
*/
class SocialIssue
{
/**
* @var Collection<SocialIssue>
*
* @ORM\OneToMany(targetEntity=SocialIssue::class, mappedBy="parent")
*/
private Collection $children;
/**
* @ORM\Column(type="datetime", nullable=true)
*/
private ?\DateTimeInterface $desactivationDate = null;
/**
* @ORM\Id
*
* @ORM\GeneratedValue
*
* @ORM\Column(type="integer")
*/
private ?int $id = null;
/**
* @ORM\Column(type="float", name="ordering", options={"default": 0.0})
*/
private float $ordering = 0.0;
/**
* @ORM\ManyToOne(targetEntity=SocialIssue::class, inversedBy="children")
*/
private ?SocialIssue $parent = null;
/**
* @var Collection<SocialAction>
*
* @ORM\OneToMany(targetEntity=SocialAction::class, mappedBy="issue")
*/
private Collection $socialActions;
/**
* @ORM\Column(type="json")
*
* @Groups({"read"})
*/
private array $title = [];
public function __construct()
{
$this->children = new ArrayCollection();
$this->socialActions = new ArrayCollection();
}
/**
* @internal use @see{SocialIssue::setParent} instead
*
* @return $this
*/
public function addChild(self $child): self
{
if (!$this->children->contains($child)) {
$this->children[] = $child;
}
return $this;
}
public function addSocialAction(SocialAction $socialAction): self
{
if (!$this->socialActions->contains($socialAction)) {
$this->socialActions[] = $socialAction;
$socialAction->setIssue($this);
}
return $this;
}
/**
* In a SocialIssues's collection, find the elements which are an ancestor of
* other elements.
*
* 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|SocialIssue[] $socialIssues
*
* @return Collection|SocialIssue[]
*/
public static function findAncestorSocialIssues(array|Collection $socialIssues): Collection
{
$ancestors = new ArrayCollection();
foreach ($socialIssues as $candidateChild) {
if ($ancestors->contains($candidateChild)) {
continue;
}
foreach ($socialIssues as $candidateParent) {
if ($ancestors->contains($candidateParent)) {
continue;
}
if ($candidateChild->isDescendantOf($candidateParent)) {
$ancestors->add($candidateParent);
}
}
}
return $ancestors;
}
/**
* get all the ancestors of the social issue.
*
* @param bool $includeThis if the array in the result must include the present SocialIssue
*/
public function getAncestors(bool $includeThis = true): array
{
$ancestors = [];
if ($includeThis) {
$ancestors[] = $this;
}
$current = $this;
while ($current->hasParent()) {
$ancestors[] = $current = $current->getParent();
}
return $ancestors;
}
/**
* @return Collection|self[]
*/
public function getChildren(): Collection
{
return $this->children;
}
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|SocialAction[] All the descendant social actions of the entity
*/
public function getDescendantsSocialActions(): Collection
{
$descendantsSocialActions = new ArrayCollection();
foreach ($this->getSocialActions() as $socialAction) {
foreach ($socialAction->getDescendantsWithThis() as $descendant) {
if (!$descendantsSocialActions->contains($descendant)) {
$descendantsSocialActions->add($descendant);
}
}
}
return $descendantsSocialActions;
}
/**
* @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 array|SocialIssue[] $socialIssues
*/
public static function getDescendantsWithThisForIssues(array|Collection $socialIssues): Collection
{
$unique = [];
foreach ($socialIssues as $issue) {
foreach ($issue->getDescendantsWithThis() as $child) {
$unique[spl_object_hash($child)] = $child;
}
}
return new ArrayCollection(array_values($unique));
}
public function getId(): ?int
{
return $this->id;
}
public function getOrdering(): float
{
return $this->ordering;
}
public function getParent(): ?self
{
return $this->parent;
}
/**
* @return Collection<SocialAction> All the descendant social actions of all
* the descendants of the entity
*/
public function getRecursiveSocialActions(): Collection
{
$recursiveSocialActions = new ArrayCollection();
foreach ($this->getDescendantsWithThis() as $socialIssue) {
foreach ($socialIssue->getDescendantsSocialActions() as $descendant) {
if (!$recursiveSocialActions->contains($descendant)) {
$recursiveSocialActions->add($descendant);
}
}
}
return $recursiveSocialActions;
}
/**
* @return Collection<SocialAction>
*/
public function getSocialActions(): Collection
{
return $this->socialActions;
}
public function getTitle(): array
{
return $this->title;
}
public function hasChildren(): bool
{
return 0 < $this->getChildren()->count();
}
public function hasParent(): bool
{
return null !== $this->parent;
}
/**
* Recursive method which return true if the current $issue is a descendant
* of the $issue given in parameter.
*/
public function isDescendantOf(SocialIssue $issue): bool
{
if (!$this->hasParent()) {
return false;
}
if ($this->getParent() === $issue) {
return true;
}
return $this->getParent()->isDescendantOf($issue);
}
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 removeSocialAction(SocialAction $socialAction): self
{
if ($this->socialActions->removeElement($socialAction)) {
// set the owning side to null (unless already changed)
if ($socialAction->getIssue() === $this) {
$socialAction->setIssue(null);
}
}
return $this;
}
public function setDesactivationDate(?\DateTimeInterface $desactivationDate): self
{
$this->desactivationDate = $desactivationDate;
return $this;
}
public function setOrdering(float $ordering): SocialIssue
{
$this->ordering = $ordering;
return $this;
}
/**
* @internal use @see{SocialIssue::addChild()} instead
*/
public function setParent(?self $parent): self
{
$this->parent = $parent;
if (null !== $parent) {
$parent->addChild($this);
}
return $this;
}
public function setTitle(array $title): self
{
$this->title = $title;
return $this;
}
}