wip: age based filtering of options
This commit is contained in:
@@ -0,0 +1,115 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\BusProNet\XmlParser;
|
||||
|
||||
use App\BusProNet\Model\AgeConstraintResult;
|
||||
|
||||
/**
|
||||
* Registry for managing and executing age constraint parsers.
|
||||
*
|
||||
* This registry coordinates multiple age constraint parsers and can handle
|
||||
* complex constraint data with multiple types separated by semicolons
|
||||
* (e.g., 'JG:2007-2009;GL:5-8').
|
||||
*/
|
||||
class AgeConstraintParserRegistry
|
||||
{
|
||||
/** @var AgeConstraintParserInterface[] */
|
||||
private array $parsers = [];
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
// Register built-in parsers
|
||||
$this->addParser(new BirthYearConstraintParser());
|
||||
}
|
||||
|
||||
public function addParser(AgeConstraintParserInterface $parser): void
|
||||
{
|
||||
$this->parsers[] = $parser;
|
||||
}
|
||||
|
||||
public function parseConstraints(string $constraintData): AgeConstraintResult
|
||||
{
|
||||
// Handle multiple constraint types (semicolon-separated, e.g., 'JG:2007-2009;GL:5-8')
|
||||
$constraints = array_map('trim', explode(';', $constraintData));
|
||||
$results = [];
|
||||
|
||||
foreach ($constraints as $constraint) {
|
||||
if (empty($constraint)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach ($this->parsers as $parser) {
|
||||
if (true === $parser->canParse($constraint)) {
|
||||
$results[] = $parser->parse($constraint);
|
||||
break; // First matching parser wins
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Merge results if multiple constraints found
|
||||
return $this->mergeConstraintResults($results, $constraintData);
|
||||
}
|
||||
|
||||
private function mergeConstraintResults(array $results, string $rawData): AgeConstraintResult
|
||||
{
|
||||
if (empty($results)) {
|
||||
return new AgeConstraintResult(type: 'unknown', rawData: $rawData);
|
||||
}
|
||||
|
||||
if (1 === count($results)) {
|
||||
return $results[0];
|
||||
}
|
||||
|
||||
// Merge multiple constraint results
|
||||
$type = 'mixed';
|
||||
$ageFrom = null;
|
||||
$ageTo = null;
|
||||
$birthYearFrom = null;
|
||||
$birthYearTo = null;
|
||||
$metadata = ['merged_from' => []];
|
||||
|
||||
foreach ($results as $result) {
|
||||
$ageFrom = $this->mergeMinValue($ageFrom, $result->ageFrom);
|
||||
$ageTo = $this->mergeMaxValue($ageTo, $result->ageTo);
|
||||
$birthYearFrom = $this->mergeMinValue($birthYearFrom, $result->birthYearFrom);
|
||||
$birthYearTo = $this->mergeMaxValue($birthYearTo, $result->birthYearTo);
|
||||
$metadata['merged_from'][] = $result->type;
|
||||
}
|
||||
|
||||
return new AgeConstraintResult(
|
||||
type: $type,
|
||||
ageFrom: $ageFrom,
|
||||
ageTo: $ageTo,
|
||||
birthYearFrom: $birthYearFrom,
|
||||
birthYearTo: $birthYearTo,
|
||||
metadata: $metadata,
|
||||
rawData: $rawData
|
||||
);
|
||||
}
|
||||
|
||||
private function mergeMinValue(?int $current, ?int $new): ?int
|
||||
{
|
||||
if (null === $current) {
|
||||
return $new;
|
||||
}
|
||||
if (null === $new) {
|
||||
return $current;
|
||||
}
|
||||
|
||||
return max($current, $new); // Most restrictive minimum
|
||||
}
|
||||
|
||||
private function mergeMaxValue(?int $current, ?int $new): ?int
|
||||
{
|
||||
if (null === $current) {
|
||||
return $new;
|
||||
}
|
||||
if (null === $new) {
|
||||
return $current;
|
||||
}
|
||||
|
||||
return min($current, $new); // Most restrictive maximum
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user