<?php
namespace App\Entity\Menu;
use App\Entity\Menu;
use App\Entity\Page;
use App\Entity\Utils\Traits\PositionTrait;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\Common\Collections\Criteria;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\ORM\PersistentCollection;
use Symfony\Component\Validator\Constraints as Assert;
/**
* Class Item.
*/
#[ORM\Table(name: 'menu_item')]
#[ORM\Entity(repositoryClass: \App\Repository\Menu\ItemRepository::class)]
class Item
{
use PositionTrait;
final public const TYPE_PAGE = 'page';
final public const TYPE_CUSTOM = 'custom';
final public const TARGET_SELF = '_self';
final public const TARGET_BLANK = '_blank';
/**
* Id.
*/
#[ORM\Id]
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::INTEGER)]
#[ORM\GeneratedValue]
protected ?int $id = null;
/**
* Type.
*/
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING, length: 255)]
#[Assert\NotBlank(message: 'form.error.required')]
protected string $label;
/**
* Type.
*/
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING, length: 255)]
#[Assert\NotBlank(message: 'form.error.required')]
protected string $type;
/**
* Target.
*/
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING, length: 255)]
#[Assert\NotBlank(message: 'form.error.required')]
protected string $target;
/**
* Link.
*/
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING, length: 255, nullable: true)]
#[Assert\Length(max: 255, maxMessage: 'form.error.long')]
#[Assert\Regex(pattern: '/^(https?:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?$/', match: true, message: 'form.error.link')]
protected ?string $link = null;
/**
* Class.
*/
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING, length: 255, nullable: true)]
#[Assert\Length(max: 255, maxMessage: 'form.error.long')]
protected ?string $class = null;
#[ORM\ManyToOne(targetEntity: \App\Entity\Page::class, inversedBy: 'menuItems', cascade: ['persist'])]
#[ORM\JoinColumn(name: 'page_id')]
protected ?Page $page = null;
#[ORM\ManyToOne(targetEntity: \App\Entity\Menu::class, inversedBy: 'items', cascade: ['all'])]
#[ORM\JoinColumn(name: 'menu_id')]
protected ?Menu $menu = null;
/**
* Children.
*/
#[ORM\OneToMany(targetEntity: 'Item', mappedBy: 'parent', cascade: ['all'], orphanRemoval: true)]
protected Collection $children;
/**
* Master.
*/
#[ORM\ManyToOne(targetEntity: 'Item', inversedBy: 'children', cascade: ['all'])]
#[ORM\JoinColumn(name: 'parent_id', onDelete: 'CASCADE')]
protected ?Item $parent = null;
protected array $tmpData;
/**
* Item constructor.
*/
public function __construct()
{
$this->children = new ArrayCollection();
}
public function setId(int $id): void
{
$this->id = $id;
}
public function getId(): int
{
return $this->id;
}
public function getLabel(): string
{
return $this->label;
}
public function setLabel(string $label): void
{
$this->label = $label;
}
public function getType(): string
{
return $this->type;
}
public function setType(string $type): void
{
$this->type = $type;
}
public function getTarget(): string
{
return $this->target;
}
public function setTarget(string $target): void
{
$this->target = $target;
}
public function getLink(): ?string
{
return $this->link;
}
public function setLink(?string $link): void
{
$this->link = $link;
}
public function getClass(): ?string
{
return $this->class;
}
public function setClass(?string $class): void
{
$this->class = $class;
}
public function getPage(): ?Page
{
return $this->page;
}
public function setPage(Page $page = null): void
{
$this->page = $page;
}
public function getMenu(): Menu
{
return $this->menu;
}
public function setMenu(?Menu $menu = null): void
{
$this->menu = $menu;
}
public function getChildren(): Collection
{
return $this->children;
}
public function addChild(Item $child): void
{
$this->children[] = $child;
$child->setParent($this);
}
public function removeChild(Item $child): void
{
$this->children->removeElement($child);
$child->setParent(null);
}
public function removeAllChildren(): void
{
foreach ($this->children as $child) {
$this->removeChild($child);
}
}
public function hasChildren(): int
{
return count($this->children);
}
public function isRoot(): bool
{
return !$this->parent;
}
public function getParent(): Item
{
return $this->parent;
}
public function setParent(?Item $parent = null): void
{
$this->parent = $parent;
}
public function getArrayData(): array
{
$children = [];
if (count($this->children)) {
/** @var Item $child */
foreach ($this->children as $child) {
$children[] = $child->getArrayData();
}
}
return [
'id' => $this->id,
'label' => $this->label,
'type' => $this->type,
'target' => $this->target,
'page' => $this->page?->getId(),
'link' => $this->link,
'position' => $this->position,
'class' => $this->class,
'children' => $children,
];
}
public function setArrayData(array $data): void
{
$this->removeAllChildren();
$this->children->clear();
$cpt = 0;
if (isset($data['children'])) {
foreach ($data['children'] as $childData) {
$child = new Item();
$child->setArrayData($childData);
$child->setPosition($cpt);
$this->addChild($child);
++$cpt;
}
}
$this->setLabel($data['label']);
$this->setType($data['type']);
$this->setTarget($data['target']);
$this->setLink($data['link'] ?? null);
$this->setPosition($data['position'] ?? 0);
$this->setClass($data['class'] ?? null);
$this->setTmpData([
'page' => $data['page'] ?? null,
]);
}
public function reorderChildren(string $field): void
{
/** @var PersistentCollection $children */
$children = $this->children;
if (!$children->isInitialized()) {
$children->initialize();
}
$criteria = Criteria::create()
->orderBy([$field => Criteria::ASC]);
$children = $children->matching($criteria);
if (!$this->children->isInitialized()) {
$this->children->initialize();
}
$this->children->clear();
/** @var Item $child */
foreach ($children as $key => $child) {
$this->children->set($key, $child);
}
}
public function getTmpData(): array
{
return $this->tmpData;
}
public function setTmpData(array $tmpData): void
{
$this->tmpData = $tmpData;
}
}