<?php
namespace MedBrief\MSR\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection as DoctrineCollection;
use Doctrine\ORM\Mapping as ORM;
use Gedmo\Mapping\Annotation as Gedmo;
use MedBrief\MSR\Repository\InterpartyDisclosureRepository;
use MedBrief\MSR\Traits\FilterableClassConstantsTrait;
use Symfony\Component\Validator\Constraints as Assert;
/**
* @ORM\Entity(repositoryClass=InterpartyDisclosureRepository::class)
*/
class InterpartyDisclosure
{
use FilterableClassConstantsTrait;
public const STATUS_DRAFT = 'draft';
public const STATUS_DRAFT__LABEL = 'Draft';
public const STATUS_PENDING = 'pending';
public const STATUS_PENDING__LABEL = 'Pending';
public const STATUS_PROCESSING = 'processing';
public const STATUS_PROCESSING__LABEL = 'Processing';
public const STATUS_FAILED = 'failed';
public const STATUS_FAILED__LABEL = 'Failed';
public const STATUS_ACTIVE = 'active';
public const STATUS_ACTIVE__LABEL = 'Active';
public const STATUS_EXPIRED = 'expired';
public const STATUS_EXPIRED__LABEL = 'Expired';
public const STATUS_REVOKED = 'revoked';
public const STATUS_REVOKED__LABEL = 'Revoked';
public const STATUS_UPDATED = 'updated';
public const STATUS_UPDATED__LABEL = 'Updated';
public const DEFAULT_EXPIRY_DAYS = 30;
public const DEFAULT_EXPIRY_EXTENSION_DAYS = 14;
public const HAS_RADIOLOGY_STUDIES_YES = 'yes';
public const HAS_RADIOLOGY_STUDIES_YES__LABEL = 'Yes';
public const HAS_RADIOLOGY_STUDIES_NO = 'no';
public const HAS_RADIOLOGY_STUDIES_NO__LABEL = 'No';
public const RADIOLOGY_FAILED_DISCS_YES = 'yes';
public const RADIOLOGY_FAILED_DISCS_YES__LABEL = 'Yes';
public const RADIOLOGY_FAILED_DISCS_NO = 'no';
public const RADIOLOGY_FAILED_DISCS_NO__LABEL = 'No';
public const HAS_MEDICAL_RECORDS_YES = 'yes';
public const HAS_MEDICAL_RECORDS_YES__LABEL = 'Yes';
public const HAS_MEDICAL_RECORDS_NO = 'no';
public const HAS_MEDICAL_RECORDS_NO__LABEL = 'No';
/**
* @ORM\Id
*
* @ORM\GeneratedValue
*
* @ORM\Column(type="integer")
*/
private ?int $id;
/**
* @ORM\Column(type="string", length=32, options={"default":self::STATUS_ACTIVE})
*/
private ?string $status = self::STATUS_ACTIVE;
/**
* @ORM\Column(type="datetime", nullable=true)
*/
private ?\DateTime $expiryDate;
/**
* @ORM\Column(type="datetime")
*
* @Gedmo\Timestampable(on="create")
*/
private ?\DateTime $created;
/**
* @ORM\Column(type="datetime", nullable=true)
*
* @Gedmo\Timestampable(on="update")
*/
private ?\DateTime $updated;
/**
* @ORM\Column(type="datetime", nullable=true)
*/
private ?\DateTime $recordsModifiedDate;
/**
* @ORM\ManyToOne(targetEntity=Project::class, inversedBy="interpartyDisclosures")
*
* @ORM\JoinColumn(nullable=false)
*/
private ?Project $project;
/**
* @ORM\OneToMany(targetEntity=InterpartyDisclosureRecipientFirm::class, mappedBy="interpartyDisclosure", orphanRemoval=true, cascade={"persist", "remove"})
*
* @Assert\Valid(groups={"third-party"})
*
* @Assert\Count(min=1, minMessage="At least one recipient firm is required.", groups={"third-party"})
*/
private ?DoctrineCollection $recipientFirms;
/**
* @ORM\Column(type="datetime", nullable=true)
*/
private ?\DateTime $revokeDate;
/**
* @ORM\ManyToOne(targetEntity=User::class)
*/
private ?User $createdBy;
/**
* @ORM\ManyToOne(targetEntity=User::class)
*/
private ?User $revokedBy;
/**
* @ORM\Column(type="datetime", nullable=true)
*/
private ?\DateTime $reactivateDate;
/**
* @ORM\Column(type="json", nullable=true)
*/
private $selectedRecordsPayload = [];
/**
* @ORM\Column(type="json", nullable=true)
*/
private $recordsSnapshot = [];
/**
* @ORM\OneToMany(targetEntity=InterpartyDisclosureStudy::class, mappedBy="interpartyDisclosure", orphanRemoval=true, cascade={"persist", "remove"})
*/
private ?DoctrineCollection $interpartyDisclosureStudies;
/**
* @ORM\OneToMany(targetEntity=InterpartyDisclosureDisc::class, mappedBy="interpartyDisclosure", orphanRemoval=true, cascade={"persist", "remove"})
*/
private ?DoctrineCollection $interpartyDisclosureDiscs;
/**
* @ORM\Column(type="integer", options={"default":0})
*/
private ?int $medicalRecordsCount = 0;
/**
* @ORM\OneToOne(targetEntity="InterpartyDisclosure", inversedBy="child")
*/
private ?InterpartyDisclosure $parent = null;
/**
* @ORM\OneToOne(targetEntity="InterpartyDisclosure", mappedBy="parent")
*/
private ?InterpartyDisclosure $child = null;
/**
* Represents a child copy of a disclosure which has not been updated yet.
*
* @ORM\Column(type="boolean", options={"default":false})
*/
private ?bool $pureCopy = false;
/**
* @ORM\ManyToOne(targetEntity=Project::class, inversedBy="disclosureSources")
*/
private ?Project $disclosureTarget = null;
/**
* @ORM\Column(type="boolean", options={"default":false})
*/
private ?bool $savedAsDraft = false;
// Non-mapped property
private bool $isClone = false;
/**
* @ORM\Column(type="boolean", options={"default":false})
*/
private ?bool $recordsUpdated = false;
/**
* @ORM\Column(type="boolean", options={"default":false})
*/
private ?bool $radiologyUpdated = false;
public function __construct()
{
$this->recipientFirms = new ArrayCollection();
$this->interpartyDisclosureStudies = new ArrayCollection();
$this->interpartyDisclosureDiscs = new ArrayCollection();
}
public function __clone()
{
// Do not clone objects that don't have an identity - Doctrine recommendation.
if ($this->id) {
$this->id = null;
// Mark it as a clone, so we can do some logic against it in the setters e.g. setPureCopy.
$this->isClone = true;
$this->setPureCopy(true);
$this->setSavedAsDraft(false);
$this->setStatus(self::STATUS_DRAFT);
// Auto date fields
$this->setCreatedBy(null);
$this->setUpdated(null);
// Revoked fields
$this->setRevokedBy(null);
$this->setRevokeDate(null);
// Versioning
$this->setParent(null);
$this->setChild(null);
// Other dates
$this->setExpiryDate(null);
$this->setRecordsModifiedDate(null);
$this->setReactivateDate(null);
// Other flags
$this->setRadiologyUpdated(false);
$this->setRecordsUpdated(false);
// Clone firms
$recipientFirms = $this->getRecipientFirms();
$this->recipientFirms = new ArrayCollection();
foreach ($recipientFirms as $recipientFirm) {
$this->addRecipientFirm(clone $recipientFirm);
}
// Clone studies
$interpartyDisclosureStudies = $this->getInterpartyDisclosureStudies();
$this->interpartyDisclosureStudies = new ArrayCollection();
foreach ($interpartyDisclosureStudies as $study) {
$this->addInterpartyDisclosureStudy(clone $study);
}
// Clone discs
$interpartyDisclosureDiscs = $this->getInterpartyDisclosureDiscs();
$this->interpartyDisclosureDiscs = new ArrayCollection();
foreach ($interpartyDisclosureDiscs as $disc) {
$this->addInterpartyDisclosureDisc(clone $disc);
}
}
}
/**
* @return int|null
*/
public function getId(): ?int
{
return $this->id;
}
/**
* @return string
*/
public function getStatus(): string
{
return $this->status;
}
/**
* @return array
*/
public static function getStatusOptions(): array
{
return array_flip(self::getConstantsWithLabelsAsChoices('STATUS'));
}
/**
* @return string
*/
public function getStatusLabel(): string
{
$options = self::getStatusOptions();
return $options[$this->getStatus()] ?? '';
}
/**
* @param string $status
*
* @return self
*/
public function setStatus(string $status): self
{
// if status is changing to expired, clear the recordsUpdates and radiologyUpdated fields
if ($status === self::STATUS_EXPIRED) {
$this->setRecordsUpdated(false);
$this->setRadiologyUpdated(false);
}
$this->status = $status;
return $this;
}
/**
* @return bool
*/
public function isStatusDraft(): bool
{
return $this->getStatus() === self::STATUS_DRAFT;
}
/**
* @return bool
*/
public function isStatusPending(): bool
{
return $this->getStatus() === self::STATUS_PENDING;
}
/**
* @return bool
*/
public function isStatusProcessing(): bool
{
return $this->getStatus() === self::STATUS_PROCESSING;
}
/**
* @return bool
*/
public function isStatusFailed(): bool
{
return $this->getStatus() === self::STATUS_FAILED;
}
/**
* @return bool
*/
public function isStatusActive(): bool
{
return $this->getStatus() === self::STATUS_ACTIVE;
}
/**
* @return bool
*/
public function isStatusRevoked(): bool
{
return $this->getStatus() === self::STATUS_REVOKED;
}
/**
* @return bool
*/
public function isStatusUpdated(): bool
{
return $this->getStatus() === self::STATUS_UPDATED;
}
/**
* @return bool
*/
public function isStatusExpired(): bool
{
return $this->getStatus() === self::STATUS_EXPIRED;
}
/**
* @return \DateTime|null
*/
public function getExpiryDate(): ?\DateTime
{
return $this->expiryDate;
}
/**
* @param \DateTime|null $expiryDate
*
* @return self
*/
public function setExpiryDate(?\DateTime $expiryDate): self
{
$this->expiryDate = $expiryDate;
return $this;
}
/**
* NOTE: Extension is based only on the parent expiry date.
* Extends the expiry date if the remaining days is less than our extension period.
*
* @return self
*/
public function extendExpiryDateIfDue(): self
{
if ($this->getParent() === null) {
throw new \InvalidArgumentException('A parent disclosure is expected to extend the expiry date.');
}
$parentExpiryDate = clone $this->getParent()->getExpiryDate();
// If the parent disclosure was set to expire in less than the extension days, extend it further by the extension days.
if ($this->getParent()->getExpiryDate() < new \DateTime(sprintf('+%1$s days', self::DEFAULT_EXPIRY_EXTENSION_DAYS))) {
$this->setExpiryDate($parentExpiryDate->modify(sprintf('+%1$s days', self::DEFAULT_EXPIRY_EXTENSION_DAYS)));
} else {
// Else, give it the original expiry date of the parent.
$this->setExpiryDate($parentExpiryDate);
}
return $this;
}
/**
* Calculates and sets the expiry date.
*
* Important: should be called before any status change of the disclosure.
*
* @return self
*/
public function calculateExpiryDate(): self
{
if ($this->getParent() === null || $this->isStatusExpired() === true || $this->isParentExpired()) {
// This is the original disclosure, or the disclosure is expired and we're not updating, give it a normal expiry date.
$this->setExpiryDate(new \DateTime(sprintf('+%1$s days', self::DEFAULT_EXPIRY_DAYS)));
} else {
// else, we're simply updating an existing disclosure and need to extend with the expiry date
// using some additional logic.
$this->extendExpiryDateIfDue();
}
return $this;
}
/**
* @return \DateTimeInterface|null
*/
public function getCreated(): ?\DateTimeInterface
{
return $this->created;
}
/**
* @param \DateTimeInterface $created
*
* @return self
*/
public function setCreated(\DateTimeInterface $created): self
{
$this->created = $created;
return $this;
}
/**
* @return \DateTimeInterface|null
*/
public function getUpdated(): ?\DateTimeInterface
{
return $this->updated;
}
/**
* @param \DateTimeInterface|null $updated
*
* @return self
*/
public function setUpdated(?\DateTimeInterface $updated): self
{
$this->updated = $updated;
return $this;
}
/**
* @return Project|null
*/
public function getProject(): ?Project
{
return $this->project;
}
/**
* @param Project|null $project
*
* @return self
*/
public function setProject(?Project $project): self
{
$this->project = $project;
return $this;
}
/**
* @return DoctrineCollection<int, InterpartyDisclosureRecipientFirm>
*/
public function getRecipientFirms(): DoctrineCollection
{
return $this->recipientFirms;
}
/**
* Returns the recipient firms reference number - limited to the first recipient firm.
*
* @return string
*/
public function getRecipientFirmReference(): string
{
return $this->getRecipientFirms()->count() > 0 ? $this->getRecipientFirms()->first()->getMatterNumber() : '';
}
/**
* Retrieve a string of Recipient Firm name/s.
* If there are multiple Firms then prefixes each name with a bracketed number.
*
* @return string
*/
public function getRecipientFirmsString(): string
{
$firmsArray = $this->getRecipientFirms()->map(function (InterpartyDisclosureRecipientFirm $recipientFirm) {
return $recipientFirm->getName();
})->toArray();
if (count($firmsArray) === 1) {
return $firmsArray[0];
}
$firmsStr = implode(' ', array_map(function (string $currentItem, $currentKey) {
return sprintf('(%1$s) %2$s', $currentKey + 1, $currentItem);
}, $firmsArray, array_keys($firmsArray)));
return $firmsStr;
}
/**
* Retrieve a string of Recipient Firm name/s postfixed with bracketed office field if not empty.
* If there are multiple Firms then prefixes each name with a bracketed number.
*
* @return string
*/
public function getRecipientFirmsWithOfficeString(): string
{
$firmsArray = $this->getRecipientFirms()->map(function (InterpartyDisclosureRecipientFirm $recipientFirm) {
$office = is_null($recipientFirm->getOffice()) ? '' : ' (' . $recipientFirm->getOffice() . ')';
return $recipientFirm->getName() . $office;
})->toArray();
if (count($firmsArray) === 1) {
return $firmsArray[0];
}
$firmsStr = implode(' ', array_map(function (string $currentItem, $currentKey) {
return sprintf('(%1$s) %2$s', $currentKey + 1, $currentItem);
}, $firmsArray, array_keys($firmsArray)));
return $firmsStr;
}
/**
* Retrieves all recipient contacts belonging to a disclosure
*
* @return array
*/
public function getAllInterpartyDisclosureContacts(): array
{
if ($this->getRecipientFirms()->count() === 0) {
return [];
}
$allContacts = [];
foreach ($this->getRecipientFirms() as $firm) {
foreach ($firm->getRecipientContacts() as $contact) {
$allContacts[] = $contact;
}
}
return $allContacts;
}
/**
* @param InterpartyDisclosureRecipientFirm $recipientFirm
*
* @return self
*/
public function addRecipientFirm(InterpartyDisclosureRecipientFirm $recipientFirm): self
{
if (!$this->recipientFirms->contains($recipientFirm)) {
$this->recipientFirms[] = $recipientFirm;
$recipientFirm->setInterpartyDisclosure($this);
}
return $this;
}
/**
* @param InterpartyDisclosureRecipientFirm $recipientFirm
*
* @return self
*/
public function removeRecipientFirm(InterpartyDisclosureRecipientFirm $recipientFirm): self
{
if ($this->recipientFirms->removeElement($recipientFirm)) {
// set the owning side to null (unless already changed)
if ($recipientFirm->getInterpartyDisclosure() === $this) {
$recipientFirm->setInterpartyDisclosure(null);
}
}
return $this;
}
/**
* @return \DateTimeInterface|null
*/
public function getRevokeDate(): ?\DateTimeInterface
{
return $this->revokeDate;
}
/**
* @param \DateTimeInterface|null $revokeDate
*
* @return self
*/
public function setRevokeDate(?\DateTimeInterface $revokeDate): self
{
$this->revokeDate = $revokeDate;
return $this;
}
/**
* @return \DateTimeInterface|null
*/
public function getReactivateDate(): ?\DateTimeInterface
{
return $this->reactivateDate;
}
/**
* @param \DateTimeInterface|null $reactivateDate
*
* @return self
*/
public function setReactivateDate(?\DateTimeInterface $reactivateDate): self
{
$this->reactivateDate = $reactivateDate;
return $this;
}
/**
* @return User|null
*/
public function getRevokedBy(): ?User
{
return $this->revokedBy;
}
/**
* @param User|null $revokedBy
*
* @return self
*/
public function setRevokedBy(?User $revokedBy): self
{
$this->revokedBy = $revokedBy;
return $this;
}
/**
* @return DoctrineCollection<int, InterpartyDisclosureStudy>
*/
public function getInterpartyDisclosureStudies(): DoctrineCollection
{
return $this->interpartyDisclosureStudies;
}
/**
* @param InterpartyDisclosureStudy $interpartyDisclosureStudy
*
* @return self
*/
public function addInterpartyDisclosureStudy(InterpartyDisclosureStudy $interpartyDisclosureStudy): self
{
if (!$this->interpartyDisclosureStudies->contains($interpartyDisclosureStudy)) {
$this->interpartyDisclosureStudies[] = $interpartyDisclosureStudy;
$interpartyDisclosureStudy->setInterpartyDisclosure($this);
}
return $this;
}
/**
* @param InterpartyDisclosureStudy $interpartyDisclosureStudy
*
* @return self
*/
public function removeInterpartyDisclosureStudy(InterpartyDisclosureStudy $interpartyDisclosureStudy): self
{
if ($this->interpartyDisclosureStudies->removeElement($interpartyDisclosureStudy)) {
// set the owning side to null (unless already changed)
if ($interpartyDisclosureStudy->getInterpartyDisclosure() === $this) {
$interpartyDisclosureStudy->setInterpartyDisclosure(null);
}
}
return $this;
}
/**
* @return DoctrineCollection<int, Study>
*/
public function getStudies(): DoctrineCollection
{
return $this->getInterpartyDisclosureStudies()->map(function (InterpartyDisclosureStudy $disclosureStudy) {
return $disclosureStudy->getStudy();
});
}
/**
* @param Study $study
*
* @return self
*/
public function addStudy(Study $study): self
{
$disclosureStudy = new InterpartyDisclosureStudy();
$disclosureStudy->setStudy($study);
$discs = $study->getDiscs();
$disclosureDiscs = $discs->map(function ($disc) {
return [
'name' => $disc->getName(),
'id' => $disc->getId(),
];
});
$disclosureStudy->setPayload(
[
'date' => $study->getStudyDate(),
'description' => $study->getStudyDescription(),
'discs' => $disclosureDiscs,
]
);
$this->addInterpartyDisclosureStudy($disclosureStudy);
return $this;
}
/**
* @param Study $study
*
* @return self
*/
public function removeStudy(Study $study): self
{
foreach ($this->getInterpartyDisclosureStudies() as $disclosureStudy) {
if ($disclosureStudy->getStudy() === $study) {
$this->removeInterpartyDisclosureStudy($disclosureStudy);
}
}
return $this;
}
/**
* @return DoctrineCollection<int, InterpartyDisclosureDisc>
*/
public function getInterpartyDisclosureDiscs(): DoctrineCollection
{
return $this->interpartyDisclosureDiscs;
}
/**
* @param InterpartyDisclosureDisc $interpartyDisclosureDisc
*
* @return self
*/
public function addInterpartyDisclosureDisc(?InterpartyDisclosureDisc $interpartyDisclosureDisc): self
{
if (!$this->interpartyDisclosureDiscs->contains($interpartyDisclosureDisc)) {
$this->interpartyDisclosureDiscs[] = $interpartyDisclosureDisc;
$interpartyDisclosureDisc->setInterpartyDisclosure($this);
}
return $this;
}
/**
* @param InterpartyDisclosureDisc $interpartyDisclosureDisc
*
* @return self
*/
public function removeInterpartyDisclosureDisc(InterpartyDisclosureDisc $interpartyDisclosureDisc): self
{
if ($this->interpartyDisclosureDiscs->removeElement($interpartyDisclosureDisc)) {
// set the owning side to null (unless already changed)
if ($interpartyDisclosureDisc->getInterpartyDisclosure() === $this) {
$interpartyDisclosureDisc->setInterpartyDisclosure(null);
}
}
return $this;
}
/**
* @return DoctrineCollection<int, Disc>
*/
public function getDiscs(): DoctrineCollection
{
return $this->getInterpartyDisclosureDiscs()->map(function (InterpartyDisclosureDisc $disclosureDisc) {
return $disclosureDisc->getDisc();
});
}
/**
* @param Disc $disc
*
* @return self
*/
public function addDisc(Disc $disc): self
{
$disclosureDisc = new InterpartyDisclosureDisc();
$disclosureDisc->setDisc($disc);
$disclosureDisc->setPayload(
[
'id' => $disc->getId(),
'name' => $disc->getName(),
]
);
$this->addInterpartyDisclosureDisc($disclosureDisc);
return $this;
}
/**
* @param Disc $disc
*
* @return self
*/
public function removeDisc(Disc $disc): self
{
foreach ($this->getInterpartyDisclosureDiscs() as $disclosureDisc) {
if ($disclosureDisc->getDisc() === $disc) {
$this->removeInterpartyDisclosureDisc($disclosureDisc);
}
}
return $this;
}
/**
* @return array|null
*/
public function getSelectedRecordsPayload(): ?array
{
return $this->selectedRecordsPayload;
}
/**
* @param array|null $selectedRecordsPayload
*
* @return self
*/
public function setSelectedRecordsPayload(?array $selectedRecordsPayload): self
{
$this->selectedRecordsPayload = $selectedRecordsPayload;
if ($selectedRecordsPayload === null) {
$this->setMedicalRecordsCount(0);
} else {
$this->setMedicalRecordsCount(count($selectedRecordsPayload));
}
return $this;
}
/**
* @return User|null
*/
public function getCreatedBy(): ?User
{
return $this->createdBy;
}
/**
* @param User|null $createdBy
*
* @return self
*/
public function setCreatedBy(?User $createdBy): self
{
$this->createdBy = $createdBy;
return $this;
}
/**
* Counts the number of third parties, i.e. recipient firm contacts that have
* access to the interparty disclosure
*
* @return int|null
*/
public function getContactPersonCount(): ?int
{
$count = 0;
foreach ($this->getRecipientFirms() as $firm) {
$count += $firm->getRecipientContacts()->count();
}
return $count;
}
/**
* Counts the number of radiology studies that an interparty disclosure has associated
* with it.
*
* @return int|null
*/
public function getRadiologyStudyCount(): ?int
{
return $this->getInterpartyDisclosureStudies()->count();
}
/**
* @return array
*/
public static function getHasRadiologyStudiesOptions(): array
{
return array_flip(self::getConstantsWithLabelsAsChoices('HAS_RADIOLOGY_STUDIES'));
}
/**
* Counts the number of failed radiology discs that an interparty disclosure
* has associated with it.
*
* @return int|null
*/
public function getRadiologyFailedDiscsCount(): ?int
{
return $this->getInterpartyDisclosureDiscs()->count();
}
/**
* @return array
*/
public static function getRadiologyFailedDiscsOptions(): array
{
return array_flip(self::getConstantsWithLabelsAsChoices('RADIOLOGY_FAILED_DISCS'));
}
/**
* @return int
*/
public function getRadiologyItemTotalCount(): int
{
return $this->getRadiologyStudyCount() + $this->getRadiologyFailedDiscsCount();
}
/**
* @return string|null
*/
public function getThirdPartyContacts(): ?string
{
$contactDetails = [];
foreach ($this->getRecipientFirms() as $firm) {
foreach ($firm->getRecipientContacts() as $contact) {
$contactDetails[] = $contact;
}
}
$contactNames = array_map(function ($contact) {
return $contact->getFullName();
}, $contactDetails);
return implode(',', $contactNames);
}
/**
* @return self|null
*/
public function getParent(): ?self
{
return $this->parent;
}
/**
* @param self|null $parent
*
* @return self
*/
public function setParent(?self $parent): self
{
$this->parent = $parent;
return $this;
}
/**
* @return self|null
*/
public function getChild(): ?self
{
return $this->child;
}
/**
* @param self|null $child
*
* @return self
*/
public function setChild(?self $child): self
{
// unset the owning side of the relation if necessary
if ($child === null && $this->child !== null) {
$this->child->setParent(null);
}
// set the owning side of the relation if necessary
if ($child !== null && $child->getParent() !== $this) {
$child->setParent($this);
}
$this->child = $child;
return $this;
}
/**
* @return InterpartyDisclosure[]
*/
public function getPreviousVersions(): array
{
$currentElement = $this;
$previousVersions = [];
do {
if ($currentElement->getParent() !== null) {
$previousVersions[] = $currentElement->getParent();
}
$currentElement = $currentElement->getParent();
} while ($currentElement !== null);
return $previousVersions;
}
/**
* Returns true if the current disclosure is a previous disclosure of the disclosure passed in as an argument.
*
* @param InterpartyDisclosure $latestDisclosure
*
* @return bool
*/
public function isDisclosurePreviousVersionOf(InterpartyDisclosure $latestDisclosure): bool
{
return in_array($this, $latestDisclosure->getPreviousVersions());
}
/**
* @return bool
*/
public function isChildDraft(): bool
{
return $this->getParent() instanceof self && $this->isStatusDraft();
}
/**
* @return bool
*/
public function isParentExpired(): bool
{
return $this->getParent() !== null && $this->getParent()->getExpiryDate() <= new \DateTime();
}
/**
* Returns true if the disclosure chain should be considered expired.
*
* @return bool
*/
public function isDisclosureChainExpired(): bool
{
return $this->isStatusExpired() || $this->isParentExpired();
}
/**
* @return bool
*/
public function hasChildDraft(): bool
{
return $this->getChild() instanceof self && $this->getChild()->isStatusDraft();
}
/**
* @return bool
*/
public function canEdit(): bool
{
$allowedStatuses = [
self::STATUS_ACTIVE,
self::STATUS_DRAFT,
];
return in_array($this->getStatus(), $allowedStatuses);
}
/**
* Returns the ID of the entity that should be used for editing.
*
* @return int|null
*/
public function getEditId(): ?int
{
if ($this->hasChildDraft()) {
return $this->getChild()->getId();
}
return $this->getId();
}
/**
* @return bool|null
*/
public function getPureCopy(): ?bool
{
return $this->pureCopy;
}
/**
* @param bool|null $pureCopy
*
* @return self
*/
public function setPureCopy(?bool $pureCopy): self
{
if ($pureCopy === true && $this->isChildDraft() === false && $this->isClone === false) {
throw new \InvalidArgumentException('Only child drafts can be marked as pure copies.');
}
$this->pureCopy = $pureCopy;
return $this;
}
/**
* @return int|null
*/
public function getMedicalRecordsCount(): ?int
{
return $this->medicalRecordsCount;
}
/**
* @param int|null $medicalRecordsCount
*
* @return self
*/
public function setMedicalRecordsCount(?int $medicalRecordsCount): self
{
$this->medicalRecordsCount = $medicalRecordsCount;
return $this;
}
/**
* @return array
*/
public static function getHasMedicalRecordsOptions(): array
{
return array_flip(self::getConstantsWithLabelsAsChoices('HAS_MEDICAL_RECORDS'));
}
/**
* Returns true if the disclosure is the current head of the chain.
* Child drafts are ignored.
*
* @return bool
*/
public function isCurrentHeadOfChain(): bool
{
return $this->getChild() === null || $this->hasChildDraft() === true;
}
/**
* @return Project|null
*/
public function getDisclosureTarget(): ?Project
{
return $this->disclosureTarget;
}
/**
* @param Project|null $disclosureTarget
*
* @return self
*/
public function setDisclosureTarget(?Project $disclosureTarget): self
{
$this->disclosureTarget = $disclosureTarget;
return $this;
}
/**
* @return array|null
*/
public function getRecordsSnapshot(): ?array
{
return $this->recordsSnapshot;
}
/**
* @param array|null $recordsSnapshot
*
* @return self
*/
public function setRecordsSnapshot(?array $recordsSnapshot): self
{
$this->recordsSnapshot = $recordsSnapshot;
return $this;
}
/**
* @return \DateTimeInterface|null
*
*/
public function getRecordsModifiedDate(): ?\DateTimeInterface
{
return $this->recordsModifiedDate;
}
/**
* @param \DateTimeInterface|null $recordsModifiedDate
*
* @return self
*
*/
public function setRecordsModifiedDate(?\DateTimeInterface $recordsModifiedDate): self
{
$this->recordsModifiedDate = $recordsModifiedDate;
return $this;
}
/**
* Determines the contacts removed from the child that were in the parent.
*
* @return InterpartyDisclosureRecipientContact[]
*/
public function getContactsRemoved(): array
{
// No parent? No contacts removed
if ($this->getParent() === null) {
return [];
}
// Start by mapping the previous set of contacts to their emails.
$prevContacts = array_map(function (InterpartyDisclosureRecipientContact $contact) {
return $contact->getEmail();
}, $this->getParent()->getAllInterpartyDisclosureContacts());
$currContacts = array_map(function (InterpartyDisclosureRecipientContact $contact) {
return $contact->getEmail();
}, $this->getAllInterpartyDisclosureContacts());
// Get the elements that are in prevContacts, but not in currContacts
$removedContacts = array_diff($prevContacts, $currContacts);
// Nothing, return empty array
if (empty($removedContacts)) {
return [];
}
// Turn them back into entities and return
return array_filter($this->getParent()->getAllInterpartyDisclosureContacts(), function (InterpartyDisclosureRecipientContact $contact) use ($removedContacts) {
return in_array($contact->getEmail(), $removedContacts) === true;
});
}
/**
* @return bool|null
*/
public function getSavedAsDraft(): ?bool
{
return $this->savedAsDraft;
}
/**
* @param bool $savedAsDraft
*
* @return self
*/
public function setSavedAsDraft(bool $savedAsDraft): self
{
$this->savedAsDraft = $savedAsDraft;
return $this;
}
/**
* Checks if passed-in disclosure is a child and that it has no child draft, then it is the most recent disclosure.
*
* @return bool
*/
public function isDisclosurePreviousVersion(): bool
{
return $this->getChild() !== null && $this->hasChildDraft() === false;
}
/**
* @return bool|null
*/
public function isRecordsUpdated(): ?bool
{
return $this->recordsUpdated;
}
/**
* @param bool $recordsUpdated
*
* @return self
*/
public function setRecordsUpdated(bool $recordsUpdated): self
{
$this->recordsUpdated = $recordsUpdated;
return $this;
}
/**
* @return bool|null
*/
public function isRadiologyUpdated(): ?bool
{
return $this->radiologyUpdated;
}
/**
* @param bool $recordsUpdated
*
* @return self
*/
public function setRadiologyUpdated(bool $recordsUpdated): self
{
$this->radiologyUpdated = $recordsUpdated;
return $this;
}
}