<?php
namespace App\Entity;
use App\Filter\ChatThreadFilter;
use Doctrine\ORM\Mapping as ORM;
use App\Repository\ChatThreadRepository;
use ApiPlatform\Core\Annotation\ApiFilter;
use App\Entity\Traits\TimestampableEntity;
use Doctrine\Common\Collections\Collection;
use ApiPlatform\Core\Annotation\ApiProperty;
use ApiPlatform\Core\Annotation\ApiResource;
use App\Entity\Interfaces\OwnerMappedInterface;
use Doctrine\Common\Collections\ArrayCollection;
use App\Entity\Interfaces\ContainerMappedInterface;
use Symfony\Component\Serializer\Annotation\Groups;
use Symfony\Component\Validator\Constraints as Assert;
use ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\OrderFilter;
use ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\SearchFilter;
/**
* @ApiResource(
* normalizationContext={"groups"={"ChatThread:Read"}, "skip_null_values"=false},
* denormalizationContext={"groups"={"ChatThread:Write"}},
* collectionOperations={
* "get"={
* "security"="is_granted('IS_AUTHENTICATED_FULLY')",
* "normalization_context"={"groups"={"ChatThread:Read", "ChatThread:MuteNotification"}, "skip_null_values"=false}
* },
* "get_my"={
* "path"="/chat_threads/get-my",
* "method"="GET",
* "normalization_context"={"groups"={"ChatThread:Read", "ChatThread:MuteNotification"}, "skip_null_values"=false},
* "security"="is_granted('IS_AUTHENTICATED_FULLY')"
* },
* "post"={"security"="is_granted('IS_AUTHENTICATED_FULLY')"}
* },
* itemOperations={
* "get"={"security"="is_granted('IS_CO_ANY_SPE_CHATTHREAD', object)"},
* "put"={"security"="is_granted('IS_CO_ANY_SPE_CHATTHREAD', object)"},
* "patch"={"security"="is_granted('IS_CO_ANY_SPE_CHATTHREAD', object)"},
* "patch_mute"={
* "route_name"="api_chat_threads_mute",
* "method"="PATCH",
* "security"="is_granted('IS_CO_ANY_SPE_CHATTHREAD', object)",
* "denormalization_context"={"groups"={"ChatThread:Mute"}}
* },
* "patch_leave_group"={
* "route_name"="api_chat_threads_leave_group",
* "method"="PATCH",
* "security"="is_granted('IS_CO_ANY_SPE_CHATTHREAD', object)",
* "denormalization_context"={"groups"={"ChatThread:LeaveGroup"}}
* },
* "delete"={"security"="is_granted('IS_CO_ANY_SPE_CHATTHREAD', object)"}
* }
* )
* @ApiFilter(SearchFilter::class, properties={"container.id": "exact", "name": "partial", "status": "exact", "threadType": "exact", "owner.id", "exact"})
* @ApiFilter(OrderFilter::class, properties={"id": "ASC", "lastMessageAt", "createdAt", "updatedAt"})
* @ApiFilter(ChatThreadFilter::class, properties={"search": "partial"})
* @ORM\Entity(repositoryClass=ChatThreadRepository::class)
*/
class ChatThread implements ContainerMappedInterface
{
/**
* Hook timestampable behavior
* updates createdAt, updatedAt fields
*/
use TimestampableEntity;
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
* @Groups({"ChatThread:Read"})
*/
private $id;
/**
* @ORM\Column(type="string", length=128)
* @Groups({"ChatThread:Read", "ChatThread:Write"})
*
* @Assert\NotBlank(message="validation.chatThread:name.notBlank")
* @Assert\Length(max=128, maxMessage="validation.chatThread:name.max")
*/
private $name;
/**
* @ORM\Column(type="string", length=32)
* @ApiProperty(
* attributes={
* "openapi_context"={
* "type"="string",
* "enum"={self::THREAD_TYPE_O2O, self::THREAD_TYPE_GROUP}
* }
* }
* )
* @Groups({"ChatThread:Read", "ChatThread:Write"})
*
* @Assert\NotBlank(message="validation.chatThread:threadType.notBlank")
* @Assert\Length(max=32, maxMessage="validation.chatThread:threadType.max")
* @Assert\Choice({self::THREAD_TYPE_O2O, self::THREAD_TYPE_GROUP})
*/
public $threadType;
public const THREAD_TYPE_O2O = 'O2O';
public const THREAD_TYPE_GROUP = 'GROUP';
/**
* @ORM\Column(type="string", length=32)
* @ApiProperty(
* attributes={
* "openapi_context"={
* "type"="string",
* "enum"={self::STATUS_NEW, self::STATUS_ARCHIVED}
* }
* }
* )
* @Groups({"ChatThread:Read", "ChatThread:Write"})
*
* @Assert\NotBlank(message="validation.chatThread:status.notBlank")
* @Assert\Length(max=32, maxMessage="validation.chatThread:status.max")
* @Assert\Choice({self::STATUS_NEW, self::STATUS_ARCHIVED})
*/
private $status;
public const STATUS_NEW = 'NEW';
public const STATUS_ARCHIVED = 'ARCHIVED';
/**
* @ORM\ManyToOne(targetEntity=Container::class)
* @ORM\JoinColumn(nullable=false, onDelete="CASCADE")
* @Groups({"ChatThread:Read", "ChatThread:Write"})
*/
private $container;
/**
* @ORM\ManyToMany(targetEntity=User::class, inversedBy="chatThreads")
* @Groups({"ChatThread:Read", "ChatThread:Write"})
*/
private $users;
/**
* @ORM\OneToMany(targetEntity=ChatMessage::class, mappedBy="chatThread")
*/
private $chatMessages;
/**
* @ORM\Column(type="datetime", nullable=true)
* @Groups({"ChatThread:Read"})
*/
private $lastMessageAt;
/**
* @ORM\ManyToOne(targetEntity=User::class)
* @ORM\JoinColumn(nullable=true, onDelete="CASCADE")
* @Groups({"ChatThread:Read", "ChatThread:Write"})
*/
public $owner;
/**
* @ORM\OneToMany(targetEntity=MuteThreadNotification::class, mappedBy="chatThread", orphanRemoval=true, cascade={"persist"})
* @Groups({"ChatThread:MuteNotification"})
*/
private $muteThreadNotifications;
private $newUsers;
public function __construct()
{
$this->users = new ArrayCollection();
$this->chatMessages = new ArrayCollection();
$this->muteThreadNotifications = new ArrayCollection();
}
public function getId(): ?int
{
return $this->id;
}
public function getName()
{
return $this->name;
}
public function setName($name)
{
$this->name = $name;
return $this;
}
public function getThreadType()
{
return $this->threadType;
}
public function setThreadType($threadType)
{
$this->threadType = $threadType;
return $this;
}
public function getStatus(): ?string
{
return $this->status;
}
public function setStatus(string $status): self
{
$this->status = $status;
return $this;
}
public function getContainer(): ?Container
{
return $this->container;
}
public function setContainer(?Container $container): self
{
$this->container = $container;
return $this;
}
/**
* @return Collection|User[]
*/
public function getUsers(): Collection
{
return $this->users;
}
public function addUser(User $user): self
{
$nu = [];
if (!$this->users->contains($user)) {
$this->users[] = $user;
$nu[] = $user->getId();
}
$this->setNewUsers($nu);
return $this;
}
public function removeUser(User $user): self
{
$this->users->removeElement($user);
return $this;
}
/**
* @return Collection|ChatMessage[]
*/
public function getChatMessages(): Collection
{
return $this->chatMessages;
}
public function addChatMessage(ChatMessage $chatMessage): self
{
if (!$this->chatMessages->contains($chatMessage)) {
$this->chatMessages[] = $chatMessage;
$chatMessage->setSession($this);
}
return $this;
}
public function removeChatMessage(ChatMessage $chatMessage): self
{
if ($this->chatMessages->removeElement($chatMessage)) {
// set the owning side to null (unless already changed)
if ($chatMessage->getSession() === $this) {
$chatMessage->setSession(null);
}
}
return $this;
}
public function getLastMessageAt(): ?\DateTimeInterface
{
return $this->lastMessageAt;
}
public function setLastMessageAt(?\DateTimeInterface $lastMessageAt): self
{
$this->lastMessageAt = $lastMessageAt;
return $this;
}
public function getOwner(): ?User
{
return $this->owner;
}
public function setOwner(?User $owner): self
{
$this->owner = $owner;
return $this;
}
/**
* @return Collection<int, MuteThreadNotification>
*/
public function getMuteThreadNotifications(): Collection
{
return $this->muteThreadNotifications;
}
public function addMuteThreadNotification(MuteThreadNotification $muteThreadNotification): self
{
if (!$this->muteThreadNotifications->contains($muteThreadNotification)) {
$this->muteThreadNotifications[] = $muteThreadNotification;
$muteThreadNotification->setChatThread($this);
}
return $this;
}
public function removeMuteThreadNotification(MuteThreadNotification $muteThreadNotification): self
{
if ($this->muteThreadNotifications->removeElement($muteThreadNotification)) {
// set the owning side to null (unless already changed)
if ($muteThreadNotification->getChatThread() === $this) {
$muteThreadNotification->setChatThread(null);
}
}
return $this;
}
public function isUserMuteThreadNotification(User $user): bool
{
foreach ($this->muteThreadNotifications as $mn) {
if ($mn->getUser()->getId() === $user->getId()) {
return true;
}
}
return false;
}
public function getNewUsers()
{
return $this->newUsers;
}
public function setNewUsers($newUsers)
{
$this->newUsers = $newUsers;
return $this;
}
}