126 lines
4.2 KiB
PHP
126 lines
4.2 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Form\Service;
|
|
|
|
use App\Form\Model\BookingDtoInterface;
|
|
use App\Form\ParticipantFieldHandler\Condition\FieldConditionInterface;
|
|
use App\Form\ParticipantFieldHandler\Condition\MutabilityCondition;
|
|
use App\Form\ParticipantFieldHandler\Condition\ApplicantCondition;
|
|
use App\Form\ParticipantFieldHandler\Condition\CompositeCondition;
|
|
|
|
/**
|
|
* Field state provider for the booking edit workflow.
|
|
*
|
|
* This service calculates dynamic field states (readonly, disabled, etc.)
|
|
* for participant fields in the edit flow, using edit-specific conditions.
|
|
*
|
|
* It is designed to be extensible and composable, allowing reuse of
|
|
* existing condition classes and easy registration of new logic.
|
|
*/
|
|
class EditFieldStateProvider implements FieldStateProviderInterface
|
|
{
|
|
/** @var array<string, array<string, FieldConditionInterface>> */
|
|
private array $fieldStateConditions = [];
|
|
|
|
public function __construct()
|
|
{
|
|
$this->registerFieldStateConditions();
|
|
}
|
|
|
|
/**
|
|
* Registers field state conditions for the edit workflow.
|
|
*
|
|
* Add or modify conditions as needed for your domain.
|
|
*/
|
|
private function registerFieldStateConditions(): void
|
|
{
|
|
// Make all personal data fields readonly if not mutable OR if applicant
|
|
$personalDataFields = [
|
|
'firstName',
|
|
'lastName',
|
|
'dateOfBirth',
|
|
'gender',
|
|
'nationality',
|
|
'email',
|
|
'mobile',
|
|
];
|
|
foreach ($personalDataFields as $field) {
|
|
$this->fieldStateConditions[$field] = [
|
|
'readonly' => CompositeCondition::or(
|
|
new ApplicantCondition(),
|
|
new MutabilityCondition()
|
|
),
|
|
];
|
|
}
|
|
|
|
// Example: Only applicant can edit email
|
|
$this->fieldStateConditions['email']['readonly'] = new ApplicantCondition();
|
|
}
|
|
|
|
public function getFieldState(string $fieldName, BookingDtoInterface $bookingDto, int $participantIndex, array $formData = []): array
|
|
{
|
|
if (!isset($this->fieldStateConditions[$fieldName])) {
|
|
return [];
|
|
}
|
|
|
|
$stateModifications = [];
|
|
$attributes = [];
|
|
|
|
foreach ($this->fieldStateConditions[$fieldName] as $stateType => $condition) {
|
|
if ($condition->evaluate($bookingDto, $participantIndex, $formData)) {
|
|
switch ($stateType) {
|
|
case 'readonly':
|
|
$attributes['readonly'] = true;
|
|
break;
|
|
case 'disabled':
|
|
$stateModifications['disabled'] = true;
|
|
break;
|
|
case 'required':
|
|
$stateModifications['required'] = true;
|
|
break;
|
|
case 'hidden':
|
|
$attributes['style'] = ($attributes['style'] ?? '').' display: none;';
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!empty($attributes)) {
|
|
$stateModifications['attr'] = $attributes;
|
|
}
|
|
|
|
return $stateModifications;
|
|
}
|
|
|
|
public function hasStateConditions(string $fieldName): bool
|
|
{
|
|
return isset($this->fieldStateConditions[$fieldName]) && !empty($this->fieldStateConditions[$fieldName]);
|
|
}
|
|
|
|
public function getFieldStateDependencies(string $fieldName): array
|
|
{
|
|
if (!isset($this->fieldStateConditions[$fieldName])) {
|
|
return [];
|
|
}
|
|
|
|
$dependencies = [];
|
|
foreach ($this->fieldStateConditions[$fieldName] as $condition) {
|
|
$dependencies = array_merge($dependencies, $condition->getDependentFields());
|
|
}
|
|
return array_unique($dependencies);
|
|
}
|
|
|
|
public function getAllFieldStates(BookingDtoInterface $bookingDto, int $participantIndex, array $formData = []): array
|
|
{
|
|
$allStates = [];
|
|
foreach (array_keys($this->fieldStateConditions) as $fieldName) {
|
|
$fieldState = $this->getFieldState($fieldName, $bookingDto, $participantIndex, $formData);
|
|
if (!empty($fieldState)) {
|
|
$allStates[$fieldName] = $fieldState;
|
|
}
|
|
}
|
|
return $allStates;
|
|
}
|
|
}
|