Completed
Pull Request — master (#27)
by Davide
03:18
created

Validation::retrieveRouteInfo()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 7
ccs 4
cts 4
cp 1
rs 9.4285
cc 2
eloc 5
nc 2
nop 1
crap 2
1
<?php
2
3
namespace DavidePastore\Slim\Validation;
4
5
use Respect\Validation\Exceptions\NestedValidationException;
6
7
/**
8
 * Validation for Slim.
9
 */
10
class Validation
11
{
12
    /**
13
     * Validators.
14
     *
15
     * @var array
16
     */
17
    protected $validators = [];
18
19
    /**
20
     * Options.
21
     *
22
     * @var array
23
     */
24
    protected $options = [
25
      'useTemplate' => false,
26
    ];
27
28
    /**
29
     * The translator to use fro 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
94
     * @param callable                                 $next     Next middleware
95
     *
96
     * @return \Psr\Http\Message\ResponseInterface
97
     */
98 25
    public function __invoke($request, $response, $next)
99
    {
100 25
        $this->errors = [];
101 25
        $params = $request->getParams();
102 25
        $params = array_merge((array) $this->retrieveRouteInfo($request), $params);
103 25
        $this->validate($params, $this->validators);
104
105 25
        $request = $request->withAttribute($this->errors_name, $this->getErrors());
106 25
        $request = $request->withAttribute($this->has_errors_name, $this->hasErrors());
107 25
        $request = $request->withAttribute($this->validators_name, $this->getValidators());
108 25
        $request = $request->withAttribute($this->translator_name, $this->getTranslator());
109
110 25
        return $next($request, $response);
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 25
    private function validate($params = [], $validators = [], $actualKeys = [])
122
    {
123
        //Validate every parameters in the validators array
124 25
      foreach ($validators as $key => $validator) {
125 24
          $actualKeys[] = $key;
126 24
          $param = $this->getNestedParam($params, $actualKeys);
127 24
          if (is_array($validator)) {
128 8
              $this->validate($params, $validator, $actualKeys);
129 8
          } else {
130
              try {
131 24
                  $validator->assert($param);
132 24
              } catch (NestedValidationException $exception) {
133 14
                  if ($this->translator) {
134 2
                      $exception->setParam('translator', $this->translator);
135 2
                  }
136 14
                  if ($this->options['useTemplate']) {
137 1
                      $this->errors[implode('.', $actualKeys)] = [$exception->getMainMessage()];
138 1
                  } else {
139 13
                      $this->errors[implode('.', $actualKeys)] = $exception->getMessages();
140
                  }
141
              }
142
          }
143
144
          //Remove the key added in this foreach
145 24
          array_pop($actualKeys);
146 25
      }
147 25
    }
148
149
    /**
150
     * Get the nested parameter value.
151
     *
152
     * @param array $params An array that represents the values of the parameters.
153
     * @param array $keys   An array that represents the tree of keys to use.
154
     *
155
     * @return mixed The nested parameter value by the given params and tree of keys.
156
     */
157 24
    private function getNestedParam($params = [], $keys = [])
158
    {
159 24
        if (empty($keys)) {
160 22
            return $params;
161
        } else {
162 24
            $firstKey = array_shift($keys);
163 24
            if (array_key_exists($firstKey, $params)) {
164 22
                $params = (array) $params;
165 22
                $paramValue = $params[$firstKey];
166
167 22
                return $this->getNestedParam($paramValue, $keys);
168
            } else {
169 2
                return;
170
            }
171
        }
172
    }
173
174
    /**
175
     * Retrieve the route info as an array if any.
176
     *
177
     * @param \Psr\Http\Message\ServerRequestInterface $request  PSR7 request
178
     *
179
     * @return array An array with the array info.
180
     */
181 25
    private function retrieveRouteInfo($request){
0 ignored issues
show
Unused Code introduced by
This method is not used, and could be removed.
Loading history...
182 25
        if(isset($request->getAttribute('routeInfo')[2])){
183 2
            return (array) $request->getAttribute('routeInfo')[2];
184
        } else {
185 23
            return [];
186
        }
187
    }
188
189
    /**
190
     * Check if there are any errors.
191
     *
192
     * @return bool
193
     */
194 25
    public function hasErrors()
195
    {
196 25
        return !empty($this->errors);
197
    }
198
199
    /**
200
     * Get errors.
201
     *
202
     * @return array The errors array.
203
     */
204 25
    public function getErrors()
205
    {
206 25
        return $this->errors;
207
    }
208
209
    /**
210
     * Get validators.
211
     *
212
     * @return array The validators array.
213
     */
214 25
    public function getValidators()
215
    {
216 25
        return $this->validators;
217
    }
218
219
    /**
220
     * Set validators.
221
     *
222
     * @param array $validators The validators array.
223
     */
224 1
    public function setValidators($validators)
225
    {
226 1
        $this->validators = $validators;
227 1
    }
228
229
    /**
230
     * Get translator.
231
     *
232
     * @return callable The translator.
233
     */
234 25
    public function getTranslator()
235
    {
236 25
        return $this->translator;
237
    }
238
239
    /**
240
     * Set translator.
241
     *
242
     * @param callable $translator The translator.
243
     */
244 1
    public function setTranslator($translator)
245
    {
246 1
        $this->translator = $translator;
247 1
    }
248
}
249