144 lines
5.0 KiB
PHP
144 lines
5.0 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Form\Service\Condition;
|
|
|
|
use App\BusProNet\Model\Room;
|
|
use App\Form\Model\BookingDto;
|
|
use App\Form\Service\Contract\FieldConditionInterface;
|
|
|
|
/**
|
|
* Condition that evaluates whether a participant has selected a room with specific code(s).
|
|
*
|
|
* This condition checks if a participant has selected a room that matches any of the
|
|
* configured room codes. This allows for flexible room-based field visibility logic
|
|
* where different fields can be shown based on the selected room type.
|
|
*/
|
|
class RoomSelectionCondition implements FieldConditionInterface
|
|
{
|
|
private const MATCH_MODE_PREFIX = 'prefix';
|
|
|
|
/** @var list<string> */
|
|
private array $requiredRoomCodes;
|
|
private string $matchMode;
|
|
|
|
/**
|
|
* Creates a new room selection condition for specified room codes.
|
|
*
|
|
* @param array<string> $requiredRoomCodes Room codes that should trigger this condition
|
|
* @param string $matchMode Match mode: 'prefix' (default) or 'exact'
|
|
*/
|
|
public function __construct(array $requiredRoomCodes, string $matchMode = self::MATCH_MODE_PREFIX)
|
|
{
|
|
$this->requiredRoomCodes = array_map('strtolower', $requiredRoomCodes);
|
|
$this->matchMode = $matchMode;
|
|
}
|
|
|
|
/**
|
|
* Evaluates whether the participant has selected a room with one of the required codes.
|
|
*
|
|
* Checks both submitted form data and participant DTO data to determine
|
|
* if the selected room matches any of the configured room codes.
|
|
*
|
|
* @param BookingDto $bookingDto The current booking data (create or edit)
|
|
* @param int $participantIndex The index of the participant being evaluated
|
|
* @param array<string, mixed> $formData Current form data for condition evaluation
|
|
*
|
|
* @return bool True if room with matching code is selected, false otherwise
|
|
*/
|
|
public function evaluate(BookingDto $bookingDto, int $participantIndex, array $formData): bool
|
|
{
|
|
// First check submitted form data for room selection
|
|
if (isset($formData['participants'][$participantIndex]['assignedRoomId'])) {
|
|
$selectedRoomId = $formData['participants'][$participantIndex]['assignedRoomId'];
|
|
if (true === is_numeric($selectedRoomId)) {
|
|
$room = $this->findRoomById((int) $selectedRoomId, $bookingDto);
|
|
if (null !== $room && $this->matchesRoomCode($room->code ?? '')) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Then check participant DTO data for existing room selection
|
|
$participant = $bookingDto->getParticipant($participantIndex);
|
|
if (null !== $participant && null !== $participant->assignedRoomId) {
|
|
$room = $this->findRoomById($participant->assignedRoomId, $bookingDto);
|
|
if (null !== $room && $this->matchesRoomCode($room->code ?? '')) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Returns field names that trigger re-evaluation of this condition.
|
|
*
|
|
* This condition depends on the assignedRoomId field, so any changes to room
|
|
* selection should trigger re-evaluation of dependent fields.
|
|
*
|
|
* @return string[] Array containing the field names that affect this condition
|
|
*/
|
|
public function getDependentFields(): array
|
|
{
|
|
return ['assignedRoomId'];
|
|
}
|
|
|
|
/**
|
|
* Returns a human-readable description of this condition.
|
|
*
|
|
* @return string A brief description of the condition logic
|
|
*/
|
|
public function getDescription(): string
|
|
{
|
|
$codes = implode(', ', $this->requiredRoomCodes);
|
|
$matchType = self::MATCH_MODE_PREFIX === $this->matchMode ? 'starting with' : 'matching';
|
|
|
|
return "Field visible when room with code(s) {$matchType} [{$codes}] is selected";
|
|
}
|
|
|
|
/**
|
|
* Finds a room by ID in the available travel rooms.
|
|
*
|
|
* @param int $roomId The room ID to find
|
|
* @param BookingDto $bookingDto The booking DTO containing travel data
|
|
*
|
|
* @return Room|null The found room or null if not found
|
|
*/
|
|
private function findRoomById(int $roomId, BookingDto $bookingDto): ?Room
|
|
{
|
|
foreach ($bookingDto->travel->rooms as $room) {
|
|
if ($room->id === $roomId) {
|
|
return $room;
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Checks if a room code matches any of the required codes based on match mode.
|
|
*
|
|
* @param string $roomCode The room code to check
|
|
*
|
|
* @return bool True if the room code matches, false otherwise
|
|
*/
|
|
private function matchesRoomCode(string $roomCode): bool
|
|
{
|
|
$roomCode = strtolower($roomCode);
|
|
|
|
if (self::MATCH_MODE_PREFIX === $this->matchMode) {
|
|
foreach ($this->requiredRoomCodes as $code) {
|
|
if (str_starts_with($roomCode, $code)) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
return in_array($roomCode, $this->requiredRoomCodes, true);
|
|
}
|
|
}
|