60 lines
1.9 KiB
PHP
60 lines
1.9 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Enum;
|
|
|
|
/**
|
|
* Room type as the website's travel search filters it ("Zimmerarten").
|
|
*
|
|
* Taken from the room's capacity, as TYPO3's RoomTypeResolver does since the room-code
|
|
* mapping was retired: `maxPax` 1-8 maps directly, 9 and up is "9er+". A bed shared with
|
|
* other customers is sold per bed (`maxPax` 1), so it is recognised by its label instead;
|
|
* without that, a bed in a dorm would count as an Einzelzimmer.
|
|
*/
|
|
enum RoomType: string
|
|
{
|
|
case ForOne = 'EZ';
|
|
case ForTwo = 'DZ';
|
|
case ForThree = '3er';
|
|
case ForFour = '4er';
|
|
case ForFive = '5er';
|
|
case ForSix = '6er';
|
|
case ForSeven = '7er';
|
|
case ForEight = '8er';
|
|
case ForNinePlus = '9er+';
|
|
case WithOthers = 'mit anderen';
|
|
|
|
/** The "Babypreis 0-2 Jährige" row: priced like a room, but not one. */
|
|
public const BABY_CODE = 'Baby';
|
|
|
|
/** Label phrases (lower case) that mark a bed shared with other customers. */
|
|
private const WITH_OTHERS_MARKERS = ['bett im', 'mit ander'];
|
|
|
|
/**
|
|
* Null for the baby row, which is not a room.
|
|
*/
|
|
public static function classify(?string $code, ?string $label, ?int $maxPax, ?int $minPax): ?self
|
|
{
|
|
if (self::BABY_CODE === trim((string) $code)) {
|
|
return null;
|
|
}
|
|
|
|
$label = mb_strtolower((string) $label);
|
|
foreach (self::WITH_OTHERS_MARKERS as $marker) {
|
|
if (str_contains($label, $marker)) {
|
|
return self::WithOthers;
|
|
}
|
|
}
|
|
|
|
$pax = ($maxPax ?? 0) > 0 ? (int) $maxPax : (int) $minPax;
|
|
|
|
return match (true) {
|
|
$pax >= 9 => self::ForNinePlus,
|
|
$pax >= 1 => [1 => self::ForOne, self::ForTwo, self::ForThree, self::ForFour, self::ForFive, self::ForSix, self::ForSeven, self::ForEight][$pax],
|
|
// No usable occupancy: TYPO3 files it under "mit anderen" as well.
|
|
default => self::WithOthers,
|
|
};
|
|
}
|
|
}
|