diff --git a/src/Bundle/ChillDocGeneratorBundle/Controller/DocGeneratorTemplateController.php b/src/Bundle/ChillDocGeneratorBundle/Controller/DocGeneratorTemplateController.php index 493bcb92e..a0768cdca 100644 --- a/src/Bundle/ChillDocGeneratorBundle/Controller/DocGeneratorTemplateController.php +++ b/src/Bundle/ChillDocGeneratorBundle/Controller/DocGeneratorTemplateController.php @@ -16,6 +16,7 @@ use ChampsLibres\AsyncUploaderBundle\TempUrl\TempUrlGeneratorInterface; use Chill\DocGeneratorBundle\Context\ContextManager; use Chill\DocGeneratorBundle\Context\Exception\ContextNotFoundException; use Chill\DocGeneratorBundle\Entity\DocGeneratorTemplate; +use Chill\DocGeneratorBundle\GeneratorDriver\DriverInterface; use Chill\DocGeneratorBundle\Repository\DocGeneratorTemplateRepository; use Chill\DocStoreBundle\Entity\StoredObject; use Chill\MainBundle\Pagination\PaginatorFactory; @@ -54,17 +55,22 @@ final class DocGeneratorTemplateController extends AbstractController private TempUrlGeneratorInterface $tempUrlGenerator; + private DriverInterface $driver; + public function __construct( ContextManager $contextManager, DocGeneratorTemplateRepository $docGeneratorTemplateRepository, + DriverInterface $driver, LoggerInterface $logger, PaginatorFactory $paginatorFactory, TempUrlGeneratorInterface $tempUrlGenerator, KernelInterface $kernel, HttpClientInterface $client + ) { $this->contextManager = $contextManager; $this->docGeneratorTemplateRepository = $docGeneratorTemplateRepository; + $this->driver = $driver; $this->logger = $logger; $this->paginatorFactory = $paginatorFactory; $this->tempUrlGenerator = $tempUrlGenerator; @@ -134,71 +140,41 @@ final class DocGeneratorTemplateController extends AbstractController throw new \Exception('Error during Decrypt ', 1); } - $tmpfnameDeCrypted = tempnam($this->kernel->getCacheDir(), 'DECRYPT_DOC_TEMPLATE'); // plus ou moins - - if (!$handle = fopen($tmpfnameDeCrypted, 'ab')) { - $this->logger->error("Cannot open file ({$tmpfnameDeCrypted})"); + if (false === $templateResource = fopen('php://memory', 'r+')) { + $this->logger->error("Could not write data to memory"); throw new HttpException(500); } - if (false === $ftemplate = fwrite($handle, $dataDecrypted)) { - $this->logger->error("Cannot write to file ({$tmpfnameDeCrypted})"); - - throw new HttpException(500); - } - - dump("Success, wrote (to file ({$tmpfnameDeCrypted})"); - - fclose($handle); + fwrite($templateResource, $dataDecrypted); + rewind($templateResource); $datas = $context->getData($template, $entity, $contextGenerationData); + dump('datas compiled', $datas); - dump('process the data', $datas); + $generatedResource = $this->driver->generateFromResource($templateResource, $template->getFile()->getType(), $datas, $template->getFile()->getFilename()); - /* - $templateProcessor = new TemplateProcessor($tmpfnameDeCrypted); + fclose($templateResource); - foreach ($datas['setValues'] as $setValuesConf) { - $templateProcessor->setValues($setValuesConf); - } - - foreach ($datas['cloneRowAndSetValues'] as $cloneRowAndSetValues) { - $templateProcessor->cloneRowAndSetValues($cloneRowAndSetValues[0], $cloneRowAndSetValues[1]); - } - $tmpfnameGenerated = tempnam($this->kernel->getCacheDir(), 'DOC_GENERATED'); - - $fileContent = fopen($tmpfnameGenerated, 'rb'); // the generated file content - */ - - $genDocName = 'doc_' . sprintf('%010d', mt_rand()) . '.docx'; + $genDocName = 'doc_' . sprintf('%010d', mt_rand()).'odt'; $getUrlGen = $this->tempUrlGenerator->generate( 'PUT', $genDocName ); - unlink($tmpfnameDeCrypted); - //unlink($tmpfnameGenerated); - $client = new Client(); try { - /* $putResponse = $client->request('PUT', $getUrlGen->url, [ - 'body' => $fileContent, - ]); - */ - $putResponse = $client->request('PUT', $getUrlGen->url, [ - 'body' => $ftemplate, + 'body' => $generatedResource, ]); if ($putResponse->getStatusCode() === 201) { $em = $this->getDoctrine()->getManager(); $storedObject = new StoredObject(); $storedObject - // currently, only docx is supported - ->setType('application/vnd.openxmlformats-officedocument.wordprocessingml.document') + ->setType($template->getFile()->getType()) ->setFilename($genDocName); $em->persist($storedObject); diff --git a/src/Bundle/ChillDocGeneratorBundle/DependencyInjection/ChillDocGeneratorExtension.php b/src/Bundle/ChillDocGeneratorBundle/DependencyInjection/ChillDocGeneratorExtension.php index 15fd49140..0622377f9 100644 --- a/src/Bundle/ChillDocGeneratorBundle/DependencyInjection/ChillDocGeneratorExtension.php +++ b/src/Bundle/ChillDocGeneratorBundle/DependencyInjection/ChillDocGeneratorExtension.php @@ -26,6 +26,10 @@ class ChillDocGeneratorExtension extends Extension implements PrependExtensionIn { public function load(array $configs, ContainerBuilder $container) { + $configuration = new Configuration(); + $config = $this->processConfiguration($configuration, $configs); + $container->setParameter('chill_doc_generator', $config); + $loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__ . '/../config')); $loader->load('services.yaml'); $loader->load('services/controller.yaml'); @@ -37,6 +41,26 @@ class ChillDocGeneratorExtension extends Extension implements PrependExtensionIn { $this->preprendRoutes($container); $this->prependCruds($container); + $this->prependClientConfig($container); + } + + private function prependClientConfig(ContainerBuilder $container) + { + $configs = $container->getExtensionConfig($this->getAlias()); + $resolvingBag = $container->getParameterBag(); + $configs = $resolvingBag->resolveValue($configs); + + $config = $this->processConfiguration(new Configuration(), $configs); + + $container->prependExtensionConfig('framework', [ + 'http_client' => [ + 'scoped_clients' => [ + 'relatorio.client' => [ + 'scope' => $config['driver']['relatorio']['url'], + ] + ] + ] + ]); } protected function prependCruds(ContainerBuilder $container) diff --git a/src/Bundle/ChillDocGeneratorBundle/DependencyInjection/Configuration.php b/src/Bundle/ChillDocGeneratorBundle/DependencyInjection/Configuration.php index 161886d87..678a871f7 100644 --- a/src/Bundle/ChillDocGeneratorBundle/DependencyInjection/Configuration.php +++ b/src/Bundle/ChillDocGeneratorBundle/DependencyInjection/Configuration.php @@ -14,21 +14,36 @@ namespace Chill\DocGeneratorBundle\DependencyInjection; use Symfony\Component\Config\Definition\Builder\TreeBuilder; use Symfony\Component\Config\Definition\ConfigurationInterface; -/** - * This is the class that validates and merges configuration from your app/config files. - * - * To learn more see {@link http://symfony.com/doc/current/cookbook/bundles/configuration.html} - */ class Configuration implements ConfigurationInterface { public function getConfigTreeBuilder() { - $treeBuilder = new TreeBuilder('chill_calendar'); - $rootNode = $treeBuilder->getRootNode('chill_calendar'); + $treeBuilder = new TreeBuilder('chill_doc_generator'); + $rootNode = $treeBuilder->getRootNode(); - // Here you should define the parameters that are allowed to - // configure your bundle. See the documentation linked above for - // more information on that topic. + $rootNode + ->children() + ->arrayNode('driver') + ->addDefaultsIfNotSet() + ->children() + ->enumNode('type') + ->isRequired() + ->values(['relatorio']) + ->defaultValue('relatorio') + ->end() + ->arrayNode('relatorio') + ->addDefaultsIfNotSet() + ->children() + ->scalarNode('url') + ->isRequired() + ->defaultValue('http://relatorio:8888/') + ->end() + ->end() + ->end() + ->end() + ->end() + ->end() + ; return $treeBuilder; } diff --git a/src/Bundle/ChillDocGeneratorBundle/GeneratorDriver/DriverInterface.php b/src/Bundle/ChillDocGeneratorBundle/GeneratorDriver/DriverInterface.php new file mode 100644 index 000000000..0e1828f3e --- /dev/null +++ b/src/Bundle/ChillDocGeneratorBundle/GeneratorDriver/DriverInterface.php @@ -0,0 +1,12 @@ +relatorioClient = $relatorioClient; + $this->logger = $logger; + $this->url = $parameterBag->get('chill_doc_generator')['driver']['relatorio']['url']; + } + + public function generateFromResource($template, string $resourceType, array $data, string $templateName = null) + { + $formFields = [ + 'variables' => \json_encode($data), + 'template' => new DataPart($template, $templateName ?? uniqid('template_'), $resourceType), + ]; + $form = new FormDataPart($formFields); + + try { + $response = $this->relatorioClient->request('POST', $this->url, [ + 'headers' => $form->getPreparedHeaders()->toArray(), + 'body' => $form->bodyToIterable(), + ]); + + return $response->toStream(); + } catch (HttpExceptionInterface $e) { + $this->logger->error("relatorio: error while generating document", [ + 'msg' => $e->getMessage(), + 'response' => $e->getResponse()->getStatusCode(), + 'content' => $e->getResponse()->getContent(false), + ]); + + throw $e; + } catch (TransportExceptionInterface $e) { + $this->logger->error("relatorio: transport exception", [ + 'msg' => $e->getMessage(), + 'e' => $e->getTraceAsString(), + ]); + + throw $e; + } catch (DecodingExceptionInterface $e) { + $this->logger->error("relatorio: could not decode response", [ + 'msg' => $e->getMessage(), + 'e' => $e->getTraceAsString(), + ]); + + throw $e; + } + } +} diff --git a/src/Bundle/ChillDocGeneratorBundle/config/services.yaml b/src/Bundle/ChillDocGeneratorBundle/config/services.yaml index 25ed037f7..011317959 100644 --- a/src/Bundle/ChillDocGeneratorBundle/config/services.yaml +++ b/src/Bundle/ChillDocGeneratorBundle/config/services.yaml @@ -26,6 +26,13 @@ services: autowire: true autoconfigure: true + Chill\DocGeneratorBundle\GeneratorDriver\: + resource: "../GeneratorDriver/" + autowire: true + autoconfigure: true + + Chill\DocGeneratorBundle\Driver\RelatorioDriver: '@Chill\DocGeneratorBundle\Driver\DriverInterface' + Chill\DocGeneratorBundle\Context\ContextManager: arguments: $contexts: !tagged_iterator { tag: chill_docgen.context, default_index_method: getKey } diff --git a/src/Bundle/ChillDocStoreBundle/Resources/public/module/async_upload/downloader.js b/src/Bundle/ChillDocStoreBundle/Resources/public/module/async_upload/downloader.js index deeb2828f..b8abcae62 100644 --- a/src/Bundle/ChillDocStoreBundle/Resources/public/module/async_upload/downloader.js +++ b/src/Bundle/ChillDocStoreBundle/Resources/public/module/async_upload/downloader.js @@ -5,7 +5,7 @@ var algo = 'AES-CBC'; var initializeButtons = (root) => { var buttons = root.querySelectorAll('a[data-download-button]'); - + for (let i = 0; i < buttons.length; i ++) { initialize(buttons[i]); } @@ -33,9 +33,12 @@ var download = (button) => { fetchError = "Error while fetching file", key, url ; - + + console.log('keyData', keyData); + console.log('ivData', ivData); + button.textContent = labelPreparing; - + window.fetch(urlGenerator) .then((r) => { if (r.ok) { @@ -46,26 +49,19 @@ var download = (button) => { }) .then(data => { url = data.url; - - return window.crypto.subtle.importKey('jwk', keyData, { name: algo, iv: iv}, false, ['decrypt']); - }) - .catch(e => { - console.error("error while importing key"); - console.error(e); - button.appendChild(document.createTextNode(decryptError)); + + if (keyData.length > 0) { + return window.crypto.subtle.importKey('jwk', keyData, { name: algo, iv: iv}, false, ['decrypt']); + } + return Promise.resolve(undefined); }) .then(nKey => { key = nKey; return window.fetch(url); }) - .catch(e => { - console.error("error while fetching data"); - console.error(e); - button.textContent = ""; - button.appendChild(document.createTextNode(fetchError)); - }) .then(r => { + console.log('r', r); if (r.ok) { return r.arrayBuffer(); } else { @@ -73,16 +69,16 @@ var download = (button) => { } }) .then(buffer => { - return window.crypto.subtle.decrypt({ name: algo, iv: iv }, key, buffer); - }) - .catch(e => { - console.error("error while importing key"); - console.error(e); - button.textContent = ""; - button.appendChild(document.createTextNode(decryptError)); + console.log('buffer', buffer); + if (keyData.length > 0) { + return window.crypto.subtle.decrypt({ name: algo, iv: iv }, key, buffer); + } + + return Promise.resolve(buffer); }) .then(decrypted => { - var + console.log('decrypted', decrypted); + var blob = new Blob([decrypted], { type: mimeType }), url = window.URL.createObjectURL(blob) ;