Files
myep/src/Controller/Voucher/IndexController.php
T

109 lines
4.1 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Controller\Voucher;
use App\Exception\VoucherShopUnavailableException;
use App\Form\Model\VoucherPurchaseDto;
use App\Htmx\HxTrait;
use App\Model\PurchaseFlow;
use App\Service\PurchaseFlowResolver;
use App\Service\VoucherPurchaseSessionManager;
use App\Service\VoucherTemplateProvider;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Attribute\MapQueryParameter;
use Symfony\Component\Routing\Attribute\Route;
/**
* Entry, cancellation and error pages of the voucher purchase flow, which replaces the voucher
* shop hosted by BusProNet (maske_gutschein.php).
*/
class IndexController extends AbstractController
{
use HxTrait;
public function __construct(
private readonly VoucherPurchaseSessionManager $sessionManager,
private readonly VoucherTemplateProvider $templateProvider,
private readonly PurchaseFlowResolver $purchaseFlowResolver,
) {
}
/**
* Entry point: starts a purchase, or resumes the unfinished one, and sends the visitor to the
* login page (sign in or continue as guest).
*
* A GET with side effects, kept safe for speculative fetches by being idempotent: an existing
* draft is never reset, only its return URL is updated when one is given. Starting over goes through cancel, and
* a completed purchase clears the draft. /voucher is an English alias for links.
*/
#[Route('/gutschein', name: 'app_voucher', methods: ['GET'])]
#[Route('/voucher', name: 'app_voucher_alias', methods: ['GET'])]
public function index(Request $request, #[MapQueryParameter('r')] ?string $returnUrl = null): Response
{
$resumed = null !== $this->sessionManager->find($request);
if (!$resumed || null !== $returnUrl) {
$this->sessionManager->storeReturnUrl($request, $returnUrl);
}
if (!$resumed) {
try {
$templates = $this->templateProvider->getTemplates();
$paymentMethod = $this->templateProvider->getPaymentMethod();
} catch (VoucherShopUnavailableException) {
$this->addFlash('error', 'Gutscheine können gerade nicht gekauft werden. Bitte versuche es später noch einmal.');
return $this->redirectToRoute('app_voucher_error');
}
$dto = new VoucherPurchaseDto();
$dto->minAmount = $templates->minAmount;
$dto->maxAmount = $templates->maxAmount;
$dto->paymentMethod = $paymentMethod;
if (1 === \count($templates->templates)) {
$dto->template = $templates->templates[0];
}
$this->sessionManager->save($request, $dto);
}
$this->purchaseFlowResolver->markStarted($request, PurchaseFlow::Voucher);
return $this->redirectToRoute('app_login');
}
#[Route('/vouchers/cancel', name: 'app_voucher_cancel', methods: ['GET', 'POST'])]
public function cancel(Request $request): Response
{
if (Request::METHOD_POST !== $request->getMethod()) {
return $this->render('voucher/modal_cancel.html.twig');
}
$returnUrl = $this->sessionManager->getReturnUrl($request);
$this->sessionManager->clear($request);
// Without this, a later login would send the user back into the cancelled purchase
$request->getSession()->remove('_security.main.target_path');
if (null !== $this->getUser()) {
$this->addFlash('info', 'Gutscheinkauf abgebrochen.');
return $this->htmxRedirect($request, $this->generateUrl('app_account'));
}
return $this->htmxRedirect($request, $returnUrl);
}
#[Route('/vouchers/create/error', name: 'app_voucher_error', methods: ['GET'])]
public function error(Request $request): Response
{
return $this->render('booking/create/error.html.twig', [
'returnUrl' => $this->sessionManager->getReturnUrl($request),
'defaultErrorMessage' => 'Es ist ein Fehler beim Gutscheinkauf aufgetreten.',
]);
}
}