feat: improved dynamic validation
This commit is contained in:
@@ -9,9 +9,9 @@ use App\BusProNet\Model\Pickup;
|
||||
use App\BusProNet\Model\Service;
|
||||
use App\Validator\Constraints as AppAssert;
|
||||
use Symfony\Component\Validator\Constraints as Assert;
|
||||
use Symfony\Component\Validator\Context\ExecutionContextInterface;
|
||||
|
||||
#[AppAssert\Participant(groups: ['booking_edit', 'booking_create'])]
|
||||
#[AppAssert\Booking(groups: ['booking_edit', 'booking_create'])]
|
||||
class ParticipantDto
|
||||
{
|
||||
/**
|
||||
@@ -42,8 +42,10 @@ class ParticipantDto
|
||||
public bool $mutable = false;
|
||||
public bool $touched = false;
|
||||
|
||||
#[Assert\NotBlank(message: 'Bitte angeben', groups: ['strict_required'])]
|
||||
public ?string $firstName = null;
|
||||
|
||||
#[Assert\NotBlank(message: 'Bitte angeben', groups: ['strict_required'])]
|
||||
public ?string $lastName = null;
|
||||
public ?string $title = null;
|
||||
public ?string $gender = null;
|
||||
@@ -53,9 +55,11 @@ class ParticipantDto
|
||||
public ?string $shoeSize = null;
|
||||
public ?string $weight = null;
|
||||
|
||||
#[Assert\NotNull(message: 'Bitte angeben', groups: ['strict_required'])]
|
||||
public ?\DateTimeImmutable $dateOfBirth = null;
|
||||
|
||||
#[Assert\Email(message: 'Bitte eine gültige E-Mail Adresse angeben', mode: 'strict', groups: ['booking_edit', 'booking_create'])]
|
||||
#[Assert\NotBlank(message: 'Bitte angeben', groups: ['strict_required'])]
|
||||
public ?string $email = null;
|
||||
|
||||
public ?string $mobile = null;
|
||||
@@ -64,7 +68,7 @@ class ParticipantDto
|
||||
#[Assert\NotNull(message: 'Bitte Adresse angeben', groups: ['applicant_address'])]
|
||||
public ?Address $address = null;
|
||||
|
||||
#[Assert\NotNull(message: 'Bitte ein Zimmer auswählen', groups: ['booking_create'])]
|
||||
#[Assert\NotNull(message: 'Bitte ein Zimmer auswählen', groups: ['strict_required'])]
|
||||
public ?int $assignedRoomId = null;
|
||||
|
||||
public ?string $remarksRoom = null;
|
||||
@@ -72,6 +76,7 @@ class ParticipantDto
|
||||
public array $courses = [];
|
||||
public array $additionalServices = [];
|
||||
|
||||
#[Assert\NotNull(message: 'Bitte auswählen', groups: ['strict_required'])]
|
||||
public ?Service $skiPass = null;
|
||||
|
||||
public array $board = [];
|
||||
@@ -82,7 +87,9 @@ class ParticipantDto
|
||||
public bool $rentalInsuranceSelected = false;
|
||||
|
||||
// Transportation services with improved naming (outbound/inbound)
|
||||
#[Assert\NotNull(message: 'Bitte auswählen', groups: ['strict_required'])]
|
||||
public ?Service $transportationOutbound = null;
|
||||
#[Assert\NotNull(message: 'Bitte auswählen', groups: ['strict_required'])]
|
||||
public ?Service $transportationInbound = null;
|
||||
|
||||
// Pickup location (applies to both directions)
|
||||
@@ -98,6 +105,7 @@ class ParticipantDto
|
||||
public ?string $licensePlate = null;
|
||||
|
||||
// Selected insurance for this participant (individual insurance selection per participant)
|
||||
#[Assert\NotNull(message: 'Bitte auswählen', groups: ['strict_required'])]
|
||||
public ?Insurance $insurance = null;
|
||||
|
||||
// Bulk insurance booking flag (applicant only: when checked, assigns same insurance type to all participants)
|
||||
@@ -252,4 +260,54 @@ class ParticipantDto
|
||||
|
||||
return $ageThreshold > $age;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates that the applicant (index 0) has a complete address.
|
||||
*
|
||||
* This callback only applies to the applicant participant. Address validation includes:
|
||||
* - Address object must exist
|
||||
* - All required address fields must be filled (street, postCode, city, country)
|
||||
*/
|
||||
#[Assert\Callback(groups: ['strict_required'])]
|
||||
public function validateApplicantAddress(ExecutionContextInterface $context): void
|
||||
{
|
||||
// Only validate applicant's address
|
||||
if (0 !== $this->index) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Address object is required for applicant
|
||||
if (null === $this->address) {
|
||||
$context->buildViolation('Bitte angeben')
|
||||
->atPath('address')
|
||||
->addViolation();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Validate address subfields
|
||||
if (null === $this->address->street || '' === trim($this->address->street)) {
|
||||
$context->buildViolation('Bitte angeben')
|
||||
->atPath('address.street')
|
||||
->addViolation();
|
||||
}
|
||||
|
||||
if (null === $this->address->postCode || '' === trim($this->address->postCode)) {
|
||||
$context->buildViolation('Bitte angeben')
|
||||
->atPath('address.postCode')
|
||||
->addViolation();
|
||||
}
|
||||
|
||||
if (null === $this->address->city || '' === trim($this->address->city)) {
|
||||
$context->buildViolation('Bitte angeben')
|
||||
->atPath('address.city')
|
||||
->addViolation();
|
||||
}
|
||||
|
||||
if (null === $this->address->country || '' === trim($this->address->country)) {
|
||||
$context->buildViolation('Bitte angeben')
|
||||
->atPath('address.country')
|
||||
->addViolation();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,6 @@ use Symfony\Component\Validator\Context\ExecutionContextInterface;
|
||||
* the participant being edited and the full booking context needed for
|
||||
* cross-participant validation.
|
||||
*/
|
||||
#[AppAssert\Booking(groups: ['booking_edit', 'booking_create'])]
|
||||
class ParticipantEditDto
|
||||
{
|
||||
public function __construct(
|
||||
|
||||
Reference in New Issue
Block a user