mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-06-07 18:44:08 +00:00
generate document with relatorio: config and driver
This commit is contained in:
parent
475b40e896
commit
2245f83631
@ -16,6 +16,7 @@ use ChampsLibres\AsyncUploaderBundle\TempUrl\TempUrlGeneratorInterface;
|
|||||||
use Chill\DocGeneratorBundle\Context\ContextManager;
|
use Chill\DocGeneratorBundle\Context\ContextManager;
|
||||||
use Chill\DocGeneratorBundle\Context\Exception\ContextNotFoundException;
|
use Chill\DocGeneratorBundle\Context\Exception\ContextNotFoundException;
|
||||||
use Chill\DocGeneratorBundle\Entity\DocGeneratorTemplate;
|
use Chill\DocGeneratorBundle\Entity\DocGeneratorTemplate;
|
||||||
|
use Chill\DocGeneratorBundle\GeneratorDriver\DriverInterface;
|
||||||
use Chill\DocGeneratorBundle\Repository\DocGeneratorTemplateRepository;
|
use Chill\DocGeneratorBundle\Repository\DocGeneratorTemplateRepository;
|
||||||
use Chill\DocStoreBundle\Entity\StoredObject;
|
use Chill\DocStoreBundle\Entity\StoredObject;
|
||||||
use Chill\MainBundle\Pagination\PaginatorFactory;
|
use Chill\MainBundle\Pagination\PaginatorFactory;
|
||||||
@ -54,17 +55,22 @@ final class DocGeneratorTemplateController extends AbstractController
|
|||||||
|
|
||||||
private TempUrlGeneratorInterface $tempUrlGenerator;
|
private TempUrlGeneratorInterface $tempUrlGenerator;
|
||||||
|
|
||||||
|
private DriverInterface $driver;
|
||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
ContextManager $contextManager,
|
ContextManager $contextManager,
|
||||||
DocGeneratorTemplateRepository $docGeneratorTemplateRepository,
|
DocGeneratorTemplateRepository $docGeneratorTemplateRepository,
|
||||||
|
DriverInterface $driver,
|
||||||
LoggerInterface $logger,
|
LoggerInterface $logger,
|
||||||
PaginatorFactory $paginatorFactory,
|
PaginatorFactory $paginatorFactory,
|
||||||
TempUrlGeneratorInterface $tempUrlGenerator,
|
TempUrlGeneratorInterface $tempUrlGenerator,
|
||||||
KernelInterface $kernel,
|
KernelInterface $kernel,
|
||||||
HttpClientInterface $client
|
HttpClientInterface $client
|
||||||
|
|
||||||
) {
|
) {
|
||||||
$this->contextManager = $contextManager;
|
$this->contextManager = $contextManager;
|
||||||
$this->docGeneratorTemplateRepository = $docGeneratorTemplateRepository;
|
$this->docGeneratorTemplateRepository = $docGeneratorTemplateRepository;
|
||||||
|
$this->driver = $driver;
|
||||||
$this->logger = $logger;
|
$this->logger = $logger;
|
||||||
$this->paginatorFactory = $paginatorFactory;
|
$this->paginatorFactory = $paginatorFactory;
|
||||||
$this->tempUrlGenerator = $tempUrlGenerator;
|
$this->tempUrlGenerator = $tempUrlGenerator;
|
||||||
@ -134,71 +140,41 @@ final class DocGeneratorTemplateController extends AbstractController
|
|||||||
throw new \Exception('Error during Decrypt ', 1);
|
throw new \Exception('Error during Decrypt ', 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
$tmpfnameDeCrypted = tempnam($this->kernel->getCacheDir(), 'DECRYPT_DOC_TEMPLATE'); // plus ou moins
|
if (false === $templateResource = fopen('php://memory', 'r+')) {
|
||||||
|
$this->logger->error("Could not write data to memory");
|
||||||
if (!$handle = fopen($tmpfnameDeCrypted, 'ab')) {
|
|
||||||
$this->logger->error("Cannot open file ({$tmpfnameDeCrypted})");
|
|
||||||
|
|
||||||
throw new HttpException(500);
|
throw new HttpException(500);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (false === $ftemplate = fwrite($handle, $dataDecrypted)) {
|
fwrite($templateResource, $dataDecrypted);
|
||||||
$this->logger->error("Cannot write to file ({$tmpfnameDeCrypted})");
|
rewind($templateResource);
|
||||||
|
|
||||||
throw new HttpException(500);
|
|
||||||
}
|
|
||||||
|
|
||||||
dump("Success, wrote (to file ({$tmpfnameDeCrypted})");
|
|
||||||
|
|
||||||
fclose($handle);
|
|
||||||
|
|
||||||
$datas = $context->getData($template, $entity, $contextGenerationData);
|
$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());
|
||||||
|
|
||||||
/*
|
fclose($templateResource);
|
||||||
$templateProcessor = new TemplateProcessor($tmpfnameDeCrypted);
|
|
||||||
|
|
||||||
foreach ($datas['setValues'] as $setValuesConf) {
|
$genDocName = 'doc_' . sprintf('%010d', mt_rand()).'odt';
|
||||||
$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';
|
|
||||||
|
|
||||||
$getUrlGen = $this->tempUrlGenerator->generate(
|
$getUrlGen = $this->tempUrlGenerator->generate(
|
||||||
'PUT',
|
'PUT',
|
||||||
$genDocName
|
$genDocName
|
||||||
);
|
);
|
||||||
|
|
||||||
unlink($tmpfnameDeCrypted);
|
|
||||||
//unlink($tmpfnameGenerated);
|
|
||||||
|
|
||||||
$client = new Client();
|
$client = new Client();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
/*
|
|
||||||
$putResponse = $client->request('PUT', $getUrlGen->url, [
|
$putResponse = $client->request('PUT', $getUrlGen->url, [
|
||||||
'body' => $fileContent,
|
'body' => $generatedResource,
|
||||||
]);
|
|
||||||
*/
|
|
||||||
$putResponse = $client->request('PUT', $getUrlGen->url, [
|
|
||||||
'body' => $ftemplate,
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
if ($putResponse->getStatusCode() === 201) {
|
if ($putResponse->getStatusCode() === 201) {
|
||||||
$em = $this->getDoctrine()->getManager();
|
$em = $this->getDoctrine()->getManager();
|
||||||
$storedObject = new StoredObject();
|
$storedObject = new StoredObject();
|
||||||
$storedObject
|
$storedObject
|
||||||
// currently, only docx is supported
|
->setType($template->getFile()->getType())
|
||||||
->setType('application/vnd.openxmlformats-officedocument.wordprocessingml.document')
|
|
||||||
->setFilename($genDocName);
|
->setFilename($genDocName);
|
||||||
|
|
||||||
$em->persist($storedObject);
|
$em->persist($storedObject);
|
||||||
|
@ -26,6 +26,10 @@ class ChillDocGeneratorExtension extends Extension implements PrependExtensionIn
|
|||||||
{
|
{
|
||||||
public function load(array $configs, ContainerBuilder $container)
|
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 = new Loader\YamlFileLoader($container, new FileLocator(__DIR__ . '/../config'));
|
||||||
$loader->load('services.yaml');
|
$loader->load('services.yaml');
|
||||||
$loader->load('services/controller.yaml');
|
$loader->load('services/controller.yaml');
|
||||||
@ -37,6 +41,26 @@ class ChillDocGeneratorExtension extends Extension implements PrependExtensionIn
|
|||||||
{
|
{
|
||||||
$this->preprendRoutes($container);
|
$this->preprendRoutes($container);
|
||||||
$this->prependCruds($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)
|
protected function prependCruds(ContainerBuilder $container)
|
||||||
|
@ -14,21 +14,36 @@ namespace Chill\DocGeneratorBundle\DependencyInjection;
|
|||||||
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
|
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
|
||||||
use Symfony\Component\Config\Definition\ConfigurationInterface;
|
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
|
class Configuration implements ConfigurationInterface
|
||||||
{
|
{
|
||||||
public function getConfigTreeBuilder()
|
public function getConfigTreeBuilder()
|
||||||
{
|
{
|
||||||
$treeBuilder = new TreeBuilder('chill_calendar');
|
$treeBuilder = new TreeBuilder('chill_doc_generator');
|
||||||
$rootNode = $treeBuilder->getRootNode('chill_calendar');
|
$rootNode = $treeBuilder->getRootNode();
|
||||||
|
|
||||||
// Here you should define the parameters that are allowed to
|
$rootNode
|
||||||
// configure your bundle. See the documentation linked above for
|
->children()
|
||||||
// more information on that topic.
|
->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;
|
return $treeBuilder;
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,12 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Chill\DocGeneratorBundle\GeneratorDriver;
|
||||||
|
|
||||||
|
interface DriverInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @param resource $template
|
||||||
|
* @return resource
|
||||||
|
*/
|
||||||
|
public function generateFromResource($template, string $resourceType, array $data, string $templateName = null);
|
||||||
|
}
|
@ -0,0 +1,73 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Chill\DocGeneratorBundle\GeneratorDriver;
|
||||||
|
|
||||||
|
use Nelmio\Alice\ParameterBag;
|
||||||
|
use Psr\Log\LoggerInterface;
|
||||||
|
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
|
||||||
|
use Symfony\Component\HttpClient\Exception\TransportException;
|
||||||
|
use Symfony\Component\Mime\Part\DataPart;
|
||||||
|
use Symfony\Component\Mime\Part\Multipart\FormDataPart;
|
||||||
|
use Symfony\Contracts\HttpClient\Exception\DecodingExceptionInterface;
|
||||||
|
use Symfony\Contracts\HttpClient\Exception\HttpExceptionInterface;
|
||||||
|
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
|
||||||
|
use Symfony\Contracts\HttpClient\HttpClientInterface;
|
||||||
|
|
||||||
|
class RelatorioDriver implements DriverInterface
|
||||||
|
{
|
||||||
|
private LoggerInterface $logger;
|
||||||
|
|
||||||
|
private HttpClientInterface $relatorioClient;
|
||||||
|
|
||||||
|
private string $url;
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
HttpClientInterface $relatorioClient,
|
||||||
|
ParameterBagInterface $parameterBag,
|
||||||
|
LoggerInterface $logger
|
||||||
|
) {
|
||||||
|
$this->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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -26,6 +26,13 @@ services:
|
|||||||
autowire: true
|
autowire: true
|
||||||
autoconfigure: true
|
autoconfigure: true
|
||||||
|
|
||||||
|
Chill\DocGeneratorBundle\GeneratorDriver\:
|
||||||
|
resource: "../GeneratorDriver/"
|
||||||
|
autowire: true
|
||||||
|
autoconfigure: true
|
||||||
|
|
||||||
|
Chill\DocGeneratorBundle\Driver\RelatorioDriver: '@Chill\DocGeneratorBundle\Driver\DriverInterface'
|
||||||
|
|
||||||
Chill\DocGeneratorBundle\Context\ContextManager:
|
Chill\DocGeneratorBundle\Context\ContextManager:
|
||||||
arguments:
|
arguments:
|
||||||
$contexts: !tagged_iterator { tag: chill_docgen.context, default_index_method: getKey }
|
$contexts: !tagged_iterator { tag: chill_docgen.context, default_index_method: getKey }
|
||||||
|
@ -34,6 +34,9 @@ var download = (button) => {
|
|||||||
key, url
|
key, url
|
||||||
;
|
;
|
||||||
|
|
||||||
|
console.log('keyData', keyData);
|
||||||
|
console.log('ivData', ivData);
|
||||||
|
|
||||||
button.textContent = labelPreparing;
|
button.textContent = labelPreparing;
|
||||||
|
|
||||||
window.fetch(urlGenerator)
|
window.fetch(urlGenerator)
|
||||||
@ -47,25 +50,18 @@ var download = (button) => {
|
|||||||
.then(data => {
|
.then(data => {
|
||||||
url = data.url;
|
url = data.url;
|
||||||
|
|
||||||
return window.crypto.subtle.importKey('jwk', keyData, { name: algo, iv: iv}, false, ['decrypt']);
|
if (keyData.length > 0) {
|
||||||
})
|
return window.crypto.subtle.importKey('jwk', keyData, { name: algo, iv: iv}, false, ['decrypt']);
|
||||||
.catch(e => {
|
}
|
||||||
console.error("error while importing key");
|
return Promise.resolve(undefined);
|
||||||
console.error(e);
|
|
||||||
button.appendChild(document.createTextNode(decryptError));
|
|
||||||
})
|
})
|
||||||
.then(nKey => {
|
.then(nKey => {
|
||||||
key = nKey;
|
key = nKey;
|
||||||
|
|
||||||
return window.fetch(url);
|
return window.fetch(url);
|
||||||
})
|
})
|
||||||
.catch(e => {
|
|
||||||
console.error("error while fetching data");
|
|
||||||
console.error(e);
|
|
||||||
button.textContent = "";
|
|
||||||
button.appendChild(document.createTextNode(fetchError));
|
|
||||||
})
|
|
||||||
.then(r => {
|
.then(r => {
|
||||||
|
console.log('r', r);
|
||||||
if (r.ok) {
|
if (r.ok) {
|
||||||
return r.arrayBuffer();
|
return r.arrayBuffer();
|
||||||
} else {
|
} else {
|
||||||
@ -73,15 +69,15 @@ var download = (button) => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
.then(buffer => {
|
.then(buffer => {
|
||||||
return window.crypto.subtle.decrypt({ name: algo, iv: iv }, key, buffer);
|
console.log('buffer', buffer);
|
||||||
})
|
if (keyData.length > 0) {
|
||||||
.catch(e => {
|
return window.crypto.subtle.decrypt({ name: algo, iv: iv }, key, buffer);
|
||||||
console.error("error while importing key");
|
}
|
||||||
console.error(e);
|
|
||||||
button.textContent = "";
|
return Promise.resolve(buffer);
|
||||||
button.appendChild(document.createTextNode(decryptError));
|
|
||||||
})
|
})
|
||||||
.then(decrypted => {
|
.then(decrypted => {
|
||||||
|
console.log('decrypted', decrypted);
|
||||||
var
|
var
|
||||||
blob = new Blob([decrypted], { type: mimeType }),
|
blob = new Blob([decrypted], { type: mimeType }),
|
||||||
url = window.URL.createObjectURL(blob)
|
url = window.URL.createObjectURL(blob)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user