<?php
namespace App\Entity\ConversationMessage;
use App\Entity\AutomatedConversationMessagesMailing;
use App\Entity\DirectEmailCommunication\IncomingDirectEmailCommunicationMessage;
use App\Entity\DirectEmailCommunication\OutgoingDirectEmailCommunicationMessage;
use App\Entity\MobileApp\PushNotification;
use App\Entity\MultiConversationMessagesMailing;
use App\Entity\OccupationalField;
use App\Entity\Profile;
use App\Entity\Profile\JoboffererProfile;
use App\Entity\Profile\JobseekerProfile;
use App\Entity\RecurrentJob;
use App\Entity\Search\AbstractSearchBlockDefinition;
use App\Entity\WantedJob;
use App\Utility\DateTimeUtility;
use App\Utility\GuidUtility;
use DateTime;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Exception;
use InvalidArgumentException;
use Symfony\Component\Validator\Constraints as Assert;
/**
* @ORM\Entity
*
* @ORM\Table(
* name="conversation_messages",
* indexes={
*
* @ORM\Index(name="jobseeker_profiles_id_sent_at_idx", columns={"jobseeker_profiles_id", "sent_at"}),
* @ORM\Index(name="jobofferer_profiles_id_sent_at_idx", columns={"jobofferer_profiles_id", "sent_at"}),
* @ORM\Index(name="is_deleted_by_receiver_is_read_sent_at_idx", columns={"is_deleted_by_receiver", "is_read", "sent_at"}),
* @ORM\Index(name="jobseeker_profiles_id_unread_idx", columns={"jobseeker_profiles_id", "sender", "is_read", "is_deleted_by_receiver", "sent_at"}),
* @ORM\Index(name="jobofferer_profiles_id_unread_idx", columns={"jobofferer_profiles_id", "sender", "is_read", "is_deleted_by_receiver", "sent_at"}),
* @ORM\Index(name="read_deleted_by_receiver_automated_mailing_id_idx", columns={"is_read", "is_deleted_by_receiver", "automated_conversation_messages_mailings_id"})
* }
* )
*
* @ORM\Entity(repositoryClass="App\Repository\ConversationMessageRepository")
*/
class ConversationMessage
{
public const SENDER_JOBSEEKER = 0;
public const SENDER_JOBOFFERER = 1;
public const ASSERTION_SUBJECT_MIN_LENGTH = 2;
public const ASSERTION_SUBJECT_MAX_LENGTH = 255;
public const ASSERTION_BODY_MIN_LENGTH = 2;
public const ASSERTION_BODY_MAX_LENGTH = 8192;
public const MESSAGE_TYPE_PROFILE_MESSAGE = 1;
public const MESSAGE_TYPE_AUTOMATED_JOBRADAR_MESSAGE = 2;
public const MESSAGE_TYPE_OTHER_AUTOMATED_MESSAGE = 3;
public function __construct()
{
$this->subject = '';
$this->body = '';
$this->read = false;
$this->deletedBySender = false;
$this->deletedByReceiver = false;
$this->deletedBySenderAt = null;
$this->deletedByReceiverAt = null;
$this->sentAt = DateTimeUtility::createDateTimeUtc();
$this->isDirectApplied = false;
$this->conversationMessageAttachmentFiles = new ArrayCollection();
$this->occupationalField = null;
$this->relatedConversationMessage = null;
$this->relatedWantedJob = null;
$this->relatedRecurrentJob = null;
}
/**
* @var string
*
* @ORM\GeneratedValue(strategy="CUSTOM")
*
* @ORM\CustomIdGenerator(class="App\Utility\DatabaseIdGenerator")
*
* @ORM\Column(name="id", type="guid")
*
* @ORM\Id
*/
private $id;
public function setId(string $id)
{
GuidUtility::validOrThrow($id);
$this->id = $id;
}
public function getId()
{
return $this->id;
}
/**
* @var JobseekerProfile
*
* @ORM\ManyToOne(targetEntity="App\Entity\Profile\JobseekerProfile", inversedBy="conversationMessages", cascade={"persist"})
*
* @ORM\JoinColumn(name="jobseeker_profiles_id", referencedColumnName="id", nullable=false, onDelete="CASCADE")
*/
private $jobseekerProfile;
public function getJobseekerProfile(): JobseekerProfile
{
return $this->jobseekerProfile;
}
public function setJobseekerProfile(JobseekerProfile $jobseekerProfile)
{
$this->jobseekerProfile = $jobseekerProfile;
}
/**
* @var JoboffererProfile
*
* @ORM\ManyToOne(targetEntity="App\Entity\Profile\JoboffererProfile", inversedBy="conversationMessages", cascade={"persist"})
*
* @ORM\JoinColumn(name="jobofferer_profiles_id", referencedColumnName="id", nullable=false, onDelete="CASCADE")
*/
private $joboffererProfile;
public function getJoboffererProfile(): JoboffererProfile
{
return $this->joboffererProfile;
}
public function setJoboffererProfile(JoboffererProfile $joboffererProfile)
{
$this->joboffererProfile = $joboffererProfile;
}
/**
* @var int
*
* @ORM\Column(name="sender", type="smallint", nullable=false)
*/
private $sender;
public function getSender(): int
{
return $this->sender;
}
/** @throws Exception */
public function setSender(int $sender): void
{
if (!($sender === self::SENDER_JOBSEEKER || $sender === self::SENDER_JOBOFFERER)) {
throw new Exception('sender must be 0 or 1.');
}
$this->sender = $sender;
}
/**
* @var AutomatedConversationMessagesMailing
*
* @ORM\ManyToOne(targetEntity="App\Entity\AutomatedConversationMessagesMailing", inversedBy="conversationMessages", cascade={"persist"}, fetch="EXTRA_LAZY")
*
* @ORM\JoinColumn(name="automated_conversation_messages_mailings_id", referencedColumnName="id", nullable=true, onDelete="CASCADE")
*/
private $automatedConversationMessagesMailing;
public function getAutomatedConversationMessagesMailing(): ?AutomatedConversationMessagesMailing
{
return $this->automatedConversationMessagesMailing;
}
public function setAutomatedConversationMessagesMailing(AutomatedConversationMessagesMailing $automatedConversationMessagesMailing): void
{
$this->automatedConversationMessagesMailing = $automatedConversationMessagesMailing;
}
/** @var string|null
* @ORM\Column(name="block_in_which_acmm_found_result", type="string", length=255, nullable=true)
*/
private $blockNameInWhichAutomatedConversationMessagesMailingFoundResult;
public function getBlockNameInWhichAutomatedConversationMessagesMailingFoundResult(): ?string
{
return $this->blockNameInWhichAutomatedConversationMessagesMailingFoundResult;
}
public function setBlockNameInWhichAutomatedConversationMessagesMailingFoundResult(?AbstractSearchBlockDefinition $blockInWhichAutomatedConversationMessagesMailingFoundResult): void
{
if (!is_null($blockInWhichAutomatedConversationMessagesMailingFoundResult)) {
$this->blockNameInWhichAutomatedConversationMessagesMailingFoundResult = $blockInWhichAutomatedConversationMessagesMailingFoundResult->getName(
);
}
}
/**
* @var MultiConversationMessagesMailing
*
* @ORM\ManyToOne(targetEntity="App\Entity\MultiConversationMessagesMailing", inversedBy="conversationMessages", cascade={"persist"})
*
* @ORM\JoinColumn(name="multi_conversation_messages_mailings_id", referencedColumnName="id", nullable=true, onDelete="SET NULL")
*/
private $multiConversationMessagesMailing;
public function getMultiConversationMessagesMailing(): ?MultiConversationMessagesMailing
{
return $this->multiConversationMessagesMailing;
}
public function setMultiConversationMessagesMailing(MultiConversationMessagesMailing $multiConversationMessagesMailing): void
{
$this->multiConversationMessagesMailing = $multiConversationMessagesMailing;
}
/**
* @var OutgoingDirectEmailCommunicationMessage|null
*
* @ORM\OneToOne(targetEntity="App\Entity\DirectEmailCommunication\OutgoingDirectEmailCommunicationMessage", mappedBy="conversationMessage", cascade={"persist", "remove"})
*/
private $outgoingDirectEmailCommunicationMessage;
public function getOutgoingDirectEmailCommunicationMessage(): ?OutgoingDirectEmailCommunicationMessage
{
return $this->outgoingDirectEmailCommunicationMessage;
}
public function setOutgoingDirectEmailCommunicationMessage(?OutgoingDirectEmailCommunicationMessage $outgoingDirectEmailCommunicationMessage): void
{
$this->outgoingDirectEmailCommunicationMessage = $outgoingDirectEmailCommunicationMessage;
}
/**
* @var IncomingDirectEmailCommunicationMessage|null
*
* @ORM\OneToOne(targetEntity="App\Entity\DirectEmailCommunication\IncomingDirectEmailCommunicationMessage", mappedBy="conversationMessage", cascade={"persist", "remove"})
*/
private $incomingDirectEmailCommunicationMessage;
public function getIncomingDirectEmailCommunicationMessage(): ?IncomingDirectEmailCommunicationMessage
{
return $this->incomingDirectEmailCommunicationMessage;
}
public function setIncomingDirectEmailCommunicationMessage(?IncomingDirectEmailCommunicationMessage $incomingDirectEmailCommunicationMessage): void
{
$this->incomingDirectEmailCommunicationMessage = $incomingDirectEmailCommunicationMessage;
}
/**
* @var string
*
* @ORM\Column(name="subject", type="string", length=255, nullable=false)
*
* @Assert\NotBlank()
*
* @Assert\Length(
* min = ConversationMessage::ASSERTION_SUBJECT_MIN_LENGTH,
* max = ConversationMessage::ASSERTION_SUBJECT_MAX_LENGTH,
* )
*/
private $subject;
public function getSubject(): string
{
return $this->subject;
}
public function setSubject(string $subject): void
{
$this->subject = mb_substr($subject, 0, 255);
}
/**
* @var string
*
* @ORM\Column(name="body", type="string", length=8192, nullable=false)
*
* @Assert\NotBlank()
*
* @Assert\Length(
* min = ConversationMessage::ASSERTION_BODY_MIN_LENGTH,
* max = ConversationMessage::ASSERTION_BODY_MAX_LENGTH,
* )
*/
private $body;
public function getBody(): string
{
return $this->body;
}
public function setBody(string $body): void
{
$this->body = mb_substr($body, 0, 8192);
}
/**
* @var bool
*
* @ORM\Column(name="is_read", type="boolean", nullable=false)
*/
private $read;
public function isRead(): bool
{
return $this->read;
}
public function setRead(bool $read): void
{
$this->read = $read;
}
/**
* @var bool
*
* @ORM\Column(name="is_deleted_by_sender", type="boolean", nullable=false)
*/
private $deletedBySender;
public function isDeletedBySender(): bool
{
return $this->deletedBySender;
}
public function setDeletedBySender(bool $deletedBySender): void
{
$this->deletedBySender = $deletedBySender;
if ($deletedBySender === true) {
$this->deletedBySenderAt = DateTimeUtility::createDateTimeUtc();
} else {
$this->deletedBySenderAt = null;
}
}
/**
* @var bool
*
* @ORM\Column(name="is_deleted_by_receiver", type="boolean", nullable=false)
*/
private $deletedByReceiver;
public function isDeletedByReceiver(): bool
{
return $this->deletedByReceiver;
}
public function setDeletedByReceiver(bool $deletedByReceiver): void
{
$this->deletedByReceiver = $deletedByReceiver;
if ($deletedByReceiver === true) {
$this->deletedByReceiverAt = DateTimeUtility::createDateTimeUtc();
} else {
$this->deletedByReceiverAt = null;
}
}
/**
* @var ?DateTime
*
* @ORM\Column(name="deleted_by_sender_at", type="datetime", nullable=true)
*/
private $deletedBySenderAt;
public function getDeletedBySenderAt(): ?DateTime
{
return $this->deletedBySenderAt;
}
/**
* @var ?DateTime
*
* @ORM\Column(name="deleted_by_receiver_at", type="datetime", nullable=true)
*/
private $deletedByReceiverAt;
public function getDeletedByReceiverAt(): ?DateTime
{
return $this->deletedByReceiverAt;
}
/** @throws Exception */
public function isDeletedByOwner(Profile $ownerProfile): bool
{
if ($ownerProfile->isJobseeker() && ($this->jobseekerProfile->getId() !== $ownerProfile->getId())) {
throw new Exception("Message {$this->getId()} does not belong to jobseeker {$ownerProfile->getId()}.");
}
if ($ownerProfile->isJobofferer() && ($this->joboffererProfile->getId() !== $ownerProfile->getId())) {
throw new Exception("Message {$this->getId()} does not belong to jobofferer {$ownerProfile->getId()}.");
}
if ($this->isDeletedBySender() && $this->getSenderProfile()->getId() === $ownerProfile->getId()) {
return true;
}
if ($this->isDeletedByReceiver() && $this->getReceiverProfile()->getId() === $ownerProfile->getId()) {
return true;
}
return false;
}
/**
* @var bool
*
* @ORM\Column(name="is_direct_applied", type="boolean", nullable=false)
*/
private $isDirectApplied;
public function isDirectApplied(): bool
{
return $this->isDirectApplied;
}
public function setIsDirectApplied(bool $isDirectApplied): void
{
$this->isDirectApplied = $isDirectApplied;
}
/**
* @var DateTime
*
* @ORM\Column(name="sent_at", type="datetime", nullable=false)
*/
private $sentAt;
public function getSentAt(): DateTime
{
return $this->sentAt;
}
public function setSentAt(DateTime $sentAt): void
{
$this->sentAt = $sentAt;
}
/**
* @var ConversationMessageAttachmentFile|Collection
*
* @ORM\ManyToMany(targetEntity="App\Entity\ConversationMessage\ConversationMessageAttachmentFile", mappedBy="conversationMessages", cascade={"persist"})
*/
protected $conversationMessageAttachmentFiles;
public function setConversationMessageAttachmentFiles(Collection $conversationMessageAttachmentFiles)
{
$this->conversationMessageAttachmentFiles = $conversationMessageAttachmentFiles;
}
public function getConversationMessageAttachmentFiles(): Collection
{
return $this->conversationMessageAttachmentFiles;
}
public function isSender(Profile $profile): bool
{
if (($this->sender === self::SENDER_JOBSEEKER
&& $profile instanceof JobseekerProfile
&& $profile->getId() === $this->getJobseekerProfile()->getId())
|| ($this->sender === self::SENDER_JOBOFFERER
&& $profile instanceof JoboffererProfile
&& $profile->getId() === $this->getJoboffererProfile()->getId())
) {
return true;
} else {
return false;
}
}
public function isReceiver(Profile $profile): bool
{
if (($this->sender === self::SENDER_JOBOFFERER
&& $profile instanceof JobseekerProfile
&& $profile->getId() === $this->getJobseekerProfile()->getId())
|| ($this->sender === self::SENDER_JOBSEEKER
&& $profile instanceof JoboffererProfile
&& $profile->getId() === $this->getJoboffererProfile()->getId())
) {
return true;
} else {
return false;
}
}
/** @throws Exception */
public function getOppositeProfile(Profile $profile): Profile
{
if ($profile instanceof JobseekerProfile && $profile->getId() === $this->getJobseekerProfile()->getId()) {
return $this->getJoboffererProfile();
}
if ($profile instanceof JoboffererProfile && $profile->getId() === $this->getJoboffererProfile()->getId()) {
return $this->getJobseekerProfile();
}
throw new Exception('Profile id ' . $profile->getId() . ' does not belong to conversation message ' . $this->getId() . '.');
}
public function isAutomatedMessage(): bool
{
return !is_null($this->getAutomatedConversationMessagesMailing());
}
public function isAutomatedJobradarMessage(): bool
{
return $this->isAutomatedMessage() && $this->getAutomatedConversationMessagesMailing()->getMailingType() === AutomatedConversationMessagesMailing::MAILING_TYPE_JOBRADAR;
}
public function getSenderProfile(): Profile
{
if ($this->getSender() === self::SENDER_JOBOFFERER) {
return $this->getJoboffererProfile();
} else {
return $this->getJobseekerProfile();
}
}
public function getReceiverProfile(): Profile
{
if ($this->getSender() === self::SENDER_JOBOFFERER) {
return $this->getJobseekerProfile();
} else {
return $this->getJoboffererProfile();
}
}
public function canBeQuickReplied(): bool
{
return true;
}
public function isOutgoingDirectEmailCommunicationMessage(): bool
{
return !is_null($this->getOutgoingDirectEmailCommunicationMessage());
}
public function isIncomingDirectEmailCommunicationMessage(): bool
{
return !is_null($this->getIncomingDirectEmailCommunicationMessage());
}
public function __toString(): string
{
return (string)$this->getId();
}
/**
* @var ?OccupationalField occupationalField
*
* @ORM\ManyToOne(targetEntity="App\Entity\OccupationalField", cascade={"persist"})
*
* @ORM\JoinColumn(name="occupational_field_id", referencedColumnName="id", onDelete="SET NULL")
*/
private $occupationalField;
public function getOccupationalField(): ?OccupationalField
{
return $this->occupationalField;
}
public function setOccupationalField(?OccupationalField $occupationalField)
{
$this->occupationalField = $occupationalField;
}
/**
* @var ConversationMessage|null
*
* @ORM\ManyToOne(targetEntity="App\Entity\ConversationMessage\ConversationMessage", cascade={"persist"})
*
* @ORM\JoinColumn(name="related_conversation_messages_id", referencedColumnName="id", onDelete="SET NULL")
*/
private $relatedConversationMessage;
public function getRelatedConversationMessage(): ?ConversationMessage
{
return $this->relatedConversationMessage;
}
public function setRelatedConversationMessage(?ConversationMessage $relatedConversationMessage)
{
if (!is_null($relatedConversationMessage)) {
if ($relatedConversationMessage->getId() === $this->id) {
throw new InvalidArgumentException("Cannot set related conversation message for message {$this->id}, because the related message and this message are identical.");
}
}
$this->relatedConversationMessage = $relatedConversationMessage;
}
/**
* @var WantedJob|null
*
* @ORM\ManyToOne(targetEntity="App\Entity\WantedJob", cascade={"persist"})
*
* @ORM\JoinColumn(name="related_wanted_jobs_id", referencedColumnName="id", onDelete="SET NULL")
*/
private $relatedWantedJob;
public function getRelatedWantedJob(): ?WantedJob
{
if (is_null($this->relatedWantedJob)
&& is_null($this->getRelatedConversationMessage())
&& !is_null($this->getAutomatedConversationMessagesMailing())
&& !is_null($this->getJobseekerProfile())
) {
foreach ($this->getAutomatedConversationMessagesMailing()->getWantedJobs() as $wantedJob) {
if ($wantedJob->getJobseekerProfile()->getId() === $this->getJobseekerProfile()->getId()) {
return $wantedJob;
}
}
}
if (is_null($this->relatedWantedJob)
&& !is_null($this->getRelatedConversationMessage())
) {
return $this->getRelatedConversationMessage()->getRelatedWantedJob();
}
return $this->relatedWantedJob;
}
public function setRelatedWantedJob(?WantedJob $relatedWantedJob)
{
$this->relatedWantedJob = $relatedWantedJob;
}
/**
* @var RecurrentJob|null
*
* @ORM\ManyToOne(targetEntity="App\Entity\RecurrentJob", cascade={"persist"})
*
* @ORM\JoinColumn(name="related_recurrent_jobs_id", referencedColumnName="id", onDelete="SET NULL")
*/
private $relatedRecurrentJob;
public function getRelatedRecurrentJob(): ?RecurrentJob
{
if (is_null($this->relatedRecurrentJob) && is_null($this->getRelatedConversationMessage()) && !is_null($this->getAutomatedConversationMessagesMailing())) {
return $this->getAutomatedConversationMessagesMailing()->getRecurrentJob();
}
if (is_null($this->relatedRecurrentJob) && !is_null($this->getRelatedConversationMessage())) {
return $this->getRelatedConversationMessage()->getRelatedRecurrentJob();
}
return $this->relatedRecurrentJob;
}
public function setRelatedRecurrentJob(?RecurrentJob $relatedRecurrentJob)
{
$this->relatedRecurrentJob = $relatedRecurrentJob;
}
/**
* @var PushNotification[]|Collection
*
* @ORM\ManyToMany(targetEntity="App\Entity\MobileApp\PushNotification", mappedBy="relatedConversationMessages", cascade={"persist"})
*/
private $relatedPushNotifications;
}