Evaluator::setResult()   A
last analyzed

Complexity

Conditions 4
Paths 4

Size

Total Lines 11
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 4

Importance

Changes 0
Metric Value
cc 4
eloc 7
nc 4
nop 3
dl 0
loc 11
ccs 8
cts 8
cp 1
crap 4
rs 10
c 0
b 0
f 0
1
<?php declare(strict_types=1);
2
3
/**
4
 * @license     http://opensource.org/licenses/mit-license.php MIT
5
 * @link        https://github.com/nicoSWD
6
 * @author      Nicolas Oelgart <[email protected]>
7
 */
8
namespace nicoSWD\Rule\Evaluator;
9
10
final class Evaluator implements EvaluatorInterface
11
{
12
    private const LOGICAL_AND = '&';
13
    private const LOGICAL_OR = '|';
14
15
    private const BOOL_TRUE = '1';
16
    private const BOOL_FALSE = '0';
17
18 186
    public function evaluate(string $group): bool
19
    {
20 186
        $evalGroup = $this->evalGroup();
21 186
        $count = 0;
22
23
        do {
24 186
            $group = preg_replace_callback(
25 186
                '~\(([^()]+)\)~',
26 186
                $evalGroup,
27 186
                $group,
28 186
                limit: -1,
29 186
                count: $count
30
            );
31 186
        } while ($count > 0);
32
33 186
        return (bool) $evalGroup([1 => $group]);
34
    }
35
36 186
    private function evalGroup(): callable
37
    {
38
        return function (array $group): ?int {
39 186
            $result = null;
40 186
            $operator = null;
41 186
            $offset = 0;
42
43 186
            while (isset($group[1][$offset])) {
44 184
                $value = $group[1][$offset++];
45
46 184
                if ($this->isLogical($value)) {
47 32
                    $operator = $value;
48 184
                } elseif ($this->isBoolean($value)) {
49 182
                    $result = $this->setResult($result, (int) $value, $operator);
50
                } else {
51 2
                    throw new Exception\UnknownSymbolException(sprintf('Unexpected "%s"', $value));
52
                }
53
            }
54
55 184
            return $result;
56 186
        };
57
    }
58
59 182
    private function setResult(?int $result, int $value, ?string $operator): int
60
    {
61 182
        if (!isset($result)) {
62 182
            $result = $value;
63 32
        } elseif ($operator === self::LOGICAL_AND) {
64 28
            $result &= $value;
65 18
        } elseif ($operator === self::LOGICAL_OR) {
66 18
            $result |= $value;
67
        }
68
69 182
        return $result;
70
    }
71
72 184
    private function isLogical(string $value): bool
73
    {
74 184
        return $value === self::LOGICAL_AND || $value === self::LOGICAL_OR;
75
    }
76
77 184
    private function isBoolean(string $value): bool
78
    {
79 184
        return $value === self::BOOL_TRUE || $value === self::BOOL_FALSE;
80
    }
81
}
82