feat: integrate with MailJet API for newsletter registration
This commit is contained in:
@@ -9,12 +9,16 @@ use App\BusProNet\Exception\TimeoutException;
|
||||
use App\BusProNet\Model\Notification;
|
||||
use App\Controller\Booking\Traits\BookingCreateTrait;
|
||||
use App\Controller\Booking\Traits\BookingExceptionHandlerTrait;
|
||||
use App\Exception\NewsletterProviderException;
|
||||
use App\Form\BookingCreateStep4Type;
|
||||
use App\Form\Model\BookingDto;
|
||||
use App\Htmx\HxTrait;
|
||||
use App\Entity\User;
|
||||
use App\Service\BookingPriceCalculatorService;
|
||||
use App\Service\BookingService;
|
||||
use App\Service\BookingSummaryDataService;
|
||||
use App\Service\Newsletter\MailjetNewsletterService;
|
||||
use App\Service\Newsletter\NewsletterDoubleOptInService;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\Form\FormInterface;
|
||||
@@ -38,6 +42,8 @@ class Step4Controller extends AbstractController
|
||||
private readonly BookingPriceCalculatorService $priceCalculator,
|
||||
private readonly ApiClient $apiClient,
|
||||
private readonly CacheInterface $cache,
|
||||
private readonly MailjetNewsletterService $newsletterService,
|
||||
private readonly NewsletterDoubleOptInService $doubleOptInService,
|
||||
private readonly LoggerInterface $logger,
|
||||
) {
|
||||
}
|
||||
@@ -59,7 +65,23 @@ class Step4Controller extends AbstractController
|
||||
return $redirect;
|
||||
}
|
||||
|
||||
$form = $this->createForm(BookingCreateStep4Type::class, $bookingCreateDto);
|
||||
$newsletterTargetEmail = $this->resolveNewsletterTargetEmail($bookingCreateDto);
|
||||
$newsletterOptInVisible = false;
|
||||
if (null !== $newsletterTargetEmail) {
|
||||
try {
|
||||
$newsletterOptInVisible = false === $this->newsletterService->isSubscribed($newsletterTargetEmail);
|
||||
} catch (NewsletterProviderException $e) {
|
||||
$this->logger->warning('Could not resolve newsletter subscription state in booking step 4', [
|
||||
'email' => $newsletterTargetEmail,
|
||||
'error' => $e->getMessage(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
$form = $this->createForm(BookingCreateStep4Type::class, $bookingCreateDto, [
|
||||
'show_newsletter_opt_in' => $newsletterOptInVisible,
|
||||
'newsletter_target_email' => $newsletterTargetEmail,
|
||||
]);
|
||||
$form->handleRequest($request);
|
||||
|
||||
if (true === $form->isSubmitted() && true === $form->isValid()) {
|
||||
@@ -71,7 +93,7 @@ class Step4Controller extends AbstractController
|
||||
return $this->handleApiError(
|
||||
'Booking creation failed - API notification',
|
||||
['message' => $bookingResponse->message],
|
||||
$bookingResponse->message ?? 'Ein Fehler ist aufgetreten. Bitte versuchen Sie es erneut.',
|
||||
$bookingResponse->message ?? 'Ein Fehler ist aufgetreten. Bitte versuchen es erneut.',
|
||||
$bookingCreateDto,
|
||||
$form
|
||||
);
|
||||
@@ -92,6 +114,21 @@ class Step4Controller extends AbstractController
|
||||
);
|
||||
}
|
||||
|
||||
$newsletterOptInSelected = $newsletterOptInVisible
|
||||
&& $form->has('newsletterOptIn')
|
||||
&& true === $form->get('newsletterOptIn')->getData();
|
||||
|
||||
if (true === $newsletterOptInSelected && null !== $newsletterTargetEmail) {
|
||||
try {
|
||||
$this->doubleOptInService->requestConfirmation($newsletterTargetEmail);
|
||||
} catch (NewsletterProviderException|\InvalidArgumentException $e) {
|
||||
$this->logger->warning('Newsletter confirmation request failed after booking', [
|
||||
'email' => $newsletterTargetEmail,
|
||||
'error' => $e->getMessage(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
// Success: Store booking data in flash for conversion tracking
|
||||
$summaryData = $this->summaryDataService->getSummaryData($bookingCreateDto);
|
||||
$this->addFlash('booking_number', $bookingResponse->bookingNumber);
|
||||
@@ -114,7 +151,7 @@ class Step4Controller extends AbstractController
|
||||
'exception' => $e->getMessage(),
|
||||
'trace' => $e->getTraceAsString(),
|
||||
],
|
||||
'Die Anfrage hat zu lange gedauert. Bitte versuchen Sie es erneut.',
|
||||
'Die Anfrage hat zu lange gedauert. Bitte versuche es erneut.',
|
||||
$bookingCreateDto,
|
||||
$form
|
||||
);
|
||||
@@ -132,13 +169,18 @@ class Step4Controller extends AbstractController
|
||||
}
|
||||
}
|
||||
|
||||
return $this->renderStepForm($bookingCreateDto, $form);
|
||||
return $this->renderStepForm($bookingCreateDto, $form, $newsletterOptInVisible, $newsletterTargetEmail);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the step 4 form with standard template variables.
|
||||
*/
|
||||
private function renderStepForm(BookingDto $bookingCreateDto, FormInterface $form): Response
|
||||
private function renderStepForm(
|
||||
BookingDto $bookingCreateDto,
|
||||
FormInterface $form,
|
||||
bool $newsletterOptInVisible,
|
||||
?string $newsletterTargetEmail,
|
||||
): Response
|
||||
{
|
||||
// Get complete summary data (pricing, rooms, CMS data)
|
||||
$summaryData = $this->summaryDataService->getSummaryData($bookingCreateDto);
|
||||
@@ -148,9 +190,33 @@ class Step4Controller extends AbstractController
|
||||
'form' => $form->createView(),
|
||||
'summaryData' => $summaryData,
|
||||
'participantPrices' => $this->priceCalculator->calculateAllParticipantIndividualPrices($bookingCreateDto),
|
||||
'newsletterOptInVisible' => $newsletterOptInVisible,
|
||||
'newsletterTargetEmail' => $newsletterTargetEmail,
|
||||
]);
|
||||
}
|
||||
|
||||
private function resolveNewsletterTargetEmail(BookingDto $bookingDto): ?string
|
||||
{
|
||||
$currentUser = $this->getUser();
|
||||
$email = null;
|
||||
|
||||
if ($currentUser instanceof User) {
|
||||
$email = $currentUser->getEmail();
|
||||
}
|
||||
|
||||
if ((null === $email || '' === trim((string) $email)) && isset($bookingDto->participants[0])) {
|
||||
$email = $bookingDto->participants[0]->email;
|
||||
}
|
||||
|
||||
if (null === $email) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$normalizedEmail = mb_strtolower(trim($email));
|
||||
|
||||
return false !== filter_var($normalizedEmail, FILTER_VALIDATE_EMAIL) ? $normalizedEmail : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears travel data and availability cache after successful booking.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user