Completed
Push — master ( b6d955...929034 )
by Marcus
02:03
created

AbstractSpec::setRule()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 11
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 2.0185

Importance

Changes 0
Metric Value
dl 0
loc 11
c 0
b 0
f 0
ccs 5
cts 6
cp 0.8333
rs 9.4285
cc 2
eloc 6
nc 2
nop 1
crap 2.0185
1
<?php
2
3
namespace Mbright\Validation\Spec;
4
5
use Mbright\Validation\Exception\RuleClassNotDefinedException;
6
use Mbright\Validation\Rule\Sanitize\SanitizeRuleInterface;
7
use Mbright\Validation\Rule\Validate\ValidateRuleInterface;
8
9
abstract class AbstractSpec
10
{
11
    /**
12
     * Failure Mode for a halting failure.
13
     *
14
     * @var string
15
     */
16
    const HALTING_FAILURE = 'HALTING_FAILURE';
17
18
    /**
19
     * Failure Mode for a hard failure.
20
     *
21
     * @var string
22
     */
23
    const HARD_FAILURE = 'HARD_FAILURE';
24
25
    /**
26
     * Failure Mode for a soft failure.
27
     *
28
     * @var string
29
     */
30
    const SOFT_FAILURE = 'SOFT_FAILURE';
31
32
    /**
33
     * Field name for the spec to operate on.
34
     *
35
     * @var string
36
     */
37
    protected $field;
38
39
    /**
40
     * Rule to invoke.
41
     *
42
     * @var callable
43
     */
44
    protected $rule;
45
46
    /**
47
     * Arguments supplied to the rule
48
     *
49
     * @var array
50
     */
51
    protected $args = [];
52
53
    /**
54
     * Failure message to be used instead of the default message.
55
     *
56
     * @var string
57
     */
58
    protected $message;
59
60
    /**
61
     * Name of the rule to execute.
62
     *
63
     * @var string
64
     */
65
    protected $ruleClass;
66
67
    /**
68
     * Flag that determines the allowance of blank values.
69
     *
70
     * @var bool
71
     */
72
    protected $allowBlanks = false;
73
74
    /**
75
     * An array of values to be considered blank.
76
     *
77
     * @var array
78
     */
79
    protected $blankWhiteList = [];
80
81
    /**
82
     * AbstractSpec constructor.
83
     *
84
     * @param string $field
85
     */
86 117
    public function __construct(string $field)
87
    {
88 117
        $this->field = $field;
89 117
    }
90
91
    /**
92
     * Invokes the rule that this spec is configured for.
93
     *
94
     * @param object $subject
95
     *
96
     * @return bool
97
     */
98 33
    public function __invoke($subject): bool
99
    {
100 33
        return ($this->rule)($subject, $this->field, ...array_values($this->args));
101
    }
102
103
    /**
104
     * Set a custom message.
105
     *
106
     * @param string $message
107
     *
108
     * @return self
109
     */
110 3
    public function setMessage(string $message): self
111
    {
112 3
        $this->message = $message;
113
114 3
        return $this;
115
    }
116
117
    /**
118
     * Returns the field this spec applies to.
119
     *
120
     * @return string
121
     */
122 54
    public function getField(): string
123
    {
124 54
        return $this->field;
125
    }
126
127
    /**
128
     * Returns the failure message for this rule specification.
129
     *
130
     * @return string
131
     */
132 27
    public function getMessage(): string
133
    {
134 27
        if (!$this->message) {
135 24
            $this->message = $this->getDefaultMessage();
136
        }
137
138 27
        return $this->message;
139
    }
140
141
    /**
142
     * Returns the args this spec is configured to use.
143
     *
144
     * @return array
145
     */
146 24
    public function getArgs(): array
147
    {
148 24
        return $this->args;
149
    }
150
151
    /**
152
     * Returns the name of the rule that was ran.
153
     *
154
     * @return string
155
     */
156 24
    public function getRuleClass(): string
157
    {
158 24
        return $this->ruleClass;
159
    }
160
161
    /**
162
     * Sets the white list of values that should be considered blank.
163
     *
164
     * @param array $blankWhiteList
165
     *
166
     * @return ValidateSpec
167
     */
168 12
    public function setBlankValues(array $blankWhiteList): self
169
    {
170 12
        $this->blankWhiteList = $blankWhiteList;
171
172 12
        return $this;
173
    }
174
175
    /**
176
     * Sets the rule to halt the entire validation process on the subject.
177
     *
178
     * @return AbstractSpec
179
     */
180 3
    public function asHaltingRule(): self
181
    {
182 3
        $this->failureMode = self::HALTING_FAILURE;
0 ignored issues
show
Bug introduced by
The property failureMode does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
183
184 3
        return $this;
185
    }
186
187
    /**
188
     * Sets the rule to stop further rules from applying to the same field.
189
     *
190
     * @return AbstractSpec
191
     */
192 3
    public function asHardRule(): self
193
    {
194 3
        $this->failureMode = self::HARD_FAILURE;
195
196 3
        return $this;
197
    }
198
199
    /**
200
     * Sets the rule to allow other rules to operate on the same field.
201
     *
202
     * @return AbstractSpec
203
     */
204 3
    public function asSoftRule(): self
205
    {
206 3
        $this->failureMode = self::SOFT_FAILURE;
207
208 3
        return $this;
209
    }
210
211
    /**
212
     * Returns the current failure mode.
213
     *
214
     * @return string
215
     */
216 24
    public function getFailureMode(): string
217
    {
218 24
        return $this->failureMode;
219
    }
220
221
    /**
222
     * Determines if the field is a `valid` blank value.
223
     *
224
     * Values are considered blank if they are, not sent, null, or strings that trim down to nothing. integers, floats,
225
     * arrays, resources, objects, etc., are never considered blank. Even a value of `(int) 0` will *not* evaluate as
226
     * blank.
227
     * The optional second argument is used to supply an array of white listed items that should be considered blank.
228
     *
229
     * @param mixed $subject
230
     * @param array $blankWhiteList
0 ignored issues
show
Bug introduced by
There is no parameter named $blankWhiteList. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
231
     *
232
     * @return bool
233
     */
234 81
    public function subjectFieldIsBlank($subject): bool
235
    {
236 81
        foreach ($this->blankWhiteList as $item) {
237 9
            if ($subject->{$this->field} === $item) {
238 9
                return true;
239
            }
240
        }
241
242
        // not set, or null, means it is blank
243 72
        if (!isset($subject->{$this->field}) || $subject->{$this->field} === null) {
244 33
            return true;
245
        }
246
247
        // non-strings are not blank: int, float, object, array, resource, etc
248 39
        if (!is_string($subject->{$this->field})) {
249 18
            return false;
250
        }
251
252
        // strings that trim down to exactly nothing are blank
253 21
        return trim($subject->{$this->field}) === '';
254
    }
255
256
    /**
257
     * Returns the default failure message for this rule specification.
258
     *
259
     * @return string
260
     */
261 24
    protected function getDefaultMessage(): string
262
    {
263 24
        return $this->ruleClass . $this->argsTostring();
264
    }
265
266
    /**
267
     * Converts the args to a string.
268
     *
269
     * @return string
270
     */
271 24
    protected function argsTostring(): string
272
    {
273 24
        if (!$this->args) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->args of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
274 21
            return '()';
275
        }
276
277 3
        return '(' . implode(', ', $this->args) . ')';
278
    }
279
}
280