feat: offer a newsletter opt-in for the other participants
addresses #869etn6c5
This commit is contained in:
1 parent
96b7b3f451
commit
876e69e62c
10 files changed
+598
-71
No files matched your search
@@ -10,16 +10,14 @@ use App\BusProNet\Model\Notification;
|
||||
use App\Entity\User;
|
||||
use App\Exception\BookingSessionNotFoundException;
|
||||
use App\Exception\HotelNotInTravelException;
|
||||
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\BookingNewsletterOptIn;
|
||||
use App\Service\BookingSessionManager;
|
||||
use App\Service\NewsletterManager;
|
||||
use App\Service\ParticipantFormSupport;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\Form\FormInterface;
|
||||
@@ -41,7 +39,7 @@ class Step4Controller extends AbstractBookingCreateController
|
||||
private readonly BookingCreateContextFactory $createContextFactory,
|
||||
private readonly ApiClient $apiClient,
|
||||
private readonly CacheInterface $cache,
|
||||
private readonly NewsletterManager $doubleOptInService,
|
||||
private readonly BookingNewsletterOptIn $bookingNewsletterOptIn,
|
||||
private readonly ParticipantFormSupport $participantFormSupportService,
|
||||
private readonly LoggerInterface $logger,
|
||||
) {
|
||||
@@ -64,11 +62,15 @@ class Step4Controller extends AbstractBookingCreateController
|
||||
return $redirect;
|
||||
}
|
||||
|
||||
$newsletterTargetEmail = $this->resolveNewsletterTargetEmail($bookingCreateDto);
|
||||
$user = $this->getUser();
|
||||
$newsletterTargetEmail = $this->bookingNewsletterOptIn->resolveApplicantEmail($bookingCreateDto, $user instanceof User ? $user : null);
|
||||
$newsletterOptInVisible = null !== $newsletterTargetEmail;
|
||||
$companions = $this->bookingNewsletterOptIn->resolveCompanions($bookingCreateDto, $newsletterTargetEmail);
|
||||
$companionNewsletterOptInVisible = [] !== $companions;
|
||||
|
||||
$form = $this->createForm(BookingCreateStep4Type::class, $bookingCreateDto, [
|
||||
'show_newsletter_opt_in' => $newsletterOptInVisible,
|
||||
'show_companion_newsletter_opt_in' => $companionNewsletterOptInVisible,
|
||||
'newsletter_target_email' => $newsletterTargetEmail,
|
||||
]);
|
||||
$form->handleRequest($request);
|
||||
@@ -94,7 +96,7 @@ class Step4Controller extends AbstractBookingCreateController
|
||||
$bookingResponse->message ?? 'Ein Fehler ist aufgetreten. Bitte versuchen es erneut.',
|
||||
);
|
||||
|
||||
return $this->renderStepForm($bookingCreateDto, $form, $newsletterOptInVisible, $newsletterTargetEmail);
|
||||
return $this->renderStepForm($bookingCreateDto, $form, $newsletterOptInVisible, $newsletterTargetEmail, $companionNewsletterOptInVisible);
|
||||
}
|
||||
|
||||
if (false === $bookingResponse->isBookingSuccessful()) {
|
||||
@@ -110,7 +112,7 @@ class Step4Controller extends AbstractBookingCreateController
|
||||
$errorMessage,
|
||||
);
|
||||
|
||||
return $this->renderStepForm($bookingCreateDto, $form, $newsletterOptInVisible, $newsletterTargetEmail);
|
||||
return $this->renderStepForm($bookingCreateDto, $form, $newsletterOptInVisible, $newsletterTargetEmail, $companionNewsletterOptInVisible);
|
||||
}
|
||||
|
||||
$newsletterOptInSelected = $newsletterOptInVisible
|
||||
@@ -118,19 +120,21 @@ class Step4Controller extends AbstractBookingCreateController
|
||||
&& true === $form->get('newsletterOptIn')->getData();
|
||||
|
||||
if (true === $newsletterOptInSelected) {
|
||||
try {
|
||||
$targetParticipant = $this->resolveNewsletterTargetParticipant($bookingCreateDto);
|
||||
$this->doubleOptInService->requestConfirmation(
|
||||
$newsletterTargetEmail,
|
||||
$targetParticipant?->firstName,
|
||||
$targetParticipant?->lastName,
|
||||
);
|
||||
} catch (NewsletterProviderException|\InvalidArgumentException $e) {
|
||||
$this->logger->warning('Newsletter confirmation request failed after booking', [
|
||||
'email' => $newsletterTargetEmail,
|
||||
'error' => $e->getMessage(),
|
||||
]);
|
||||
}
|
||||
$this->bookingNewsletterOptIn->subscribeApplicant(
|
||||
$newsletterTargetEmail,
|
||||
$this->bookingNewsletterOptIn->resolveApplicantParticipant($bookingCreateDto),
|
||||
);
|
||||
}
|
||||
|
||||
$companionOptInSelected = $companionNewsletterOptInVisible
|
||||
&& $form->has('companionNewsletterOptIn')
|
||||
&& true === $form->get('companionNewsletterOptIn')->getData();
|
||||
|
||||
if (true === $companionOptInSelected) {
|
||||
$this->bookingNewsletterOptIn->subscribeCompanions(
|
||||
$companions,
|
||||
$this->bookingNewsletterOptIn->resolveRequestedByName($bookingCreateDto),
|
||||
);
|
||||
}
|
||||
|
||||
// Success: Store booking data in flash for conversion tracking
|
||||
@@ -171,7 +175,7 @@ class Step4Controller extends AbstractBookingCreateController
|
||||
}
|
||||
}
|
||||
|
||||
return $this->renderStepForm($bookingCreateDto, $form, $newsletterOptInVisible, $newsletterTargetEmail);
|
||||
return $this->renderStepForm($bookingCreateDto, $form, $newsletterOptInVisible, $newsletterTargetEmail, $companionNewsletterOptInVisible);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -185,6 +189,7 @@ class Step4Controller extends AbstractBookingCreateController
|
||||
FormInterface $form,
|
||||
bool $newsletterOptInVisible,
|
||||
?string $newsletterTargetEmail,
|
||||
bool $companionNewsletterOptInVisible,
|
||||
): Response {
|
||||
$bookingCreateContext = $this->createContextFactory->createWithParticipantPrices($bookingCreateDto);
|
||||
|
||||
@@ -193,45 +198,10 @@ class Step4Controller extends AbstractBookingCreateController
|
||||
'form' => $form,
|
||||
'newsletterOptInVisible' => $newsletterOptInVisible,
|
||||
'newsletterTargetEmail' => $newsletterTargetEmail,
|
||||
'companionNewsletterOptInVisible' => $companionNewsletterOptInVisible,
|
||||
]);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
Reference in new issue
Block a user