423 lines
9.7 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\MainBundle\Entity;
use Chill\MainBundle\Doctrine\Model\TrackUpdateInterface;
use DateTimeImmutable;
use DateTimeInterface;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
use function count;
use function in_array;
/**
* @ORM\Entity
* @ORM\Table(
* name="chill_main_notification",
* indexes={
* @ORM\Index(name="chill_main_notification_related_entity_idx", columns={"relatedentityclass", "relatedentityid"})
* }
* )
* @ORM\HasLifecycleCallbacks
*/
class Notification implements TrackUpdateInterface
{
/**
* @ORM\Column(type="text", nullable=false)
*/
private string $accessKey;
private array $addedAddresses = [];
/**
* @ORM\ManyToMany(targetEntity=User::class)
* @ORM\JoinTable(name="chill_main_notification_addresses_user")
*/
private Collection $addressees;
/**
* a list of destinee which will receive notifications.
*
* @var array|string[]
* @ORM\Column(type="json")
*/
private array $addressesEmails = [];
/**
* a list of emails adresses which were added to the notification.
*
* @var array|string[]
*/
private array $addressesEmailsAdded = [];
private ?ArrayCollection $addressesOnLoad = null;
/**
* @ORM\OneToMany(targetEntity=NotificationComment::class, mappedBy="notification", orphanRemoval=true)
* @ORM\OrderBy({"createdAt": "ASC"})
*/
private Collection $comments;
/**
* @ORM\Column(type="datetime_immutable")
*/
private DateTimeImmutable $date;
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
*/
private ?int $id = null;
/**
* @ORM\Column(type="text")
*/
private string $message = '';
/**
* @ORM\Column(type="string", length=255)
*/
private string $relatedEntityClass = '';
/**
* @ORM\Column(type="integer")
*/
private int $relatedEntityId;
private array $removedAddresses = [];
/**
* @ORM\ManyToOne(targetEntity=User::class)
* @ORM\JoinColumn(nullable=true)
*/
private ?User $sender = null;
/**
* @ORM\Column(type="text", options={"default": ""})
* @Assert\NotBlank(message="notification.Title must be defined")
*/
private string $title = '';
/**
* @ORM\ManyToMany(targetEntity=User::class)
* @ORM\JoinTable(name="chill_main_notification_addresses_unread")
*/
private Collection $unreadBy;
/**
* @ORM\Column(type="datetime_immutable")
*/
private ?DateTimeImmutable $updatedAt;
/**
* @ORM\ManyToOne(targetEntity=User::class)
*/
private ?User $updatedBy;
public function __construct()
{
$this->addressees = new ArrayCollection();
$this->unreadBy = new ArrayCollection();
$this->comments = new ArrayCollection();
$this->setDate(new DateTimeImmutable());
$this->accessKey = bin2hex(openssl_random_pseudo_bytes(24));
}
public function addAddressee(User $addressee): self
{
if (!$this->addressees->contains($addressee)) {
$this->addressees[] = $addressee;
$this->addedAddresses[] = $addressee;
}
return $this;
}
public function addAddressesEmail(string $email)
{
if (!in_array($email, $this->addressesEmails, true)) {
$this->addressesEmails[] = $email;
$this->addressesEmailsAdded[] = $email;
}
}
public function addComment(NotificationComment $comment): self
{
if (!$this->comments->contains($comment)) {
$this->comments[] = $comment;
$comment->setNotification($this);
}
return $this;
}
public function addUnreadBy(User $user): self
{
if (!$this->unreadBy->contains($user)) {
$this->unreadBy[] = $user;
}
return $this;
}
/**
* @Assert\Callback
*
* @param array $payload
*/
public function assertCountAddresses(ExecutionContextInterface $context, $payload): void
{
if (0 === (count($this->getAddressesEmails()) + count($this->getAddressees()))) {
$context->buildViolation('notification.At least one addressee')
->atPath('addressees')
->addViolation();
}
}
public function getAccessKey(): string
{
return $this->accessKey;
}
public function getAddedAddresses(): array
{
return $this->addedAddresses;
}
/**
* @return Collection|User[]
*/
public function getAddressees(): Collection
{
// keep a copy to compute changes later
if (null === $this->addressesOnLoad) {
$this->addressesOnLoad = new ArrayCollection($this->addressees->toArray());
}
return $this->addressees;
}
/**
* @return array|string[]
*/
public function getAddressesEmails(): array
{
return $this->addressesEmails;
}
/**
* @return array|string[]
*/
public function getAddressesEmailsAdded(): array
{
return $this->addressesEmailsAdded;
}
public function getComments(): Collection
{
return $this->comments;
}
public function getDate(): ?DateTimeImmutable
{
return $this->date;
}
public function getId(): ?int
{
return $this->id;
}
public function getMessage(): ?string
{
return $this->message;
}
public function getRelatedEntityClass(): ?string
{
return $this->relatedEntityClass;
}
public function getRelatedEntityId(): ?int
{
return $this->relatedEntityId;
}
public function getSender(): ?User
{
return $this->sender;
}
public function getTitle(): string
{
return $this->title;
}
public function getUnreadBy(): Collection
{
return $this->unreadBy;
}
public function getUpdatedAt(): ?DateTimeImmutable
{
return $this->updatedAt;
}
public function getUpdatedBy(): ?User
{
return $this->updatedBy;
}
public function isReadBy(User $user): bool
{
return !$this->unreadBy->contains($user);
}
public function isSystem(): bool
{
return null === $this->sender;
}
public function markAsReadBy(User $user): self
{
return $this->removeUnreadBy($user);
}
public function markAsUnreadBy(User $user): self
{
return $this->addUnreadBy($user);
}
/**
* @ORM\PreFlush
*/
public function registerUnread()
{
foreach ($this->addedAddresses as $addressee) {
$this->addUnreadBy($addressee);
}
foreach ($this->removedAddresses as $addressee) {
$this->removeAddressee($addressee);
}
if (null !== $this->addressesOnLoad) {
foreach ($this->addressees as $existingAddresse) {
if (!$this->addressesOnLoad->contains($existingAddresse)) {
$this->addUnreadBy($existingAddresse);
}
}
foreach ($this->addressesOnLoad as $onLoadAddressee) {
if (!$this->addressees->contains($onLoadAddressee)) {
$this->removeUnreadBy($onLoadAddressee);
}
}
}
$this->removedAddresses = [];
$this->addedAddresses = [];
$this->addressesOnLoad = null;
}
public function removeAddressee(User $addressee): self
{
if ($this->addressees->removeElement($addressee)) {
$this->removedAddresses[] = $addressee;
}
return $this;
}
public function removeAddressesEmail(string $email)
{
if (in_array($email, $this->addressesEmails, true)) {
$this->addressesEmails = array_filter($this->addressesEmails, static fn ($e) => $e !== $email);
$this->addressesEmailsAdded = array_filter($this->addressesEmailsAdded, static fn ($e) => $e !== $email);
}
}
public function removeComment(NotificationComment $comment): self
{
$this->comments->removeElement($comment);
return $this;
}
public function removeUnreadBy(User $user): self
{
$this->unreadBy->removeElement($user);
return $this;
}
public function setDate(DateTimeImmutable $date): self
{
$this->date = $date;
return $this;
}
public function setMessage(?string $message): self
{
$this->message = (string) $message;
return $this;
}
public function setRelatedEntityClass(string $relatedEntityClass): self
{
$this->relatedEntityClass = $relatedEntityClass;
return $this;
}
public function setRelatedEntityId(int $relatedEntityId): self
{
$this->relatedEntityId = $relatedEntityId;
return $this;
}
public function setSender(?User $sender): self
{
$this->sender = $sender;
return $this;
}
public function setTitle(?string $title): Notification
{
$this->title = (string) $title;
return $this;
}
public function setUpdatedAt(DateTimeInterface $datetime): self
{
$this->updatedAt = $datetime;
return $this;
}
public function setUpdatedBy(User $user): self
{
$this->updatedBy = $user;
return $this;
}
}