<?php
namespace App\Entity;
use App\Repository\WorkroomChatMessageRepository;
use Doctrine\ORM\Mapping as ORM;
/**
* Message du chat workroom (= panneau "Messagerie" en bas-droite des
* sections workroom). Remplace l'ancienne entité {@see Chat} basée sur un
* unique BLOB HTML géré par CKEditor Cloud Services.
*
* Architecture nouveau chat (Phase 23) :
* - Storage : 1 ligne par message (pas de blob)
* - Presence : éphémère via Mercure, pas de table
* - Auth : membre du workroom (voter `WorkroomVoter::WORKROOM_VIEW`)
* - Realtime : Mercure SSE topic `/workroom/{uuid}/chat`
*/
#[ORM\Entity(repositoryClass: WorkroomChatMessageRepository::class)]
#[ORM\Table(name: 'workroom_chat_message')]
#[ORM\Index(name: 'idx_workroom_created', columns: ['workroom_id', 'created_at'])]
#[ORM\Index(name: 'idx_arena_created', columns: ['workroom_arena_id', 'created_at'])]
class WorkroomChatMessage
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column(type: 'integer')]
private ?int $id = null;
/**
* Container du chat : exactement UN des deux est non-null.
* - workroom : chat partagé du workroom (= panneau "Messagerie")
* - workroomArena : chat scopé à une arène (fork) — conversation
* séparée du chat du workroom parent
*/
#[ORM\ManyToOne(targetEntity: Workroom::class)]
#[ORM\JoinColumn(nullable: true, onDelete: 'CASCADE')]
private ?Workroom $workroom = null;
#[ORM\ManyToOne(targetEntity: WorkroomArena::class)]
#[ORM\JoinColumn(name: 'workroom_arena_id', nullable: true, onDelete: 'CASCADE')]
private ?WorkroomArena $workroomArena = null;
#[ORM\ManyToOne(targetEntity: User::class)]
#[ORM\JoinColumn(nullable: false, onDelete: 'CASCADE')]
private ?User $user = null;
/** Cap à 4000 chars — au-delà l'utilisateur passe par un commentaire de
* section. Pas de markdown / HTML rich → texte brut, escape côté front. */
#[ORM\Column(type: 'string', length: 4000)]
private string $text = '';
#[ORM\Column(type: 'datetime_immutable')]
private \DateTimeImmutable $createdAt;
public function __construct()
{
$this->createdAt = new \DateTimeImmutable();
}
public function getId(): ?int { return $this->id; }
public function getWorkroom(): ?Workroom { return $this->workroom; }
public function setWorkroom(?Workroom $w): self { $this->workroom = $w; return $this; }
public function getWorkroomArena(): ?WorkroomArena { return $this->workroomArena; }
public function setWorkroomArena(?WorkroomArena $a): self { $this->workroomArena = $a; return $this; }
public function getUser(): ?User { return $this->user; }
public function setUser(User $u): self { $this->user = $u; return $this; }
public function getText(): string { return $this->text; }
public function setText(string $t): self
{
$this->text = mb_substr(trim($t), 0, 4000);
return $this;
}
public function getCreatedAt(): \DateTimeImmutable { return $this->createdAt; }
public function toArray(): array
{
return [
'id' => $this->id,
'text' => $this->text,
'user' => $this->user ? [
'id' => $this->user->getId(),
'firstName' => $this->user->getFirstName(),
'lastName' => $this->user->getLastName(),
] : null,
'createdAt' => $this->createdAt->format(\DateTimeInterface::ATOM),
];
}
}