ValidationAwareMethods   A
last analyzed

Complexity

Total Complexity 17

Size/Duplication

Total Lines 206
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 4

Test Coverage

Coverage 66.67%

Importance

Changes 0
Metric Value
wmc 17
lcom 1
cbo 4
dl 0
loc 206
ccs 38
cts 57
cp 0.6667
rs 10
c 0
b 0
f 0

13 Methods

Rating   Name   Duplication   Size   Complexity  
getValue() 0 1 ?
A isValid() 0 8 2
A isMultipleValid() 0 8 2
A validate() 0 12 2
A validateArray() 0 10 3
A setInvalid() 0 5 1
A getValidationChain() 0 7 2
A setValidationChain() 0 5 1
B addValidator() 0 23 4
setRequired() 0 1 ?
getInstance() 0 1 ?
isMultiple() 0 1 ?
isRendering() 0 1 ?
1
<?php
2
3
/**
4
 * This file is part of slick/form package
5
 *
6
 * For the full copyright and license information, please view the LICENSE
7
 * file that was distributed with this source code.
8
 */
9
10
namespace Slick\Form\Input;
11
12
use Slick\Form\ElementInterface;
13
use Slick\Form\Exception\InvalidArgumentException;
14
use Slick\Form\InputInterface;
15
use Slick\Validator\NotEmpty;
16
use Slick\Validator\StaticValidator;
17
use Slick\Validator\ValidationChain;
18
use Slick\Validator\ValidationChainInterface;
19
use Slick\Validator\ValidatorInterface;
20
use Slick\Validator\Exception as ValidatorException;
21
22
/**
23
 * Implementation for ValidationAwareInterface
24
 *
25
 * @package Slick\Form\Input
26
 * @author  Filipe Silva <[email protected]>
27
 */
