<?php declare(strict_types=1);
namespace Uandi\UandiEfbErpSynchronization\Storefront\Controller;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
use Psr\Log\LoggerInterface;
use Shopware\Core\Checkout\Cart\Exception\CustomerNotLoggedInException;
use Shopware\Core\Checkout\Customer\CustomerEntity;
use Shopware\Core\Content\ImportExport\Exception\FileNotFoundException;
use Shopware\Core\Framework\Routing\Annotation\LoginRequired;
use Shopware\Core\Framework\Routing\Annotation\RouteScope;
use Shopware\Core\System\SalesChannel\SalesChannelContext;
use Shopware\Storefront\Controller\StorefrontController;
use Shopware\Storefront\Page\GenericPageLoaderInterface;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\ResponseHeaderBag;
use Symfony\Component\Mime\FileinfoMimeTypeGuesser;
use Symfony\Component\Routing\Annotation\Route;
use Uandi\UandiEfbErpSynchronization\Service\Document\File;
use Uandi\UandiEfbErpSynchronization\Service\Document\Lists\DocumentListServiceInterface;
use Uandi\UandiEfbErpSynchronization\Service\Document\Lists\ExistingOrdersPdfService;
use Uandi\UandiEfbErpSynchronization\Service\Document\Lists\ListingServiceFactory;
/**
* @RouteScope(scopes={"storefront"})
*/
class ErpDocumentListController extends StorefrontController
{
private File $fileService;
private ListingServiceFactory $listingServiceFactory;
private GenericPageLoaderInterface $pageLoader;
private LoggerInterface $logger;
public function __construct(
File $fileService,
ListingServiceFactory $listingServiceFactory,
GenericPageLoaderInterface $pageLoader,
LoggerInterface $logger
) {
$this->fileService = $fileService;
$this->listingServiceFactory = $listingServiceFactory;
$this->pageLoader = $pageLoader;
$this->logger = $logger;
}
/**
* @LoginRequired()
* @Route("/documentList/{type}", name="frontend.erpdocuments.page", methods={"GET"})
*
* @throws CustomerNotLoggedInException
*/
public function index(Request $request, SalesChannelContext $context, CustomerEntity $customer): Response
{
$type = $request->get('type');
$request->query->set('customerNumber', $customer->getCustomerNumber());
$listingService = $this->getListingService($type);
$fileList = $listingService->fetchDocumentList($request, $context);
if ($type == ExistingOrdersPdfService::DOCUMENT_TYPE_TEXT) {
return $this->getExistingOrdersResponse($fileList, $customer, $type);
}
$mode = 'standard';
if ($this->isB2b()) {
$mode = 'b2bsuite';
}
$page = $this->pageLoader->load($request, $context);
return $this->renderStorefront(sprintf('@UandiEfbErpSynchronization/storefront/page/erp-documents/%s-wrapper.html.twig', $mode), [
'page' => $page,
'type' => $type,
'availableErpDocumentTypes' => $this->listingServiceFactory->getAvailableTypes(),
'availableFilters' => $listingService->getAvailableFilters(),
'searchResult' => $fileList,
]);
}
/**
* @LoginRequired()
* @Route("/documentList/download/{type}/{id}", name="frontend.erpdocuments.download", methods={"GET"})
*
* @throws CustomerNotLoggedInException
*/
public function download(Request $request, CustomerEntity $customer, SalesChannelContext $salesChannelContext): Response
{
$file = $this->fileService->getFile(
$salesChannelContext,
$customer->getCustomerNumber(),
$request->get('id'),
$request->get('type')
);
if (empty($file)) {
throw new FileNotFoundException($request->get('id'));
}
return $this->createDownloadResponse($file['tempFile'], $file['fileName']);
}
/**
* Get the required service from the factory.
*
* @param string $type
*
* @return DocumentListServiceInterface|null
*/
private function getListingService(string $type): ?DocumentListServiceInterface
{
if (false === $this->listingServiceFactory->has($type)) {
throw $this->createNotFoundException();
}
return $this->listingServiceFactory->create($type);
}
/**
* @return bool
*/
private function isB2b(): bool
{
try {
return $this->container->get('b2b_front_auth.authentication_service')->isB2b();
} catch (NotFoundExceptionInterface | ContainerExceptionInterface $exception) {
return false;
}
}
/**
* For the supplied filenames (stored file / display to the user) create an appropriate download response.
*
* @param string $filePath
* @param string $frontendFileName
*
* @return BinaryFileResponse
*/
private function createDownloadResponse(string $filePath, string $frontendFileName): BinaryFileResponse
{
$response = new BinaryFileResponse($filePath);
$mimeTypeGuesser = new FileinfoMimeTypeGuesser();
$response->headers->set('Content-Type', $mimeTypeGuesser->guessMimeType($filePath));
$response->setContentDisposition(ResponseHeaderBag::DISPOSITION_ATTACHMENT, $frontendFileName);
return $response;
}
/**
* Handle the existing orders response.
*
* @param array $fileList
* @param CustomerEntity $customer
* @param string $type
*
* @return BinaryFileResponse
*/
public function getExistingOrdersResponse(array $fileList, CustomerEntity $customer, string $type): BinaryFileResponse
{
if (!array_key_exists('base64_data_stream', $fileList)) {
$this->logger->error(
sprintf(
'%s: Customer %s: %s: no stream on API response (response: %s)',
__METHOD__,
$customer->getCustomerNumber(),
$type,
print_r($fileList, true)
)
);
throw $this->createNotFoundException();
}
$fileName = $this->fileService->storePdf($fileList);
return $this->createDownloadResponse($fileName, 'Auftragsbestandsliste.pdf');
}
}