wip: age based filtering of options
This commit is contained in:
@@ -0,0 +1,196 @@
|
||||
<?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 '';
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user