Completed
Branch master (b7a0b6)
by Adrian
04:26 queued 02:31
created

ValueValidator::getMessages()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 0
crap 1
1
<?php
2
3
namespace Sirius\Validation;
4
5
use Sirius\Validation\Rule\AbstractRule;
6
7
class ValueValidator
8
{
9
10
    /**
11
     * The error messages generated after validation or set manually
12
     *
13
     * @var array
14
     */
15
    protected $messages = array();
16
17
    /**
18
     * Will be used to construct the rules
19
     *
20
     * @var \Sirius\Validation\RuleFactory
21
     */
22
    protected $ruleFactory;
23
24
    /**
25
     * The prototype that will be used to generate the error message
26
     *
27
     * @var \Sirius\Validation\ErrorMessage
28
     */
29
    protected $errorMessagePrototype;
30
31
    /**
32
     * The rule collections for the validation
33
     *
34
     * @var \Sirius\Validation\RuleCollection
35
     */
36
    protected $rules;
37
38
    /**
39
     * The label of the value to be validated
40
     *
41
     * @var string
42
     */
43
    protected $label;
44
45
46 22
    public function __construct(
47
        RuleFactory $ruleFactory = null,
48
        ErrorMessage $errorMessagePrototype = null,
49
        $label = null
50
    ) {
51 22
        if (!$ruleFactory) {
52 6
            $ruleFactory = new RuleFactory();
53 6
        }
54 22
        $this->ruleFactory = $ruleFactory;
55 22
        if (!$errorMessagePrototype) {
56 6
            $errorMessagePrototype = new ErrorMessage();
57 6
        }
58 22
        $this->errorMessagePrototype = $errorMessagePrototype;
59 22
        if ($label) {
60 2
            $this->label = $label;
61 2
        }
62 22
        $this->rules = new RuleCollection;
63 22
    }
64
65 1
    public function setLabel($label = null)
66
    {
67 1
        $this->label = $label;
68
69 1
        return $this;
70
    }
71
72
    /**
73
     * Add 1 or more validation rules
74
     *
75
     * @example
76
     * // add multiple rules at once
77
     * $validator->add(array(
78
     *   'required',
79
     *   array('required', array('email', null, '{label} must be an email', 'Field B')),
80
     * ));
81
     *
82
     * // add multiple rules using a string
83
     * $validator->add('required | email');
84
     *
85
     * // add validator with options
86
     * $validator->add('minlength', array('min' => 2), '{label} should have at least {min} characters', 'Field label');
87
     *
88
     * // add validator with string and parameters as JSON string
89
     * $validator->add('minlength({"min": 2})({label} should have at least {min} characters)(Field label)');
90
     *
91
     * // add validator with string and parameters as query string
92
     * $validator->add('minlength(min=2)({label} should have at least {min} characters)(Field label)');
93
     *
94
     * @param string|callback $name
95
     * @param string|array $options
96
     * @param string $messageTemplate
97
     * @param string $label
98
     *
99
     * @return ValueValidator
100
     */
101 22
    public function add($name, $options = null, $messageTemplate = null, $label = null)
102
    {
103 22
        if (is_array($name) && !is_callable($name)) {
104
            return $this->addMultiple($name);
105
        }
106 22
        if (is_string($name)) {
107
            // rule was supplied like 'required | email'
108 22
            if (strpos($name, ' | ') !== false) {
109 4
                return $this->addMultiple(explode(' | ', $name));
110
            }
111
            // rule was supplied like this 'length(2,10)(error message template)(label)'
112 22
            if (strpos($name, '(') !== false) {
113 5
                list($name, $options, $messageTemplate, $label) = $this->parseRule($name);
114 5
            }
115 22
        }
116
117
        // check for the default label
118 22
        if (!$label && $this->label) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $label of type string|null is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
119 2
            $label = $this->label;
120 2
        }
121
122 22
        $validator = $this->ruleFactory->createRule($name, $options, $messageTemplate, $label);
123
124 20
        return $this->addRule($validator);
125
    }
126
127
    /**
128
     * @param array $rules
129
     *
130
     * @return ValueValidator
131
     */
132 4
    public function addMultiple($rules)
133
    {
134 4
        foreach ($rules as $singleRule) {
135
            // make sure the rule is an array (the parameters of subsequent calls);
136 4
            $singleRule = is_array($singleRule) ? $singleRule : array(
137
                $singleRule
138 4
            );
139 4
            call_user_func_array(
140
                array(
141 4
                    $this,
142
                    'add'
143 4
                ),
144
                $singleRule
145 4
            );
146 4
        }
147
148 4
        return $this;
149
    }
