chore: fix phpstan errors
This commit is contained in:
@@ -11,6 +11,7 @@ use Symfony\Component\Form\Extension\Core\Type\TextType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
|
||||
/** @extends AbstractType<Address> */
|
||||
class AddressType extends AbstractType
|
||||
{
|
||||
public function buildForm(FormBuilderInterface $builder, array $options): void
|
||||
|
||||
@@ -11,6 +11,7 @@ use Symfony\Component\Form\Extension\Core\Type\TextType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
|
||||
/** @extends AbstractType<BankAccountDto> */
|
||||
class BankAccountType extends AbstractType
|
||||
{
|
||||
public function buildForm(FormBuilderInterface $builder, array $options): void
|
||||
|
||||
@@ -10,6 +10,7 @@ use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
|
||||
/** @extends AbstractType<ParticipantDto> */
|
||||
class BodyDimensionsType extends AbstractType
|
||||
{
|
||||
public function buildForm(FormBuilderInterface $builder, array $options): void
|
||||
|
||||
@@ -8,6 +8,7 @@ use Symfony\Component\Form\Extension\Core\Type\CollectionType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
|
||||
/** @extends AbstractType<BookingDto> */
|
||||
class BookingCreateStep1Type extends AbstractType
|
||||
{
|
||||
public function buildForm(FormBuilderInterface $builder, array $options): void
|
||||
|
||||
@@ -17,6 +17,7 @@ use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
* in separate forms. This form validates the complete BookingDto before proceeding
|
||||
* to Step 3, ensuring all participants have valid and complete data.
|
||||
*/
|
||||
/** @extends AbstractType<BookingDto> */
|
||||
class BookingCreateStep2Type extends AbstractType
|
||||
{
|
||||
public function buildForm(FormBuilderInterface $builder, array $options): void
|
||||
|
||||
@@ -12,8 +12,10 @@ use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\Form\FormEvent;
|
||||
use Symfony\Component\Form\FormEvents;
|
||||
use Symfony\Component\Form\FormInterface;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
|
||||
/** @extends AbstractType<BookingDto> */
|
||||
class BookingCreateStep3Type extends AbstractType
|
||||
{
|
||||
public function buildForm(FormBuilderInterface $builder, array $options): void
|
||||
@@ -76,7 +78,8 @@ class BookingCreateStep3Type extends AbstractType
|
||||
/**
|
||||
* Adds the bank account field to the form.
|
||||
*/
|
||||
private function addBankAccountField($form): void
|
||||
/** @param FormInterface<mixed> $form */
|
||||
private function addBankAccountField(FormInterface $form): void
|
||||
{
|
||||
$form->add('bankAccount', BankAccountType::class, [
|
||||
'label' => false,
|
||||
|
||||
@@ -11,6 +11,7 @@ use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
use Symfony\Component\Validator\Constraints as Assert;
|
||||
|
||||
/** @extends AbstractType<BookingDto> */
|
||||
class BookingCreateStep4Type extends AbstractType
|
||||
{
|
||||
public function __construct(
|
||||
|
||||
@@ -17,6 +17,7 @@ use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
* This form validates the complete BookingDto before allowing updates,
|
||||
* ensuring all participants have valid and complete data.
|
||||
*/
|
||||
/** @extends AbstractType<BookingDto> */
|
||||
class BookingEditType extends AbstractType
|
||||
{
|
||||
public function buildForm(FormBuilderInterface $builder, array $options): void
|
||||
|
||||
@@ -24,6 +24,7 @@ use Symfony\Component\Form\FormEvents;
|
||||
use Symfony\Component\Form\FormInterface;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
|
||||
/** @extends AbstractType<ParticipantEditDto> */
|
||||
class BookingParticipantType extends AbstractType
|
||||
{
|
||||
private FieldStateProviderInterface $fieldStateProvider;
|
||||
@@ -80,10 +81,6 @@ class BookingParticipantType extends AbstractType
|
||||
/** @var ParticipantEditDto $data */
|
||||
$data = $form->getData();
|
||||
|
||||
if (null === $data || null === $data->participant) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Process all field handlers for this participant and sync submitted data
|
||||
$syncedData = $this->fieldHandlerRegistry->processFieldsForParticipantAndSync(
|
||||
$submittedData,
|
||||
@@ -110,11 +107,7 @@ class BookingParticipantType extends AbstractType
|
||||
$form = $event->getForm();
|
||||
|
||||
// Use bookingContext from wrapper DTO or fallback to passed option
|
||||
$bookingDto = $data->bookingContext ?? $bookingContext ?? $this->fieldStateProvider->getBookingDtoFromForm($form);
|
||||
|
||||
if (null === $bookingDto) {
|
||||
return;
|
||||
}
|
||||
$bookingDto = $data->bookingContext;
|
||||
|
||||
// Add base fields with states applied
|
||||
$this->addBaseFields($form, $bookingDto, $data->participant->index);
|
||||
@@ -134,16 +127,8 @@ class BookingParticipantType extends AbstractType
|
||||
/** @var ParticipantEditDto $data */
|
||||
$data = $form->getData();
|
||||
|
||||
if (null === $data || null === $data->participant) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Use bookingContext from wrapper DTO or fallback to passed option
|
||||
$bookingDto = $data->bookingContext ?? $bookingContext ?? $this->fieldStateProvider->getBookingDtoFromForm($form);
|
||||
|
||||
if (null === $bookingDto) {
|
||||
return;
|
||||
}
|
||||
$bookingDto = $data->bookingContext;
|
||||
|
||||
// Rebuild all fields with updated states based on submitted data
|
||||
$this->rebuildFieldsWithStates($form, $bookingDto, $data->participant->index, $submittedData);
|
||||
@@ -154,6 +139,7 @@ class BookingParticipantType extends AbstractType
|
||||
/**
|
||||
* Adds base fields to the form with field states applied.
|
||||
*/
|
||||
/** @param FormInterface<mixed> $form */
|
||||
private function addBaseFields(FormInterface $form, BookingDto $bookingDto, int $participantIndex): void
|
||||
{
|
||||
// Get field states for base fields
|
||||
@@ -280,6 +266,10 @@ class BookingParticipantType extends AbstractType
|
||||
* @param int $participantIndex The participant index
|
||||
* @param array<string, mixed> $submittedData Submitted form data for state calculation
|
||||
*/
|
||||
/**
|
||||
* @param FormInterface<mixed> $form
|
||||
* @param array<string, mixed> $submittedData
|
||||
*/
|
||||
private function removeExcludedFields(FormInterface $form, BookingDto $bookingDto, int $participantIndex, array &$submittedData = []): void
|
||||
{
|
||||
foreach (ParticipantDto::DYNAMIC_FIELDS as $fieldName) {
|
||||
@@ -296,6 +286,10 @@ class BookingParticipantType extends AbstractType
|
||||
/**
|
||||
* Rebuilds all fields with updated states based on submitted data.
|
||||
*/
|
||||
/**
|
||||
* @param FormInterface<mixed> $form
|
||||
* @param array<string, mixed> $submittedData
|
||||
*/
|
||||
private function rebuildFieldsWithStates(FormInterface $form, BookingDto $bookingDto, int $participantIndex, array &$submittedData): void
|
||||
{
|
||||
// First, remove fields that should be excluded entirely
|
||||
@@ -326,6 +320,7 @@ class BookingParticipantType extends AbstractType
|
||||
/**
|
||||
* Adds all configured dynamic fields to the form with state conditions applied.
|
||||
*/
|
||||
/** @param FormInterface<mixed> $form */
|
||||
private function addDynamicFields(FormInterface $form, BookingDto $bookingDto, int $participantIndex): void
|
||||
{
|
||||
$dynamicFields = [
|
||||
|
||||
@@ -16,12 +16,12 @@ use Symfony\Component\Form\Exception\TransformationFailedException;
|
||||
* the full object (including price) via choiceData while the form binds
|
||||
* the scalar ID to the participant's assignedRoomId property.
|
||||
*
|
||||
* @implements DataTransformerInterface<int|null, RoomSelectionDto|null>
|
||||
* @implements DataTransformerInterface<mixed, mixed>
|
||||
*/
|
||||
class RoomSelectionToIdTransformer implements DataTransformerInterface
|
||||
{
|
||||
/**
|
||||
* @param RoomSelectionDto[] $roomSelections Available room selections for reverse lookup
|
||||
* @param array<RoomSelectionDto> $roomSelections Available room selections for reverse lookup
|
||||
*/
|
||||
public function __construct(
|
||||
private readonly array $roomSelections,
|
||||
@@ -29,11 +29,8 @@ class RoomSelectionToIdTransformer implements DataTransformerInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms an integer room ID to a RoomSelectionDto for form display.
|
||||
*
|
||||
* @param int|null $value The room ID from the model
|
||||
*
|
||||
* @return RoomSelectionDto|null The matching RoomSelectionDto or null
|
||||
* Converts the persisted room id from the model into the matching
|
||||
* RoomSelectionDto so the form can render labels and pricing details.
|
||||
*/
|
||||
public function transform(mixed $value): ?RoomSelectionDto
|
||||
{
|
||||
@@ -51,29 +48,28 @@ class RoomSelectionToIdTransformer implements DataTransformerInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms a RoomSelectionDto back to an integer room ID for the model.
|
||||
* Converts the submitted choice value back into the model's integer room id.
|
||||
*
|
||||
* @param RoomSelectionDto|null $value The selected RoomSelectionDto from the form
|
||||
*
|
||||
* @return int|null The room ID or null
|
||||
*
|
||||
* @throws TransformationFailedException If an unexpected value type is received
|
||||
* ChoiceType submits the selected room id as a scalar, so this method accepts
|
||||
* an empty value, an int, or a digit-only string and rejects everything else.
|
||||
*/
|
||||
public function reverseTransform(mixed $value): ?int
|
||||
{
|
||||
if (null === $value) {
|
||||
if (null === $value || '' === $value) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ($value instanceof RoomSelectionDto) {
|
||||
return $value->id;
|
||||
if (is_int($value)) {
|
||||
return $value;
|
||||
}
|
||||
|
||||
// Handle case where form submits scalar ID directly
|
||||
if (is_int($value) || is_string($value)) {
|
||||
if (is_string($value) && ctype_digit($value)) {
|
||||
return (int) $value;
|
||||
}
|
||||
|
||||
throw new TransformationFailedException(sprintf('Expected RoomSelectionDto, int, or null, got %s', get_debug_type($value)));
|
||||
throw new TransformationFailedException(sprintf(
|
||||
'Invalid room id value: %s',
|
||||
get_debug_type($value)
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,9 +34,9 @@ class BankAccountDto
|
||||
#[Assert\IsTrue(message: 'Bitte akzeptiere das SEPA-Mandat.')]
|
||||
public bool $sepaMandateAccepted = false;
|
||||
|
||||
public static function fromBankAccount(BankAccount $bankAccount): static
|
||||
public static function fromBankAccount(BankAccount $bankAccount): self
|
||||
{
|
||||
$instance = new static();
|
||||
$instance = new self();
|
||||
$instance->iban = $bankAccount->iban;
|
||||
$instance->accountHolder = $bankAccount->holder;
|
||||
$instance->bankName = $bankAccount->bankName;
|
||||
|
||||
@@ -153,6 +153,7 @@ class BookingDto
|
||||
});
|
||||
}
|
||||
|
||||
/** @return array<int, ParticipantDto> */
|
||||
public function getParticipants(): array
|
||||
{
|
||||
return $this->participants;
|
||||
|
||||
@@ -88,19 +88,27 @@ class ParticipantDto
|
||||
)]
|
||||
public ?string $remarksRoom = null;
|
||||
|
||||
/** @var list<Service> */
|
||||
public array $courses = [];
|
||||
/** @var list<Service> */
|
||||
public array $additionalServices = [];
|
||||
/** @var list<int> */
|
||||
public array $autoBookOptOutServiceIds = [];
|
||||
/** @var list<int> */
|
||||
public array $autoBookOptOutSkiPassIds = [];
|
||||
/** @var list<int> */
|
||||
public array $autoBookOptOutBoardIds = [];
|
||||
/** @var list<int> */
|
||||
public array $autoBookOptOutRentalIds = [];
|
||||
|
||||
// Note: Ski pass validation is conditional - see ParticipantEditDto::validateSkiPassRequired()
|
||||
// Babies (0-2 years) are exempt from ski pass requirement
|
||||
public ?Service $skiPass = null;
|
||||
|
||||
/** @var list<Service> */
|
||||
public array $board = [];
|
||||
public ?Service $veg = null;
|
||||
/** @var list<Service> */
|
||||
public array $rentals = [];
|
||||
public ?Service $rentalInsurance = null;
|
||||
|
||||
@@ -190,9 +198,9 @@ class ParticipantDto
|
||||
$this->address = new Address();
|
||||
}
|
||||
|
||||
public static function fromPersonalData(PersonalData $personalData): static
|
||||
public static function fromPersonalData(PersonalData $personalData): self
|
||||
{
|
||||
$instance = new static();
|
||||
$instance = new self();
|
||||
|
||||
$instance->status = $personalData->status;
|
||||
$instance->addressId = $personalData->addressId;
|
||||
@@ -203,15 +211,15 @@ class ParticipantDto
|
||||
$instance->title = $personalData->title;
|
||||
$instance->gender = $personalData->gender;
|
||||
$instance->nationality = $personalData->nationality ?: 'D';
|
||||
$instance->email = $personalData->communication?->email;
|
||||
$instance->mobile = $personalData->communication?->mobile;
|
||||
$instance->email = $personalData->communication->email;
|
||||
$instance->mobile = $personalData->communication->mobile;
|
||||
$instance->dateOfBirth = $personalData->dateOfBirth;
|
||||
$instance->height = $personalData->height;
|
||||
$instance->weight = $personalData->weight;
|
||||
$instance->shoeSize = $personalData->shoeSize;
|
||||
|
||||
// Clone address to prevent shared object references that could cause mutations
|
||||
$instance->address = null !== $personalData->address ? clone $personalData->address : null;
|
||||
$instance->address = clone $personalData->address;
|
||||
|
||||
$instance->remarksRoom = $personalData->remarksRoom;
|
||||
$instance->licensePlate = $personalData->licensePlate;
|
||||
@@ -292,7 +300,7 @@ class ParticipantDto
|
||||
*/
|
||||
public function getInsurancePrice(): float
|
||||
{
|
||||
return $this->insurance?->price ?? 0.0;
|
||||
return $this->insurance->price ?? 0.0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -14,6 +14,7 @@ use Symfony\Component\Form\FormEvent;
|
||||
use Symfony\Component\Form\FormEvents;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
|
||||
/** @extends AbstractType<BookingDto> */
|
||||
class PaymentType extends AbstractType
|
||||
{
|
||||
public function buildForm(FormBuilderInterface $builder, array $options): void
|
||||
|
||||
@@ -12,6 +12,7 @@ use Symfony\Component\Form\Extension\Core\Type\EmailType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
|
||||
/** @extends AbstractType<mixed> */
|
||||
class PersonalDataType extends AbstractType
|
||||
{
|
||||
public function buildForm(FormBuilderInterface $builder, array $options): void
|
||||
|
||||
@@ -10,6 +10,7 @@ use Symfony\Component\Form\Extension\Core\Type\TextType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
|
||||
/** @extends AbstractType<RegistrationDto> */
|
||||
class RegistrationType extends AbstractType
|
||||
{
|
||||
public function buildForm(FormBuilderInterface $builder, array $options): void
|
||||
|
||||
@@ -19,6 +19,7 @@ use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
* RoomSelectionDto objects (for template access to price data) and integer IDs
|
||||
* (for the participant's assignedRoomId property).
|
||||
*/
|
||||
/** @extends AbstractType<mixed> */
|
||||
class RoomAssignmentType extends AbstractType
|
||||
{
|
||||
public function buildForm(FormBuilderInterface $builder, array $options): void
|
||||
|
||||
@@ -13,6 +13,7 @@ use Symfony\Component\Form\FormInterface;
|
||||
use Symfony\Component\Form\FormView;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
|
||||
/** @extends AbstractType<RoomSelectionDto> */
|
||||
class RoomSelectType extends AbstractType
|
||||
{
|
||||
public function buildForm(FormBuilderInterface $builder, array $options): void
|
||||
|
||||
@@ -36,10 +36,10 @@ abstract class AbstractFieldOptionsProvider implements FieldOptionsProviderInter
|
||||
* used when building the form field. These options are merged with any
|
||||
* static options defined in the form type.
|
||||
*
|
||||
* @param string $fieldName The name of the field to configure
|
||||
* @param BookingDto $bookingDto The current booking data for context (create or edit)
|
||||
* @param int $participantIndex The index of the participant being configured
|
||||
* @param array $options Additional options to customize field behavior
|
||||
* @param string $fieldName The name of the field to configure
|
||||
* @param BookingDto $bookingDto The current booking data for context (create or edit)
|
||||
* @param int $participantIndex The index of the participant being configured
|
||||
* @param array<string, mixed> $options Additional options to customize field behavior
|
||||
*
|
||||
* @return array<string, mixed> Symfony form field options, or empty array if field not supported
|
||||
*/
|
||||
|
||||
@@ -79,6 +79,7 @@ class BulkInsuranceBookingCondition implements FieldConditionInterface
|
||||
/**
|
||||
* Gets the bulk insurance booking flag value from form data or participant DTO.
|
||||
*/
|
||||
/** @param array<string, mixed> $formData */
|
||||
private function getBulkInsuranceBookingValue(array $formData, object $applicant): bool
|
||||
{
|
||||
// First check form data (for fresh submissions)
|
||||
|
||||
@@ -168,6 +168,7 @@ class CompositeCondition implements FieldConditionInterface
|
||||
* Returns false as soon as any condition evaluates to false,
|
||||
* avoiding unnecessary evaluation of remaining conditions.
|
||||
*/
|
||||
/** @param array<string, mixed> $formData */
|
||||
private function evaluateAnd(BookingDto $bookingDto, int $participantIndex, array $formData): bool
|
||||
{
|
||||
foreach ($this->conditions as $condition) {
|
||||
@@ -185,6 +186,7 @@ class CompositeCondition implements FieldConditionInterface
|
||||
* Returns true as soon as any condition evaluates to true,
|
||||
* avoiding unnecessary evaluation of remaining conditions.
|
||||
*/
|
||||
/** @param array<string, mixed> $formData */
|
||||
private function evaluateOr(BookingDto $bookingDto, int $participantIndex, array $formData): bool
|
||||
{
|
||||
foreach ($this->conditions as $condition) {
|
||||
@@ -199,6 +201,7 @@ class CompositeCondition implements FieldConditionInterface
|
||||
/**
|
||||
* Evaluates NOT logic by inverting the result of the single condition.
|
||||
*/
|
||||
/** @param array<string, mixed> $formData */
|
||||
private function evaluateNot(BookingDto $bookingDto, int $participantIndex, array $formData): bool
|
||||
{
|
||||
return !$this->conditions[0]->evaluate($bookingDto, $participantIndex, $formData);
|
||||
@@ -219,6 +222,7 @@ class CompositeCondition implements FieldConditionInterface
|
||||
/**
|
||||
* Validates condition count based on operator requirements.
|
||||
*/
|
||||
/** @param list<mixed> $conditions */
|
||||
private function validateConditionCount(string $operator, array $conditions): void
|
||||
{
|
||||
$conditionCount = count($conditions);
|
||||
|
||||
@@ -175,6 +175,7 @@ class FieldValueCondition implements FieldConditionInterface
|
||||
/**
|
||||
* Retrieves field value from form data or participant data.
|
||||
*/
|
||||
/** @param array<string, mixed> $formData */
|
||||
private function getFieldValue(array $formData, int $participantIndex, BookingDto $bookingDto): mixed
|
||||
{
|
||||
// First check participant-specific form data
|
||||
@@ -212,6 +213,7 @@ class FieldValueCondition implements FieldConditionInterface
|
||||
/**
|
||||
* Checks if field value is in array of expected values.
|
||||
*/
|
||||
/** @param list<mixed> $expectedValues */
|
||||
private function compareIn(mixed $fieldValue, array $expectedValues): bool
|
||||
{
|
||||
foreach ($expectedValues as $expectedValue) {
|
||||
|
||||
@@ -28,10 +28,6 @@ class RentalInsuranceAvailableCondition implements FieldConditionInterface
|
||||
*/
|
||||
public function evaluate(BookingDto $bookingDto, int $participantIndex, array $formData): bool
|
||||
{
|
||||
if (null === $bookingDto->travel) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$services = $bookingDto->travel->getAdditionalServicesBySubTypes(
|
||||
Constants::TOKEN_RENTAL_INSURANCE,
|
||||
true
|
||||
|
||||
@@ -49,12 +49,7 @@ class RentalSelectionCondition implements FieldConditionInterface
|
||||
if (null !== $participant) {
|
||||
$rentals = $participant->rentals;
|
||||
if (false === empty($rentals)) {
|
||||
// Check if any rental services are actually selected
|
||||
foreach ($rentals as $rental) {
|
||||
if ($rental instanceof Service) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -17,9 +17,9 @@ use App\Form\Service\Contract\FieldConditionInterface;
|
||||
*/
|
||||
class RoomSelectionCondition implements FieldConditionInterface
|
||||
{
|
||||
private const MATCH_MODE_EXACT = 'exact';
|
||||
private const MATCH_MODE_PREFIX = 'prefix';
|
||||
|
||||
/** @var list<string> */
|
||||
private array $requiredRoomCodes;
|
||||
private string $matchMode;
|
||||
|
||||
|
||||
@@ -161,6 +161,7 @@ class ServiceSubTypeCondition implements FieldConditionInterface
|
||||
/**
|
||||
* Retrieves service from form data or participant data.
|
||||
*/
|
||||
/** @param array<string, mixed> $formData */
|
||||
private function getService(array $formData, int $participantIndex, BookingDto $bookingDto): ?Service
|
||||
{
|
||||
// First check participant-specific form data
|
||||
@@ -185,6 +186,7 @@ class ServiceSubTypeCondition implements FieldConditionInterface
|
||||
/**
|
||||
* Checks if sub-type is in the expected array.
|
||||
*/
|
||||
/** @param string|list<string> $expectedSubTypes */
|
||||
private function isSubTypeIn(string $actualSubType, string|array $expectedSubTypes): bool
|
||||
{
|
||||
if (is_string($expectedSubTypes)) {
|
||||
@@ -214,6 +216,7 @@ class ServiceSubTypeCondition implements FieldConditionInterface
|
||||
/**
|
||||
* Validates expected sub-type based on operator requirements.
|
||||
*/
|
||||
/** @param string|list<string> $expectedSubType */
|
||||
private function validateExpectedSubType(string $operator, string|array $expectedSubType): void
|
||||
{
|
||||
if (in_array($operator, [self::OPERATOR_IN, self::OPERATOR_NOT_IN], true) && !is_array($expectedSubType)) {
|
||||
|
||||
@@ -4,7 +4,6 @@ declare(strict_types=1);
|
||||
|
||||
namespace App\Form\Service\Condition;
|
||||
|
||||
use App\BusProNet\Model\Service;
|
||||
use App\Form\Model\BookingDto;
|
||||
use App\Form\Service\Contract\FieldConditionInterface;
|
||||
|
||||
@@ -39,7 +38,7 @@ class SkiPassSelectionCondition implements FieldConditionInterface
|
||||
// First check submitted form data for skipass selection
|
||||
if (isset($formData['participants'][$participantIndex]['skiPass'])) {
|
||||
$selectedSkiPass = $formData['participants'][$participantIndex]['skiPass'];
|
||||
if (null !== $selectedSkiPass && '' !== $selectedSkiPass) {
|
||||
if ('' !== $selectedSkiPass) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -47,10 +46,7 @@ class SkiPassSelectionCondition implements FieldConditionInterface
|
||||
// Then check participant DTO data for existing skipass selection
|
||||
$participant = $bookingDto->getParticipant($participantIndex);
|
||||
if (null !== $participant && null !== $participant->skiPass) {
|
||||
// Check if skipass is actually a Service object
|
||||
if ($participant->skiPass instanceof Service) {
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
@@ -41,10 +41,10 @@ interface FieldOptionsProviderInterface
|
||||
* used when building the form field. These options are merged with any
|
||||
* static options defined in the form type.
|
||||
*
|
||||
* @param string $fieldName The name of the field to configure
|
||||
* @param BookingDto $bookingDto The current booking data for context (create or edit)
|
||||
* @param int $participantIndex The index of the participant being configured
|
||||
* @param array $options Additional options to customize field behavior
|
||||
* @param string $fieldName The name of the field to configure
|
||||
* @param BookingDto $bookingDto The current booking data for context (create or edit)
|
||||
* @param int $participantIndex The index of the participant being configured
|
||||
* @param array<string, mixed> $options Additional options to customize field behavior
|
||||
*
|
||||
* @return array<string, mixed> Symfony form field options, or empty array if field not supported
|
||||
*/
|
||||
|
||||
@@ -5,6 +5,7 @@ declare(strict_types=1);
|
||||
namespace App\Form\Service\Contract;
|
||||
|
||||
use App\Form\Model\BookingDto;
|
||||
use Symfony\Component\Form\FormInterface;
|
||||
|
||||
/**
|
||||
* Interface for providing dynamic field state based on conditions.
|
||||
@@ -30,6 +31,15 @@ use App\Form\Model\BookingDto;
|
||||
*/
|
||||
interface FieldStateProviderInterface
|
||||
{
|
||||
/**
|
||||
* Gets the BookingDto from the root of the form tree.
|
||||
*
|
||||
* @param FormInterface<mixed> $form The form to start traversing from
|
||||
*
|
||||
* @return BookingDto|null The booking DTO or null if not found
|
||||
*/
|
||||
public function getBookingDtoFromForm(FormInterface $form): ?BookingDto;
|
||||
|
||||
/**
|
||||
* Determines whether a field should be included in the form at all.
|
||||
*
|
||||
|
||||
@@ -131,6 +131,10 @@ class ParticipantAdditionalServicesFieldHandler extends AbstractParticipantField
|
||||
$participant->additionalServices = $validSelections;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<int, Service> $availableServices
|
||||
* @param list<Service> $validSelections
|
||||
*/
|
||||
private function updateAutoBookOptOutServices(
|
||||
ParticipantDto $participant,
|
||||
array $availableServices,
|
||||
@@ -140,10 +144,6 @@ class ParticipantAdditionalServicesFieldHandler extends AbstractParticipantField
|
||||
): void {
|
||||
$currentlySelectedAutoBookIds = [];
|
||||
foreach ($participant->additionalServices as $selectedService) {
|
||||
if (false === $selectedService instanceof Service) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (null === $selectedService->id || true === $selectedService->mandatory || false === $selectedService->autoBook) {
|
||||
continue;
|
||||
}
|
||||
@@ -186,12 +186,12 @@ class ParticipantAdditionalServicesFieldHandler extends AbstractParticipantField
|
||||
* and the participant's age constraints. Services that are no longer available
|
||||
* or appropriate for the participant's age are filtered out.
|
||||
*
|
||||
* @param array $selectedServices List of currently selected services
|
||||
* @param array $availableServices List of all available additional services
|
||||
* @param BookingDto $bookingDto The booking DTO for context
|
||||
* @param int $participantIndex The participant index for age evaluation
|
||||
* @param list<mixed> $selectedServices List of currently selected services
|
||||
* @param array<int, Service> $availableServices List of all available additional services
|
||||
* @param BookingDto $bookingDto The booking DTO for context
|
||||
* @param int $participantIndex The participant index for age evaluation
|
||||
*
|
||||
* @return array Filtered array of valid service selections
|
||||
* @return list<Service> Filtered array of valid service selections
|
||||
*/
|
||||
private function filterValidServiceSelections(
|
||||
array $selectedServices,
|
||||
@@ -220,10 +220,10 @@ class ParticipantAdditionalServicesFieldHandler extends AbstractParticipantField
|
||||
* This method checks if a selected service exists in the available services
|
||||
* and meets the age constraints for the current participant.
|
||||
*
|
||||
* @param mixed $selectedService The selected service to validate
|
||||
* @param array $availableServices Array of available services
|
||||
* @param BookingDto $bookingDto The booking DTO for context
|
||||
* @param int $participantIndex The participant index for age evaluation
|
||||
* @param mixed $selectedService The selected service to validate
|
||||
* @param array<int, Service> $availableServices Array of available services
|
||||
* @param BookingDto $bookingDto The booking DTO for context
|
||||
* @param int $participantIndex The participant index for age evaluation
|
||||
*
|
||||
* @return bool True if the service is valid for the participant, false otherwise
|
||||
*/
|
||||
|
||||
@@ -89,6 +89,10 @@ class ParticipantBoardFieldHandler extends AbstractParticipantFieldHandler
|
||||
$participant->board = $validSelections;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<int, Service> $availableBoard
|
||||
* @param list<Service> $validSelections
|
||||
*/
|
||||
private function updateAutoBookOptOutBoard(
|
||||
ParticipantDto $participant,
|
||||
array $availableBoard,
|
||||
@@ -98,10 +102,6 @@ class ParticipantBoardFieldHandler extends AbstractParticipantFieldHandler
|
||||
): void {
|
||||
$currentlySelectedAutoBookIds = [];
|
||||
foreach ($participant->board as $selectedService) {
|
||||
if (false === $selectedService instanceof Service) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (null === $selectedService->id || true === $selectedService->mandatory || false === $selectedService->autoBook) {
|
||||
continue;
|
||||
}
|
||||
@@ -135,6 +135,12 @@ class ParticipantBoardFieldHandler extends AbstractParticipantFieldHandler
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param list<mixed> $selectedServices
|
||||
* @param array<int, Service> $availableServices
|
||||
*
|
||||
* @return list<Service>
|
||||
*/
|
||||
private function filterValidServiceSelections(
|
||||
array $selectedServices,
|
||||
array $availableServices,
|
||||
@@ -156,6 +162,9 @@ class ParticipantBoardFieldHandler extends AbstractParticipantFieldHandler
|
||||
return $validSelections;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<int, Service> $availableServices
|
||||
*/
|
||||
private function isServiceValidForParticipant(
|
||||
mixed $selectedService,
|
||||
array $availableServices,
|
||||
|
||||
@@ -114,12 +114,12 @@ class ParticipantCoursesFieldHandler extends AbstractParticipantFieldHandler
|
||||
/**
|
||||
* Filters course selections to keep only those valid for the participant's age.
|
||||
*
|
||||
* @param array $selectedServices List of currently selected courses
|
||||
* @param array $availableServices List of all available courses
|
||||
* @param BookingDto $bookingDto The booking DTO for context
|
||||
* @param int $participantIndex The participant index for age evaluation
|
||||
* @param list<mixed> $selectedServices List of currently selected courses
|
||||
* @param array<int, Service> $availableServices List of all available courses
|
||||
* @param BookingDto $bookingDto The booking DTO for context
|
||||
* @param int $participantIndex The participant index for age evaluation
|
||||
*
|
||||
* @return array Filtered array of valid course selections
|
||||
* @return list<Service> Filtered array of valid course selections
|
||||
*/
|
||||
private function filterValidServiceSelections(
|
||||
array $selectedServices,
|
||||
@@ -145,10 +145,10 @@ class ParticipantCoursesFieldHandler extends AbstractParticipantFieldHandler
|
||||
/**
|
||||
* Validates if a selected course is still valid for the participant.
|
||||
*
|
||||
* @param mixed $selectedService The selected course to validate
|
||||
* @param array $availableServices Array of available courses
|
||||
* @param BookingDto $bookingDto The booking DTO for context
|
||||
* @param int $participantIndex The participant index for age evaluation
|
||||
* @param mixed $selectedService The selected course to validate
|
||||
* @param array<int, Service> $availableServices Array of available courses
|
||||
* @param BookingDto $bookingDto The booking DTO for context
|
||||
* @param int $participantIndex The participant index for age evaluation
|
||||
*
|
||||
* @return bool True if the course is valid for the participant, false otherwise
|
||||
*/
|
||||
|
||||
@@ -100,9 +100,9 @@ class ParticipantDateOfBirthFieldHandler extends AbstractParticipantFieldHandler
|
||||
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'] ?? ''))
|
||||
|| '' === trim((string) $value['year'])
|
||||
|| '' === trim((string) $value['month'])
|
||||
|| '' === trim((string) $value['day'])
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -511,7 +511,7 @@ class ParticipantFieldOptionsProvider extends AbstractFieldOptionsProvider
|
||||
return [
|
||||
'label' => 'Hinfahrt',
|
||||
'choices' => $choices,
|
||||
'choice_label' => fn (Service $service) => $service?->label,
|
||||
'choice_label' => fn (Service $service) => $service->label,
|
||||
'choice_value' => 'id',
|
||||
'expanded' => true,
|
||||
'multiple' => false,
|
||||
@@ -551,7 +551,7 @@ class ParticipantFieldOptionsProvider extends AbstractFieldOptionsProvider
|
||||
return [
|
||||
'label' => 'Rückfahrt',
|
||||
'choices' => $choices,
|
||||
'choice_label' => fn (Service $service) => $service?->label,
|
||||
'choice_label' => fn (Service $service) => $service->label,
|
||||
'choice_value' => 'id',
|
||||
'expanded' => true,
|
||||
'multiple' => false,
|
||||
@@ -622,7 +622,7 @@ class ParticipantFieldOptionsProvider extends AbstractFieldOptionsProvider
|
||||
$hasOutboundBus = null !== $participant?->transportationOutbound
|
||||
&& DirectionMapper::SUBTYPE_BUS_API === $participant->transportationOutbound->subType;
|
||||
|
||||
if ($hasOutboundBus && false === ($participant->differentDropOff ?? false)) {
|
||||
if ($hasOutboundBus && false === $participant->differentDropOff) {
|
||||
return [];
|
||||
}
|
||||
|
||||
@@ -806,11 +806,11 @@ class ParticipantFieldOptionsProvider extends AbstractFieldOptionsProvider
|
||||
* as the participant's selected skipass. This ensures rental equipment
|
||||
* is only available for the exact duration of the skipass.
|
||||
*
|
||||
* @param array $rentals Array of rental Service objects to filter
|
||||
* @param BookingDto $bookingDto The booking DTO containing participant data
|
||||
* @param int $participantIndex Index of the participant to evaluate
|
||||
* @param array<int, Service> $rentals Array of rental Service objects to filter
|
||||
* @param BookingDto $bookingDto The booking DTO containing participant data
|
||||
* @param int $participantIndex Index of the participant to evaluate
|
||||
*
|
||||
* @return array Filtered array of rentals matching skipass duration
|
||||
* @return array<int, Service> Filtered array of rentals matching skipass duration
|
||||
*/
|
||||
private function filterRentalsBySkiPassDuration(array $rentals, BookingDto $bookingDto, int $participantIndex): array
|
||||
{
|
||||
@@ -914,8 +914,8 @@ class ParticipantFieldOptionsProvider extends AbstractFieldOptionsProvider
|
||||
/**
|
||||
* Checks if a service array contains a service with the given ID.
|
||||
*
|
||||
* @param array $services Array of Service objects
|
||||
* @param int $serviceId Service ID to search for
|
||||
* @param array<int, Service> $services Array of Service objects
|
||||
* @param int $serviceId Service ID to search for
|
||||
*
|
||||
* @return bool True if the service is found in the array
|
||||
*/
|
||||
@@ -937,11 +937,11 @@ class ParticipantFieldOptionsProvider extends AbstractFieldOptionsProvider
|
||||
* If no age evaluator is configured or participant has no birth date,
|
||||
* returns empty array to be handled by field visibility conditions.
|
||||
*
|
||||
* @param array $services Array of Service objects to filter
|
||||
* @param BookingDto $bookingDto The booking DTO containing participant data
|
||||
* @param int $participantIndex Index of the participant to evaluate
|
||||
* @param array<int, Service> $services Array of Service objects to filter
|
||||
* @param BookingDto $bookingDto The booking DTO containing participant data
|
||||
* @param int $participantIndex Index of the participant to evaluate
|
||||
*
|
||||
* @return array Filtered array of available services
|
||||
* @return array<int, Service> Filtered array of available services
|
||||
*/
|
||||
private function filterServicesByAgeConstraints(array $services, BookingDto $bookingDto, int $participantIndex): array
|
||||
{
|
||||
@@ -1112,6 +1112,7 @@ class ParticipantFieldOptionsProvider extends AbstractFieldOptionsProvider
|
||||
/**
|
||||
* Gets the rental insurance description for help text.
|
||||
*/
|
||||
/** @param list<Service> $rentalInsuranceManagers */
|
||||
private function getRentalInsuranceDescription(array $rentalInsuranceManagers): ?string
|
||||
{
|
||||
if (empty($rentalInsuranceManagers)) {
|
||||
@@ -1131,7 +1132,7 @@ class ParticipantFieldOptionsProvider extends AbstractFieldOptionsProvider
|
||||
* @param BookingDto $bookingDto The booking DTO containing travel and participant data
|
||||
* @param int $participantIndex The index of the participant to get eligible insurances for
|
||||
*
|
||||
* @return array Array of eligible insurance objects filtered by age, family status, and other constraints
|
||||
* @return list<Insurance> Array of eligible insurance objects filtered by age, family status, and other constraints
|
||||
*/
|
||||
private function getEligibleInsurances(BookingDto $bookingDto, int $participantIndex): array
|
||||
{
|
||||
@@ -1180,11 +1181,11 @@ class ParticipantFieldOptionsProvider extends AbstractFieldOptionsProvider
|
||||
* got the discount to change their mind (e.g., select bus instead), making the discount available
|
||||
* for others in the same booking session.
|
||||
*
|
||||
* @param array $services Transportation services from Travel model
|
||||
* @param BookingDto $bookingDto Current booking DTO with participant selections
|
||||
* @param int $participantIndex Current participant being processed
|
||||
* @param array<int, Service> $services Transportation services from Travel model
|
||||
* @param BookingDto $bookingDto Current booking DTO with participant selections
|
||||
* @param int $participantIndex Current participant being processed
|
||||
*
|
||||
* @return array Filtered transportation choices with smart PKW option selection
|
||||
* @return array<int, Service> Filtered transportation choices with smart PKW option selection
|
||||
*/
|
||||
private function filterTransportationChoices(array $services, BookingDto $bookingDto, int $participantIndex): array
|
||||
{
|
||||
|
||||
@@ -128,6 +128,10 @@ class ParticipantRentalsFieldHandler extends AbstractParticipantFieldHandler
|
||||
$participant->rentals = $validSelections;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<int, Service> $availableRentals
|
||||
* @param list<Service> $validSelections
|
||||
*/
|
||||
private function updateAutoBookOptOutRentals(
|
||||
ParticipantDto $participant,
|
||||
array $availableRentals,
|
||||
@@ -137,10 +141,6 @@ class ParticipantRentalsFieldHandler extends AbstractParticipantFieldHandler
|
||||
): void {
|
||||
$currentlySelectedAutoBookIds = [];
|
||||
foreach ($participant->rentals as $selectedService) {
|
||||
if (false === $selectedService instanceof Service) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (null === $selectedService->id || true === $selectedService->mandatory || false === $selectedService->autoBook) {
|
||||
continue;
|
||||
}
|
||||
@@ -174,6 +174,12 @@ class ParticipantRentalsFieldHandler extends AbstractParticipantFieldHandler
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param list<mixed> $selectedServices
|
||||
* @param array<int, Service> $availableServices
|
||||
*
|
||||
* @return list<Service>
|
||||
*/
|
||||
private function filterValidServiceSelections(
|
||||
array $selectedServices,
|
||||
array $availableServices,
|
||||
@@ -195,6 +201,9 @@ class ParticipantRentalsFieldHandler extends AbstractParticipantFieldHandler
|
||||
return $validSelections;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<int, Service> $availableServices
|
||||
*/
|
||||
private function isServiceValidForParticipant(
|
||||
mixed $selectedService,
|
||||
array $availableServices,
|
||||
@@ -222,12 +231,12 @@ class ParticipantRentalsFieldHandler extends AbstractParticipantFieldHandler
|
||||
* - rental.dateFrom === skipass.dateFrom
|
||||
* - rental.dateTo === skipass.dateTo
|
||||
*
|
||||
* @param array $rentals All available rental services
|
||||
* @param ParticipantDto $participant The participant with skipass selection
|
||||
* @param array<int, Service> $rentals All available rental services
|
||||
* @param ParticipantDto $participant The participant with skipass selection
|
||||
*
|
||||
* @return array Filtered rentals matching the skipass duration
|
||||
* @return array<int, Service> Filtered rentals matching the skipass duration
|
||||
*/
|
||||
private function filterRentalsBySkiPassDuration(array $rentals, $participant): array
|
||||
private function filterRentalsBySkiPassDuration(array $rentals, ParticipantDto $participant): array
|
||||
{
|
||||
$selectedSkiPass = $participant->skiPass;
|
||||
|
||||
|
||||
@@ -129,6 +129,7 @@ class ParticipantSkiPassFieldHandler extends AbstractParticipantFieldHandler
|
||||
$participant->skiPass = $validSelection;
|
||||
}
|
||||
|
||||
/** @param array<int, Service> $availableSkipasses */
|
||||
private function getSelectedAutoBookSkiPassId(
|
||||
ParticipantDto $participant,
|
||||
array $availableSkipasses,
|
||||
@@ -184,10 +185,10 @@ class ParticipantSkiPassFieldHandler extends AbstractParticipantFieldHandler
|
||||
* This method checks both age constraints (via birth year ranges) and
|
||||
* date constraints (skipass dates must be within travel dates).
|
||||
*
|
||||
* @param mixed $selectedService The selected skipass to validate
|
||||
* @param array $availableServices Array of available skipasses
|
||||
* @param BookingDto $bookingDto The booking DTO for context
|
||||
* @param int $participantIndex The participant index for age evaluation
|
||||
* @param mixed $selectedService The selected skipass to validate
|
||||
* @param array<int, Service> $availableServices Array of available skipasses
|
||||
* @param BookingDto $bookingDto The booking DTO for context
|
||||
* @param int $participantIndex The participant index for age evaluation
|
||||
*
|
||||
* @return bool True if the skipass is valid for the participant, false otherwise
|
||||
*/
|
||||
|
||||
@@ -107,10 +107,10 @@ class ParticipantVegFieldHandler extends AbstractParticipantFieldHandler
|
||||
*
|
||||
* This method checks age constraints if they exist for the service.
|
||||
*
|
||||
* @param mixed $selectedService The selected veg option to validate
|
||||
* @param array $availableServices Array of available veg options
|
||||
* @param BookingDto $bookingDto The booking DTO for context
|
||||
* @param int $participantIndex The participant index for age evaluation
|
||||
* @param mixed $selectedService The selected veg option to validate
|
||||
* @param array<int, Service> $availableServices Array of available veg options
|
||||
* @param BookingDto $bookingDto The booking DTO for context
|
||||
* @param int $participantIndex The participant index for age evaluation
|
||||
*
|
||||
* @return bool True if the option is valid for the participant, false otherwise
|
||||
*/
|
||||
|
||||
@@ -26,7 +26,7 @@ trait FormTraversalTrait
|
||||
* 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
|
||||
* @param FormInterface<mixed> $form The form to start traversing from
|
||||
*
|
||||
* @return BookingDto|null The booking DTO or null if not found
|
||||
*/
|
||||
|
||||
@@ -8,6 +8,7 @@ use Symfony\Component\Form\FormInterface;
|
||||
use Symfony\Component\Form\FormView;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
|
||||
/** @extends AbstractType<mixed> */
|
||||
class StepSelectChoiceType extends AbstractType
|
||||
{
|
||||
public function getParent(): string
|
||||
|
||||
Reference in New Issue
Block a user