Passed
Push — master ( 781476...75fa6b )
by Maxim
03:03
created

ConditionsSuit::executeCondition()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
cc 2
eloc 4
nc 2
nop 2
dl 0
loc 6
ccs 0
cts 4
cp 0
crap 6
rs 9.4285
c 0
b 0
f 0
1
<?php
2
/**
3
 * This file is a part of "Axessors" library.
4
 *
5
 * @author <[email protected]>
6
 * @license GPL
7
 */
8
9
namespace NoOne4rever\Axessors;
10
11
use NoOne4rever\Axessors\Exceptions\TypeError;
12
13
/**
14
 * Class ConditionsSuit.
15
 * 
16
 * Processes Axessors conditions.
17
 * 
18
 * @package NoOne4rever\Axessors
19
 */
20
class ConditionsSuit extends RunningSuit
21
{
22
    /** @var string method name */
23
    private $method;
24
25
    /**
26
     * ConditionsSuit constructor.
27
     * 
28
     * @param int $mode mode of execution
29
     * @param PropertyData $data property data
30
     * @param string $class class
31
     * @param string $method method name
32
     * @param object|null $object object
33
     */
34
    public function __construct(int $mode, PropertyData $data, string $class, string $method, $object = null)
35
    {
36
        parent::__construct($mode, $data, $class, $object);
37
        $this->method = $method;
38
    }
39
40
    /**
41
     * Checks the conditions defined in the Axessors comment.
42
     *
43
     * Creates logical tree of the conditions and then checks if the general result is true.
44
     *
45
     * @param $value mixed value of the property
46
     * @return bool result of checking of the conditions
47
     */
48
    public function processConditions($value): bool
49
    {
50
        $conditions = $this->calculateConditions($value);
51
        if (empty($conditions)) {
52
            return true;
53
        }
54
        foreach ($conditions as $condition) {
55
            if (is_array($condition)) {
56
                foreach ($condition as $subCondition) {
57
                    if (!$subCondition) {
58
                        continue 2;
59
                    }
60
                }
61
                return true;
62
            }
63
            if ($condition) {
64
                return true;
65
            }
66
        }
67
        return false;
68
    }
69
70
    /**
71
     * Calculates every condition defined in the Axessors comment.
72
     *
73
     * @param $value mixed value of the property
74
     * @return bool[] results of the conditions
75
     */
76
    private function calculateConditions($value): array
77
    {
78
        $calculatedConditions = [];
79
        $conditions = $this->mode == RunningSuit::OUTPUT_MODE ? $this->propertyData->getOutputConditions() : $this->propertyData->getInputConditions();
80
        foreach ($conditions as $number => $complexCondition) {
81
            if (is_array($complexCondition)) {
82
                foreach ($complexCondition as $condition) {
83
                    $calculatedConditions[$number][] = $this->executeCondition($condition, $value);
84
                }
85
            } else {
86
                $calculatedConditions[$number] = $this->executeCondition($complexCondition, $value);
87
            }
88
        }
89
        return $calculatedConditions;
90
    }
91
92
    /**
93
     * Calculates a condition defined in the Axessors comment.
94
     *
95
     * @param $condition string the condition
96
     * @param $value mixed value of the property
97
     * @return bool result of the condition
98
     */
99
    private function executeCondition(string $condition, $value): bool
100
    {
101
        if (strpos($condition, '`') !== false) {
102
            return $this->executeInjectedString($condition, $value, true);
103
        } else {
104
            return $this->runStandardCondition($condition, $value);
105
        }
106
    }
107
108
    /**
109
     * Runs Axessors condition.
110
     * 
111
     * @param string $condition condition
112
     * @param mixed $value value to check 
113
     * @return bool the result of the checkout
114
     */
115
    private function runStandardCondition(string $condition, $value): bool 
116
    {
117
        $value = $this->count($value);
118
        if (strpos($condition, '..') !== false) {
119
            $condition = explode('..', $condition);
120
            $condition = "<= {$condition[1]} && $value >= {$condition[0]}";
121
        }
122
        return eval("return $value $condition;");
123
    }
124
125
    /**
126
     * Casts the property to integer.
127
     *
128
     * If the property is string or array returns it's length.
129
     * If the property is integer of float returns the property itself.
130
     *
131
     * @param $value mixed value of the property
132
     * @return int integer value of the property
133
     * @throws TypeError if the property can't be turned into integer
134
     */
135
    private function count($value): int
136
    {
137
        switch (gettype($value)) {
138
            case 'integer':
139
            case 'float':
140
                break;
141
            case 'string':
142
                $value = strlen($value);
143
                break;
144
            case 'array':
145
                $value = count($value);
146
                break;
147
            default:
148
                throw new TypeError('value "' . var_export($value, true) . "\" passed to {$this->class}::{$this->method}() is not countable");
149
        }
150
        return $value;
151
    }
152
}