332 lines
8.1 KiB
PHP

<?php
declare(strict_types=1);
/*
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\DocStoreBundle\Entity;
use Chill\DocStoreBundle\Validator\Constraints\AsyncFileExists;
use ChampsLibres\WopiLib\Contract\Entity\Document;
use Chill\DocGeneratorBundle\Entity\DocGeneratorTemplate;
use Chill\MainBundle\Doctrine\Model\TrackCreationInterface;
use Chill\MainBundle\Doctrine\Model\TrackCreationTrait;
use Doctrine\ORM\Mapping as ORM;
use Ramsey\Uuid\Uuid;
use Ramsey\Uuid\UuidInterface;
use Symfony\Component\Serializer\Annotation as Serializer;
/**
* Represent a document stored in an object store.
*
* StoredObjects 's content should be read and written using the @see{StoredObjectManagerInterface}.
*
* The property `$deleteAt` allow a deletion of the document after the given date. But this property should
* be set before the document is actually written by the StoredObjectManager.
*/
#[ORM\Entity]
#[ORM\Table('chill_doc.stored_object')]
#[AsyncFileExists(message: 'The file is not stored properly')]
class StoredObject implements Document, TrackCreationInterface
{
use TrackCreationTrait;
final public const STATUS_READY = 'ready';
final public const STATUS_PENDING = 'pending';
final public const STATUS_FAILURE = 'failure';
#[Serializer\Groups(['write'])]
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::JSON, name: 'datas')]
private array $datas = [];
#[Serializer\Groups(['write'])]
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::TEXT)]
private string $filename = '';
#[Serializer\Groups(['write'])]
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::INTEGER)]
private ?int $id = null;
/**
* @var int[]
*/
#[Serializer\Groups(['write'])]
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::JSON, name: 'iv')]
private array $iv = [];
#[Serializer\Groups(['write'])]
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::JSON, name: 'key')]
private array $keyInfos = [];
#[Serializer\Groups(['write'])]
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::TEXT, name: 'title')]
private string $title = '';
#[Serializer\Groups(['write'])]
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::TEXT, name: 'type', options: ['default' => ''])]
private string $type = '';
#[Serializer\Groups(['write'])]
#[ORM\Column(type: 'uuid', unique: true)]
private UuidInterface $uuid;
#[ORM\ManyToOne(targetEntity: DocGeneratorTemplate::class)]
private ?DocGeneratorTemplate $template = null;
/**
* Store the number of times a generation has been tryied for this StoredObject.
*
* This is a workaround, as generation consume lot of memory, and out-of-memory errors
* are not handled by messenger.
*/
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::INTEGER, options: ['default' => 0])]
private int $generationTrialsCounter = 0;
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::DATETIME_IMMUTABLE, nullable: true, options: ['default' => null])]
private ?\DateTimeImmutable $deleteAt = null;
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::TEXT, nullable: false, options: ['default' => ''])]
private string $generationErrors = '';
/**
* @param StoredObject::STATUS_* $status
*/
public function __construct(
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::TEXT, options: ['default' => 'ready'])]
private string $status = 'ready'
) {
$this->uuid = Uuid::uuid4();
}
public function addGenerationTrial(): self
{
++$this->generationTrialsCounter;
return $this;
}
/**
* @deprecated
*/
#[Serializer\Groups(['write'])]
public function getCreationDate(): \DateTime
{
if (null === $this->createdAt) {
// this scenario will quite never happens
return new \DateTime('now');
}
return \DateTime::createFromImmutable($this->createdAt);
}
public function getDatas(): array
{
return $this->datas;
}
public function getFilename(): string
{
return $this->filename;
}
public function getGenerationTrialsCounter(): int
{
return $this->generationTrialsCounter;
}
public function getId(): ?int
{
return $this->id;
}
public function getIv(): array
{
return $this->iv;
}
public function getKeyInfos(): array
{
return $this->keyInfos;
}
/**
* @deprecated use method "getFilename()"
*/
public function getObjectName()
{
return $this->getFilename();
}
/**
* @return StoredObject::STATUS_*
*/
public function getStatus(): string
{
return $this->status;
}
public function getTitle()
{
return $this->title;
}
public function getType()
{
return $this->type;
}
public function getUuid(): UuidInterface
{
return $this->uuid;
}
public function getWopiDocId(): string
{
return (string) $this->uuid;
}
/**
* @deprecated
*/
#[Serializer\Groups(['write'])]
public function setCreationDate(\DateTime $creationDate): self
{
$this->createdAt = \DateTimeImmutable::createFromMutable($creationDate);
return $this;
}
public function setDatas(?array $datas): self
{
$this->datas = (array) $datas;
return $this;
}
public function setFilename(?string $filename): self
{
$this->filename = (string) $filename;
return $this;
}
public function setIv(?array $iv): self
{
$this->iv = (array) $iv;
return $this;
}
public function setKeyInfos(?array $keyInfos): self
{
$this->keyInfos = (array) $keyInfos;
return $this;
}
/**
* @param StoredObject::STATUS_* $status
*/
public function setStatus(string $status): self
{
$this->status = $status;
return $this;
}
public function setTitle(?string $title): self
{
$this->title = (string) $title;
return $this;
}
public function setType(?string $type): self
{
$this->type = (string) $type;
return $this;
}
public function getTemplate(): ?DocGeneratorTemplate
{
return $this->template;
}
public function hasTemplate(): bool
{
return null !== $this->template;
}
public function setTemplate(?DocGeneratorTemplate $template): StoredObject
{
$this->template = $template;
return $this;
}
public function isPending(): bool
{
return self::STATUS_PENDING === $this->getStatus();
}
public function isFailure(): bool
{
return self::STATUS_FAILURE === $this->getStatus();
}
public function getDeleteAt(): ?\DateTimeImmutable
{
return $this->deleteAt;
}
public function setDeleteAt(?\DateTimeImmutable $deleteAt): StoredObject
{
$this->deleteAt = $deleteAt;
return $this;
}
public function getGenerationErrors(): string
{
return $this->generationErrors;
}
/**
* Adds generation errors to the stored object.
*
* The existing generation errors are not removed
*
* @param string $generationErrors the generation errors to be added
*
* @return StoredObject the modified StoredObject instance
*/
public function addGenerationErrors(string $generationErrors): StoredObject
{
$this->generationErrors = $this->generationErrors.$generationErrors."\n";
return $this;
}
public function saveHistory(): void
{
if ('' === $this->getFilename()) {
return;
}
$this->datas['history'][] = [
'filename' => $this->getFilename(),
'iv' => $this->getIv(),
'key_infos' => $this->getKeyInfos(),
'type' => $this->getType(),
'before' => (new \DateTimeImmutable('now'))->getTimestamp(),
];
}
}