config = $config; $this->entityManager = $entityManager; $this->acl = $acl; $this->defaultLanguage = $defaultLanguage; $this->selectBuilderFactory = $selectBuilderFactory; $this->builder = $builder; $this->serviceContainer = $serviceContainer; $this->dataLoaderManager = $dataLoaderManager; } /** * @param iterable $entityList * @throws Error */ public function generateMailMerge( string $entityType, iterable $entityList, Template $template, string $name, ?string $campaignId = null ): string { $collection = $this->entityManager->getCollectionFactory()->create($entityType); foreach ($entityList as $entity) { $collection[] = $entity; } $params = Params::create()->withAcl(); $idDataMap = IdDataMap::create(); $service = $this->serviceContainer->get($entityType); foreach ($entityList as $entity) { $service->loadAdditionalFields($entity); $idDataMap->set( $entity->getId(), $this->dataLoaderManager->load($entity, $params) ); // deprecated if (method_exists($service, 'loadAdditionalFieldsForPdf')) { $service->loadAdditionalFieldsForPdf($entity); } } $engine = $this->config->get('pdfEngine') ?? self::DEFAULT_ENGINE; $templateWrapper = new TemplateWrapper($template); $printer = $this->builder ->setTemplate($templateWrapper) ->setEngine($engine) ->build(); $contents = $printer->printCollection($collection, $params, $idDataMap); $filename = Util::sanitizeFileName($name) . '.pdf'; $attachment = $this->entityManager->getNewEntity('Attachment'); $attachment->set([ 'name' => $filename, 'relatedType' => 'Campaign', 'type' => 'application/pdf', 'relatedId' => $campaignId, 'role' => 'Mail Merge', 'contents' => $contents->getString(), ]); $this->entityManager->saveEntity($attachment); return $attachment->getId(); } /** * @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(); } $result = $this->buildFromTemplateInternal($entity, $template, false, null, $params, $data); assert($result !== null); return $result; } /** * @param ?array $additionalData * @throws Error * @throws Forbidden * @deprecated */ public function buildFromTemplate( Entity $entity, Template $template, bool $displayInline = false, ?array $additionalData = null ): ?string { return $this->buildFromTemplateInternal($entity, $template, $displayInline, $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; } 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(); } }