150 lines
5.6 KiB
PHP
150 lines
5.6 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Form\Service;
|
|
|
|
use App\Form\Model\BookingDto;
|
|
use App\Form\Service\Abstract\AbstractParticipantFieldHandler;
|
|
|
|
/**
|
|
* Handles processing of the dateOfBirth field for booking participants.
|
|
*
|
|
* This handler manages date of birth processing for participants in the booking creation
|
|
* and edit processes. It processes the dateOfBirth field from form submissions and updates
|
|
* the participant DTO with the provided date. This is crucial for age-based field visibility
|
|
* and service filtering during HTMX form updates.
|
|
*
|
|
* Field Processing:
|
|
* - Extracts date of birth from submitted form data
|
|
* - Converts form date strings to DateTimeImmutable objects
|
|
* - Handles empty selections (converting them to null)
|
|
* - Updates the participant's dateOfBirth property
|
|
*
|
|
* Dependencies: None (this is a base field that other handlers may depend on)
|
|
*/
|
|
class ParticipantDateOfBirthFieldHandler extends AbstractParticipantFieldHandler
|
|
{
|
|
/**
|
|
* Returns the form field name this handler processes.
|
|
*
|
|
* This handler is responsible for the 'dateOfBirth' field, which contains
|
|
* the birth date for each participant in the booking form.
|
|
*
|
|
* @return string The field name 'dateOfBirth'
|
|
*/
|
|
public function getFieldName(): string
|
|
{
|
|
return 'dateOfBirth';
|
|
}
|
|
|
|
/**
|
|
* Processes the dateOfBirth field for a specific participant.
|
|
*
|
|
* This method extracts the date of birth from the submitted form data and
|
|
* updates the corresponding participant in the booking DTO. It handles the
|
|
* conversion from form date strings to DateTimeImmutable objects and properly
|
|
* handles empty selections.
|
|
*
|
|
* Processing steps:
|
|
* 1. Safely retrieves the participant object from the DTO
|
|
* 2. Extracts the dateOfBirth value from submitted data
|
|
* 3. Normalizes the value (empty string → null, date string → DateTimeImmutable)
|
|
* 4. Updates the participant's dateOfBirth property
|
|
*
|
|
* @param array<string, mixed> $submittedData The submitted participant form data
|
|
* @param BookingDto $bookingDto The booking DTO to update (create or edit)
|
|
* @param int $participantIndex The index of the participant being processed
|
|
*/
|
|
public function processField(array $submittedData, BookingDto $bookingDto, int $participantIndex): void
|
|
{
|
|
// Safely get the participant object, returning early if not found
|
|
$participant = $this->getParticipant($bookingDto, $participantIndex);
|
|
|
|
if (null === $participant) {
|
|
return;
|
|
}
|
|
|
|
// Extract the date of birth from form data (defaults to null if not present)
|
|
$dateOfBirth = $this->getFieldValue($submittedData, $this->getFieldName());
|
|
|
|
// Convert form date to DateTimeImmutable, handling empty selections as null
|
|
$participant->dateOfBirth = $this->normalizeDateValue($dateOfBirth);
|
|
}
|
|
|
|
/**
|
|
* Normalizes a date value from form submission to DateTimeImmutable or null.
|
|
*
|
|
* This method handles the conversion of form date values to proper DateTimeImmutable
|
|
* objects. It gracefully handles empty strings, null values, invalid date formats,
|
|
* and array input from multi-field date widgets (BirthdayType).
|
|
*
|
|
* Supported input formats:
|
|
* - Array: ['year' => int, 'month' => int, 'day' => int] from BirthdayType
|
|
* - DateTimeInterface: Already converted DateTime objects
|
|
* - String: ISO date strings or any format parseable by DateTimeImmutable
|
|
* - Null/empty: No date selected
|
|
*
|
|
* @param mixed $value The raw value from form submission
|
|
*
|
|
* @return \DateTimeImmutable|null The normalized date or null if empty/invalid
|
|
*/
|
|
private function normalizeDateValue(mixed $value): ?\DateTimeImmutable
|
|
{
|
|
// Handle null first
|
|
if (null === $value) {
|
|
return null;
|
|
}
|
|
|
|
// Handle array input from multi-field date widget (BirthdayType)
|
|
if (true === is_array($value)) {
|
|
// Check if all required fields are present and valid
|
|
if (false === isset($value['year'], $value['month'], $value['day'])
|
|
|| '' === trim((string) ($value['year'] ?? ''))
|
|
|| '' === trim((string) ($value['month'] ?? ''))
|
|
|| '' === trim((string) ($value['day'] ?? ''))
|
|
) {
|
|
return null;
|
|
}
|
|
|
|
try {
|
|
// Create date string in ISO format (YYYY-MM-DD)
|
|
$dateString = sprintf(
|
|
'%04d-%02d-%02d',
|
|
(int) $value['year'],
|
|
(int) $value['month'],
|
|
(int) $value['day']
|
|
);
|
|
|
|
return new \DateTimeImmutable($dateString);
|
|
} catch (\Exception $e) {
|
|
// Invalid date components (e.g., Feb 31, invalid year)
|
|
return null;
|
|
}
|
|
}
|
|
|
|
// If already a DateTimeInterface, convert to DateTimeImmutable
|
|
if ($value instanceof \DateTimeInterface) {
|
|
return \DateTimeImmutable::createFromInterface($value);
|
|
}
|
|
|
|
// Handle string date (including empty string check)
|
|
if (true === is_string($value)) {
|
|
// Empty string means no date selected
|
|
if ('' === trim($value)) {
|
|
return null;
|
|
}
|
|
|
|
try {
|
|
return new \DateTimeImmutable($value);
|
|
} catch (\Exception $e) {
|
|
// Invalid date format, return null
|
|
return null;
|
|
}
|
|
}
|
|
|
|
// Unsupported type, return null
|
|
return null;
|
|
}
|
|
}
|