Skip to content

feat: Add support for fact-to-fact comparison #1

@chrisaugu

Description

@chrisaugu

With fact-to-fact support, it allows the engine to dynamically test the rules at runtime.

Rule.php

    private function evaluateCondition(array $condition, Facts $facts, array $allRules): bool
    {
        $factName = $condition['fact'] ?? null;
        $operator = $condition['operator'] ?? null;
        $value = $condition['value'] ?? null;
        $path = $condition['path'] ?? null; // Optional path to drill down into fact data

        if (!$factName || !$operator) {
            throw new Exception('Invalid condition: fact and operator are required');
        }

        $factData = $facts->get($factName, $path);

        // Resolve value if it's another fact
        if (is_array($value) && isset($value['fact'])) {
            $value = $facts->get($value['fact'], $value['path'] ?? null);
        }

        return match ($operator) {
            'equal'                => $factData === $value,
            'lessThanInclusive'    => $factData <= $value,
            'greaterThanInclusive' => $factData >= $value,
            'lessThan'             => $factData < $value,
            'greaterThan'          => $factData > $value,
            'in'                   => in_array($factData, $value, true),
            'notIn'                => !in_array($factData, $value, true),
            'contains'             => is_array($factData) && in_array($value, $factData),
            default                => throw new Exception("Unknown operator: $operator"),
        };
    }

Implementation

$engine = new Engine();

$ruleConfig = [
    "name" => "test.factToFact",
    "conditions" => [
        "all" => [
            [
                "fact" => "distance",
                "operator" => "lessThanInclusive",
                "value" => ["fact" => "limit"]
            ]
        ]
    ],
    "event" => ["type" => "passed", "params" => []],
    "failureEvent" => ["type" => "failed", "params" => []]
];

$engine->addRule(new Rule($ruleConfig));
$engine->setTargetRule('test.factToFact');

$engine->addFact('distance', 40);
$engine->addFact('limit', 50);
$results1 = $engine->evaluate();

Metadata

Metadata

Assignees

Labels

No labels
No labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions