<?php
namespace App\Twig;
use ApiPlatform\Core\DataProvider\ItemDataProviderInterface;
use ApiPlatform\Core\Exception\ResourceClassNotSupportedException;
use App\Model\CustomerFile\CustomerFile;
use App\Service\ApiWebService;
use App\Service\CustomerFile\CustomerFileDownloadManager;
use App\Service\Provider\ApiGedProvider;
use App\V4\Logger\SentryLogger;
use Psr\Log\LogLevel;
use ReflectionException;
use Symfony\Component\HttpClient\Exception\ClientException;
use Symfony\Component\HttpClient\Exception\ServerException;
use Symfony\Component\HttpFoundation\Request;
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 Throwable;
use Twig\Extension\AbstractExtension;
use Twig\TwigFunction;
class GedImageExtension extends AbstractExtension
{
private const MIME_TYPES_SUPPORTED = ['image/gif', 'image/png', 'image/jpeg', 'image/bmp', 'image/webp'];
/**
* @var ItemDataProviderInterface
*/
private $itemDataProvider;
/**
* @var CustomerFileDownloadManager
*/
private $customerFileDownloadManager;
/**
* @var ApiGedProvider
*/
private $apiGedProvider;
/**
* @var ApiWebService
*/
private $apiWebService;
/**
* @var SentryLogger
*/
private $sentryLogger;
/**
* @param ItemDataProviderInterface $itemDataProvider
* @param CustomerFileDownloadManager $customerFileDownloadManager
* @param ApiGedProvider $apiGedProvider
* @param ApiWebService $apiWebService
* @param SentryLogger $sentryLogger
*/
public function __construct(
ItemDataProviderInterface $itemDataProvider,
CustomerFileDownloadManager $customerFileDownloadManager,
ApiGedProvider $apiGedProvider,
ApiWebService $apiWebService,
SentryLogger $sentryLogger
) {
$this->itemDataProvider = $itemDataProvider;
$this->customerFileDownloadManager = $customerFileDownloadManager;
$this->apiGedProvider = $apiGedProvider;
$this->apiWebService = $apiWebService;
$this->sentryLogger = $sentryLogger;
}
/**
* @return TwigFunction[]
*/
public function getFunctions(): array
{
return [
new TwigFunction('gedImage', [$this, 'getGedImage']),
new TwigFunction('gedImageByPath', [$this, 'getGedImageByPath']),
];
}
/**
* @param string $id
*
* @return string
*
* @throws ResourceClassNotSupportedException
* @throws TransportExceptionInterface
* @throws \Exception
*/
public function getGedImage(string $id): ?string
{
/** @var CustomerFile $customerFile */
$customerFile = $this->itemDataProvider->getItem(CustomerFile::class, $id);
if (!$customerFile instanceof CustomerFile) {
$this->sentryLogger->captureMessage(
SentryLogger::CHANNEL_DATA_RETRIEVER,
sprintf('CustomerFile with id %s cannot be found', $customerFile->getId()),
[
'catchOnClass' => self::class,
'imageId' => $customerFile->getId(),
],
LogLevel::WARNING
);
return null;
}
if (!in_array($customerFile->getMimeType(), self::MIME_TYPES_SUPPORTED, true)) {
$this->sentryLogger->captureMessage(
SentryLogger::CHANNEL_DATA_RETRIEVER,
sprintf('CustomerFile with id %s has the wrong mimeTypes : %s', $customerFile->getId(), $customerFile->getMimeType()),
[
'catchOnClass' => self::class,
'imageId' => $customerFile->getId(),
],
LogLevel::WARNING
);
return null;
}
try {
return $this->getCustomerFileContentForTwig($customerFile);
} catch (Throwable $exception) {
$this->sentryLogger->captureException(
SentryLogger::CHANNEL_DATA_RETRIEVER,
$exception,
[
'catchOnClass' => self::class,
'imageId' => $customerFile->getId(),
]
);
}
return null;
}
/**
* @param string $path
*
* @return string
*
* @throws ClientExceptionInterface
* @throws RedirectionExceptionInterface
* @throws ServerExceptionInterface
* @throws TransportExceptionInterface
* @throws ReflectionException
* @throws \Exception
*/
public function getGedImageByPath(string $path): ?string
{
try {
$response = $this
->apiWebService
->addFilterCustomer()
->addFilter('path', $path)
->send($this->apiGedProvider, Request::METHOD_GET, '/api/customer_resource/get_by_path')
;
$result = json_decode($response->getContent(), true);
} catch (ClientException | ServerException $e) {
$this->sentryLogger->captureException(
SentryLogger::CHANNEL_TWIG_EXTENSION,
$e,
[
'catchOnClass' => self::class,
'apiCalled' => $this->apiGedProvider->getHost(),
'urlCalled' => '/api/customer_resource/get_by_path',
'method' => Request::METHOD_GET,
'params' => [
'path' => $path,
],
]
);
return null;
}
if (null === $result) {
$this->sentryLogger->captureMessage(
SentryLogger::CHANNEL_TWIG_EXTENSION,
'JsonResponse cannot be decode',
[
'catchOnClass' => self::class,
'jsonResponse' => $response->getContent(),
],
LogLevel::CRITICAL
);
return null;
}
$customerFile = (new CustomerFile())->importFromData($result);
if (!in_array($customerFile->getMimeType(), self::MIME_TYPES_SUPPORTED, true)) {
$this->sentryLogger->captureMessage(
SentryLogger::CHANNEL_TWIG_EXTENSION,
sprintf('CustomerFile with id %s has the wrong mimeTypes : %s', $customerFile->getId(), $customerFile->getMimeType()),
[
'catchOnClass' => self::class,
],
LogLevel::WARNING
);
return null;
}
return $this->getCustomerFileContentForTwig($customerFile);
}
/**
* @param CustomerFile $customerFile
*
* @return string
*
* @throws TransportExceptionInterface
*/
private function getCustomerFileContentForTwig(CustomerFile $customerFile): string
{
$tpmPath = $this->customerFileDownloadManager->getFile($customerFile);
return sprintf('data:%s;base64, %s', $customerFile->getMimeType(), base64_encode(file_get_contents($tpmPath)));
}
}