Passed
Push — master ( 817cab...57b58d )
by Paul
09:30 queued 02:21
created

Validator::getSizeMessage()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 3
nc 1
nop 3
dl 0
loc 5
ccs 0
cts 4
cp 0
crap 2
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace GeminiLabs\SiteReviews\Modules;
4
5
use BadMethodCallException;
6
use GeminiLabs\SiteReviews\Defaults\ValidationStringsDefaults;
7
use GeminiLabs\SiteReviews\Helper;
8
use GeminiLabs\SiteReviews\Helpers\Str;
9
use GeminiLabs\SiteReviews\Modules\Validator\ValidationRules;
10
11
/**
12
 * @see \Illuminate\Validation\Validator (5.3)
13
 */
14
class Validator
15
{
16
    use ValidationRules;
17
18
    /**
19
     * @var array
20
     */
21
    public $errors = [];
22
23
    /**
24
     * The data under validation.
25
     * @var array
26
     */
27
    protected $data = [];
28
29
    /**
30
     * The failed validation rules.
31
     * @var array
32
     */
33
    protected $failedRules = [];
34
35
    /**
36
     * The rules to be applied to the data.
37
     * @var array
38
     */
39
    protected $rules = [];
40
41
    /**
42
     * The size related validation rules.
43
     * @var array
44
     */
45
    protected $sizeRules = [
46
        'Between', 'Max', 'Min',
47
    ];
48
49
    /**
50
     * The validation rules that imply the field is required.
51
     * @var array
52
     */
53
    protected $implicitRules = [
54
        'Required',
55
    ];
56
57
    /**
58
     * The numeric related validation rules.
59
     * @var array
60
     */
61
    protected $numericRules = [
62
        'Number',
63
    ];
64
65
    /**
66
     * Run the validator's rules against its data.
67
     * @param mixed $data
68
     * @return array
69
     */
70 2
    public function validate($data, array $rules = [])
71
    {
72 2
        $this->normalizeData($data);
73 2
        $this->setRules($rules);
74 2
        foreach ($this->rules as $attribute => $rules) {
75 2
            foreach ($rules as $rule) {
76 2
                $this->validateAttribute($attribute, $rule);
77 2
                if ($this->shouldStopValidating($attribute)) {
78 2
                    break;
79
                }
80
            }
81
        }
82 2
        return $this->errors;
83
    }
84
85
    /**
86
     * Validate a given attribute against a rule.
87
     * @param string $attribute
88
     * @param string $rule
89
     * @return void
90
     * @throws BadMethodCallException
91
     */
92 2
    public function validateAttribute($attribute, $rule)
93
    {
94 2
        list($rule, $parameters) = $this->parseRule($rule);
95 2
        if ('' == $rule) {
96
            return;
97
        }
98 2
        $value = $this->getValue($attribute);
99 2
        $method = Helper::buildMethodName($rule, 'validate');
100 2
        if (!method_exists($this, $method)) {
101
            throw new BadMethodCallException("Method [$method] does not exist.");
102
        }
103 2
        if (!$this->$method($value, $attribute, $parameters)) {
104 2
            $this->addFailure($attribute, $rule, $parameters);
105
        }
106 2
    }
107
108
    /**
109
     * Add an error message to the validator's collection of errors.
110
     * @param string $attribute
111
     * @param string $rule
112
     * @return void
113
     */
114 2
    protected function addError($attribute, $rule, array $parameters)
115
    {
116 2
        $message = $this->getMessage($attribute, $rule, $parameters);
117 2
        $this->errors[$attribute][] = $message;
118 2
    }
119
120
    /**
121
     * Add a failed rule and error message to the collection.
122
     * @param string $attribute
123
     * @param string $rule
124
     * @return void
125
     */
126 2
    protected function addFailure($attribute, $rule, array $parameters)
127
    {
128 2
        $this->addError($attribute, $rule, $parameters);
129 2
        $this->failedRules[$attribute][$rule] = $parameters;
130 2
    }
131
132
    /**
133
     * Get the data type of the given attribute.
134
     * @param string $attribute
135
     * @return string
136
     */
137
    protected function getAttributeType($attribute)
138
    {
139
        return !$this->hasRule($attribute, $this->numericRules)
140
            ? 'length'
141
            : '';
142
    }
143
144
    /**
145
     * Get the validation message for an attribute and rule.
146
     * @param string $attribute
147
     * @param string $rule
148
     * @return string|null
149
     */
150 2
    protected function getMessage($attribute, $rule, array $parameters)
151
    {
152 2
        if (in_array($rule, $this->sizeRules)) {
153
            return $this->getSizeMessage($attribute, $rule, $parameters);
154
        }
155 2
        $lowerRule = Str::snakeCase($rule);
156 2
        return $this->translator($lowerRule, $parameters);
157
    }
158
159
    /**
160
     * Get a rule and its parameters for a given attribute.
161
     * @param string $attribute
162
     * @param string|array $rules
163
     * @return array|null|void
164
     */
165 2
    protected function getRule($attribute, $rules)
166
    {
167 2
        if (!array_key_exists($attribute, $this->rules)) {
168
            return;
169
        }
170 2
        $rules = (array) $rules;
171 2
        foreach ($this->rules[$attribute] as $rule) {
172 2
            list($rule, $parameters) = $this->parseRule($rule);
173 2
            if (in_array($rule, $rules)) {
174 2
                return [$rule, $parameters];
175
            }
176
        }
177 2
    }
178
179
    /**
180
     * Get the size of an attribute.
181
     * @param string $attribute
182
     * @param mixed $value
183
     * @return mixed
184
     */
185 1
    protected function getSize($attribute, $value)
186
    {
187 1
        $hasNumeric = $this->hasRule($attribute, $this->numericRules);
188 1
        if (is_numeric($value) && $hasNumeric) {
189 1
            return $value;
190
        } elseif (is_array($value)) {
191
            return count($value);
192
        }
193
        return function_exists('mb_strlen')
194
            ? mb_strlen($value)
195
            : strlen($value);
196
    }
197
198
    /**
199
     * Get the proper error message for an attribute and size rule.
200
     * @param string $attribute
201
     * @param string $rule
202
     * @return string|null
203
     */
204
    protected function getSizeMessage($attribute, $rule, array $parameters)
205
    {
206
        $type = $this->getAttributeType($attribute);
207
        $lowerRule = Str::snakeCase($rule.$type);
208
        return $this->translator($lowerRule, $parameters);
209
    }
210
211
    /**
212
     * Get the value of a given attribute.
213
     * @param string $attribute
214
     * @return mixed
215
     */
216 2
    protected function getValue($attribute)
217
    {
218 2
        if (isset($this->data[$attribute])) {
219 2
            return $this->data[$attribute];
220
        }
221
    }
222
223
    /**
224
     * Determine if the given attribute has a rule in the given set.
225
     * @param string $attribute
226
     * @param string|array $rules
227
     * @return bool
228
     */
229 2
    protected function hasRule($attribute, $rules)
230
    {
231 2
        return !is_null($this->getRule($attribute, $rules));
232
    }
233
234
    /**
235
     * Normalize the provided data to an array.
236
     * @param mixed $data
237
     * @return void
238
     */
239 2
    protected function normalizeData($data)
240
    {
241 2
        $this->data = is_object($data)
242
            ? get_object_vars($data)
243 2
            : $data;
244 2
    }
245
246
    /**
247
     * Parse a parameter list.
248
     * @param string $rule
249
     * @param string $parameter
250
     * @return array
251
     */
252 1
    protected function parseParameters($rule, $parameter)
253
    {
254 1
        return 'regex' == strtolower($rule)
255
            ? [$parameter]
256 1
            : str_getcsv($parameter);
257
    }
258
259
    /**
260
     * Extract the rule name and parameters from a rule.
261
     * @param string $rule
262
     * @return array
263
     */
264 2
    protected function parseRule($rule)
265
    {
266 2
        $parameters = [];
267 2
        if (Str::contains(':', $rule)) {
268 1
            list($rule, $parameter) = explode(':', $rule, 2);
269 1
            $parameters = $this->parseParameters($rule, $parameter);
270
        }
271 2
        $rule = Str::camelCase($rule);
272 2
        return [$rule, $parameters];
273
    }
274
275
    /**
276
     * Set the validation rules.
277
     * @return void
278
     */
279 2
    protected function setRules(array $rules)
280
    {
281 2
        foreach ($rules as $key => $rule) {
282 2
            $rules[$key] = is_string($rule)
283 2
                ? explode('|', $rule)
284
                : $rule;
285
        }
286 2
        $this->rules = $rules;
287 2
    }
288
289
    /**
290
     * Check if we should stop further validations on a given attribute.
291
     * @param string $attribute
292
     * @return bool
293
     */
294 2
    protected function shouldStopValidating($attribute)
295
    {
296 2
        return $this->hasRule($attribute, $this->implicitRules)
297 2
            && isset($this->failedRules[$attribute])
298 2
            && array_intersect(array_keys($this->failedRules[$attribute]), $this->implicitRules);
299
    }
300
301
    /**
302
     * Returns a translated message for the attribute.
303
     * @param string $key
304
     * @return void|string
305
     */
306 2
    protected function translator($key, array $parameters)
307
    {
308 2
        $strings = glsr(ValidationStringsDefaults::class)->defaults();
309 2
        if (isset($strings[$key])) {
310 2
            return $this->replace($strings[$key], $parameters);
311
        }
312
        return 'error';
313
    }
314
}
315