Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
37 / 37
100.00% covered (success)
100.00%
6 / 6
CRAP
100.00% covered (success)
100.00%
1 / 1
Validator
100.00% covered (success)
100.00%
37 / 37
100.00% covered (success)
100.00%
6 / 6
16
100.00% covered (success)
100.00%
1 / 1
 validate
100.00% covered (success)
100.00%
30 / 30
100.00% covered (success)
100.00%
1 / 1
11
 map
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 mapBack
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 getData
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getErrors
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 addErrors
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2
3declare(strict_types=1);
4
5namespace Engelsystem\Http\Validation;
6
7use Illuminate\Support\Str;
8use InvalidArgumentException;
9use Respect\Validation\Exceptions\ComponentException;
10use Respect\Validation\Validator as RespectValidator;
11
12class Validator
13{
14    /** @var string[] */
15    protected array $errors = [];
16
17    protected array $data = [];
18
19    protected array $mapping = [
20        'accepted' => 'Checked',
21        'int'      => 'IntVal',
22        'float'    => 'FloatVal',
23        'required' => 'NotEmpty',
24        'optional' => 'nullable',
25    ];
26
27    public function validate(array $data, array $rules): bool
28    {
29        $this->errors = [];
30        $this->data = [];
31
32        $validData = [];
33        foreach ($rules as $fieldName => $rulesList) {
34            $v = new RespectValidator();
35            $v->with('\\Engelsystem\\Http\\Validation\\Rules', true);
36
37            $value = $data[$fieldName] ?? null;
38            $rulesList = is_array($rulesList) ? $rulesList : explode('|', $rulesList);
39
40            // Configure the check to be run for every rule
41            foreach ($rulesList as $parameters) {
42                $parameters = is_array($parameters) ? $parameters : explode(':', $parameters);
43                $rule = array_shift($parameters);
44                $rule = Str::camel($rule);
45                $rule = $this->map($rule);
46
47                // Handle empty/optional values
48                if ($rule == 'nullable') {
49                    if (is_null($value) || $value === '') {
50                        $validData[$fieldName] = null;
51                        break;
52                    }
53
54                    $validData[$fieldName] = $value;
55                    continue;
56                }
57
58                // Configure the validation
59                try {
60                    $v = call_user_func_array([$v, $rule], $parameters);
61                } catch (ComponentException $e) {
62                    throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e);
63                }
64
65                // Run validation
66                if ($v->validate($value)) {
67                    $validData[$fieldName] = $value;
68                } else {
69                    $this->errors[$fieldName][] = implode('.', ['validation', $fieldName, $this->mapBack($rule)]);
70                }
71
72                $v->removeRules();
73            }
74        }
75
76        $success = empty($this->errors);
77        if ($success) {
78            $this->data = $validData;
79        }
80
81        return $success;
82    }
83
84    protected function map(string $rule): string
85    {
86        return $this->mapping[$rule] ?? $rule;
87    }
88
89    protected function mapBack(string $rule): string
90    {
91        $mapping = array_flip($this->mapping);
92
93        return $mapping[$rule] ?? $rule;
94    }
95
96    public function getData(): array
97    {
98        return $this->data;
99    }
100
101    /**
102     * @return string[]
103     */
104    public function getErrors(): array
105    {
106        return $this->errors;
107    }
108
109    public function addErrors(array $errors): self
110    {
111        $this->errors = array_merge($this->errors, $errors);
112
113        return $this;
114    }
115}