mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-07-08 01:46:13 +00:00
481 lines
12 KiB
PHP
481 lines
12 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 Doctrine\Common\Collections\ArrayCollection;
|
|
use Doctrine\Common\Collections\Collection;
|
|
use Doctrine\DBAL\Types\Types;
|
|
use Doctrine\ORM\Mapping as ORM;
|
|
use Symfony\Component\Validator\Constraints as Assert;
|
|
use Symfony\Component\Validator\Context\ExecutionContextInterface;
|
|
|
|
#[ORM\Entity]
|
|
#[ORM\HasLifecycleCallbacks]
|
|
#[ORM\Table(name: 'chill_main_notification')]
|
|
#[ORM\Index(columns: ['relatedentityclass', 'relatedentityid'], name: 'chill_main_notification_related_entity_idx')]
|
|
class Notification implements TrackUpdateInterface
|
|
{
|
|
#[ORM\Column(type: Types::TEXT, nullable: false)]
|
|
private string $accessKey;
|
|
|
|
private array $addedAddresses = [];
|
|
|
|
/**
|
|
* @var Collection<int, User>
|
|
*/
|
|
#[ORM\ManyToMany(targetEntity: User::class)]
|
|
#[ORM\JoinTable(name: 'chill_main_notification_addresses_user')]
|
|
private Collection $addressees;
|
|
|
|
/**
|
|
* @var Collection<int, User>
|
|
*/
|
|
#[ORM\ManyToMany(targetEntity: UserGroup::class)]
|
|
#[ORM\JoinTable(name: 'chill_main_notification_addressee_user_group')]
|
|
private Collection $addresseeUserGroups;
|
|
|
|
/**
|
|
* @deprecated
|
|
* a list of destinee which will receive notifications
|
|
*
|
|
* @var array|string[]
|
|
*/
|
|
#[ORM\Column(type: Types::JSON, options: ['default' => '[]', 'jsonb' => true])]
|
|
private array $addressesEmails = [];
|
|
|
|
/**
|
|
* @deprecated
|
|
* a list of emails adresses which were added to the notification
|
|
*
|
|
* @var array|string[]
|
|
*/
|
|
private array $addressesEmailsAdded = [];
|
|
|
|
private ?ArrayCollection $addressesOnLoad = null;
|
|
|
|
/**
|
|
* @var Collection<int, NotificationComment>
|
|
*/
|
|
#[ORM\OneToMany(mappedBy: 'notification', targetEntity: NotificationComment::class, orphanRemoval: true)]
|
|
#[ORM\OrderBy(['createdAt' => \Doctrine\Common\Collections\Criteria::ASC])]
|
|
private Collection $comments;
|
|
|
|
#[ORM\Column(type: Types::DATETIME_IMMUTABLE)]
|
|
private \DateTimeImmutable $date;
|
|
|
|
#[ORM\Id]
|
|
#[ORM\GeneratedValue]
|
|
#[ORM\Column(type: Types::INTEGER)]
|
|
private ?int $id = null;
|
|
|
|
#[ORM\Column(type: Types::TEXT)]
|
|
private string $message = '';
|
|
|
|
#[ORM\Column(type: Types::STRING, length: 255)]
|
|
private string $relatedEntityClass = '';
|
|
|
|
#[ORM\Column(type: Types::INTEGER)]
|
|
private int $relatedEntityId;
|
|
|
|
private array $removedAddresses = [];
|
|
|
|
#[ORM\ManyToOne(targetEntity: User::class)]
|
|
#[ORM\JoinColumn(nullable: true)]
|
|
private ?User $sender = null;
|
|
|
|
#[Assert\NotBlank(message: 'notification.Title must be defined')]
|
|
#[ORM\Column(type: Types::TEXT, options: ['default' => ''])]
|
|
private string $title = '';
|
|
|
|
/**
|
|
* @var Collection<int, User>
|
|
*/
|
|
#[ORM\ManyToMany(targetEntity: User::class)]
|
|
#[ORM\JoinTable(name: 'chill_main_notification_addresses_unread')]
|
|
private Collection $unreadBy;
|
|
|
|
#[ORM\Column(type: Types::DATETIME_IMMUTABLE)]
|
|
private ?\DateTimeImmutable $updatedAt = null;
|
|
|
|
#[ORM\ManyToOne(targetEntity: User::class)]
|
|
private ?User $updatedBy = null;
|
|
|
|
#[ORM\Column(name: 'type', type: Types::STRING, nullable: true)]
|
|
private string $type;
|
|
|
|
public function __construct()
|
|
{
|
|
$this->addressees = new ArrayCollection();
|
|
$this->addresseeUserGroups = 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|UserGroup $addressee): self
|
|
{
|
|
if ($addressee instanceof User) {
|
|
if (!$this->addressees->contains($addressee)) {
|
|
$this->addressees->add($addressee);
|
|
|
|
return $this;
|
|
}
|
|
}
|
|
|
|
$this->addresseeUserGroups->add($addressee);
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* @deprecated
|
|
*/
|
|
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;
|
|
}
|
|
|
|
/**
|
|
* @param array $payload
|
|
*/
|
|
#[Assert\Callback]
|
|
public function assertCountAddresses(ExecutionContextInterface $context, $payload): void
|
|
{
|
|
if (0 === (\count($this->getAddresseeUserGroups()) + \count($this->getAddressees()))) {
|
|
$context->buildViolation('notification.At least one addressee')
|
|
->atPath('addressees')
|
|
->addViolation();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @return Collection<UserGroup>
|
|
*/
|
|
public function getAddresseeUserGroups(): Collection
|
|
{
|
|
return $this->addresseeUserGroups;
|
|
}
|
|
|
|
public function setAddresseeUserGroups(Collection $addresseeUserGroups): void
|
|
{
|
|
$this->addresseeUserGroups = $addresseeUserGroups;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
public function getAllAddressees(): array
|
|
{
|
|
$allUsers = [];
|
|
|
|
foreach ($this->getAddressees() as $user) {
|
|
$allUsers[$user->getId()] = $user;
|
|
}
|
|
|
|
foreach ($this->getAddresseeUserGroups() as $userGroup) {
|
|
foreach ($userGroup->getUsers() as $user) {
|
|
$allUsers[$user->getId()] = $user;
|
|
}
|
|
}
|
|
|
|
return array_values($allUsers);
|
|
}
|
|
|
|
/**
|
|
* @return array|string[]
|
|
*
|
|
* @deprecated
|
|
*/
|
|
public function getAddressesEmails(): array
|
|
{
|
|
return $this->addressesEmails;
|
|
}
|
|
|
|
/**
|
|
* @return array|string[]
|
|
*
|
|
* @deprecated
|
|
*/
|
|
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|UserGroup $addressee): self
|
|
{
|
|
if ($addressee instanceof User) {
|
|
if ($this->addressees->contains($addressee)) {
|
|
$this->addressees->removeElement($addressee);
|
|
|
|
return $this;
|
|
}
|
|
}
|
|
|
|
$this->addresseeUserGroups->removeElement($addressee);
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* @deprecated
|
|
*/
|
|
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;
|
|
}
|
|
|
|
public function setType(string $type): self
|
|
{
|
|
$this->type = $type;
|
|
|
|
return $this;
|
|
}
|
|
|
|
public function getType(): string
|
|
{
|
|
return $this->type;
|
|
}
|
|
|
|
public function isSendImmediately(User $user): bool
|
|
{
|
|
$notificationFlags = $user->getNotificationFlags();
|
|
$notificationType = $this->getType();
|
|
|
|
// Check if the user has a preference for this notification type
|
|
$emailPreference = $notificationFlags[$notificationType] ?? null;
|
|
|
|
return 'immediate-email' === $emailPreference;
|
|
}
|
|
}
|