<?php
namespace App\Entity\Content;
use App\Entity\EntityId;
use App\Entity\ObjectFileHandlingInterface;
use App\Entity\Redaktor\RedaktorPortraitImage;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\Finder\Finder;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Webmozart\Assert\Assert;
#[ORM\Entity]
#[ORM\Table(name: 'content')]
class Content implements ObjectFileHandlingInterface
{
public const int MAX_LENGTH_CONTENT_DESCRIPTION = 300;
public const int MAX_LENGTH_CODE = 32;
public const int MAX_WIDTH_IMAGE = 2048;
#[ORM\Column(name: 'code', type: 'string', length: 32, unique: true)]
private string $code;
#[ORM\Column(name: 'contentHtml', type: 'text', nullable: true)]
private ?string $contentHtml = null;
#[ORM\Column(name: 'content_html_editable', type: 'boolean', nullable: true)]
private bool $contentHtmlEditable = true;
#[ORM\Column(name: 'content_text', type: 'text', nullable: true)]
private ?string $contentText = null;
#[ORM\Column(name: 'content_text_editable', type: 'boolean', nullable: true)]
private ?bool $contentTextEditable = false;
#[ORM\Column(name: 'content_description', type: 'text', length: 300, nullable: true)]
private ?string $contentDescription = null;
#[ORM\Column(name: 'content_image', type: 'json', nullable: true)]
private ?array $contentImage = [];
#[ORM\Column(name: 'content_image_editable', type: 'boolean', nullable: true)]
private bool $contentImageEditable = false;
#[ORM\Column(name: 'edit_sysadmin_only', type: 'boolean', nullable: true)]
private bool $editSysadminOnly = true;
#[ORM\Column(name: 'is_visible_on_frontend', type: 'boolean', nullable: true)]
private bool $isVisibleOnFrontend = true;
#[ORM\Column(name: 'edit_at', type: 'datetime', nullable: false)]
private ?\DateTimeInterface $editAt = null;
public function __construct(
#[ORM\Id]
#[ORM\Column(name: 'id', type: 'entityId')]
#[ORM\GeneratedValue(strategy: 'NONE')]
private readonly EntityId $id)
{
$this->code = 'NEW_'.date('Ymd_His');
$this->setEditAtNow();
}
public function id(): EntityId
{
return $this->id;
}
public function changeConfig(array $options): void
{
$resolver = new OptionsResolver();
$resolver->setRequired([
'code',
'content_description',
'edit_sysadmin_only',
'content_image_editable',
'content_html_editable',
'content_text_editable',
]);
$options = $resolver->resolve($options);
$this->code = $options['code'];
$this->setContentDescription($options['content_description']);
$this->setEditSysadminOnly($options['edit_sysadmin_only']);
$this->setContentImageEditable($options['content_image_editable']);
$this->setContentHtmlEditable($options['content_html_editable']);
$this->setContentTextEditable($options['content_text_editable']);
$this->setEditAtNow();
}
public function change(array $options): void
{
$resolver = new OptionsResolver();
$resolver->setRequired('is_visible_on_frontend');
$resolver->setDefined(
[
'content_image',
'content_html',
'content_text',
]
);
$options = $resolver->resolve($options);
$this->setIsVisibleOnFrontend($options['is_visible_on_frontend']);
if (array_key_exists('content_image', $options)) {
$this->setContentImage($options['content_image']);
}
if (array_key_exists('content_html', $options)) {
$this->setContentHtml($options['content_html']);
}
if (array_key_exists('content_text', $options)) {
$this->setContentText($options['content_text']);
}
$this->setEditAtNow();
}
public function code(): string
{
return $this->code;
}
public function contentHtml(): ?string
{
return $this->contentHtml;
}
public function contentText(): ?string
{
return $this->contentText;
}
public function contentDescription(): ?string
{
return $this->contentDescription;
}
public function editSysadminOnly(): bool
{
return $this->editSysadminOnly;
}
public function contentImageEditable(): bool
{
return $this->contentImageEditable;
}
public function contentHtmlEditable(): bool
{
return $this->contentHtmlEditable;
}
public function contentTextEditable(): ?bool
{
return $this->contentTextEditable;
}
public function isVisibleOnFrontend(): bool
{
return $this->isVisibleOnFrontend;
}
public function editAt(): ?\DateTimeInterface
{
return $this->editAt;
}
private function setContentDescription(?string $contentDescription): void
{
Assert::maxLength($contentDescription, self::MAX_LENGTH_CONTENT_DESCRIPTION);
$this->contentDescription = $contentDescription;
}
private function setContentHtml(?string $contentHtml): void
{
$this->contentHtml = $contentHtml;
}
private function setContentHtmlEditable(bool $bool): void
{
Assert::boolean($bool);
$this->contentHtmlEditable = $bool;
}
private function setContentText(?string $contentText): void
{
$this->contentText = $contentText;
}
private function setContentTextEditable(bool $bool): void
{
Assert::boolean($bool);
$this->contentTextEditable = $bool;
}
private function setEditSysadminOnly(bool $editSysadminOnly): void
{
Assert::boolean($editSysadminOnly);
$this->editSysadminOnly = $editSysadminOnly;
}
private function setContentImageEditable(bool $bool): void
{
Assert::boolean($bool);
$this->contentImageEditable = $bool;
}
private function setIsVisibleOnFrontend(bool $isVisibleOnFrontend): void
{
Assert::boolean($isVisibleOnFrontend);
$this->isVisibleOnFrontend = $isVisibleOnFrontend;
}
private function setEditAtNow(): void
{
$this->editAt = new \DateTime();
}
private function setContentImage(ContentImage $image): void
{
$this->contentImage['filename'] = $image->getFilename();
$this->contentImage['alt'] = $image->getAlt();
$this->contentImage['caption'] = $image->getCaption();
$this->contentImage['click_url'] = $image->getClickUrl();
}
public function contentImage(): RedaktorPortraitImage|ContentImage
{
if ($this->contentImage && array_key_exists('filename', $this->contentImage)) {
$fileName = $this->contentImage['filename'];
$alt = array_key_exists('alt', $this->contentImage) ? $this->contentImage['alt'] : '';
$caption = array_key_exists('caption', $this->contentImage) ? $this->contentImage['caption'] : '';
$clickUrl = array_key_exists('click_url', $this->contentImage) ? $this->contentImage['click_url'] : '';
return ContentImage::create($fileName, $alt, $caption, $clickUrl, $this->baseObjectServerDirPath(), $this->baseObjectWebDirPath());
}
return ContentImage::createNonExistImage();
}
#[\Override]
public function baseObjectServerDirPath(): string
{
return __DIR__.'/../../../var/data/public/content/'.$this->id;
}
#[\Override]
public function baseObjectWebDirPath(): string
{
return '/data/content/'.$this->id;
}
#[\Override]
public function removeUnusedFiles(): void
{
$serverPath = $this->baseObjectServerDirPath();
// Auflistung aller effektiv benötigter Filenamen dieses Objects, damit diese erhalten bleiben
$usedFiles_ = [];
if ($this->contentImage()->getFilename()) {
$usedFiles_[] = $this->contentImage()->getFilename();
}
// Ende
// Lösche alle Files aus dem Objektverzeichnis, welche nicht im Objekt vorhanden sind
$fs = new Filesystem();
if ($fs->exists($serverPath)) {
$finder = new Finder();
$finder->files()->in($serverPath);
foreach ($finder as $file) {
if (!in_array($file->getFilename(), $usedFiles_)) {
$fs->remove($file->getRealPath());
}
}
}
// Ende
}
}