'Y-m-d'])] public ?\DateTimeImmutable $dateFrom = null; #[Groups(['api:list', 'api:single'])] #[Context([DateTimeNormalizer::FORMAT_KEY => 'Y-m-d'])] public ?\DateTimeImmutable $dateTo = null; #[Groups(['api:list', 'api:single'])] public ?string $type = null; #[Groups(['api:list', 'api:single'])] public ?float $priceFrom = null; #[Groups(['api:single'])] public array $selectionGroups = []; #[Groups(['api:single'])] public array $additionalServices = []; #[Groups(['api:single'])] public bool $additionalServicesMutable = true; #[Groups(['api:single'])] public array $transportationServices = []; #[Groups(['api:single'])] public bool $transportationServicesMutable = true; #[Groups(['api:single'])] public array $pickupsTo = []; #[Groups(['api:single'])] public array $pickupsFro = []; #[Groups(['api:single'])] public bool $pickupsMutable = true; #[Groups(['api:single'])] public array $rooms = []; #[Groups(['api:single'])] public bool $roomsMutable = true; #[Groups(['api:single'])] public bool $participantDataMutable = true; #[Groups(['api:single'])] public bool $participantCountMutable = true; #[Groups(['api:single'])] public ?Guide $guide = null; /** * Retrieves additional services filtered by group and availability. * * Filters additional services based on the provided group(s) and optionally * by availability. Services are sorted alphabetically by label. * * @param mixed $group The service group(s) to filter by * @param bool $availableOnly Whether to include only available services * * @return array The filtered and sorted services array */ public function getAdditionalServicesByGroup(mixed $group, bool $availableOnly = true): array { $group = (array) $group; $services = array_filter($this->additionalServices, function (Service $service) use ($group, $availableOnly) { return true === in_array($service->subType, $group) && (false === $availableOnly || 0 < $service->available); }); usort($services, function (Service $a, Service $b) { return $a->label <=> $b->label; }); return $services; } /** * Retrieves transportation services filtered by direction and availability. * * Filters transportation services based on travel direction and optionally * by availability. Services are sorted by subtype. * * @param string $direction The travel direction to filter by * @param bool $availableOnly Whether to include only available services * * @return array The filtered and sorted transportation services */ public function getTransportationServicesByDirection(string $direction, bool $availableOnly = true): array { $services = array_filter($this->transportationServices, function (Service $service) use ($direction, $availableOnly) { return $direction === $service->direction && $service->price >= 0 && (false === $availableOnly || $service->available > 0); }); usort($services, function (Service $a, Service $b) { return $a->subType <=> $b->subType; }); return $services; } /** * Retrieves included services from selection groups. * * Maps selection group IDs to their corresponding services based on * the predefined included services mapping. * * @return array The included services from selection groups */ public function getIncludedServices(): array { $services = []; foreach (CrmSelectionGroup::$includedServicesMapping as $id => $label) { if (true === isset($this->selectionGroups[$id])) { $services[] = $this->selectionGroups[$id]; } } return $services; } /** * Retrieves rooms filtered by their IDs. * * Filters the rooms array to return only rooms whose IDs match * the provided array of IDs. Returns an empty array if no matching * rooms are found. * * @param array $ids The array of room IDs to filter by * * @return array The filtered rooms array */ public function getRoomsByIds(array $ids): array { if (true === empty($ids)) { return []; } return array_filter($this->rooms, function (Room $room) use ($ids) { return in_array($room->id, $ids, true); }); } /** * Retrieves all available rooms for booking. * * Filters the rooms collection to return only rooms that have availability * greater than zero and have an available status. This ensures only * bookable rooms are returned for selection. * * @return array The filtered array of available rooms, indexed by room ID */ public function getAvailableRooms(): array { $result = []; foreach ($this->rooms as $room) { if ($room->available > 0 && Constants::STATUS_AVAILABLE === $room->status) { $result[$room->id] = $room; } } return $result; } }