Completed
Push — master ( 78c4ab...8e9826 )
by James Ekow Abaka
02:04
created

Validator::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 3
cts 3
cp 1
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 1
crap 1
1
<?php
2
3
/*
4
 * Ntentan Framework
5
 * Copyright (c) 2008-2017 James Ekow Abaka Ainooson
6
 *
7
 * Permission is hereby granted, free of charge, to any person obtaining
8
 * a copy of this software and associated documentation files (the
9
 * "Software"), to deal in the Software without restriction, including
10
 * without limitation the rights to use, copy, modify, merge, publish,
11
 * distribute, sublicense, and/or sell copies of the Software, and to
12
 * permit persons to whom the Software is furnished to do so, subject to
13
 * the following conditions:
14
 *
15
 * The above copyright notice and this permission notice shall be
16
 * included in all copies or substantial portions of the Software.
17
 *
18
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
22
 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23
 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25
 *
26
 */
27
28
namespace ntentan\utils;
29
30
use ntentan\panie\Container;
31
32
/**
33
 * Base validator class for validating data in associative arrays.
34
 * Validator class allows general validation rules to be defined that could be used to validate data in arbitrary
35
 * associative arrays. Rules are defined in an array where different validation types point the the fields in a given
36
 * associative array that will be validated. ntentan\utils ships with a set of default validations for lenght (or size),
37
 * regular expressions, numbers and presence (fields that are required).
38
 */
39
class Validator
40
{
41
42
    /**
43
     * An array which represnts the validation rules.
44
     * 
45
     * @var array
46
     */
47
    private $rules = [];
48
49
    /**
50
     * An array which holds the validation errors found after the last
51
     * validation was run.
52
     * 
53
     * @var array
54
     */
55
    private $invalidFields = [];
56
57
    /**
58
     * An array of loaded validations for this validator.
59
     * 
60
     * @var array 
61
     */
62
    private $validations = [];
63
64
    /**
65
     * A register of validations that could be used by this validator.
66
     * 
67
     * @var array
68
     */
69
    private $validationRegister = [
70
        'required' => '\ntentan\utils\validator\validations\RequiredValidation',
71
        'length' => '\ntentan\utils\validator\validations\LengthValidation',
72
        'numeric' => '\ntentan\utils\validator\validations\NumericValidation',
73
        'regexp' => '\ntentan\utils\validator\validations\RegexpValidation',
74
    ];
75
    private $validationData = [];
76
77
    /**
78
     * A DI container for initializing the validations.
79
     *
80
     * @var Container
81
     */
82
    private $container;
83
84
85
    /**
86
     * Constructor for Validator
87
     *
88
     * @param Container $container
89
     */
90 16
    public function __construct(Container $container = null)
91
    {
92 16
        $this->container = $container;
93 16
    }
94
95
    /**
96
     * Returns a new instance of the Validator.
97
     * 
98
     * @return \ntentan\utils\Validator
0 ignored issues
show
Documentation introduced by
Should the return type not be \self?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
99
     */
100 16
    public static function getInstance(Container $container = null): self
101
    {
102 16
        return new self($container);
103
    }
104
105
    /**
106
     * Get an instance of a validation class.
107
     * 
108
     * @param string $name
109
     * @return validator\Validation
110
     * @throws exceptions\ValidatorException
111
     */
112 16
    private function getValidation(string $name): validator\Validation
113
    {
114 16
        if (!isset($this->validations[$name])) {
115 16
            if (isset($this->validationRegister[$name])) {
116 14
                $class = $this->validationRegister[$name];
117
            } else {
118 2
                throw new exceptions\ValidatorException("Validator [$name] not found");
119
            }
120
121 14
            $params = isset($this->validationData[$name]) ? $this->validationData[$name] : null;
122 14
            if($this->container) {
123 6
                $this->validations[$name] = $this->container->resolve($class, ['params' => $params]);
124
            } else {
125 8
                $this->validations[$name] = new $class($params);
126
            }
127
        }
128 14
        return $this->validations[$name];
129
    }
130
131
    /**
132
     * Register a validation type.
133
     * 
134
     * @param string $name The name of the validation to be used in validation descriptions.
135
     * @param string $class The name of the validation class to load.
136
     * @param mixed $data Any extra validation data that would be necessary for the validation.
137
     */
138 2
    protected function registerValidation(string $name, string $class, $data = null) : void
139
    {
140 2
        $this->validationRegister[$name] = $class;
141 2
        $this->validationData[$name] = $data;
142 2
    }
143
144
    /**
145
     * Set the validation rules.
146
     * 
147
     * @param array $rules
148
     */
149 16
    public function setRules(array $rules) : void
150
    {
151 16
        $this->rules = $rules;
152 16
    }
153
154
    /**
155
     * Returns an associative array of all the errors that occurred the last time the validator was run.
156
     * 
157
     * @return array
158
     */
159 14
    public function getInvalidFields(): array
160
    {
161 14
        return $this->invalidFields;
162
    }
163
164
    /**
165
     * Build a uniform field info array for various types of validations.
166
     * 
167
     * @param mixed $key
168
     * @param mixed $value
169
     * @return array
170
     */
171 16
    private function getFieldInfo($key, $value): array
172
    {
173 16
        $name = null;
174 16
        $options = [];
175 16
        if (is_numeric($key) && is_string($value)) {
176 6
            $name = $value;
177 10
        } else if (is_numeric($key) && is_array($value)) {
178 2
            $name = array_shift($value);
179 2
            $options = $value;
180 8
        } else if (is_string($key)) {
181 8
            $name = $key;
182 8
            $options = $value;
183
        }
184 16
        return ['name' => $name, 'options' => $options];
185
    }
186
187
    /**
188
     * Validate data according to validation rules that have been set into
189
     * this validator.
190
     * 
191
     * @param array $data The data to be validated
192
     * @return bool
193
     */
194 16
    public function validate(array $data) : bool
195
    {
196 16
        $passed = true;
197 16
        $this->invalidFields = [];
198 16
        foreach ($this->rules as $validation => $fields) {
199 16
            foreach ($fields as $key => $value) {
200 16
                $field = $this->getFieldInfo($key, $value);
201 16
                $validationInstance = $this->getValidation($validation);
202 14
                $passed = $passed && $validationInstance->run($field, $data);
203 14
                $this->invalidFields = array_merge_recursive(
204 14
                        $this->invalidFields, $validationInstance->getMessages()
205
                );
206
            }
207
        }
208 14
        return $passed;
209
    }
210
211
}
212