Completed
Push — master ( f06ad0...9cb85d )
by Nico
06:26
created

Evaluator::evaluate()   A

Complexity

Conditions 2
Paths 1

Size

Total Lines 16
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 2

Importance

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