<?php
namespace App\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping as ORM;
use Gedmo\Mapping\Annotation as Gedmo;
/**
* @ORM\Entity
* @ORM\Table(name="categoria_foro")
*/
class CategoriaForo
{
/**
* @ORM\Id
* @ORM\Column(type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @ORM\Column(type="string", nullable=false)
*/
private $nombre;
/**
* @ORM\Column(type="text", nullable=true)
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $descripcion;
/**
* @ORM\Column(type="string", unique=true, nullable=true)
* @Gedmo\Slug(fields={"nombre"})
*/
private $slug;
/**
* @ORM\Column(type="integer", nullable=true, options={"default":0})
*/
private $ordenacion;
/**
* @ORM\Column(type="boolean", nullable=true, options={"default":true})
*/
private $activa;
/**
* @ORM\Column(type="datetime", nullable=true, name="deleted_at")
*/
private $deletedAt;
/**
* @ORM\Column(type="datetime", nullable=false, name="updated_at", options={"default":"2024-01-01 00:00:00"})
* @Gedmo\Timestampable(on="update")
*/
private $updatedAt;
/**
* @ORM\Column(type="datetime", nullable=false, name="created_at", options={"default":"2024-01-01 00:00:00"})
* @Gedmo\Timestampable(on="create")
*/
private $createdAt;
/**
* Roles permitidos para ver esta categoría
* @ORM\Column(type="json", nullable=true, name="roles_permitidos")
*/
private ?array $rolesPermitidos = [];
/**
* Relación jerárquica - Categoría padre
* @ORM\ManyToOne(targetEntity=\App\Entity\CategoriaForo::class, inversedBy="subcategorias")
* @ORM\JoinColumn(name="categoria_padre_id", referencedColumnName="id")
*/
private $categoriaPadre;
/**
* Relación jerárquica - Subcategorías
* @ORM\OneToMany(targetEntity=\App\Entity\CategoriaForo::class, mappedBy="categoriaPadre", cascade={"persist"})
* @ORM\OrderBy({"ordenacion":"ASC","nombre":"ASC"})
*/
private $subcategorias;
/**
* @ORM\OneToMany(targetEntity=\App\Entity\Tema::class, mappedBy="categoriaForo")
* @ORM\OrderBy({"updatedAt":"DESC"})
*/
private $temas;
public function __construct()
{
$this->subcategorias = new ArrayCollection();
$this->temas = new ArrayCollection();
$this->activa = true;
$this->ordenacion = 0;
}
public function __toString(): string
{
return $this->getNombre() ?? '--';
}
public function getId(): ?int
{
return $this->id;
}
public function setId($id)
{
$this->id = $id;
return $this;
}
public function getNombre(): ?string
{
return $this->nombre;
}
public function setNombre(string $nombre): static
{
$this->nombre = $nombre;
return $this;
}
public function getDescripcion(): ?string
{
return $this->descripcion;
}
public function setDescripcion(?string $descripcion): static
{
$this->descripcion = $descripcion;
return $this;
}
public function getSlug(): ?string
{
return $this->slug;
}
public function setSlug(?string $slug): static
{
$this->slug = $slug;
return $this;
}
public function getOrdenacion(): ?int
{
return $this->ordenacion;
}
public function setOrdenacion(?int $ordenacion): static
{
$this->ordenacion = $ordenacion;
return $this;
}
public function isActiva(): bool
{
return $this->activa ?? true;
}
public function setActiva(?bool $activa): static
{
$this->activa = $activa;
return $this;
}
public function getDeletedAt(): ?\DateTimeInterface
{
return $this->deletedAt;
}
public function setDeletedAt(?\DateTimeInterface $deletedAt): static
{
$this->deletedAt = $deletedAt;
return $this;
}
public function getUpdatedAt(): ?\DateTimeInterface
{
return $this->updatedAt;
}
public function setUpdatedAt(\DateTimeInterface $updatedAt): static
{
$this->updatedAt = $updatedAt;
return $this;
}
public function getCreatedAt(): ?\DateTimeInterface
{
return $this->createdAt;
}
public function setCreatedAt(\DateTimeInterface $createdAt): static
{
$this->createdAt = $createdAt;
return $this;
}
public function getCategoriaPadre(): ?self
{
return $this->categoriaPadre;
}
public function setCategoriaPadre(?self $categoriaPadre): static
{
$this->categoriaPadre = $categoriaPadre;
return $this;
}
/**
* @return Collection<int, CategoriaForo>
*/
public function getSubcategorias(): Collection
{
return $this->subcategorias;
}
public function addSubcategoria(CategoriaForo $subcategoria): static
{
if (!$this->subcategorias->contains($subcategoria)) {
$this->subcategorias->add($subcategoria);
$subcategoria->setCategoriaPadre($this);
}
return $this;
}
public function removeSubcategoria(CategoriaForo $subcategoria): static
{
if ($this->subcategorias->removeElement($subcategoria)) {
if ($subcategoria->getCategoriaPadre() === $this) {
$subcategoria->setCategoriaPadre(null);
}
}
return $this;
}
/**
* @return Collection<int, Tema>
*/
public function getTemas(): Collection
{
return $this->temas;
}
public function addTema(Tema $tema): static
{
if (!$this->temas->contains($tema)) {
$this->temas->add($tema);
$tema->setCategoriaForo($this);
}
return $this;
}
public function removeTema(Tema $tema): static
{
if ($this->temas->removeElement($tema)) {
if ($tema->getCategoriaForo() === $this) {
$tema->setCategoriaForo(null);
}
}
return $this;
}
/**
* Métodos helper para la jerarquía
*/
public function esCategoriaPadre(): bool
{
return $this->categoriaPadre === null;
}
public function esSubcategoria(): bool
{
return $this->categoriaPadre !== null;
}
public function tieneSubcategorias(): bool
{
return $this->subcategorias->count() > 0;
}
public function getNivel(): int
{
$nivel = 0;
$categoria = $this;
while ($categoria->getCategoriaPadre() !== null) {
$nivel++;
$categoria = $categoria->getCategoriaPadre();
}
return $nivel;
}
public function getNumeroTemas(): int
{
return $this->temas->count();
}
public function getNumeroTemasTotal(): int
{
$total = $this->getNumeroTemas();
foreach ($this->subcategorias as $subcategoria) {
$total += $subcategoria->getNumeroTemasTotal();
}
return $total;
}
/**
* Get roles permitidos para esta categoría
*/
public function getRolesPermitidos(): ?array
{
return $this->rolesPermitidos;
}
/**
* Set roles permitidos para esta categoría
*/
public function setRolesPermitidos(?array $rolesPermitidos): static
{
$this->rolesPermitidos = $rolesPermitidos;
return $this;
}
/**
* Verifica si un array de roles tiene acceso a esta categoría
*/
public function tieneAcceso(array $userRoles): bool
{
// Si no hay roles específicos configurados, la categoría es pública
if (empty($this->rolesPermitidos)) {
return true;
}
// Verificar si hay al menos un rol en común
return !empty(array_intersect($userRoles, $this->rolesPermitidos));
}
/**
* Verifica si la categoría es pública (sin restricciones de roles)
*/
public function esPublica(): bool
{
return empty($this->rolesPermitidos);
}
/**
* Obtiene los labels de los roles permitidos para mostrar en interfaz
*/
public function getRolesPermitidosLabels(): array
{
if (empty($this->rolesPermitidos)) {
return ['Pública (todos los roles)'];
}
$labels = [];
foreach ($this->rolesPermitidos as $rol) {
$labels[] = \App\Enum\RolEnum::getLabel($rol);
}
return $labels;
}
/**
* Obtiene los roles permitidos como string para mostrar
*/
public function getRolesPermitidosString(): string
{
$labels = $this->getRolesPermitidosLabels();
return implode(', ', $labels);
}
}