contextManager = $contextManager; $this->docGeneratorTemplateRepository = $docGeneratorTemplateRepository; $this->driver = $driver; $this->logger = $logger; $this->paginatorFactory = $paginatorFactory; $this->tempUrlGenerator = $tempUrlGenerator; $this->kernel = $kernel; $this->client = $client; } /** * @Route( * "{_locale}/admin/doc/gen/generate/test/from/{template}/for/{entityClassName}/{entityId}", * name="chill_docgenerator_test_generate_from_template" * ) */ public function adminTestGenerateDocFromTemplateAction( DocGeneratorTemplate $template, string $entityClassName, int $entityId, Request $request ): Response { return $this->generateDocFromTemplate( $template, $entityClassName, $entityId, $request, true ); } /** * @Route( * "{_locale}/doc/gen/generate/from/{template}/for/{entityClassName}/{entityId}", * name="chill_docgenerator_generate_from_template" * ) */ public function generateDocFromTemplateAction( DocGeneratorTemplate $template, string $entityClassName, int $entityId, Request $request ): Response { return $this->generateDocFromTemplate( $template, $entityClassName, $entityId, $request, false ); } /** * @Route( * "/api/1.0/docgen/templates/by-entity/{entityClassName}", * name="chill_docgenerator_templates_for_entity_api" * ) */ public function listTemplateApiAction(string $entityClassName): Response { $nb = $this->docGeneratorTemplateRepository->countByEntity($entityClassName); $paginator = $this->paginatorFactory->create($nb); $entities = $this->docGeneratorTemplateRepository->findByEntity( $entityClassName, $paginator->getCurrentPageFirstItemNumber(), $paginator->getItemsPerPage() ); return $this->json( new Collection($entities, $paginator), Response::HTTP_OK, [], [AbstractNormalizer::GROUPS => ['read']] ); } /** * @Route( * "{_locale}/admin/doc/gen/generate/test/redirect", * name="chill_docgenerator_test_generate_redirect" * ) * * @return void */ public function redirectToTestGenerate(Request $request): RedirectResponse { $template = $request->query->getInt('template'); if (null === $template) { throw new BadRequestHttpException('template parameter is missing'); } $entityClassName = $request->query->get('entityClassName'); if (null === $entityClassName) { throw new BadRequestHttpException('entityClassName is missing'); } $entityId = $request->query->get('entityId'); if (null === $entityId) { throw new BadRequestHttpException('entityId is missing'); } return $this->redirectToRoute( 'chill_docgenerator_test_generate_from_template', ['template' => $template, 'entityClassName' => $entityClassName, 'entityId' => $entityId, 'returnPath' => $request->query->get('returnPath', '/'), ] ); } private function generateDocFromTemplate( DocGeneratorTemplate $template, string $entityClassName, int $entityId, Request $request, bool $isTest ): Response { try { $context = $this->contextManager->getContextByDocGeneratorTemplate($template); } catch (ContextNotFoundException $e) { throw new NotFoundHttpException($e->getMessage(), $e); } $entity = $this->getDoctrine()->getRepository($context->getEntityClass())->find($entityId); if (null === $entity) { throw new NotFoundHttpException("Entity with classname {$entityClassName} and id {$entityId} is not found"); } $contextGenerationData = []; if ( $context instanceof DocGeneratorContextWithPublicFormInterface && $context->hasPublicForm($template, $entity) || $isTest ) { if ($context instanceof DocGeneratorContextWithPublicFormInterface) { $builder = $this->createFormBuilder( array_merge( $context->getFormData($template, $entity), $isTest ? ['test_file' => null] : [] ) ); } else { $builder = $this->createFormBuilder( ['test_file' => null] ); } $context->buildPublicForm($builder, $template, $entity); if ($isTest) { $builder->add('test_file', FileType::class, [ 'label' => 'Template file', 'required' => false, ]); } $form = $builder->getForm()->handleRequest($request); if ($form->isSubmitted() && $form->isValid()) { $contextGenerationData = $form->getData(); } elseif (!$form->isSubmitted() || ($form->isSubmitted() && !$form->isValid())) { $templatePath = '@ChillDocGenerator/Generator/basic_form.html.twig'; $templateOptions = ['entity' => $entity, 'form' => $form->createView(), 'template' => $template, 'context' => $context, ]; return $this->render($templatePath, $templateOptions); } } if ($isTest && null !== $contextGenerationData['test_file']) { /** @var File $file */ $file = $contextGenerationData['test_file']; $templateResource = fopen($file->getPathname(), 'rb'); } else { $getUrlGen = $this->tempUrlGenerator->generate( 'GET', $template->getFile()->getFilename() ); $data = $this->client->request('GET', $getUrlGen->url); $iv = $template->getFile()->getIv(); // iv as an Array $ivGoodFormat = pack('C*', ...$iv); // iv as a String (ok for openssl_decrypt) $method = 'AES-256-CBC'; $key = $template->getFile()->getKeyInfos()['k']; $keyGoodFormat = Base64Url::decode($key); $dataDecrypted = openssl_decrypt($data->getContent(), $method, $keyGoodFormat, 1, $ivGoodFormat); if (false === $dataDecrypted) { throw new Exception('Error during Decrypt ', 1); } if (false === $templateResource = fopen('php://memory', 'r+b')) { $this->logger->error('Could not write data to memory'); throw new HttpException(500); } fwrite($templateResource, $dataDecrypted); rewind($templateResource); } $datas = $context->getData($template, $entity, $contextGenerationData); try { $generatedResource = $this->driver->generateFromResource($templateResource, $template->getFile()->getType(), $datas, $template->getFile()->getFilename()); } catch (TemplateException $e) { $msg = implode("\n", $e->getErrors()); return new Response($msg, 400, [ 'Content-Type' => 'text/plain', ]); } fclose($templateResource); if ($isTest) { return new StreamedResponse( static function () use ($generatedResource) { fpassthru($generatedResource); fclose($generatedResource); }, Response::HTTP_OK, [ 'Content-Transfer-Encoding', 'binary', 'Content-Type' => 'application/vnd.oasis.opendocument.text', 'Content-Disposition' => sprintf('attachment; filename="%s.odt"', 'generated'), 'Content-Length' => fstat($generatedResource)['size'], ], ); } $genDocName = 'doc_' . sprintf('%010d', mt_rand()) . 'odt'; $getUrlGen = $this->tempUrlGenerator->generate( 'PUT', $genDocName ); $client = new Client(); try { $putResponse = $client->request('PUT', $getUrlGen->url, [ 'body' => $generatedResource, ]); if ($putResponse->getStatusCode() === 201) { $em = $this->getDoctrine()->getManager(); $storedObject = new StoredObject(); $storedObject ->setType($template->getFile()->getType()) ->setFilename($genDocName); $em->persist($storedObject); try { $context->storeGenerated($template, $storedObject, $entity, $contextGenerationData); } catch (Exception $e) { $this->logger->error('Could not store the associated document to entity', [ 'entityClassName' => $entityClassName, 'entityId' => $entityId, 'contextKey' => $context->getName(), ]); throw $e; } $em->flush(); return $this->redirectToRoute('chill_wopi_file_edit', [ 'fileId' => $storedObject->getUuid(), 'returnPath' => $request->query->get('returnPath', '/'), ]); } } catch (TransferException $e) { throw $e; } throw new Exception('Unable to generate document.'); } }