<?php
namespace MedBrief\MSR\Entity;
use DH\Auditor\Provider\Doctrine\Auditing\Annotation as Audit;
use Doctrine\Common\Collections\Criteria;
use Doctrine\ORM\Mapping as ORM;
use Gedmo\Mapping\Annotation as Gedmo;
use MedBrief\MSR\Repository\PatientRepository;
/**
* Patient
*
* @ORM\Table(name="Patient", indexes={@ORM\Index(name="orthanc_patient_id_index", columns={"orthanc_patient_id"})})
*
* @ORM\Entity(repositoryClass=PatientRepository::class)
*
* @Gedmo\SoftDeleteable(fieldName="deletedAt", timeAware=false)
*
* @Audit\Auditable
*
* @Audit\Security(view={"ROLE_ALLOWED_TO_AUDIT"})
*/
class Patient
{
public const ORTHANC_SYNC_STATUS_PENDING = 1;
public const ORTHANC_SYNC_STATUS_FAILED = 2;
public const ORTHANC_SYNC_STATUS_SUCCESS = 3;
/**
* @var int
*
* @ORM\Column(name="id", type="integer")
*
* @ORM\Id
*
* @ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* @var \DateTime|null
*
* @ORM\Column(name="deletedAt", type="datetime", nullable=true)
*/
private $deletedAt;
/**
* @var string|null
*
* @ORM\Column(name="dicom_patient_name", type="string", nullable=true)
*/
private $dicom_patient_name;
/**
* @var string|null
*
* @ORM\Column(name="dicom_patient_id", type="string", nullable=true)
*/
private $dicom_patient_id;
/**
* @var int|null
*
* @ORM\Column(name="orthanc_sync_status", type="integer", nullable=true)
*/
private $orthanc_sync_status;
/**
* @var string|null
*
* @ORM\Column(name="orthanc_patient_id", type="string", nullable=true)
*/
private $orthanc_patient_id;
/**
* @var \DateTime
*
* @ORM\Column(name="created", type="datetime")
*
* @Gedmo\Timestampable(on="create")
*/
private $created;
/**
* @var \DateTime
*
* @ORM\Column(name="updated", type="datetime")
*
* @Gedmo\Timestampable(on="update")
*/
private $updated;
/**
* @var \Doctrine\Common\Collections\Collection
*
* @ORM\OneToMany(targetEntity="MedBrief\MSR\Entity\Study", mappedBy="patient")
*/
private $studies;
/**
* @var \Doctrine\Common\Collections\Collection
*
* @ORM\OneToMany(targetEntity="MedBrief\MSR\Entity\OrthancTransaction", mappedBy="patient", cascade={"all"})
*/
private $orthancTransactions;
/**
* @var Project
*
* @ORM\ManyToOne(targetEntity="MedBrief\MSR\Entity\Project", inversedBy="patients")
*
* @ORM\JoinColumns({
*
* @ORM\JoinColumn(name="project_id", referencedColumnName="id", nullable=false)
* })
*/
private $project;
/**
* Constructor
*/
public function __construct()
{
$this->studies = new \Doctrine\Common\Collections\ArrayCollection();
$this->orthancTransactions = new \Doctrine\Common\Collections\ArrayCollection();
}
public function __clone()
{
if ($this->id) {
$this->id = null;
$this->studies = new \Doctrine\Common\Collections\ArrayCollection();
$this->orthancTransactions = new \Doctrine\Common\Collections\ArrayCollection();
}
}
public function __toString()
{
return $this->getOrthancPatientName();
}
/**
* Get id
*
* @return int
*/
public function getId()
{
return $this->id;
}
/**
* Set dicom_patient_name
*
* @param string $dicomPatientName
*
* @return Patient
*/
public function setDicomPatientName($dicomPatientName)
{
$this->dicom_patient_name = $dicomPatientName;
return $this;
}
/**
* Get dicom_patient_name
*
* @return string
*/
public function getDicomPatientName()
{
return $this->dicom_patient_name;
}
/**
* Set dicom_patient_id
*
* @param string $dicomPatientId
*
* @return Patient
*/
public function setDicomPatientId($dicomPatientId)
{
$this->dicom_patient_id = $dicomPatientId;
return $this;
}
/**
* Get dicom_patient_id
*
* @return string
*/
public function getDicomPatientId()
{
return $this->dicom_patient_id;
}
/**
* Set created
*
* @param \DateTime $created
*
* @return Patient
*/
public function setCreated($created)
{
$this->created = $created;
return $this;
}
/**
* Get created
*
* @return \DateTime
*/
public function getCreated()
{
return $this->created;
}
/**
* Set updated
*
* @param \DateTime $updated
*
* @return Patient
*/
public function setUpdated($updated)
{
$this->updated = $updated;
return $this;
}
/**
* Get updated
*
* @return \DateTime
*/
public function getUpdated()
{
return $this->updated;
}
/**
* Add studies
*
* @param Study $studies
*
* @return Patient
*/
public function addStudy(Study $studies)
{
$this->studies[] = $studies;
return $this;
}
/**
* Remove studies
*
* @param Study $studies
*/
public function removeStudy(Study $studies)
{
$this->studies->removeElement($studies);
}
/**
* Get studies
*
* @return \Doctrine\Common\Collections\Collection|Study[]
*/
public function getStudies()
{
return $this->studies;
}
/**
* Set project
*
* @param Project $project
*
* @return Patient
*/
public function setProject(Project $project)
{
$this->project = $project;
return $this;
}
/**
* Get project
*
* @return Project
*/
public function getProject()
{
return $this->project;
}
/**
* Set orthancPatientId
*
* @param string $orthancPatientId
*
* @return Patient
*/
public function setOrthancPatientId($orthancPatientId)
{
$this->orthanc_patient_id = $orthancPatientId;
return $this;
}
/**
* Get orthancPatientId
*
* @return string
*/
public function getOrthancPatientId()
{
return $this->orthanc_patient_id;
}
/**
* Add orthancTransaction
*
* @param OrthancTransaction $orthancTransaction
*
* @return Patient
*/
public function addOrthancTransaction(OrthancTransaction $orthancTransaction)
{
$this->orthancTransactions[] = $orthancTransaction;
// based on the type of the transaction, we run the appropriate function
// on this Patient
switch ($orthancTransaction->getType()) {
case OrthancTransaction::TYPE_PATIENT_DETAILS:
$this->processOrthancPatientDetailsTransaction($orthancTransaction);
break;
default:
throw new \Exception('Invalid OrthancTransaction Type Assigned to Patient: ' . $orthancTransaction->getType());
}
return $this;
}
/**
* Given the orthancTransaction (which is assumed to be of type PATIENT DETAILS)
* We update the appropriate values on this Patient to indicate the various
* orthanc data returned by the storage transaction.
*
* @todo at the moment we dont actually store any extra information on the
* Patient
*
* @param OrthancTransaction $orthancTransaction
*/
public function processOrthancPatientDetailsTransaction(OrthancTransaction $orthancTransaction)
{
// first - set the submissions status to pending at the outset
$this->setOrthancSyncStatus(self::ORTHANC_SYNC_STATUS_PENDING);
// if the given transaction wasn't a success, the storage status of this
// document is automatically also a fail
if ($orthancTransaction->getTransactionStatus() != OrthancTransaction::TRANSACTION_STATUS_SUCCESS) {
$this->setOrthancSyncStatus(self::ORTHANC_SYNC_STATUS_FAILED);
return false;
}
//$jsonObject = json_decode($orthancTransaction->getTransactionResponse());
//$this->setOrthancParentPatientId($jsonObject->ParentPatient);
// set the status as successful
$this->setOrthancSyncStatus(self::ORTHANC_SYNC_STATUS_SUCCESS);
}
/**
* Remove orthancTransaction
*
* @param OrthancTransaction $orthancTransaction
*/
public function removeOrthancTransaction(OrthancTransaction $orthancTransaction)
{
$this->orthancTransactions->removeElement($orthancTransaction);
}
/**
* Get orthancTransactions
*
* @return \Doctrine\Common\Collections\Collection
*/
public function getOrthancTransactions()
{
return $this->orthancTransactions;
}
/**
* Set orthancSyncStatus
*
* @param int $orthancSyncStatus
*
* @return Patient
*/
public function setOrthancSyncStatus($orthancSyncStatus)
{
$this->orthanc_sync_status = $orthancSyncStatus;
return $this;
}
/**
* Get orthancSyncStatus
*
* @return int
*/
public function getOrthancSyncStatus()
{
return $this->orthanc_sync_status;
}
/**
* Returns a Associative Array which is a json_decoded array from the latest Orthanc
* Transaction that performed a details request for this Patient
*
* @return array
*/
public function getOrthancDetails()
{
// get the latest successfull Patient Detals Transaction
$latestOrthancPatientDetailsTransaction = $this->getLatestOrthancPatientDetailsTransaction();
// if there isn't one, then we return null
if (!$latestOrthancPatientDetailsTransaction) {
return null;
}
// otherwise we return the json decoded response
$transactionResponse = $latestOrthancPatientDetailsTransaction->getTransactionResponse();
return json_decode($transactionResponse, true);
}
/**
* Returns the most recent Orthanc Patient Details Transaction linked to this
* Patient. If there is one, then it will contain all the details about
* this Patient that are currently stored in Orthanc
*
* @return mixed
*/
public function getLatestOrthancPatientDetailsTransaction()
{
// create some criteria that will find sucessful transactions of the
// appropriate type, ordered latest first
$criteria = Criteria::create()
->andWhere(Criteria::expr()->eq('transaction_status', OrthancTransaction::TRANSACTION_STATUS_SUCCESS))
->andWhere(Criteria::expr()->eq('type', OrthancTransaction::TYPE_PATIENT_DETAILS))
->orderBy(['created' => Criteria::DESC])
;
// apply the criteria
$matchingTransactions = $this->getOrthancTransactions()->matching($criteria);
// if there are not matches, then return null
if ($matchingTransactions->isEmpty()) {
return null;
}
// else return the first match
$firstMatchingTransaction = $matchingTransactions->first();
return $firstMatchingTransaction;
}
public function getOrthancPatientName()
{
// first prize is that this Patient has already been synced to Orthanc
// and the details have already been retrieved for this patient
$orthancDetails = $this->getOrthancDetails();
// if not then we need to at least return something
if (!$orthancDetails) {
return 'Unknown Patient';
}
// otherwise we assume that our Orthanc Details are structured correctly
// and we return the Patient Name
// note the leading ampersands which suppress notices, which we can't
// have in the __toString method;
$patientName = @$orthancDetails['MainDicomTags']['PatientName'] ?: @$orthancDetails['MainDicomTags']['PatientID'];
if (empty($patientName)) {
$patientName = 'No Patient Name';
}
return $patientName;
}
public function getOrthancDicomId()
{
// first prize is that this Patient has already been synced to Orthanc
// and the details have already been retrieved for this patient
$orthancDetails = $this->getOrthancDetails();
// if not then we need to at least return something
if (!$orthancDetails) {
return 'Unknown Patient';
}
// otherwise we assume that our Orthanc Details are structured correctly
// and we return the Patient Name
$patientId = $orthancDetails['MainDicomTags']['PatientID'];
if (empty($patientId)) {
$patientId = 'No Patient Id';
}
return $patientId;
}
/**
* Set deletedAt
*
* @param \DateTime $deletedAt
*
* @return Patient
*/
public function setDeletedAt($deletedAt)
{
$this->deletedAt = $deletedAt;
return $this;
}
/**
* Get deletedAt
*
* @return \DateTime
*/
public function getDeletedAt()
{
return $this->deletedAt;
}
}