150
151
    /**
152
     * @param AbstractValidator $validationRule
153
     *
154
     * @return ValueValidator
155
     */
156 20
    public function addRule(AbstractRule $validationRule)
157
    {
158 20
        $validationRule->setErrorMessagePrototype($this->errorMessagePrototype);
159 20
        $this->rules->attach($validationRule);
160
161 20
        return $this;
162
    }
163
164
    /**
165
     * Remove validation rule
166
     *
167
     * @param mixed $name
168
     *            rule name or true if all rules should be deleted for that selector
169
     * @param mixed $options
170
     *            rule options, necessary for rules that depend on params for their ID
171
     *
172
     * @throws \InvalidArgumentException
173
     * @internal param string $selector data selector
174
     * @return self
175
     */
176 4
    public function remove($name = true, $options = null)
177
    {
178 4
        if ($name === true) {
179 2
            $this->rules = new RuleCollection();
180
181 2
            return $this;
182
        }
183 2
        $validator = $this->ruleFactory->createRule($name, $options);
0 ignored issues
show
Documentation introduced by
$name is of type *, but the function expects a callable.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
184 2
        $this->rules->detach($validator);
185
186 2
        return $this;
187
    }
188
189
    /**
190
     * Converts a rule that was supplied as string into a set of options that define the rule
191
     *
192
     * @example 'minLength({"min":2})({label} must have at least {min} characters)(Street)'
193
     *
194
     *          will be converted into
195
     *
196
     *          array(
197
     *          'minLength', // validator name
198
     *          array('min' => 2'), // validator options
199
     *          '{label} must have at least {min} characters',
200
     *          'Street' // label
201
     *          )
202
     *
203
     * @param string $ruleAsString
204
     *
205
     * @return array
206
     */
207 5
    protected function parseRule($ruleAsString)
208
    {
209 5
        $ruleAsString    = trim($ruleAsString);
210 5
        $options         = array();
211 5
        $messageTemplate = null;
212 5
        $label           = null;
213
214 5
        $name         = substr($ruleAsString, 0, strpos($ruleAsString, '('));
215 5
        $ruleAsString = substr($ruleAsString, strpos($ruleAsString, '('));
216 5
        $matches      = array();
217 5
        preg_match_all('/\(([^\)]*)\)/', $ruleAsString, $matches);
218
219 5
        if (isset($matches[1])) {
220 5
            if (isset($matches[1][0]) && $matches[1][0]) {
221 5
                $options = $matches[1][0];
222 5
            }
223 5
            if (isset($matches[1][1]) && $matches[1][1]) {
224 2
                $messageTemplate = $matches[1][1];
225 2
            }
226 5
            if (isset($matches[1][2]) && $matches[1][2]) {
227 2
                $label = $matches[1][2];
228 2
            }
229 5
        }
230
231
        return array(
232 5
            $name,
233 5
            $options,
234 5
            $messageTemplate,
235
            $label
236 5
        );
237
    }
238
239
240 20
    public function validate($value, $valueIdentifier = null, DataWrapper\WrapperInterface $context = null)
241
    {
242 20
        $this->messages = array();
243 20
        $isRequired     = false;
244 20
        foreach ($this->rules as $rule) {
245 20
            if ($rule instanceof Rule\Required) {
246 14
                $isRequired = true;
247 14
                break;
248
            }
249 20
        }
250
251 20
        if (!$isRequired && $value === null) {
252 5
            return true;
253
        }
254
255
        /* @var $rule \Sirius\Validation\Rule\AbstractValidator */
256 19
        foreach ($this->rules as $rule) {
257 19
            $rule->setContext($context);
258 19
            if (!$rule->validate($value, $valueIdentifier)) {
259 19
                $this->addMessage($rule->getMessage());
260 19
            }
261
            // if field is required and we have an error,
262
            // do not continue with the rest of rules
263 19
            if ($isRequired && count($this->messages)) {
264 13
                break;
265
            }
266 19
        }
267
268 19
        return count($this->messages) === 0;
269
    }
270
271 18
    public function getMessages()
272
    {
273 18
        return $this->messages;
274
    }
275
276 19
    public function addMessage($message)
277
    {
278 19
        array_push($this->messages, $message);
279
280 19
        return $this;
281
    }
282
283 1
    public function getRules()
284
    {
285 1
        return $this->rules;
286
    }
287
}
288