| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238 |
- <?php
- declare(strict_types=1);
- namespace App\Service\Export;
- use App\ApiResources\Export\ExportRequest;
- use App\Entity\Core\File;
- use App\Enum\Core\FileTypeEnum;
- use App\Enum\Core\FileVisibilityEnum;
- use App\Repository\Access\AccessRepository;
- use App\Repository\Core\FileRepository;
- use App\Service\Export\Model\ExportModelInterface;
- use App\Service\File\FileManager;
- use App\Service\ServiceIterator\EncoderIterator;
- use App\Service\Utils\FileUtils;
- use App\Service\Utils\StringsUtils;
- use Doctrine\ORM\EntityManagerInterface;
- use Psr\Log\LoggerInterface;
- use Symfony\Contracts\Service\Attribute\Required;
- use Twig\Environment;
- /**
- * Classe de base des services d'export.
- */
- abstract class BaseExporter
- {
- // dependencies injections
- protected AccessRepository $accessRepository;
- protected FileRepository $fileRepository;
- protected Environment $twig;
- protected EncoderIterator $encoderIterator;
- protected EntityManagerInterface $entityManager;
- protected LoggerInterface $logger;
- protected FileManager $fileManager;
- protected FileUtils $fileUtils;
- #[Required]
- public function setAccessRepository(AccessRepository $accessRepository): void
- {
- $this->accessRepository = $accessRepository;
- }
- #[Required]
- public function setFileRepository(FileRepository $fileRepository): void
- {
- $this->fileRepository = $fileRepository;
- }
- #[Required]
- public function setTwig(Environment $twig): void
- {
- $this->twig = $twig;
- }
- #[Required]
- public function setEncoderIterator(EncoderIterator $encoderIterator): void
- {
- $this->encoderIterator = $encoderIterator;
- }
- #[Required]
- public function setEntityManager(EntityManagerInterface $entityManager): void
- {
- $this->entityManager = $entityManager;
- }
- #[Required]
- public function setFileManager(FileManager $fileManager): void
- {
- $this->fileManager = $fileManager;
- }
- #[Required]
- public function setLogger(LoggerInterface $logger): void
- {
- $this->logger = $logger;
- }
- #[Required]
- public function setFileUtils(FileUtils $fileUtils): void
- {
- $this->fileUtils = $fileUtils;
- }
- public function support(ExportRequest $exportRequest): bool
- {
- return false;
- }
- /**
- * Exécute l'opération d'export correspondant à la requête passée
- * en paramètre.
- */
- public function export(ExportRequest $exportRequest): File
- {
- $requesterId = $exportRequest->getRequesterId();
- $requester = $this->accessRepository->find($requesterId);
- if ($requester === null) {
- throw new \RuntimeException('Unable to determine the user; abort.');
- }
- // Génère le modèle à partir de l'exportRequest
- $model = $this->buildModel($exportRequest);
- // Génère le html à partir du template et du service
- $html = $this->render($model);
- // Encode le html au format voulu
- $content = $this->encode($html, $exportRequest->getFormat()->value);
- // Met à jour ou créé l'enregistrement du fichier en base
- if ($exportRequest->getFileId() !== null) {
- $file = $this->fileRepository->find($exportRequest->getFileId());
- } else {
- // Todo: voir si ce else est nécessaire une fois tous les exports implémentés (c'est
- // juste au cas où le record File n'existe pas encore en base)
- $organization = $requester->getOrganization();
- if ($organization === null) {
- throw new \RuntimeException('Unable to determine the organization of the curent user; abort.');
- }
- $file = $this->prepareFile($exportRequest, false);
- }
- return $this->fileManager->write($file, $content, $requester);
- }
- /**
- * Create a pending file record in the database.
- */
- public function prepareFile(ExportRequest $exportRequest, bool $flushFile = true): File
- {
- $requesterId = $exportRequest->getRequesterId();
- $requester = $this->accessRepository->find($requesterId);
- if ($requester === null) {
- throw new \RuntimeException('Unable to determine the current user; abort.');
- }
- $filename = $this->getFileBasename($exportRequest);
- if (!preg_match('/^.+\.'.$exportRequest->getFormat()->value.'$/i', $filename)) {
- $filename .= '.'.$exportRequest->getFormat()->value;
- }
- return $this->fileManager->prepareFile(
- $requester,
- $filename,
- $this->getFileType(),
- $requester,
- true,
- FileVisibilityEnum::NOBODY,
- $this->fileUtils->getMimeTypeFromExt($exportRequest->getFormat()->value),
- $flushFile
- );
- }
- /**
- * Construit le modèle de données qui servira au render du template.
- */
- public function buildModel(ExportRequest $exportRequest): ExportModelInterface
- {
- throw new \RuntimeException('not implemented error');
- }
- /**
- * Retourne le nom par défaut de cet export,
- * utilisé pour trouver le template twig ou encore pour nommer
- * le fichier exporté.
- */
- protected function getBasename(): string
- {
- $arr = explode('\\', static::class);
- $classname = end($arr);
- return StringsUtils::camelToSnake(
- preg_replace(
- '/^([\w]+)Exporter$/',
- '$1',
- $classname,
- 1)
- );
- }
- /**
- * Return the path of the twig template for this export.
- */
- protected function getTemplatePath(): string
- {
- return '@templates/export/'.$this->getBasename().'.html.twig';
- }
- /**
- * Génère le rendu HTML à partir du template twig et du modèle de données.
- *
- * Attention : Les liens vers les fichiers statiques ou dynamiques doivent être des chemins d'accès absolus pour
- * être traités par wkhtmltoX; Les images peuvent être incluses au format base64;
- *
- * @see App\Service\Twig\AssetsExtension
- *
- * @return string Rendu HTML
- */
- protected function render(ExportModelInterface $model): string
- {
- try {
- return $this->twig->render(
- $this->getTemplatePath(),
- ['model' => $model]
- );
- } catch (\Twig\Error\LoaderError|\Twig\Error\RuntimeError|\Twig\Error\SyntaxError $e) {
- throw new \RuntimeException('error during template rendering : '.$e);
- }
- }
- /**
- * Encode le html au format demandé.
- *
- * @param string $format @see ExportFormatEnum
- */
- protected function encode(string $html, string $format): string
- {
- return $this->encoderIterator->getEncoderFor($format)->encode($html);
- }
- /**
- * Retourne le nom du fichier exporté.
- */
- protected function getFileBasename(ExportRequest $exportRequest): string
- {
- return $this->getBasename();
- }
- /**
- * Retourne le type de fichier tel qu'il apparait au niveau du champ File.type.
- */
- protected function getFileType(): FileTypeEnum
- {
- return FileTypeEnum::UNKNOWN;
- }
- }
|