<?php
namespace App\V4\Service\Pdf;
use ApiPlatform\Core\DataProvider\ItemDataProviderInterface;
use ApiPlatform\Core\Exception\ResourceClassNotSupportedException;
use App\Model\CustomerFile\CustomerFile;
use App\Model\Template\Template;
use App\Service\ApiWebService;
use App\Service\Cache\CacheManager;
use App\Service\Provider\ApiGedProvider;
use App\V4\Handler\Quote\QuoteGeneratorHandler;
use App\V4\Model\Quote\Quote;
use DateTime;
use Lexik\Bundle\JWTAuthenticationBundle\TokenExtractor\TokenExtractorInterface;
use Psr\Cache\InvalidArgumentException;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface;
use Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface;
use Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface;
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
use Twig\Environment;
use Twig\Error\LoaderError;
use Twig\Error\SyntaxError;
class PdfGenerator
{
public const OPTION_MODE = 'mode';
public const MODE_ADD = 'add';
public const MODE_REPLACE = 'replace';
private const FILE_MIME_TYPE = 'application/pdf';
/**
* @var ApiWebService
*/
private $apiWebService;
/**
* @var ApiGedProvider
*/
private $apiGedProvider;
/**
* @var RouterInterface
*/
private $router;
/**
* @var RequestStack
*/
private $requestStack;
/**
* @var TokenExtractorInterface
*/
private $tokenExtractor;
/**
* @var Environment
*/
private $environment;
/**
* @var QuoteGeneratorHandler
*/
private $quoteGeneratorHandler;
/**
* @var ItemDataProviderInterface
*/
private $itemDataProvider;
/**
* @var CacheManager
*/
private $cacheManager;
public function __construct(
ApiWebService $apiWebService,
ApiGedProvider $apiGedProvider,
RouterInterface $router,
RequestStack $requestStack,
TokenExtractorInterface $tokenExtractor,
Environment $environment,
QuoteGeneratorHandler $quoteGeneratorHandler,
ItemDataProviderInterface $itemDataProvider,
CacheManager $cacheManager
) {
$this->apiWebService = $apiWebService;
$this->apiGedProvider = $apiGedProvider;
$this->router = $router;
$this->requestStack = $requestStack;
$this->tokenExtractor = $tokenExtractor;
$this->environment = $environment;
$this->quoteGeneratorHandler = $quoteGeneratorHandler;
$this->itemDataProvider = $itemDataProvider;
$this->cacheManager = $cacheManager;
}
/**
* @throws TransportExceptionInterface
*/
public function generatePdfForQuote(Quote $quote, string $base64PdfFile): bool
{
$currentDate = new DateTime();
$gedResponse = $this->apiWebService->send(
$this->apiGedProvider,
Request::METHOD_POST,
'/api/generate/pdf',
[
'customerFile' => $base64PdfFile,
'customerMimeType' => self::FILE_MIME_TYPE,
'fileLabel' => ($quote->getName() ?? 'Devis').' '.$currentDate->format('Y-m-d_H-i').'.pdf',
'customerRealFileName' => $quote->getProspectId().'_'.$quote->getId().'.pdf',
'quoteId' => $quote->getId(),
'quoteName' => $quote->getName(),
'prospectId' => $quote->getProspectId(),
'customerId' => $quote->getCustomerId(),
'isQuotePdf' => true,
]
);
return $gedResponse->getStatusCode() === Response::HTTP_OK;
}
/**
* @throws TransportExceptionInterface
* @throws ClientExceptionInterface
* @throws RedirectionExceptionInterface
* @throws ServerExceptionInterface
* @throws InvalidArgumentException
*/
public function generatePdfWithTemplateForQuote(Quote $quote, string $base64Html, string $optionMode = self::MODE_REPLACE, ?string $templateId = null): array
{
$currentDate = new DateTime();
$gedResponse = $this->apiWebService->send(
$this->apiGedProvider,
Request::METHOD_POST,
'/api/generate/pdf/template',
[
'customerFile' => $base64Html,
'customerMimeType' => self::FILE_MIME_TYPE,
'fileLabel' => ($quote->getName() ?? 'Devis').' '.$currentDate->format('Y-m-d_H-i').'.pdf',
'realFileName' => $quote->getProspectId().'_'.$quote->getId().'.pdf',
'quoteId' => $quote->getId(),
'quoteName' => $quote->getName(),
'prospectId' => $quote->getProspectId(),
'customerId' => $quote->getCustomerId(),
'templateId' => $templateId,
'isQuotePdf' => true,
self::OPTION_MODE => $optionMode,
]
);
// Then decode response and generate download link
$response = json_decode($gedResponse->getContent(), true);
$token = $this->tokenExtractor->extract($this->requestStack->getMasterRequest());
if ($token) {
$response['deleteLink'] = $this->router->generate(
'customer_files_delete_route',
['id' => $response['id']],
UrlGeneratorInterface::ABSOLUTE_URL
);
$response['downloadLink'] = $this->router->generate(
'files_download_route',
['id' => $response['id']],
UrlGeneratorInterface::ABSOLUTE_URL
);
}
$this->cacheManager->invalidateTag([CustomerFile::class]);
return $response;
}
/**
* @throws SyntaxError
* @throws LoaderError
* @throws ResourceClassNotSupportedException
*/
public function generatePdfContentByTemplate(Quote $quote, ?string $templateId = null, array $data = []): string
{
$template = $this->itemDataProvider->getItem(Template::class, $templateId);
if (!$template instanceof Template) {
throw new NotFoundHttpException("template not found");
}
$generatedTwig = $this->environment->createTemplate($template->getContent(), 'quote_pdf');
$quoteVars = $this->quoteGeneratorHandler->getQuoteVariables($quote);
if (!isset($data['currentPdfVersion'])) {
$data['currentPdfVersion'] = $quote->getCurrentPdfVersion();
}
$currentDate = new DateTime();
if (!isset($data['currentPdfVersionDate'])) {
$data['currentPdfVersionDate'] = $currentDate->format('d/m/Y');
}
if (!isset($data['quoteLinesBySection'])) {
$data['quoteLinesBySection'] = $this->quoteGeneratorHandler->getQuoteLinesBySection($quoteVars);
}
return base64_encode($generatedTwig->render(array_merge($quoteVars, $data)));
}
}