Commit 4039c79d authored by Sebastian Kehr's avatar Sebastian Kehr 🚣🏼
Browse files

simplified rule normalization and sorting

parent 1f7c9716
.idea
.vscode
vendor
\ No newline at end of file
vendor
.phpunit*
\ No newline at end of file
{
"name": "finc/rules",
"description": "Rules evaluator based on Symfony Expression Language Component.",
"license": "GPL-2.0",
"authors": [
{
"name": "Sebastian Kehr",
"email": "kehr@ub.uni-leipzig.de"
}
],
"autoload": {
"psr-4": {
"finc\\Rules\\": "src/"
}
},
"autoload-dev": {
"psr-4": { "finc\\Rules\\": "tests/" }
},
"require-dev": {
"phpunit/phpunit": "^5"
},
"require": {
"php": ">=5.6",
"symfony/expression-language": "^3.4"
"name": "finc/rules-evaluator",
"description": "Rules evaluator based on Symfony Expression Language Component.",
"license": "GPL-2.0",
"authors": [
{
"name": "Sebastian Kehr",
"email": "kehr@ub.uni-leipzig.de"
}
],
"autoload": {
"psr-4": {
"finc\\Rules\\Evaluator\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"finc\\Rules\\Evaluator\\": "tests/"
}
},
"require-dev": {
"bamarni/composer-bin-plugin": "^1.2"
},
"require": {
"php": ">=5.6",
"symfony/expression-language": "^3.4"
},
"scripts": {
"test": "phpunit --bootstrap vendor/autoload.php tests"
}
}
This diff is collapsed.
......@@ -4,7 +4,7 @@
*
* Copyright (C) 2018 Leipzig University Library <info@ub.uni-leipzig.de>
*
* PHP version 7
* PHP version 5.6
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2,
......@@ -19,71 +19,55 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* @category finc
* @package finc\Rules
* @author Sebastian Kehr <kehr@ub.uni-leipzig.de>
* @license https://opensource.org/licenses/gpl-2.0.php GNU GPLv2
* @link https://finc.info
*/
namespace finc\Rules;
namespace finc\Rules\Evaluator;
use Symfony\Component\ExpressionLanguage\ExpressionLanguage as Engine;
/**
* finc Rules evaluator
* finc Rules Evaluator
*
* @category finc
* @package finc\Rules
* @author Sebastian Kehr <kehr@ub.uni-leipzig.de>
* @license https://opensource.org/licenses/gpl-2.0.php GNU GPLv2
* @link https://finc.info
*/
class Evaluator
{
const STOP_FLAG = 'STOP';
const HEAD = 0;
const BODY = 1;
const PRIO = 2;
const DEFAULT_PRIO = 0;
/**
* @var Engine The engine to use for rule evaluation.
* @var array[] The rules to be evaluated on invocation.
*/
protected $engine;
protected $rules;
/**
* @var array The rules to be evaluated on invocation.
* @var string[] List of context variable names wich will stop further
* rule evaluation when set to some truthy value.
*/
protected $rules;
protected $stopFlags;
/**
* @var string[] List of context variable names wich will stop further rule
* evaluation when set to some truthy value.
* @var Engine The engine to use for rule evaluation.
*/
protected $stopFlags;
protected $engine;
/**
* Constructor.
*
* @param array $rules List of rules to be evaluated.
* @param string[] $stopFlag
* @param array[] $rules List of rules to be evaluated.
* @param string[] $stopFlags Optional list of stop flags.
*/
public function __construct(array $rules, array $stopFlags = [])
{
$this->engine = new Engine;
$this->rules = $rules;
$this->engine = new Engine();
$this->stopFlags = $stopFlags;
foreach ($this->rules as $index => list($head, $body)) {
$this->rules[$index] += [$head, $body, static::DEFAULT_PRIO];
}
uksort(
$this->rules,
function ($firstIdx, $secondIdx) {
$firstPrio = intval($this->rules[$firstIdx][2]);
$secondPrio = intval($this->rules[$secondIdx][2]);
return $secondPrio - $firstPrio ?: $firstIdx - $secondIdx;
}
);
$this->rules = $this->normalizeRules($rules);
}
/**
......@@ -101,17 +85,14 @@ class Evaluator
/**
* Recursively evaluates a list of rules w.r.t. to a given context.
*
* @param array $context The evaluation context.
* @param array|null $rule The next rule to be evaluated.
* @param array ...$rules The remaining rules to be evaluated.
* @param array $context The evaluation context.
* @param array|null $rule The next rule to be evaluated.
* @param array[] ...$rules The remaining rules to be evaluated.
*
* @return array The evaluation result.
*/
protected function evaluate(
array $context,
array $rule = null,
array ...$rules
) {
protected function evaluate(array $context, array $rule = null, array ...$rules)
{
if (!$rule) {
return $context;
}
......@@ -122,8 +103,27 @@ class Evaluator
}
}
list($head, $body) = $rule;
list($head, $body) = [$rule[self::HEAD], $rule[self::BODY]];
$context[$head] = $this->engine->evaluate($body, $context);
return $this->evaluate($context, ...$rules);
}
/**
* Normalizes rules to have an integer priority defaulting to 0.
*
* @param array $rules
* @return array List of normalized rules.
*/
protected function normalizeRules(array $rules)
{
foreach ($rules as &$rule) {
$rule[self::PRIO] = isset($rule[self::PRIO]) ? intval($rule[self::PRIO]) : 0;
}
usort($rules, function ($first, $second) {
return $second[self::PRIO] - $first[self::PRIO];
});
return $rules;
}
}
......@@ -4,7 +4,7 @@
*
* Copyright (C) 2018 Leipzig University Library <info@ub.uni-leipzig.de>
*
* PHP version 7
* PHP version 5.6
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2,
......@@ -19,13 +19,11 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* @category finc
* @package finc\Rules
* @author Sebastian Kehr <kehr@ub.uni-leipzig.de>
* @license https://opensource.org/licenses/gpl-2.0.php GNU GPLv2
* @link https://finc.info
*/
namespace finc\Rules;
namespace finc\Rules\Evaluator;
class ContextObject
{
......
......@@ -4,7 +4,7 @@
*
* Copyright (C) 2018 Leipzig University Library <info@ub.uni-leipzig.de>
*
* PHP version 7
* PHP version 5.6
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2,
......@@ -19,43 +19,37 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* @category finc
* @package finc\Rules
* @author Sebastian Kehr <kehr@ub.uni-leipzig.de>
* @license https://opensource.org/licenses/gpl-2.0.php GNU GPLv2
* @link https://finc.info
*/
namespace finc\Rules;
namespace finc\Rules\Evaluator;
use PHPUnit\Framework\TestCase;
/**
* finc Rules evaluator test.
*
* @category finc
* @package finc\Rules
* @author Sebastian Kehr <kehr@ub.uni-leipzig.de>
* @license https://opensource.org/licenses/gpl-2.0.php GNU GPLv2
* @link https://finc.info
*/
class EvaluatorTest extends TestCase
{
protected $rules
= [
// 5th rule
['t', '[1]', 80],
// 4th rule
['e', 'e + e', 85],
// 3rd rule
['s', '[]', 90],
// 2nd rule
['e', '1', 95],
// 1st rule
['d', 'a.f("xyz") * 2 - 2', '100'],
// last rule due to lowest priority (defaults to 0)
['e', 'd * d'],
];
protected $rules = [
['e', 'e + e'], // 4th rule
['t', '[1]'], // 5th rule
['s', '[]', 90], // 3rd rule
['e', '1', 95], // 2nd rule
['d', 'a.f("xyz") * 2 - 2', '100'], // 1st rule
['e', 'd * d'], // 6th rule
];
public function testSimple()
{
......
{
"require": {
"phpunit/phpunit": "^7.3"
}
}
This diff is collapsed.
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment