Passed
Push — master ( fadf79...5a8e38 )
by Sebastian
03:53
created

Filter::filterOne()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 2
dl 0
loc 4
ccs 0
cts 3
cp 0
crap 2
rs 10
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * Linna Filter
5
 *
6
 * @author Sebastian Rapetti <[email protected]>
7
 * @copyright (c) 2018, Sebastian Rapetti
8
 * @license http://opensource.org/licenses/MIT MIT License
9
 */
10
declare(strict_types = 1);
11
12
namespace Linna\Filter;
13
14
use ReflectionClass;
15
use ReflectionMethod;
16
17
/**
18
 * Filter.
19
 */
20
class Filter
21
{
22
    /**
23
     * @var array User data.
24
     */
25
    private $data = [];
26
27
    /**
28
     * @var array Error messages.
29
     */
30
    private $messages = [];
31
32
    /**
33
     * @var int Occurred errors.
34
     */
35
    private $errors = 0;
36
    
37
    /**
38
     * @var array Filters working rules.
39
     */
40
    private $rules;
41
    
42
    /**
43
     * Class Constructor.
44
     */
45 50
    public function __construct()
46
    {
47 50
        $this->rules = RuleBuilder::build();
48 50
    }
49
    
50
    /**
51
     * Filter one element with given rules.
52
     *
53
     * @param mixed $data
54
     * @param string $rule
55
     */
56
    public function filterOne($data, string $rule) : void
57
    {
58
        $this->data = ['data' => $data];
59
        $this->interpreteRules(['data '.$rule]);
60
    }
61
    
62
    /**
63
     * Filter an array of elementes with given rules.
64
     *
65
     * @param array $data
66
     * @param array $rules
67
     */
68 50
    public function filterMulti(array $data, array $rules) : void
69
    {
70 50
        $this->data = $data;
71 50
        $this->interpreteRules($rules);
72 50
    }
73
    
74
    /**
75
     * Return occurred error number.
76
     *
77
     * @return int
78
     */
79 41
    public function getErrors(): int
80
    {
81 41
        return $this->errors;
82
    }
83
84
    /**
85
     * Return error messages.
86
     *
87
     * @return array
88
     */
89 1
    public function getMessages(): array
90
    {
91 1
        return $this->messages;
92
    }
93
94
    /**
95
     * Return passed data.
96
     *
97
     * @return array
98
     */
99 23
    public function getData(): array
100
    {
101 23
        return $this->data;
102
    }
103
104
    /**
105
     * Get parsed rules.
106
     */
107 50
    private function interpreteRules($rules) : void
108
    {
109 50
        $parser = new Parser();
110
111 50
        foreach ($rules as $rule) {
112 50
            $this->ruleToField(
113 50
                $parser->parse(
114 50
                    Lexer::tokenize($rule),
115 50
                    $this->rules
116
                )
117
            );
118
        }
119 50
    }
120
121
    /**
122
     * Apply rules to a field.
123
     *
124
     * @param array $rules
125
     */
126 50
    private function ruleToField(array $rules) : void
127
    {
128 50
        foreach ($rules as $rule) {
129 50
            $field = $rule[0];
130 50
            $filter = $rule[2]['class'];
131
132 50
            $class = 'Linna\Filter\Rules\\' . $filter;
133 50
            $refClass = new ReflectionClass($class);
134
135 50
            $instance = $refClass->newInstance();
136
137 50
            if (!isset($this->data[$field])) {
138 3
                $this->errors++;
139 3
                $this->messages[$field][$filter] = "Form field '{$field}' missing.";
140 3
                continue;
141
            }
142
143 48
            if ($refClass->hasMethod('validate')) {
144 39
                $refMethod = new ReflectionMethod($class, 'validate');
145
146 39
                if ($refMethod->invokeArgs($instance, $this->getArguments($rule[2]['args_count'], $rule[3], $this->data[$field]))) {
147 16
                    $this->errors++;
148 16
                    $this->messages[$field][$filter] = ['expected' => $rule[3], 'received' => $this->data[$field]];
149 16
                    continue;
150
                }
151
            }
152
153 38
            if ($refClass->hasMethod('sanitize')) {
154 38
                $instance->sanitize($this->data[$field]);
155
            }
156
        }
157 50
    }
158
159
    /**
160
     * Return arguments for validation.
161
     *
162
     * @param int $args
163
     * @param mixed $expected
164
     * @param mixed $received
165
     *
166
     * @return array
167
     */
168 39
    private function getArguments(int $args, $expected, $received) : array
169
    {
170 39
        if ($args === 0) {
171 21
            return [$received];
172
        }
173
174 31
        if (is_array($expected)) {
175 5
            array_unshift($expected, $received);
176 5
            return $expected;
177
        }
178
179 26
        return [$received, $expected];
180
    }
181
}
182