mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-06-14 22:34:24 +00:00
364 lines
12 KiB
PHP
364 lines
12 KiB
PHP
<?php
|
|
|
|
/**
|
|
* Chill is a software for social workers
|
|
*
|
|
* For the full copyright and license information, please view
|
|
* the LICENSE file that was distributed with this source code.
|
|
*/
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace Chill\DocGeneratorBundle\Controller;
|
|
|
|
use Chill\DocGeneratorBundle\Context\ContextManager;
|
|
use Chill\DocGeneratorBundle\Context\DocGeneratorContextWithPublicFormInterface;
|
|
use Chill\DocGeneratorBundle\Context\Exception\ContextNotFoundException;
|
|
use Chill\DocGeneratorBundle\Entity\DocGeneratorTemplate;
|
|
use Chill\DocGeneratorBundle\GeneratorDriver\DriverInterface;
|
|
use Chill\DocGeneratorBundle\GeneratorDriver\Exception\TemplateException;
|
|
use Chill\DocGeneratorBundle\Repository\DocGeneratorTemplateRepository;
|
|
use Chill\DocStoreBundle\Entity\StoredObject;
|
|
use Chill\DocStoreBundle\Service\StoredObjectManagerInterface;
|
|
use Chill\MainBundle\Pagination\PaginatorFactory;
|
|
use Chill\MainBundle\Serializer\Model\Collection;
|
|
use Doctrine\ORM\EntityManagerInterface;
|
|
use Exception;
|
|
use Psr\Log\LoggerInterface;
|
|
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
|
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
|
|
use Symfony\Component\Form\Extension\Core\Type\FileType;
|
|
use Symfony\Component\HttpFoundation\File\File;
|
|
use Symfony\Component\HttpFoundation\RedirectResponse;
|
|
use Symfony\Component\HttpFoundation\Request;
|
|
// TODO à mettre dans services
|
|
use Symfony\Component\HttpFoundation\Response;
|
|
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
|
|
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
|
use Symfony\Component\Routing\Annotation\Route;
|
|
use Symfony\Component\Serializer\Normalizer\AbstractNormalizer;
|
|
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
|
|
use Symfony\Contracts\HttpClient\HttpClientInterface;
|
|
use Throwable;
|
|
use function strlen;
|
|
|
|
final class DocGeneratorTemplateController extends AbstractController
|
|
{
|
|
private HttpClientInterface $client;
|
|
|
|
private ContextManager $contextManager;
|
|
|
|
private DocGeneratorTemplateRepository $docGeneratorTemplateRepository;
|
|
|
|
private DriverInterface $driver;
|
|
|
|
private EntityManagerInterface $entityManager;
|
|
|
|
private LoggerInterface $logger;
|
|
|
|
private PaginatorFactory $paginatorFactory;
|
|
|
|
private StoredObjectManagerInterface $storedObjectManager;
|
|
|
|
public function __construct(
|
|
ContextManager $contextManager,
|
|
DocGeneratorTemplateRepository $docGeneratorTemplateRepository,
|
|
DriverInterface $driver,
|
|
LoggerInterface $logger,
|
|
PaginatorFactory $paginatorFactory,
|
|
HttpClientInterface $client,
|
|
StoredObjectManagerInterface $storedObjectManager,
|
|
EntityManagerInterface $entityManager
|
|
) {
|
|
$this->contextManager = $contextManager;
|
|
$this->docGeneratorTemplateRepository = $docGeneratorTemplateRepository;
|
|
$this->driver = $driver;
|
|
$this->logger = $logger;
|
|
$this->paginatorFactory = $paginatorFactory;
|
|
$this->client = $client;
|
|
$this->storedObjectManager = $storedObjectManager;
|
|
$this->entityManager = $entityManager;
|
|
}
|
|
|
|
/**
|
|
* @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(
|
|
'Context not found.',
|
|
$e
|
|
);
|
|
}
|
|
|
|
$entity = $this
|
|
->entityManager
|
|
->getRepository($context->getEntityClass())
|
|
->find($entityId);
|
|
|
|
if (null === $entity) {
|
|
throw new NotFoundHttpException(
|
|
sprintf('Entity with classname %s and id %s is not found', $entityClassName, $entityId)
|
|
);
|
|
}
|
|
|
|
$contextGenerationData = [
|
|
'test_file' => null,
|
|
];
|
|
|
|
if (
|
|
$context instanceof DocGeneratorContextWithPublicFormInterface
|
|
&& $context->hasPublicForm($template, $entity) || $isTest
|
|
) {
|
|
if ($context instanceof DocGeneratorContextWithPublicFormInterface && $context->hasPublicForm($template, $entity)) {
|
|
$builder = $this->createFormBuilder(
|
|
array_merge(
|
|
$context->getFormData($template, $entity),
|
|
$isTest ? ['test_file' => null, 'show_data' => false] : []
|
|
)
|
|
);
|
|
|
|
$context->buildPublicForm($builder, $template, $entity);
|
|
} else {
|
|
$builder = $this->createFormBuilder(
|
|
['test_file' => null, 'show_data' => false]
|
|
);
|
|
}
|
|
|
|
if ($isTest) {
|
|
$builder->add('test_file', FileType::class, [
|
|
'label' => 'Template file',
|
|
'required' => false,
|
|
]);
|
|
$builder->add('show_data', CheckboxType::class, [
|
|
'label' => 'Show data instead of generating',
|
|
'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);
|
|
}
|
|
}
|
|
|
|
$document = $template->getFile();
|
|
|
|
if ($isTest && ($contextGenerationData['test_file'] instanceof File)) {
|
|
$dataDecrypted = file_get_contents($contextGenerationData['test_file']->getPathname());
|
|
} else {
|
|
try {
|
|
$dataDecrypted = $this->storedObjectManager->read($document);
|
|
} catch (Throwable $exception) {
|
|
throw $exception;
|
|
}
|
|
}
|
|
|
|
if ($isTest && isset($form) && $form['show_data']->getData()) {
|
|
// very ugly hack...
|
|
dd($context->getData($template, $entity, $contextGenerationData));
|
|
}
|
|
|
|
try {
|
|
$generatedResource = $this
|
|
->driver
|
|
->generateFromString(
|
|
$dataDecrypted,
|
|
$template->getFile()->getType(),
|
|
$context->getData($template, $entity, $contextGenerationData),
|
|
$template->getFile()->getFilename()
|
|
);
|
|
} catch (TemplateException $e) {
|
|
return new Response(
|
|
implode("\n", $e->getErrors()),
|
|
400,
|
|
[
|
|
'Content-Type' => 'text/plain',
|
|
]
|
|
);
|
|
}
|
|
|
|
if ($isTest) {
|
|
return new Response(
|
|
$generatedResource,
|
|
Response::HTTP_OK,
|
|
[
|
|
'Content-Transfer-Encoding', 'binary',
|
|
'Content-Type' => 'application/vnd.oasis.opendocument.text',
|
|
'Content-Disposition' => 'attachment; filename="generated.odt"',
|
|
'Content-Length' => strlen($generatedResource),
|
|
],
|
|
);
|
|
}
|
|
|
|
/** @var StoredObject $storedObject */
|
|
$storedObject = (new ObjectNormalizer())
|
|
->denormalize(
|
|
[
|
|
'type' => $template->getFile()->getType(),
|
|
'filename' => sprintf('%s_odt', uniqid('doc_', true)),
|
|
],
|
|
StoredObject::class
|
|
);
|
|
|
|
try {
|
|
$this->storedObjectManager->write($storedObject, $generatedResource);
|
|
} catch (Throwable $exception) {
|
|
throw $exception;
|
|
}
|
|
|
|
$this->entityManager->persist($storedObject);
|
|
|
|
try {
|
|
$context
|
|
->storeGenerated(
|
|
$template,
|
|
$storedObject,
|
|
$entity,
|
|
$contextGenerationData
|
|
);
|
|
} catch (Exception $e) {
|
|
$this
|
|
->logger
|
|
->error(
|
|
'Unable to store the associated document to entity',
|
|
[
|
|
'entityClassName' => $entityClassName,
|
|
'entityId' => $entityId,
|
|
'contextKey' => $context->getName(),
|
|
]
|
|
);
|
|
|
|
throw $e;
|
|
}
|
|
|
|
$this->entityManager->flush();
|
|
|
|
return $this
|
|
->redirectToRoute(
|
|
'chill_wopi_file_edit',
|
|
[
|
|
'fileId' => $storedObject->getUuid(),
|
|
'returnPath' => $request->query->get('returnPath', '/'),
|
|
]
|
|
);
|
|
}
|
|
}
|