Completed
Push — master ( 630cca...f9ea9b )
by Philip
02:37
created

Validator::isValidRule()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 6
rs 9.4285
cc 2
eloc 4
nc 2
nop 3
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
     * Holds the available validators.
24
     */
25
    protected $availableValidators;
26
27
    /**
28
     * Creates instances of the available validators.
29
     *
30
     * @param array $validators
31
     * the validators to load, key = name, value = classname within the
32
     * namespace "\Valdi\Validator"
33
     */
34
    protected function createValidators(array $validators) {
35
        $this->availableValidators = array();
36
        foreach ($validators as $name => $type) {
37
            $class                            = '\\Valdi\\Validator\\' . $type;
38
            $this->availableValidators[$name] = new $class();
39
        }
40
    }
41
42
    /**
43
     * Validates a single rule.
44
     *
45
     * @param string $validator
46
     * the validator to use
47
     * @param string[] $parameters
48
     * the validation parameters, depending on the validator
49
     * @param string $value
50
     * the value to validate
51
     *
52
     * @return boolean
53
     * true if the value is valid
54
     */
55
    protected function isValidRule($validator, $parameters, $value) {
56
        if (!array_key_exists($validator, $this->availableValidators)) {
57
            throw new ValidatorException('"' . $validator . '" not found as available validator.');
58
        }
59
        return $this->availableValidators[$validator]->isValid($value, $parameters);
60
    }
61
62
    /**
63
     * Validates a value via the given rules.
64
     *
65
     * @param array $fieldRules
66
     * the validation rules
67
     * @param string $value
68
     * the value to validate
69
     *
70
     * @return string[]
71
     * the fields where the validation failed
72
     */
73
    protected function isValidField($fieldRules, $value) {
74
        $result = array();
75
        foreach ($fieldRules as $rule) {
76
            $name = $rule;
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 7 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
77
            $parameters = array();
78
            if (is_array($rule)) {
79
                $parameters = $rule;
80
                $name       = array_shift($parameters);
81
            }
82
            $valid = $this->isValidRule($name, $parameters, $value);
83
            if (!$valid) {
84
                $result[] = $name;
85
            }
86
        }
87
        return $result;
88
    }
89
90
    /**
91
     * Constructor.
92
     */
93
    public function __construct() {
94
        $validators = array(
95
            'afterDateTime' => 'AfterDateTime', 'alphabetical' => 'Alphabetical',
96
            'alphaNumerical' => 'AlphaNumerical', 'beforeDateTime' => 'BeforeDateTime',
97
            'between' => 'Between', 'boolean' => 'Boolean',
98
            'contains' => 'Contains', 'dateTime' => 'DateTime',
99
            'dateTimeBetween' => 'DateTimeBetween', 'email' => 'Email',
100
            'floating' => 'Floating', 'inSet' => 'InSet',
101
            'integer' => 'Integer', 'inTheFuture' => 'InTheFuture',
102
            'inThePast' => 'InThePast', 'ip' => 'IP',
103
            'ipv4' => 'IPv4', 'ipv6' => 'IPv6',
104
            'lengthBetween' => 'LengthBetween', 'max' => 'Max',
105
            'maxLength' => 'MaxLength', 'min' => 'Min',
106
            'minLength' => 'MinLength', 'olderThan' => 'OlderThan',
107
            'regexp' => 'Regexp', 'required' => 'Required',
108
            'slug' => 'Slug', 'url' => 'Url',
109
            'value' => 'Value', 'youngerThan' => 'YoungerThan'
110
        );
111
        $this->createValidators($validators);
112
    }
113
114
    /**
115
     * Adds additional validator. It can override existing validators as well.
116
     *
117
     * @param string $name
118
     * the name of the new validator.
119
     * @param ValidatorInterface $validator
120
     * the validator to add
121
     */
122
    public function addValidator($name, ValidatorInterface $validator) {
123
        $this->availableValidators[$name] = $validator;
124
    }
125
126
    /**
127
     * Performs the actual validation.
128
     *
129
     * @param array $rules
130
     * the validation rules: an array with a field name as key and an array
131
     * of rules to use for this field; each rule is either a string with the
132
     * validator name or an array with the validator name as first element and
133
     * parameters as following elements; example:
134
     * array('a' => array('required'), 'b' => array(array('min', 1)))
135
     * @param array $data
136
     * the data to validate as a map
137
     *
138
     * @return array<string,boolean|array>
139
     * the validation result having the keys "valid" (true or false) and
140
     * the key "errors" containing all failed fields as keys with arrays of the
141
     * failed validator names; example where the field "b" from the above sample
142
     * failed due to the min validator:
143
     * array('valid' => false, errors => array('b' => array('min')))
144
     */
145
    public function isValid(array $rules, array $data) {
146
        $errors = array();
147
        foreach ($rules as $field => $fieldRules) {
148
            $value       = isset($data[$field]) ? $data[$field] : null;
149
            $fieldErrors = $this->isValidField($fieldRules, $value);
150
            if (!empty($fieldErrors)) {
151
                $errors[$field] = $fieldErrors;
152
            }
153
        }
154
        return array(
155
            'valid' => count($errors) === 0,
156
            'errors' => $errors
157
        );
158
    }
159
160
}
161