feat: MailJet list handling with DOI, webhook receiver and API endpoint

addresses #869cut134
This commit is contained in:
Björn Fromme
2026-04-29 09:51:57 +02:00
parent df7885ca1c
commit e4ef2f7adc
46 changed files with 3389 additions and 322 deletions
@@ -14,11 +14,11 @@ use App\Exception\NewsletterProviderException;
use App\Exception\TravelNotFoundException;
use App\Form\BookingCreateStep4Type;
use App\Form\Model\BookingDto;
use App\Form\Model\ParticipantDto;
use App\Htmx\HxTrait;
use App\Service\BookingConfigurator;
use App\Service\BookingCreateContextFactory;
use App\Service\BookingSessionManager;
use App\Service\MailjetApiClient;
use App\Service\NewsletterManager;
use Psr\Log\LoggerInterface;
use Symfony\Component\Form\FormInterface;
@@ -40,7 +40,6 @@ class Step4Controller extends AbstractBookingCreateController
private readonly BookingCreateContextFactory $createContextFactory,
private readonly ApiClient $apiClient,
private readonly CacheInterface $cache,
private readonly MailjetApiClient $newsletterService,
private readonly NewsletterManager $doubleOptInService,
private readonly LoggerInterface $logger,
) {
@@ -64,17 +63,7 @@ class Step4Controller extends AbstractBookingCreateController
}
$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(),
]);
}
}
$newsletterOptInVisible = null !== $newsletterTargetEmail;
$form = $this->createForm(BookingCreateStep4Type::class, $bookingCreateDto, [
'show_newsletter_opt_in' => $newsletterOptInVisible,
@@ -122,7 +111,12 @@ class Step4Controller extends AbstractBookingCreateController
if (true === $newsletterOptInSelected && null !== $newsletterTargetEmail) {
try {
$this->doubleOptInService->requestConfirmation($newsletterTargetEmail);
$targetParticipant = $this->resolveNewsletterTargetParticipant($bookingCreateDto);
$this->doubleOptInService->requestDefaultListSubscription(
$newsletterTargetEmail,
$targetParticipant?->firstName,
$targetParticipant?->lastName,
);
} catch (NewsletterProviderException|\InvalidArgumentException $e) {
$this->logger->warning('Newsletter confirmation request failed after booking', [
'email' => $newsletterTargetEmail,
@@ -216,6 +210,20 @@ class Step4Controller extends AbstractBookingCreateController
return false !== filter_var($normalizedEmail, FILTER_VALIDATE_EMAIL) ? $normalizedEmail : null;
}
private function resolveNewsletterTargetParticipant(BookingDto $bookingDto): ?ParticipantDto
{
$participant = $bookingDto->participants[0] ?? null;
if (null === $participant) {
return null;
}
if (null === $participant->firstName && null === $participant->lastName) {
return null;
}
return $participant;
}
/**
* Clears travel data and availability cache after successful booking.
*/