diff --git a/application/Espo/Controllers/Pdf.php b/application/Espo/Controllers/Pdf.php index c42d01abc2..eda327fef1 100644 --- a/application/Espo/Controllers/Pdf.php +++ b/application/Espo/Controllers/Pdf.php @@ -29,32 +29,36 @@ namespace Espo\Controllers; -use Espo\Core\{ - Exceptions\Forbidden, - Exceptions\BadRequest, -}; +use Espo\Core\Exceptions\BadRequest; +use Espo\Core\Exceptions\Error; +use Espo\Core\Exceptions\Forbidden; -use Espo\Core\{ - Api\Request, - Acl, -}; +use Espo\Core\Acl; +use Espo\Core\Api\Request; -use Espo\Services\Pdf as Service; +use Espo\Core\Exceptions\NotFound; +use Espo\Entities\Template as TemplateEntity; +use Espo\Tools\Pdf\MassService; use stdClass; class Pdf { - private $service; + private MassService $service; + private Acl $acl; - private $acl; - - public function __construct(Service $service, Acl $acl) + public function __construct(MassService $service, Acl $acl) { $this->service = $service; $this->acl = $acl; } + /** + * @throws BadRequest + * @throws Forbidden + * @throws Error + * @throws NotFound + */ public function postActionMassPrint(Request $request): stdClass { $data = $request->getParsedBody(); @@ -71,7 +75,7 @@ class Pdf throw new BadRequest(); } - if (!$this->acl->checkScope('Template')) { + if (!$this->acl->checkScope(TemplateEntity::ENTITY_TYPE)) { throw new Forbidden(); } @@ -79,14 +83,10 @@ class Pdf throw new Forbidden(); } + $id = $this->service->generate($data->entityType, $data->idList, $data->templateId); + return (object) [ - 'id' => $this->service - ->massGenerate( - $data->entityType, - $data->idList, - $data->templateId, - true - ) + 'id' => $id, ]; } } diff --git a/application/Espo/Core/Formula/Functions/ExtGroup/PdfGroup/GenerateType.php b/application/Espo/Core/Formula/Functions/ExtGroup/PdfGroup/GenerateType.php index 31d387e598..5426932b3e 100644 --- a/application/Espo/Core/Formula/Functions/ExtGroup/PdfGroup/GenerateType.php +++ b/application/Espo/Core/Formula/Functions/ExtGroup/PdfGroup/GenerateType.php @@ -29,28 +29,27 @@ namespace Espo\Core\Formula\Functions\ExtGroup\PdfGroup; -use Espo\Core\Formula\{ - Functions\BaseFunction, - ArgumentList, - Exceptions\Error, -}; - -use Espo\Services\Pdf as Service; - +use Espo\Core\Field\LinkParent; +use Espo\Entities\Attachment; +use Espo\Entities\Template; +use Espo\Core\Formula\ArgumentList; +use Espo\Core\Formula\Exceptions\Error; +use Espo\Core\Formula\Functions\BaseFunction; use Espo\Core\Utils\Util; - use Espo\Tools\Pdf\Params; - use Espo\Core\Di; +use Espo\Tools\Pdf\Service; use Exception; class GenerateType extends BaseFunction implements Di\EntityManagerAware, - Di\ServiceFactoryAware + Di\InjectableFactoryAware, + Di\FileStorageManagerAware { use Di\EntityManagerSetter; - use Di\ServiceFactorySetter; + use Di\InjectableFactorySetter; + use Di\FileStorageManagerSetter; public function process(ArgumentList $args) { @@ -98,7 +97,8 @@ class GenerateType extends BaseFunction implements throw new Error(); } - $template = $em->getEntity('Template', $templateId); + /** @var ?Template $template */ + $template = $em->getEntityById(Template::ENTITY_TYPE, $templateId); if (!$template) { $this->log("Template {$templateId} does not exist."); @@ -117,10 +117,14 @@ class GenerateType extends BaseFunction implements $params = Params::create()->withAcl(false); try { - /** @var Service $service */ - $service = $this->serviceFactory->create('Pdf'); + $service = $this->injectableFactory->create(Service::class); - $contents = $service->generate($entity, $template, $params); + $contents = $service->generate( + $entity->getEntityType(), + $entity->getId(), + $template->getId(), + $params + ); } catch (Exception $e) { $this->log("Error while generating. Message: " . $e->getMessage() . ".", 'error'); @@ -128,14 +132,19 @@ class GenerateType extends BaseFunction implements throw new Error(); } - $attachment = $em->createEntity('Attachment', [ - 'name' => $fileName, - 'type' => 'application/pdf', - 'contents' => $contents, - 'relatedId' => $id, - 'relatedType' => $entityType, - 'role' => 'Attachment', - ]); + /** @var Attachment $attachment */ + $attachment = $em->getNewEntity(Attachment::ENTITY_TYPE); + + $attachment + ->setName($fileName) + ->setType('application/pdf') + ->setSize($contents->getStream()->getSize()) + ->setRelated(LinkParent::create($entityType, $id)) + ->setRole(Attachment::ROLE_ATTACHMENT); + + $em->saveEntity($attachment); + + $this->fileStorageManager->putStream($attachment, $contents->getStream()); return $attachment->getId(); } diff --git a/application/Espo/Entities/Template.php b/application/Espo/Entities/Template.php index 3c64f86ec0..6490969e48 100644 --- a/application/Espo/Entities/Template.php +++ b/application/Espo/Entities/Template.php @@ -29,7 +29,21 @@ namespace Espo\Entities; -class Template extends \Espo\Core\ORM\Entity +use Espo\Core\ORM\Entity; +use UnexpectedValueException; + +class Template extends Entity { public const ENTITY_TYPE = 'Template'; + + public function getTargetEntityType(): string + { + $entityType = $this->get('entityType'); + + if ($entityType === null) { + throw new UnexpectedValueException(); + } + + return $entityType; + } } diff --git a/application/Espo/EntryPoints/Pdf.php b/application/Espo/EntryPoints/Pdf.php index 1b07ea0325..0a6af9c4be 100644 --- a/application/Espo/EntryPoints/Pdf.php +++ b/application/Espo/EntryPoints/Pdf.php @@ -29,23 +29,22 @@ namespace Espo\EntryPoints; -use Espo\Core\{ - Exceptions\NotFound, - Exceptions\BadRequest, - EntryPoint\EntryPoint, - ORM\EntityManager, - Api\Request, - Api\Response, - Utils\Util, -}; - -use Espo\Services\Pdf as Service; +use Espo\Core\Api\Request; +use Espo\Core\Api\Response; +use Espo\Core\EntryPoint\EntryPoint; +use Espo\Core\Exceptions\BadRequest; +use Espo\Core\Exceptions\Error; +use Espo\Core\Exceptions\Forbidden; +use Espo\Core\Exceptions\NotFound; +use Espo\Core\ORM\EntityManager; +use Espo\Core\Utils\Util; +use Espo\Entities\Template; +use Espo\Tools\Pdf\Service; class Pdf implements EntryPoint { - private $entityManager; - - private $service; + private EntityManager $entityManager; + private Service $service; public function __construct(EntityManager $entityManager, Service $service) { @@ -53,6 +52,12 @@ class Pdf implements EntryPoint $this->service = $service; } + /** + * @throws BadRequest + * @throws Forbidden + * @throws Error + * @throws NotFound + */ public function run(Request $request, Response $response): void { $entityId = $request->getQueryParam('entityId'); @@ -63,18 +68,17 @@ class Pdf implements EntryPoint throw new BadRequest(); } - $entity = $this->entityManager->getEntity($entityType, $entityId); - $template = $this->entityManager->getEntity('Template', $templateId); + $entity = $this->entityManager->getEntityById($entityType, $entityId); + /** @var ?Template $template */ + $template = $this->entityManager->getEntityById(Template::ENTITY_TYPE, $templateId); if (!$entity || !$template) { throw new NotFound(); } - $contents = $this->service->generate($entity, $template); + $contents = $this->service->generate($entityType, $entityId, $templateId); - $fileName = Util::sanitizeFileName( - $entity->get('name') ?? 'unnamed' - ); + $fileName = Util::sanitizeFileName($entity->get('name') ?? 'unnamed'); $fileName = $fileName . '.pdf'; @@ -87,9 +91,9 @@ class Pdf implements EntryPoint ->setHeader('Content-Disposition', 'inline; filename="' . basename($fileName) . '"'); if (!$request->getServerParam('HTTP_ACCEPT_ENCODING')) { - $response->setHeader('Content-Length', (string) strlen($contents)); + $response->setHeader('Content-Length', (string) $contents->getStream()->getSize()); } - $response->writeBody($contents); + $response->writeBody($contents->getStream()); } } diff --git a/application/Espo/Services/Pdf.php b/application/Espo/Services/Pdf.php index 8f9334f06f..9790d7d2b4 100644 --- a/application/Espo/Services/Pdf.php +++ b/application/Espo/Services/Pdf.php @@ -29,336 +29,72 @@ namespace Espo\Services; +use Espo\Core\Exceptions\NotFound; use Espo\ORM\Entity; use Espo\Core\Exceptions\Error; use Espo\Core\Exceptions\Forbidden; -use Espo\Core\Exceptions\NotFound; - -use Espo\Core\Acl; -use Espo\Core\Acl\Table; -use Espo\Core\Job\QueueName; -use Espo\Core\ORM\EntityManager; -use Espo\Core\Record\ServiceContainer; -use Espo\Core\Select\SelectBuilderFactory; -use Espo\Core\Utils\Config; -use Espo\Core\Utils\Language; -use Espo\Core\Utils\Util; - -use Espo\Tools\Pdf\Builder; -use Espo\Tools\Pdf\Contents; use Espo\Tools\Pdf\Data; -use Espo\Tools\Pdf\Data\DataLoaderManager; -use Espo\Tools\Pdf\IdDataMap; use Espo\Tools\Pdf\Params; -use Espo\Tools\Pdf\TemplateWrapper; - +use Espo\Tools\Pdf\Service; use Espo\Entities\Template; -use DateTime; -use stdClass; - +/** + * @deprecated Left for bc. + */ class Pdf { - private const DEFAULT_ENGINE = 'Tcpdf'; - - private string $removeMassFilePeriod = '1 hour'; - - private $config; - private $entityManager; - private $acl; - private $defaultLanguage; - private $selectBuilderFactory; - private $builder; - private $serviceContainer; - private $dataLoaderManager; + private Service $service; public function __construct( - Config $config, - EntityManager $entityManager, - Acl $acl, - Language $defaultLanguage, - SelectBuilderFactory $selectBuilderFactory, - Builder $builder, - ServiceContainer $serviceContainer, - DataLoaderManager $dataLoaderManager + Service $service ) { - $this->config = $config; - $this->entityManager = $entityManager; - $this->acl = $acl; - $this->defaultLanguage = $defaultLanguage; - $this->selectBuilderFactory = $selectBuilderFactory; - $this->builder = $builder; - $this->serviceContainer = $serviceContainer; - $this->dataLoaderManager = $dataLoaderManager; + $this->service = $service; } /** - * @param string[] $idList - * @throws Error - * @throws NotFound - * @throws Forbidden - */ - public function massGenerate( - string $entityType, - array $idList, - string $templateId, - bool $checkAcl = false - ): string { - - $service = $this->serviceContainer->get($entityType); - - $maxCount = $this->config->get('massPrintPdfMaxCount'); - - if ($maxCount) { - if (count($idList) > $maxCount) { - throw new Error("Mass print to PDF max count exceeded."); - } - } - - $template = $this->entityManager->getEntity('Template', $templateId); - - if (!$template) { - throw new NotFound(); - } - - $params = Params::create(); - - if ($checkAcl) { - if (!$this->acl->check($template)) { - throw new Forbidden(); - } - - if (!$this->acl->checkScope($entityType)) { - throw new Forbidden(); - } - - $params = $params->withAcl(); - } - - $query = $this->selectBuilderFactory - ->create() - ->from($entityType) - ->withAccessControlFilter() - ->build(); - - $collection = $this->entityManager - ->getRDBRepository($entityType) - ->clone($query) - ->where([ - 'id' => $idList, - ]) - ->find(); - - $idDataMap = IdDataMap::create(); - - foreach ($collection as $entity) { - $service->loadAdditionalFields($entity); - - $idDataMap->set( - $entity->getId(), - $this->dataLoaderManager->load($entity, $params) - ); - - // deprecated - if (method_exists($service, 'loadAdditionalFieldsForPdf')) { - $service->loadAdditionalFieldsForPdf($entity); - } - } - - $templateWrapper = new TemplateWrapper($template); - - $engine = $this->config->get('pdfEngine') ?? self::DEFAULT_ENGINE; - - $printer = $this->builder - ->setTemplate($templateWrapper) - ->setEngine($engine) - ->build(); - - $contents = $printer->printCollection($collection, $params, $idDataMap); - - $entityTypeTranslated = $this->defaultLanguage->translateLabel($entityType, 'scopeNamesPlural'); - - $filename = Util::sanitizeFileName($entityTypeTranslated) . '.pdf'; - - $attachment = $this->entityManager->getNewEntity('Attachment'); - - $attachment->set([ - 'name' => $filename, - 'type' => 'application/pdf', - 'role' => 'Mass Pdf', - 'contents' => $contents->getString(), - ]); - - $this->entityManager->saveEntity($attachment); - - $job = $this->entityManager->getNewEntity('Job'); - - $job->set([ - 'serviceName' => 'Pdf', - 'methodName' => 'removeMassFileJob', - 'data' => [ - 'id' => $attachment->getId(), - ], - 'executeTime' => (new DateTime())->modify('+' . $this->removeMassFilePeriod)->format('Y-m-d H:i:s'), - 'queue' => QueueName::Q1, - ]); - - $this->entityManager->saveEntity($job); - - return $attachment->getId(); - } - - public function removeMassFileJob(stdClass $data): void - { - if (empty($data->id)) { - return; - } - - $attachment = $this->entityManager->getEntity('Attachment', $data->id); - - if (!$attachment) { - return; - } - - if ($attachment->get('role') !== 'Mass Pdf') { - return; - } - - $this->entityManager->removeEntity($attachment); - } - - /** - * Generate PDF. ACL check is processed if `$params` is null. - * * @throws Error * @throws Forbidden */ public function generate(Entity $entity, Template $template, ?Params $params = null, ?Data $data = null): string { - if ($params === null) { - $params = Params::create()->withAcl(); + $additionalData = null; + + if ($data) { + $additionalData = get_object_vars($data->getAdditionalTemplateData()); } - $result = $this->buildFromTemplateInternal($entity, $template, false, null, $params, $data); - - assert($result !== null); - - return $result; + return $this->buildFromTemplate($entity, $template, false, $additionalData); } /** * @param ?array $additionalData * @throws Error * @throws Forbidden - * @deprecated + * @throws NotFound + * + * @deprecated Left for bc. */ public function buildFromTemplate( Entity $entity, Template $template, bool $displayInline = false, ?array $additionalData = null - ): ?string { + ): string { - return $this->buildFromTemplateInternal($entity, $template, $displayInline, $additionalData); - } + $data = Data::create() + ->withAdditionalTemplateData( + (object) ($additionalData ?? []) + ); - /** - * @param ?array $additionalData - * @throws Error - * @throws Forbidden - * @deprecated - */ - private function buildFromTemplateInternal( - Entity $entity, - Template $template, - bool $displayInline = false, - ?array $additionalData = null, - ?Params $params = null, - ?Data $data = null - ): ?string { - - $entityType = $entity->getEntityType(); - - $service = $this->serviceContainer->get($entityType); - - $service->loadAdditionalFields($entity); - - if (method_exists($service, 'loadAdditionalFieldsForPdf')) { - // deprecated - $service->loadAdditionalFieldsForPdf($entity); - } - - if ($template->get('entityType') !== $entityType) { - throw new Error("Not matching entity types."); - } - - $applyAcl = true; - - if ($params) { - $applyAcl = $params->applyAcl(); - } - - if ($applyAcl) { - if ( - !$this->acl->check($entity, Table::ACTION_READ) || - !$this->acl->check($template, Table::ACTION_READ) - ) { - throw new Forbidden(); - } - } - - $templateWrapper = new TemplateWrapper($template); - - if (!$data) { - $data = Data::create() - ->withAdditionalTemplateData( - (object) ($additionalData ?? []) - ); - } - - $data = $this->dataLoaderManager->load($entity, $params, $data); - - $engine = $this->config->get('pdfEngine') ?? self::DEFAULT_ENGINE; - - $printer = $this->builder - ->setTemplate($templateWrapper) - ->setEngine($engine) - ->build(); - - $contents = $printer->printEntity($entity, $params, $data); - - if ($displayInline) { - $this->displayInline($entity, $contents); - - return null; - } + $contents = $this->service->generate( + $entity->getEntityType(), + $entity->getId(), + $template->getId(), + null, + $data + ); return $contents->getString(); } - - /** - * @deprecated - */ - private function displayInline(Entity $entity, Contents $contents): void - { - $fileName = Util::sanitizeFileName( - $entity->get('name') ?? 'unnamed' - ); - - $fileName = $fileName . '.pdf'; - - header('Content-Type: application/pdf'); - header('Cache-Control: private, must-revalidate, post-check=0, pre-check=0, max-age=1'); - header('Pragma: public'); - header('Expires: Sat, 26 Jul 1997 05:00:00 GMT'); - header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT'); - header('Content-Disposition: inline; filename="'.basename($fileName).'"'); - - if (!isset($_SERVER['HTTP_ACCEPT_ENCODING']) or empty($_SERVER['HTTP_ACCEPT_ENCODING'])) { - header('Content-Length: '. $contents->getLength()); - } - - echo $contents->getString(); - } } diff --git a/application/Espo/Tools/Pdf/Data/DataLoaderManager.php b/application/Espo/Tools/Pdf/Data/DataLoaderManager.php index 52611d772e..acb2982750 100644 --- a/application/Espo/Tools/Pdf/Data/DataLoaderManager.php +++ b/application/Espo/Tools/Pdf/Data/DataLoaderManager.php @@ -40,7 +40,6 @@ use Espo\Tools\Pdf\Params; class DataLoaderManager { private Metadata $metadata; - private InjectableFactory $injectableFactory; public function __construct(Metadata $metadata, InjectableFactory $injectableFactory) diff --git a/application/Espo/Tools/Pdf/Jobs/RemoveMassFile.php b/application/Espo/Tools/Pdf/Jobs/RemoveMassFile.php new file mode 100644 index 0000000000..10d2d7a3f4 --- /dev/null +++ b/application/Espo/Tools/Pdf/Jobs/RemoveMassFile.php @@ -0,0 +1,69 @@ +entityManager = $entityManager; + } + + public function run(Data $data): void + { + $id = $data->getTargetId(); + + if (!$id) { + throw new RuntimeException(); + } + + /** @var ?Attachment $attachment */ + $attachment = $this->entityManager->getEntityById(Attachment::ENTITY_TYPE, $id); + + if (!$attachment) { + return; + } + + if ($attachment->getRole() !== self::ATTACHMENT_MASS_PDF_ROLE) { + throw new RuntimeException(); + } + + $this->entityManager->removeEntity($attachment); + } +} diff --git a/application/Espo/Tools/Pdf/MassService.php b/application/Espo/Tools/Pdf/MassService.php new file mode 100644 index 0000000000..cf7f3bcc7d --- /dev/null +++ b/application/Espo/Tools/Pdf/MassService.php @@ -0,0 +1,214 @@ +serviceContainer = $serviceContainer; + $this->config = $config; + $this->entityManager = $entityManager; + $this->acl = $acl; + $this->dataLoaderManager = $dataLoaderManager; + $this->selectBuilderFactory = $selectBuilderFactory; + $this->builder = $builder; + $this->defaultLanguage = $defaultLanguage; + $this->jobSchedulerFactory = $jobSchedulerFactory; + $this->fileStorageManager = $fileStorageManager; + } + + /** + * Generate a PDF for multiple records. + * + * @param string[] $idList + * @throws Error + * @throws NotFound + * @throws Forbidden + */ + public function generate( + string $entityType, + array $idList, + string $templateId, + bool $withAcl = true + ): string { + + $service = $this->serviceContainer->get($entityType); + + $maxCount = $this->config->get('massPrintPdfMaxCount'); + + if ($maxCount && count($idList) > $maxCount) { + throw new Error("Mass print to PDF max count exceeded."); + } + + /** @var ?TemplateEntity $template */ + $template = $this->entityManager->getEntityById(TemplateEntity::ENTITY_TYPE, $templateId); + + if (!$template) { + throw new NotFound(); + } + + $params = Params::create(); + + if ($withAcl) { + if (!$this->acl->check($template)) { + throw new Forbidden(); + } + + if (!$this->acl->checkScope($entityType)) { + throw new Forbidden(); + } + + $params = $params->withAcl(); + } + + $selectBuilder = $this->selectBuilderFactory + ->create() + ->from($entityType); + + if ($withAcl) { + $selectBuilder->withAccessControlFilter(); + } + + $collection = $this->entityManager + ->getRDBRepository($entityType) + ->clone($selectBuilder->build()) + ->where([ + 'id' => $idList, + ]) + ->find(); + + $idDataMap = IdDataMap::create(); + + foreach ($collection as $entity) { + $service->loadAdditionalFields($entity); + + $idDataMap->set( + $entity->getId(), + $this->dataLoaderManager->load($entity, $params) + ); + + // For bc. + if (method_exists($service, 'loadAdditionalFieldsForPdf')) { + $service->loadAdditionalFieldsForPdf($entity); + } + } + + $templateWrapper = new TemplateWrapper($template); + + $engine = $this->config->get('pdfEngine') ?? self::DEFAULT_ENGINE; + + $printer = $this->builder + ->setTemplate($templateWrapper) + ->setEngine($engine) + ->build(); + + $contents = $printer->printCollection($collection, $params, $idDataMap); + + $entityTypeTranslated = $this->defaultLanguage->translateLabel($entityType, 'scopeNamesPlural'); + + $filename = Util::sanitizeFileName($entityTypeTranslated) . '.pdf'; + + /** @var Attachment $attachment */ + $attachment = $this->entityManager->getNewEntity(Attachment::ENTITY_TYPE); + + $attachment + ->setName($filename) + ->setType('application/pdf') + ->setRole(self::ATTACHMENT_MASS_PDF_ROLE) + ->setSize($contents->getStream()->getSize()); + + $this->entityManager->saveEntity($attachment); + + $this->fileStorageManager->putStream($attachment, $contents->getStream()); + + $this->jobSchedulerFactory + ->create() + ->setClassName(RemoveMassFile::class) + ->setData( + JobData + ::create() + ->withTargetId($attachment->getId()) + ->withTargetType(Attachment::ENTITY_TYPE) + ) + ->setTime( + (new DateTime())->modify('+' . self::REMOVE_MASS_PDF_PERIOD) + ) + ->setQueue(QueueName::Q1) + ->schedule(); + + return $attachment->getId(); + } +} diff --git a/application/Espo/Tools/Pdf/Service.php b/application/Espo/Tools/Pdf/Service.php new file mode 100644 index 0000000000..1c78e1888e --- /dev/null +++ b/application/Espo/Tools/Pdf/Service.php @@ -0,0 +1,138 @@ +entityManager = $entityManager; + $this->acl = $acl; + $this->serviceContainer = $serviceContainer; + $this->dataLoaderManager = $dataLoaderManager; + $this->config = $config; + $this->builder = $builder; + } + + /** + * Generate a PDF. + * + * @param string $entityType An entity type. + * @param string $id A record ID. + * @param string $templateId A template ID. + * @param ?Params $params Params. If null, a params with the apply-acl will be used. + * @params ?Data $data Data. + * + * @throws Error + * @throws NotFound + * @throws Forbidden + */ + public function generate( + string $entityType, + string $id, + string $templateId, + ?Params $params = null, + ?Data $data = null + ): Contents { + + $params = $params ?? Params::create()->withAcl(true); + + $applyAcl = $params->applyAcl(); + + $entity = $this->entityManager->getEntityById($entityType, $id); + + if (!$entity) { + throw new NotFound("Record not found."); + } + + /** @var ?TemplateEntity $template */ + $template = $this->entityManager->getEntityById(TemplateEntity::ENTITY_TYPE, $templateId); + + if (!$template) { + throw new NotFound("Template not found."); + } + + if ($applyAcl && !$this->acl->checkEntityRead($entity)) { + throw new Forbidden("No access to record."); + } + + if ($applyAcl && !$this->acl->checkEntityRead($template)) { + throw new Forbidden("No access to template."); + } + + $service = $this->serviceContainer->get($entityType); + + $service->loadAdditionalFields($entity); + + if (method_exists($service, 'loadAdditionalFieldsForPdf')) { + // For bc. + $service->loadAdditionalFieldsForPdf($entity); + } + + if ($template->getTargetEntityType() !== $entityType) { + throw new Error("Not matching entity types."); + } + + $data = $this->dataLoaderManager->load($entity, $params, $data); + $engine = $this->config->get('pdfEngine') ?? self::DEFAULT_ENGINE; + + $printer = $this->builder + ->setTemplate(new TemplateWrapper($template)) + ->setEngine($engine) + ->build(); + + return $printer->printEntity($entity, $params, $data); + } +}