Completed
Push — master ( 7f047f...6680e2 )
by Philip
07:06
created

Validator::isValidValue()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 12
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

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