$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; } }