65 lines
2.0 KiB
PHP
65 lines
2.0 KiB
PHP
<?php
|
|
|
|
namespace App\Domains\Routing\Services;
|
|
|
|
class SmartRoutingEngine
|
|
{
|
|
public function resolve(array $config, array $context): string
|
|
{
|
|
$rules = collect($config['rules'] ?? [])
|
|
->sortBy('priority');
|
|
|
|
foreach ($rules as $rule) {
|
|
if ($this->ruleMatches($rule, $context)) {
|
|
return $rule['target'];
|
|
}
|
|
}
|
|
|
|
return $config['fallback'] ?? '';
|
|
}
|
|
|
|
private function ruleMatches(array $rule, array $context): bool
|
|
{
|
|
$conditions = $rule['conditions'] ?? [];
|
|
$matchMode = $rule['match'] ?? 'all';
|
|
|
|
if (empty($conditions)) {
|
|
return false;
|
|
}
|
|
|
|
$results = array_map(
|
|
fn ($condition) => $this->evaluateCondition($condition, $context),
|
|
$conditions
|
|
);
|
|
|
|
return $matchMode === 'all'
|
|
? ! in_array(false, $results, true)
|
|
: in_array(true, $results, true);
|
|
}
|
|
|
|
private function evaluateCondition(array $condition, array $context): bool
|
|
{
|
|
if (! isset($condition['field'], $condition['op'], $condition['value'])) {
|
|
return false;
|
|
}
|
|
|
|
$field = $condition['field'];
|
|
$op = $condition['op'];
|
|
$expected = $condition['value'];
|
|
$actual = $context[$field] ?? null;
|
|
|
|
return match ($op) {
|
|
'equals' => $actual === $expected,
|
|
'not_equals' => $actual !== $expected,
|
|
'in' => in_array($actual, (array) $expected, true),
|
|
'not_in' => ! in_array($actual, (array) $expected, true),
|
|
'contains' => str_contains((string) $actual, (string) $expected),
|
|
'starts_with' => str_starts_with((string) $actual, (string) $expected),
|
|
'between' => is_array($expected) && count($expected) === 2 && $actual >= $expected[0] && $actual <= $expected[1],
|
|
'greater_than' => $actual > $expected,
|
|
'less_than' => $actual < $expected,
|
|
default => false,
|
|
};
|
|
}
|
|
}
|