wip: refactor to cards with individual participant forms
This commit is contained in:
@@ -36,14 +36,15 @@ abstract class AbstractParticipantFieldHandler implements ParticipantFieldHandle
|
||||
*
|
||||
* Default implementation checks if the field exists in the submitted data.
|
||||
* Override this method for more complex processing conditions (e.g., only
|
||||
* process if certain other conditions are met).
|
||||
* process if certain other conditions are met, or skip processing in edit mode).
|
||||
*
|
||||
* @param array<string, mixed> $submittedData The submitted participant form data
|
||||
* @param string $mode The booking mode (BookingDto::MODE_CREATE or MODE_EDIT)
|
||||
* @param int $participantIndex The index of the participant being processed
|
||||
*
|
||||
* @return bool True if the handler should process this field, false otherwise
|
||||
*/
|
||||
public function shouldProcess(array $submittedData, int $participantIndex): bool
|
||||
public function shouldProcess(array $submittedData, string $mode, int $participantIndex): bool
|
||||
{
|
||||
return isset($submittedData[$this->getFieldName()]);
|
||||
}
|
||||
@@ -67,6 +68,35 @@ abstract class AbstractParticipantFieldHandler implements ParticipantFieldHandle
|
||||
return $participants[$participantIndex] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the booking flow is in edit mode.
|
||||
*
|
||||
* Handlers may need to behave differently in edit mode, particularly when
|
||||
* dealing with data that isn't returned by the BPN API (like insurance selections).
|
||||
* In edit mode, missing data doesn't mean "clear this field" - it means the API
|
||||
* doesn't provide it and it should be preserved as-is.
|
||||
*
|
||||
* @param BookingDto $bookingDto The booking DTO to check
|
||||
*
|
||||
* @return bool True if in edit mode, false otherwise
|
||||
*/
|
||||
protected function isEditMode(BookingDto $bookingDto): bool
|
||||
{
|
||||
return $bookingDto->mode === BookingDto::MODE_EDIT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the booking flow is in create mode.
|
||||
*
|
||||
* @param BookingDto $bookingDto The booking DTO to check
|
||||
*
|
||||
* @return bool True if in create mode, false otherwise
|
||||
*/
|
||||
protected function isCreateMode(BookingDto $bookingDto): bool
|
||||
{
|
||||
return $bookingDto->mode === BookingDto::MODE_CREATE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Safely extracts a field value from submitted participant data.
|
||||
*
|
||||
|
||||
@@ -39,8 +39,12 @@ interface ParticipantFieldHandlerInterface
|
||||
|
||||
/**
|
||||
* Determines if this handler should process the field based on submitted participant data.
|
||||
*
|
||||
* @param array<string, mixed> $submittedData The submitted participant form data
|
||||
* @param string $mode The booking mode (BookingDto::MODE_CREATE or MODE_EDIT)
|
||||
* @param int $participantIndex The participant index being processed
|
||||
*/
|
||||
public function shouldProcess(array $submittedData, int $participantIndex): bool;
|
||||
public function shouldProcess(array $submittedData, string $mode, int $participantIndex): bool;
|
||||
|
||||
/**
|
||||
* Returns field state modifications that should be applied after processing.
|
||||
|
||||
@@ -59,11 +59,12 @@ class ParticipantAdditionalServicesFieldHandler extends AbstractParticipantField
|
||||
* services are selected.
|
||||
*
|
||||
* @param array<string, mixed> $submittedData The submitted participant form data
|
||||
* @param string $mode The booking mode (BookingDto::MODE_CREATE or MODE_EDIT)
|
||||
* @param int $participantIndex The index of the participant being processed
|
||||
*
|
||||
* @return bool Always returns true for service selection fields
|
||||
*/
|
||||
public function shouldProcess(array $submittedData, int $participantIndex): bool
|
||||
public function shouldProcess(array $submittedData, string $mode, int $participantIndex): bool
|
||||
{
|
||||
return true; // Always process to handle deselection cases
|
||||
}
|
||||
@@ -84,6 +85,7 @@ class ParticipantAdditionalServicesFieldHandler extends AbstractParticipantField
|
||||
* 5. Updates participant with filtered valid selections
|
||||
*
|
||||
* @param array<string, mixed> $submittedData The submitted participant form data
|
||||
* @param string $mode The booking mode (BookingDto::MODE_CREATE or MODE_EDIT)
|
||||
* @param BookingDto $bookingDto The booking DTO to update (create or edit)
|
||||
* @param int $participantIndex The index of the participant being processed
|
||||
*/
|
||||
|
||||
@@ -40,11 +40,12 @@ class ParticipantBoardFieldHandler extends AbstractParticipantFieldHandler
|
||||
* services are selected.
|
||||
*
|
||||
* @param array<string, mixed> $submittedData The submitted participant form data
|
||||
* @param string $mode The booking mode (BookingDto::MODE_CREATE or MODE_EDIT)
|
||||
* @param int $participantIndex The index of the participant being processed
|
||||
*
|
||||
* @return bool Always returns true for service selection fields
|
||||
*/
|
||||
public function shouldProcess(array $submittedData, int $participantIndex): bool
|
||||
public function shouldProcess(array $submittedData, string $mode, int $participantIndex): bool
|
||||
{
|
||||
return true; // Always process to handle deselection cases
|
||||
}
|
||||
|
||||
@@ -39,11 +39,12 @@ class ParticipantBulkInsuranceFieldHandler extends AbstractParticipantFieldHandl
|
||||
* the bulkInsuranceBooking checkbox - their insurance is controlled by the handler.
|
||||
*
|
||||
* @param array<string, mixed> $submittedData The submitted participant form data
|
||||
* @param string $mode The booking mode (BookingDto::MODE_CREATE or MODE_EDIT)
|
||||
* @param int $participantIndex The index of the participant being processed
|
||||
*
|
||||
* @return bool True if this is the applicant, false otherwise
|
||||
*/
|
||||
public function shouldProcess(array $submittedData, int $participantIndex): bool
|
||||
public function shouldProcess(array $submittedData, string $mode, int $participantIndex): bool
|
||||
{
|
||||
return 0 === $participantIndex; // Only process for applicant
|
||||
}
|
||||
|
||||
@@ -59,11 +59,12 @@ class ParticipantCoursesFieldHandler extends AbstractParticipantFieldHandler
|
||||
* services are selected.
|
||||
*
|
||||
* @param array<string, mixed> $submittedData The submitted participant form data
|
||||
* @param string $mode The booking mode (BookingDto::MODE_CREATE or MODE_EDIT)
|
||||
* @param int $participantIndex The index of the participant being processed
|
||||
*
|
||||
* @return bool Always returns true for service selection fields
|
||||
*/
|
||||
public function shouldProcess(array $submittedData, int $participantIndex): bool
|
||||
public function shouldProcess(array $submittedData, string $mode, int $participantIndex): bool
|
||||
{
|
||||
return true; // Always process to handle deselection cases
|
||||
}
|
||||
@@ -77,6 +78,7 @@ class ParticipantCoursesFieldHandler extends AbstractParticipantFieldHandler
|
||||
* no longer appropriate for the participant's age are automatically removed.
|
||||
*
|
||||
* @param array<string, mixed> $submittedData The submitted participant form data
|
||||
* @param string $mode The booking mode (BookingDto::MODE_CREATE or MODE_EDIT)
|
||||
* @param BookingDto $bookingDto The booking DTO to update (create or edit)
|
||||
* @param int $participantIndex The index of the participant being processed
|
||||
*/
|
||||
|
||||
@@ -4,6 +4,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace App\Form\Service;
|
||||
|
||||
use App\BusProNet\Model\Address;
|
||||
use App\BusProNet\Model\Insurance;
|
||||
use App\BusProNet\Model\Pickup;
|
||||
use App\BusProNet\Model\Service;
|
||||
@@ -132,13 +133,42 @@ class ParticipantFieldHandlerRegistry
|
||||
}
|
||||
|
||||
// Let each handler decide if it should process this participant's data
|
||||
if ($handler->shouldProcess($participantData, (int) $participantIndex)) {
|
||||
if ($handler->shouldProcess($participantData, $bookingDto->mode, (int) $participantIndex)) {
|
||||
$handler->processField($participantData, $bookingDto, (int) $participantIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes field handlers for a single participant.
|
||||
*
|
||||
* This method is used by the card-based booking flows where participants are
|
||||
* edited individually. Unlike processFields() which processes all participants,
|
||||
* this method applies all handlers to only the specified participant.
|
||||
*
|
||||
* Handlers are executed in dependency order to ensure proper data consistency.
|
||||
*
|
||||
* @param array<string, mixed> $participantData Submitted data for one participant
|
||||
* @param BookingDto $bookingDto The booking DTO to update
|
||||
* @param int $participantIndex Index of participant to process
|
||||
*/
|
||||
public function processFieldsForParticipant(array $participantData, BookingDto $bookingDto, int $participantIndex): void
|
||||
{
|
||||
// Get handlers sorted by dependency order (uses cache if available)
|
||||
$sortedHandlerNames = $this->getSortedHandlers();
|
||||
|
||||
// Apply each handler to the specified participant
|
||||
foreach ($sortedHandlerNames as $handlerName) {
|
||||
$handler = $this->handlers[$handlerName];
|
||||
|
||||
// Let each handler decide if it should process this participant's data
|
||||
if ($handler->shouldProcess($participantData, $bookingDto->mode, $participantIndex)) {
|
||||
$handler->processField($participantData, $bookingDto, $participantIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns handler names sorted by dependency order using cached results when possible.
|
||||
*
|
||||
@@ -376,7 +406,7 @@ class ParticipantFieldHandlerRegistry
|
||||
}
|
||||
|
||||
// Handle Address objects -> convert to array of properties
|
||||
if ($value instanceof \App\BusProNet\Model\Address) {
|
||||
if ($value instanceof Address) {
|
||||
return [
|
||||
'street' => $value->street,
|
||||
'postCode' => $value->postCode,
|
||||
|
||||
@@ -76,27 +76,34 @@ class ParticipantInsuranceFieldHandler extends AbstractParticipantFieldHandler
|
||||
/**
|
||||
* Determines if this handler should process the field based on submitted data.
|
||||
*
|
||||
* For insurance selection fields, we always need to process to handle cases
|
||||
* where the selection is cleared (field not present in data). This ensures
|
||||
* the participant DTO is updated with null when no insurance is selected.
|
||||
* Insurance handler should NOT process in edit mode because the BPN API does not
|
||||
* return insurance data. In edit mode, insurance data must be preserved as-is
|
||||
* and passed through to the update endpoint unchanged.
|
||||
*
|
||||
* However, when bulk insurance booking is active for a dependent participant,
|
||||
* we skip processing to prevent overwriting the insurance assigned by the
|
||||
* bulk insurance handler.
|
||||
* In create mode, we always need to process to handle cases where the selection
|
||||
* is cleared (field not present in data). However, when bulk insurance booking
|
||||
* is active for a dependent participant, we skip processing to prevent overwriting
|
||||
* the insurance assigned by the bulk insurance handler.
|
||||
*
|
||||
* @param array<string, mixed> $submittedData The submitted participant form data
|
||||
* @param string $mode The booking mode (BookingDto::MODE_CREATE or MODE_EDIT)
|
||||
* @param int $participantIndex The index of the participant being processed
|
||||
*
|
||||
* @return bool True if processing should occur, false if bulk insurance handles it
|
||||
* @return bool True if processing should occur, false otherwise
|
||||
*/
|
||||
public function shouldProcess(array $submittedData, int $participantIndex): bool
|
||||
public function shouldProcess(array $submittedData, string $mode, int $participantIndex): bool
|
||||
{
|
||||
// In edit mode, insurance data is not available from API - skip processing entirely
|
||||
if ($mode === BookingDto::MODE_EDIT) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Skip processing for dependent participants when bulk insurance booking is active
|
||||
if ($participantIndex > 0 && $this->isBulkInsuranceBookingActive($submittedData)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true; // Always process to handle deselection cases
|
||||
return true; // Always process in create mode to handle deselection cases
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -52,11 +52,12 @@ class ParticipantLicensePlateFieldHandler extends AbstractParticipantFieldHandle
|
||||
* the participant DTO is updated correctly when parking availability changes.
|
||||
*
|
||||
* @param array<string, mixed> $submittedData The submitted participant form data
|
||||
* @param string $mode The booking mode (BookingDto::MODE_CREATE or MODE_EDIT)
|
||||
* @param int $participantIndex The index of the participant being processed
|
||||
*
|
||||
* @return bool Always returns true for license plate fields
|
||||
*/
|
||||
public function shouldProcess(array $submittedData, int $participantIndex): bool
|
||||
public function shouldProcess(array $submittedData, string $mode, int $participantIndex): bool
|
||||
{
|
||||
return true; // Always process to handle deselection cases
|
||||
}
|
||||
|
||||
@@ -37,11 +37,12 @@ class ParticipantParkingFieldHandler extends AbstractParticipantFieldHandler
|
||||
* participant DTO is updated correctly when transportation switches to bus-only.
|
||||
*
|
||||
* @param array<string, mixed> $submittedData The submitted participant form data
|
||||
* @param string $mode The booking mode (BookingDto::MODE_CREATE or MODE_EDIT)
|
||||
* @param int $participantIndex The index of the participant being processed
|
||||
*
|
||||
* @return bool Always returns true for parking selection fields
|
||||
*/
|
||||
public function shouldProcess(array $submittedData, int $participantIndex): bool
|
||||
public function shouldProcess(array $submittedData, string $mode, int $participantIndex): bool
|
||||
{
|
||||
return true; // Always process for state changes
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ class ParticipantPickupFieldHandler extends AbstractParticipantFieldHandler
|
||||
return ['transportationOutbound', 'transportationInbound'];
|
||||
}
|
||||
|
||||
public function shouldProcess(array $submittedData, int $participantIndex): bool
|
||||
public function shouldProcess(array $submittedData, string $mode, int $participantIndex): bool
|
||||
{
|
||||
return true; // Always process to handle clearing pickup
|
||||
}
|
||||
|
||||
@@ -56,11 +56,12 @@ class ParticipantRentalInsuranceFieldHandler extends AbstractParticipantFieldHan
|
||||
* rental insurance is selected.
|
||||
*
|
||||
* @param array<string, mixed> $submittedData The submitted participant form data
|
||||
* @param string $mode The booking mode (BookingDto::MODE_CREATE or MODE_EDIT)
|
||||
* @param int $participantIndex The index of the participant being processed
|
||||
*
|
||||
* @return bool Always returns true for service selection fields
|
||||
*/
|
||||
public function shouldProcess(array $submittedData, int $participantIndex): bool
|
||||
public function shouldProcess(array $submittedData, string $mode, int $participantIndex): bool
|
||||
{
|
||||
return true; // Always process to handle deselection cases
|
||||
}
|
||||
@@ -74,6 +75,7 @@ class ParticipantRentalInsuranceFieldHandler extends AbstractParticipantFieldHan
|
||||
* is no longer appropriate for the participant's age, it is automatically cleared.
|
||||
*
|
||||
* @param array<string, mixed> $submittedData The submitted participant form data
|
||||
* @param string $mode The booking mode (BookingDto::MODE_CREATE or MODE_EDIT)
|
||||
* @param BookingDto $bookingDto The booking DTO to update (create or edit)
|
||||
* @param int $participantIndex The index of the participant being processed
|
||||
*/
|
||||
|
||||
@@ -48,11 +48,12 @@ class ParticipantRentalsFieldHandler extends AbstractParticipantFieldHandler
|
||||
* services are selected.
|
||||
*
|
||||
* @param array<string, mixed> $submittedData The submitted participant form data
|
||||
* @param string $mode The booking mode (BookingDto::MODE_CREATE or MODE_EDIT)
|
||||
* @param int $participantIndex The index of the participant being processed
|
||||
*
|
||||
* @return bool Always returns true for service selection fields
|
||||
*/
|
||||
public function shouldProcess(array $submittedData, int $participantIndex): bool
|
||||
public function shouldProcess(array $submittedData, string $mode, int $participantIndex): bool
|
||||
{
|
||||
return true; // Always process to handle deselection cases
|
||||
}
|
||||
|
||||
@@ -60,11 +60,12 @@ class ParticipantSkiPassFieldHandler extends AbstractParticipantFieldHandler
|
||||
* skipass is selected.
|
||||
*
|
||||
* @param array<string, mixed> $submittedData The submitted participant form data
|
||||
* @param string $mode The booking mode (BookingDto::MODE_CREATE or MODE_EDIT)
|
||||
* @param int $participantIndex The index of the participant being processed
|
||||
*
|
||||
* @return bool Always returns true for service selection fields
|
||||
*/
|
||||
public function shouldProcess(array $submittedData, int $participantIndex): bool
|
||||
public function shouldProcess(array $submittedData, string $mode, int $participantIndex): bool
|
||||
{
|
||||
return true; // Always process to handle deselection cases
|
||||
}
|
||||
@@ -79,6 +80,7 @@ class ParticipantSkiPassFieldHandler extends AbstractParticipantFieldHandler
|
||||
* age or exceeds the travel date range, it is automatically cleared.
|
||||
*
|
||||
* @param array<string, mixed> $submittedData The submitted participant form data
|
||||
* @param string $mode The booking mode (BookingDto::MODE_CREATE or MODE_EDIT)
|
||||
* @param BookingDto $bookingDto The booking DTO to update (create or edit)
|
||||
* @param int $participantIndex The index of the participant being processed
|
||||
*/
|
||||
|
||||
@@ -32,11 +32,12 @@ class ParticipantTransportationInboundFieldHandler extends AbstractParticipantFi
|
||||
* participant DTO is updated with null when no transportation is selected.
|
||||
*
|
||||
* @param array<string, mixed> $submittedData The submitted participant form data
|
||||
* @param string $mode The booking mode (BookingDto::MODE_CREATE or MODE_EDIT)
|
||||
* @param int $participantIndex The index of the participant being processed
|
||||
*
|
||||
* @return bool Always returns true for transportation selection fields
|
||||
*/
|
||||
public function shouldProcess(array $submittedData, int $participantIndex): bool
|
||||
public function shouldProcess(array $submittedData, string $mode, int $participantIndex): bool
|
||||
{
|
||||
return true; // Always process to handle deselection cases
|
||||
}
|
||||
|
||||
@@ -32,11 +32,12 @@ class ParticipantTransportationOutboundFieldHandler extends AbstractParticipantF
|
||||
* participant DTO is updated with null when no transportation is selected.
|
||||
*
|
||||
* @param array<string, mixed> $submittedData The submitted participant form data
|
||||
* @param string $mode The booking mode (BookingDto::MODE_CREATE or MODE_EDIT)
|
||||
* @param int $participantIndex The index of the participant being processed
|
||||
*
|
||||
* @return bool Always returns true for transportation selection fields
|
||||
*/
|
||||
public function shouldProcess(array $submittedData, int $participantIndex): bool
|
||||
public function shouldProcess(array $submittedData, string $mode, int $participantIndex): bool
|
||||
{
|
||||
return true; // Always process to handle deselection cases
|
||||
}
|
||||
|
||||
@@ -13,6 +13,9 @@ use Symfony\Component\Form\FormInterface;
|
||||
* This trait contains common form navigation logic used across different
|
||||
* form services and types. It centralizes the logic for finding root forms
|
||||
* and extracting booking DTOs from form hierarchies.
|
||||
*
|
||||
* Note: Card-based flows pass BookingDto via form options instead of
|
||||
* relying on form tree traversal.
|
||||
*/
|
||||
trait FormTraversalTrait
|
||||
{
|
||||
@@ -20,8 +23,8 @@ trait FormTraversalTrait
|
||||
* Gets the BookingDto from the root of the form tree.
|
||||
*
|
||||
* This helper method traverses up the form tree to find the root form
|
||||
* and extracts the BookingDto data. This is shared logic used
|
||||
* by both create and edit participant forms.
|
||||
* and extracts the BookingDto data. This is used as a fallback when
|
||||
* BookingDto is not passed explicitly via form options.
|
||||
*
|
||||
* @param FormInterface $form The form to start traversing from
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user