28
trait ValidationAwareMethods
29
{
30
    /**
31
     * @var ValidationChainInterface
32
     */
33
    protected $validationChain;
34
35
    /**
36
     * @var boolean
37
     */
38
    protected $valid = true;
39
40
    /**
41
     * @var array
42
     */
43
    protected $invalidInstances = [];
44
45
    /**
46
     * @var array
47
     */
48
    protected $context = [];
49
50
    /**
51
     * Gets the value to be validated
52
     *
53
     * @return mixed
54
     */
55
    abstract public function getValue();
56
57
    /**
58
     * Check if the value is valid
59
     *
60
     * The value should pass through all validators in the validation chain
61
     *
62
     * @return boolean True if is valid, false otherwise
63
     */
64 16
    public function isValid()
65
    {
66 16
        $valid = $this->valid;
67 16
        if ($this->isMultiple()) {
68
            $valid = $this->isMultipleValid();
69
        }
70 16
        return $valid;
71
    }
72
73
    /**
74
     * Validates when input is set to be multiple
75
     * 
76
     * @return bool
77
     */
78
    protected function isMultipleValid()
79
    {
80
        if (!$this->isRendering()) {
81
            return empty($this->invalidInstances);
82
        }
83
        
84
        return ! in_array($this->getInstance(), $this->invalidInstances);
85
    }
86
87
    /**
88
     * Validates current value so that isValid can retrieve the result of
89
     * the validation(s)
90
     *
91
     * @return self|$this|ValidationAwareInterface
92
     */
93 6
    public function validate()
94
    {
95 6
        $context = array_merge(['input' => $this], $this->context);
96 6
        $values = $this->getValue();
97 6
        if (!is_array($values)) {
98 6
            $this->valid = $this->getValidationChain()
99 6
                ->validates($this->getValue(), $context);
100 6
            return $this;
101
        }
102
        $this->validateArray($values, $context);
103 2
        return $this;
104
    }
105
106
    /**
107
     * Validates input when is set to be multiple
108
     * 
109
     * @param array $values
110
     * @param array $context
111
     */
112
    protected function validateArray(array $values, $context)
113
    {
114
        foreach ($values as $key => $value) {
115
            $valid = $this->getValidationChain()
116
                ->validates($value, $context);
117
            if (!$valid) {
118
                $this->setInvalid($key);
119
            }
120
        }
121
    }
122
123
    /**
124
     * Mark instance as invalid
125
     * 
126
     * @param int $key
127
     * 
128
     * @return $this|self
0 ignored issues
show
Comprehensibility Bug introduced by
The return type ValidationAwareMethods is a trait, and thus cannot be used for type-hinting in PHP. Maybe consider adding an interface and use that for type-hinting?

In PHP traits cannot be used for type-hinting as they do not define a well-defined structure. This is because any class that uses a trait can rename that trait’s methods.

If you would like to return an object that has a guaranteed set of methods, you could create a companion interface that lists these methods explicitly.

Loading history...
129
     */
130
    protected function setInvalid($key)
131
    {
132
        array_push($this->invalidInstances, $key);
133
        return $this;
134
    }
135
    
136
    /**
137
     * Returns the validation chain for this input
138
     *
139
     * @return ValidationChainInterface
140
     */
141 38
    public function getValidationChain()
142
    {
143 38
        if (null == $this->validationChain) {
144 38
            $this->setValidationChain(new ValidationChain());
145 38
        }
146 38
        return $this->validationChain;
147
    }
148
149
    /**
150
     * Sets input validation chain
151
     *
152
     * @param ValidationChainInterface $chain
153
     *
154
     * @return self|$this|ValidationAwareInterface
155
     */
156 40
    public function setValidationChain(ValidationChainInterface $chain)
157
    {
158 40
        $this->validationChain = $chain;
159 40
        return $this;
160
    }
161
162
    /**
163
     * Adds a validator to the validation chain
164
     *
165
     * The validator param could be a known validator alias, a FQ
166
     * ValidatorInterface class name or an object implementing
167
     * ValidatorInterface.
168
     *
169
     * @param string|ValidatorInterface $validator
170
     * @param string|array $message Error message and possible contexts
171
     *      variables.
172
     *
173
     * @return self|$this|ValidationAwareInterface|ElementInterface
174
     *
175
     * @throws InvalidArgumentException If the provided validator is an unknown
176
     *      validator alias or not a valid class name or the object passed
177
     *      does not implement the ValidatorInterface interface.
178
     */
179 36
    public function addValidator($validator, $message = null)
180
    {
181
        try {
182 36
            $msg = $message;
183 36
            if (is_array($message)) {
184 30
                $msg = array_shift($message);
185 30
                $this->context = $message;
186 30
            }
187 36
            $validator = StaticValidator::create($validator, $msg);
0 ignored issues
show
Bug introduced by
It seems like $validator defined by \Slick\Validator\StaticV...reate($validator, $msg) on line 187 can also be of type object<Slick\Validator\ValidatorInterface>; however, Slick\Validator\StaticValidator::create() does only seem to accept string, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
188 34
            $this->getValidationChain()
189 34
                ->add($validator);
190 34
            if ($validator instanceof NotEmpty) {
191 34
                $this->setRequired(true);
192 34
            }
193 36
        } catch (ValidatorException $caught) {
194 2
            throw new InvalidArgumentException(
195 2
                $caught->getMessage(),
196 2
                0,
197
                $caught
198 2
            );
199
        }
200 34
        return $this;
201
    }
202
203
    /**
204
     * Sets the required flag for this input
205
     *
206
     * @param boolean $required
207
     *
208
     * @return $this|self|InputInterface
209
     */
210
    abstract public function setRequired($required);
211
212
    /**
213
     * If input is multiple get the instance it belongs
214
     *
215
     * @return int
216
     */
217
    abstract public function getInstance();
218
219
    /**
220
     * Check if this input is for multiple usage
221
     *
222
     * @return boolean
223
     */
224
    abstract public function isMultiple();
225
226
    /**
227
     * Check if input is being rendered
228
     * 
229
     * @return boolean
230
     */
231
    abstract public function isRendering();
232
    
233
}
234