Files
myep/src/Form/Service/ServiceAgeEvaluator.php
T

198 lines
6.7 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Form\Service;
use App\BusProNet\Model\Service;
use App\Form\Model\BookingDtoInterface;
/**
* Evaluates service availability based on participant age constraints.
*
* This service handles the business logic of determining whether a service
* is available to a specific participant based on their age or birth year.
* It supports both absolute age constraints and birth year range constraints.
*/
class ServiceAgeEvaluator
{
/**
* Determines if this evaluator can process the given service.
*
* @param Service $service The service to evaluate
*
* @return bool True if the service has age constraints that can be evaluated
*/
public function canEvaluate(Service $service): bool
{
return null !== $service->ageConstraintType;
}
/**
* Evaluates if a service is available for a specific participant.
*
* Checks the participant's age or birth year against the service's
* constraint requirements. Returns false if the participant doesn't
* meet the age requirements or if no birth date is provided.
*
* @param Service $service The service to evaluate
* @param BookingDtoInterface $bookingDto The booking containing participant data
* @param int $participantIndex The index of the participant to evaluate
*
* @return bool True if the service is available for the participant
*/
public function isServiceAvailableForParticipant(Service $service, BookingDtoInterface $bookingDto, int $participantIndex): bool
{
$participant = $bookingDto->getParticipant($participantIndex);
if (null === $participant || null === $participant->dateOfBirth) {
return false; // Cannot evaluate without birth date
}
return match ($service->ageConstraintType) {
'absolute_age' => $this->evaluateAbsoluteAge($service, $participant->dateOfBirth),
'birth_year' => $this->evaluateBirthYear($service, $participant->dateOfBirth),
'mixed' => $this->evaluateAbsoluteAge($service, $participant->dateOfBirth)
&& $this->evaluateBirthYear($service, $participant->dateOfBirth),
default => true, // No constraints or unknown type
};
}
/**
* Evaluates absolute age constraints against participant's current age.
*
* @param Service $service The service with age constraints
* @param \DateTimeImmutable $dateOfBirth The participant's date of birth
*
* @return bool True if the participant meets the absolute age requirements
*/
private function evaluateAbsoluteAge(Service $service, \DateTimeImmutable $dateOfBirth): bool
{
$age = $this->calculateAge($dateOfBirth);
if (null !== $service->ageFrom && $age < $service->ageFrom) {
return false;
}
if (null !== $service->ageTo && $age > $service->ageTo) {
return false;
}
return true;
}
/**
* Evaluates birth year constraints against participant's birth year.
*
* @param Service $service The service with birth year constraints
* @param \DateTimeImmutable $dateOfBirth The participant's date of birth
*
* @return bool True if the participant meets the birth year requirements
*/
private function evaluateBirthYear(Service $service, \DateTimeImmutable $dateOfBirth): bool
{
$birthYear = (int) $dateOfBirth->format('Y');
if (null !== $service->birthYearFrom && $birthYear < $service->birthYearFrom) {
return false;
}
if (null !== $service->birthYearTo && $birthYear > $service->birthYearTo) {
return false;
}
return true;
}
/**
* Calculates age in years from a date of birth.
*
* Uses DateTimeImmutable to ensure accurate age calculations accounting
* for leap years and exact birth date anniversaries.
*
* @param \DateTimeImmutable $dateOfBirth The participant's date of birth
*
* @return int The calculated age in complete years
*/
private function calculateAge(\DateTimeImmutable $dateOfBirth): int
{
$today = new \DateTimeImmutable();
return (int) $dateOfBirth->diff($today)->y;
}
/**
* Gets a human-readable description of the service's age constraints.
*
* Generates descriptive text explaining the age requirements,
* useful for user interfaces and debugging.
*
* @param Service $service The service to describe
*
* @return string Description of the age constraints
*/
public function getConstraintDescription(Service $service): string
{
return match ($service->ageConstraintType) {
'absolute_age' => $this->getAbsoluteAgeDescription($service),
'birth_year' => $this->getBirthYearDescription($service),
'mixed' => sprintf('%s and %s',
$this->getAbsoluteAgeDescription($service),
$this->getBirthYearDescription($service)),
default => 'No age restrictions',
};
}
/**
* Gets description for absolute age constraints.
*
* @param Service $service The service with age constraints
*
* @return string Description of absolute age requirements
*/
private function getAbsoluteAgeDescription(Service $service): string
{
if (null !== $service->ageFrom && null !== $service->ageTo) {
return sprintf('Ages %d-%d', $service->ageFrom, $service->ageTo);
}
if (null !== $service->ageFrom) {
return sprintf('Age %d+', $service->ageFrom);
}
if (null !== $service->ageTo) {
return sprintf('Age up to %d', $service->ageTo);
}
return '';
}
/**
* Gets description for birth year constraints.
*
* @param Service $service The service with birth year constraints
*
* @return string Description of birth year requirements
*/
private function getBirthYearDescription(Service $service): string
{
if (null !== $service->birthYearFrom && null !== $service->birthYearTo) {
if ($service->birthYearFrom === $service->birthYearTo) {
return sprintf('Born in %d', $service->birthYearFrom);
}
return sprintf('Born %d-%d', $service->birthYearFrom, $service->birthYearTo);
}
if (null !== $service->birthYearFrom) {
return sprintf('Born %d or later', $service->birthYearFrom);
}
if (null !== $service->birthYearTo) {
return sprintf('Born up to %d', $service->birthYearTo);
}
return '';
}
}