Validator::isValidValue()   A
last analyzed

Complexity

Conditions 3
Paths 3

Size

Total Lines 12
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 3

Importance

Changes 0
Metric Value
cc 3
eloc 8
nc 3
nop 2
dl 0
loc 12
ccs 9
cts 9
cp 1
crap 3
rs 10
c 0
b 0
f 0
1
<?php
2
3
/*
4
 * This file is part of the Valdi package.
5
 *
6
 * (c) Philip Lehmann-Böhm <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Valdi;
13
14
use Valdi\Validator\ValidatorInterface;
15
16
/**
17
 * The Validator is used to chain Validators together and validate a set of data
18
 * with it.
19
 */
20
class Validator
21
{
22
23
    /**
24
     * Holds the available validators.
25
     */
26
    protected $availableValidators;
27
28
    /**
29
     * Creates instances of the available validators.
30
     *
31
     * @param array $validators the validators to load, key = name, value = classname within the namespace "\Valdi\Validator"
32
     */
33 14
    protected function createValidators(array $validators)
34
    {
35 14
        $this->availableValidators = [];
36 14
        foreach ($validators as $name => $type) {
37 14
            $class = '\\Valdi\\Validator\\' . $type;
38 14
            $this->availableValidators[$name] = new $class();
39
        }
40 14
    }
41
42
    /**
43
     * Validates a single rule.
44
     *
45
     * @param string $validator the validator to use
46
     * @param string[] $parameters the validation parameters, depending on the validator
47
     * @param null|string $value the value to validate
48
     *
49
     * @return boolean - true if the value is valid
50
     *
51
     * @throws ValidatorException - thrown if the validator is not available
52
     */
53 14
    protected function isValidRule(string $validator, array $parameters, $value)
54
    {
55 14
        if (!array_key_exists($validator, $this->availableValidators)) {
56 2
            throw new ValidatorException('"' . $validator . '" not found as available validator.');
57
        }
58 13
        return $this->availableValidators[$validator]->isValid($value, $parameters) ?
59 13
            null : $this->availableValidators[$validator]->getInvalidDetails();
60
    }
61
62
    /**
63
     * Constructor.
64
     */
65 14
    public function __construct()
66
    {
67
        $validators = [
68 14
            'afterDateTime' => 'AfterDateTime',
69
            'alphabetical' => 'Alphabetical',
70
            'alphaNumerical' => 'AlphaNumerical',
71
            'beforeDateTime' => 'BeforeDateTime',
72
            'between' => 'Between',
73
            'boolean' => 'Boolean',
74
            'collection' => 'Collection',
75
            'contains' => 'Contains',
76
            'dateTime' => 'DateTime',
77
            'dateTimeBetween' => 'DateTimeBetween',
78
            'email' => 'Email',
79
            'floating' => 'Floating',
80
            'inSet' => 'InSet',
81
            'integer' => 'Integer',
82
            'inTheFuture' => 'InTheFuture',
83
            'inThePast' => 'InThePast',
84
            'ip' => 'IP',
85
            'ipv4' => 'IPv4',
86
            'ipv6' => 'IPv6',
87
            'lengthBetween' => 'LengthBetween',
88
            'max' => 'Max',
89
            'maxLength' => 'MaxLength',
90
            'min' => 'Min',
91
            'minLength' => 'MinLength',
92
            'nested' => 'Nested',
93
            'olderThan' => 'OlderThan',
94
            'or' => 'OrCombine',
95
            'regexp' => 'Regexp',
96
            'required' => 'Required',
97
            'slug' => 'Slug',
98
            'url' => 'Url',
99
            'value' => 'Value',
100
            'youngerThan' => 'YoungerThan'
101
        ];
102 14
        $this->createValidators($validators);
103 14
    }
104
105
    /**
106
     * Adds additional validator. It can override existing validators as well.
107
     *
108
     * @param string $name the name of the new validator.
109
     * @param ValidatorInterface $validator the validator to add
110
     */
111 1
    public function addValidator(string $name, ValidatorInterface $validator)
112
    {
113 1
        $this->availableValidators[$name] = $validator;
114 1
    }
115
116
    /**
117
     * Validates a value via the given rules.
118
     *
119
     * @param array $rules the validation rules
120
     * @param null|string $value the value to validate
121
     *
122
     * @return string[] - the fields where the validation failed
123
     *
124
     * @throws ValidatorException - thrown if a validator is not available
125
     */
126 14
    public function isValidValue(array $rules, $value)
127
    {
128 14
        $result = [];
129 14
        foreach ($rules as $rule) {
130 14
            $parameters = $rule;
131 14
            $name = array_shift($parameters);
132 14
            $valid = $this->isValidRule($name, $parameters, $value);
133 13
            if ($valid !== null) {
134 13
                $result[] = $valid;
135
            }
136
        }
137 13
        return $result;
138
    }
139
140
    /**
141
     * Performs the actual validation.
142
     *
143
     * @param array $rules the validation rules: an array with a field name as key and an array of rules to use for this field; each rule is an array with the validator name as first element and parameters as following elements; example: array('a' => array(array('required')), 'b' => array(array('min', 1)))
144
     * @param array $data the data to validate as a map
145
     *
146
     * @return array<string,boolean|array> - the validation result having the keys "valid" (true or false) and the key "errors" containing all failed fields as keys with arrays of the failed validator names; example where the field "b" from the above sample failed due to the min validator: array('valid' => false, errors => array('b' => array('min'))) the "or" validator doesn't return a single string on validation error; instead, it returns an array listing all failed validators of it: array('or' => array('url', 'email')
147
     *
148
     * @throws ValidatorException - thrown if a validator is not available
149
     */
150 11
    public function isValid(array $rules, array $data)
151
    {
152 11
        $errors = [];
153 11
        foreach ($rules as $field => $fieldRules) {
154 11
            $value = isset($data[$field]) ? $data[$field] : null;
155 11
            $fieldErrors = $this->isValidValue($fieldRules, $value);
156 10
            if (!empty($fieldErrors)) {
157 10
                $errors[$field] = $fieldErrors;
158
            }
159
        }
160
        return [
161 10
            'valid' => count($errors) === 0,
162 10
            'errors' => $errors
163
        ];
164
    }
165
166
}
167