Completed
Pull Request — master (#55)
by
unknown
03:00
created

Validation::setTranslator()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 3
cts 3
cp 1
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
crap 1
1
<?php
2
3
namespace DavidePastore\Slim\Validation;
4
5
use Psr\Http\Server\RequestHandlerInterface;
6
use Respect\Validation\Exceptions\NestedValidationException;
7
8
/**
9
 * Validation for Slim.
10
 */
11
class Validation
12
{
13
    /**
14
     * Validators.
15
     *
16
     * @var array
17
     */
18
    protected $validators = [];
19
20
    /**
21
     * Options.
22
     *
23
     * @var array
24
     */
25
    protected $options = [
26
    ];
27
28
    /**
29
     * The translator to use for the exception message.
30
     *
31
     * @var callable
32
     */
33
    protected $translator = null;
34
35
    /**
36
     * Errors from the validation.
37
     *
38
     * @var array
39
     */
40
    protected $errors = [];
41
42
    /**
43
     * The 'errors' attribute name.
44
     *
45
     * @var string
46
     */
47
    protected $errors_name = 'errors';
48
49
    /**
50
     * The 'has_error' attribute name.
51
     *
52
     * @var string
53
     */
54
    protected $has_errors_name = 'has_errors';
55
56
    /**
57
     * The 'validators' attribute name.
58
     *
59
     * @var string
60
     */
61
    protected $validators_name = 'validators';
62
63
    /**
64
     * The 'translator' attribute name.
65
     *
66
     * @var string
67
     */
68
    protected $translator_name = 'translator';
69
70
    /**
71
     * Create new Validator service provider.
72
     *
73
     * @param null|array|ArrayAccess $validators
74
     * @param null|callable          $translator
75
     * @param []|array               $options
0 ignored issues
show
Documentation introduced by
The doc-type []|array could not be parsed: Unknown type name "" at position 0. [(view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
76
     */
77 25
    public function __construct($validators = null, $translator = null, $options = [])
78
    {
79
        // Set the validators
80 25
        if (is_array($validators) || $validators instanceof \ArrayAccess) {
81 24
            $this->validators = $validators;
82 25
        } elseif (is_null($validators)) {
83 1
            $this->validators = [];
84 1
        }
85 25
        $this->translator = $translator;
86 25
        $this->options = array_merge($this->options, $options);
87 25
    }
88
89
    /**
90
     * Validation middleware invokable class.
91
     *
92
     * @param \Psr\Http\Message\ServerRequestInterface $request  PSR7 request
93
     * @param \Psr\Http\Message\ResponseInterface      $response PSR7 response
0 ignored issues
show
Bug introduced by
There is no parameter named $response. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
94
     * @param callable                                 $next     Next middleware
0 ignored issues
show
Bug introduced by
There is no parameter named $next. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
95
     *
96
     * @return \Psr\Http\Message\ResponseInterface
97
     */
98
    public function __invoke($request, RequestHandlerInterface $handler)
99
    {
100
        $this->errors = [];
101
        $params = $request->getParsedBody();
102
        $params = array_merge((array) $request->getAttribute('routeInfo')[2], $params);
103
        $this->validate($params, $this->validators);
104
105
        $request = $request->withAttribute($this->errors_name, $this->getErrors());
106
        $request = $request->withAttribute($this->has_errors_name, $this->hasErrors());
107
        $request = $request->withAttribute($this->validators_name, $this->getValidators());
108
        $request = $request->withAttribute($this->translator_name, $this->getTranslator());
109
110
        return $handler->handle($request);
111
    }
112
113
    /**
114
     * Validate the parameters by the given params, validators and actual keys.
115
     * This method populates the $errors attribute.
116
     *
117
     * @param array $params     The array of parameters.
118
     * @param array $validators The array of validators.
119
     * @param array $actualKeys An array that will save all the keys of the tree to retrieve the correct value.
120
     */
121
    private function validate($params = [], $validators = [], $actualKeys = [])
122
    {
123
        //Validate every parameters in the validators array
124
        foreach ($validators as $key => $validator) {
125
            $actualKeys[] = $key;
126
            $param = $this->getNestedParam($params, $actualKeys);
127
            if (is_array($validator)) {
128
                $this->validate($params, $validator, $actualKeys);
129
            } else {
130
                try {
131
                    $validator->assert($param);
132
                } catch (NestedValidationException $exception) {
133
                    if ($this->translator) {
134
                        $exception->setParam('translator', $this->translator);
135
                    }
136
                    $this->errors[implode('.', $actualKeys)] = $exception->getMessages();
137
                }
138
            }
139
140
            //Remove the key added in this foreach
141
            array_pop($actualKeys);
142
        }
143
    }
144
145
    /**
146
     * Get the nested parameter value.
147
     *
148
     * @param array $params An array that represents the values of the parameters.
149
     * @param array $keys   An array that represents the tree of keys to use.
150
     *
151
     * @return mixed The nested parameter value by the given params and tree of keys.
152
     */
153
    private function getNestedParam($params = [], $keys = [])
154
    {
155
        if (empty($keys)) {
156
            return $params;
157
        } else {
158
            $firstKey = array_shift($keys);
159
            if ($this->isArrayLike($params) && array_key_exists($firstKey, $params)) {
160
                $params = (array) $params;
161
                $paramValue = $params[$firstKey];
162
163
                return $this->getNestedParam($paramValue, $keys);
164
            } else {
165
                return;
166
            }
167
        }
168
    }
169
170
    /**
171
     * Check if the given $params is an array like variable.
172
     *
173
     * @param array $params The variable to check.
174
     *
175
     * @return boolean Returns true if the given $params parameter is array like.
176
     */
177
    private function isArrayLike($params)
178
    {
179
        return is_array($params) || $params instanceof \SimpleXMLElement;
180
    }
181
182
    /**
183
     * Check if there are any errors.
184
     *
185
     * @return bool
186
     */
187
    public function hasErrors()
188
    {
189
        return !empty($this->errors);
190
    }
191
192
    /**
193
     * Get errors.
194
     *
195
     * @return array The errors array.
196
     */
197
    public function getErrors()
198
    {
199
        return $this->errors;
200
    }
201
202
    /**
203
     * Get validators.
204
     *
205
     * @return array The validators array.
206
     */
207
    public function getValidators()
208
    {
209
        return $this->validators;
210
    }
211
212
    /**
213
     * Set validators.
214
     *
215
     * @param array $validators The validators array.
216
     */
217 1
    public function setValidators($validators)
218
    {
219 1
        $this->validators = $validators;
220 1
    }
221
222
    /**
223
     * Get translator.
224
     *
225
     * @return callable The translator.
226
     */
227
    public function getTranslator()
228
    {
229
        return $this->translator;
230
    }
231
232
    /**
233
     * Set translator.
234
     *
235
     * @param callable $translator The translator.
236
     */
237 1
    public function setTranslator($translator)
238
    {
239 1
        $this->translator = $translator;
240 1
    }
241
}
242