115 lines
3.3 KiB
PHP
115 lines
3.3 KiB
PHP
<?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
|
|
}
|
|
} |