Passed
Pull Request — master (#97)
by Sergei
01:55
created

Rule::withFormatter()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 3
c 0
b 0
f 0
nc 1
nop 1
dl 0
loc 5
ccs 4
cts 4
cp 1
crap 1
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Validator;
6
7
/**
8
 * Rule represents a single value validation rule.
9
 */
10
abstract class Rule implements RuleInterface, ParametrizedRuleInterface, FormattableRuleInterface
11
{
12
    private ?FormatterInterface $formatter = null;
13
    private bool $skipOnEmpty = false;
14
    private bool $skipOnError = true;
15
16
    /**
17
     * @var callable|null
18
     */
19
    private $when = null;
20
21
    /**
22
     * Validates the value
23
     *
24
     * @param mixed $value value to be validated
25
     * @param DataSetInterface|null $dataSet optional data set that could be used for contextual validation
26
     * @param bool $previousRulesErrored set to true if rule is part of a group of rules and one of the previous validations failed
27
     *
28
     * @return Result
29
     */
30 134
    final public function validate($value, DataSetInterface $dataSet = null, bool $previousRulesErrored = false): Result
31
    {
32 134
        if ($this->skipOnEmpty && $this->isEmpty($value)) {
33
            return new Result();
34
        }
35
36
        if (
37 134
          ($this->skipOnError && $previousRulesErrored) ||
38 134
          (is_callable($this->when) && !($this->when)($value, $dataSet))
39
        ) {
40 6
            return new Result();
41
        }
42
43 134
        return $this->validateValue($value, $dataSet);
44
    }
45
46
    /**
47
     * Validates the value. The method should be implemented by concrete validation rules.
48
     *
49
     * @param mixed $value value to be validated
50
     * @param DataSetInterface|null $dataSet optional data set that could be used for contextual validation
51
     *
52
     * @return Result
53
     */
54
    abstract protected function validateValue($value, DataSetInterface $dataSet = null): Result;
55
56 1
    public function withFormatter(?FormatterInterface $formatter): self
57
    {
58 1
        $new = clone $this;
59 1
        $new->formatter = $formatter;
60 1
        return $new;
61
    }
62
63 165
    protected function formatMessage(string $message, array $parameters = []): string
64
    {
65 165
        if ($this->formatter === null) {
66 165
            $this->formatter = new Formatter();
67
        }
68
69 165
        return $this->formatter->format(
0 ignored issues
show
Bug introduced by
The method format() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

69
        return $this->formatter->/** @scrutinizer ignore-call */ format(

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
70 165
            $message,
71
            $parameters
72
        );
73
    }
74
75
    /**
76
     * Add a PHP callable whose return value determines whether this rule should be applied.
77
     * By default rule will be always applied.
78
     *
79
     * The signature of the callable should be `function ($value, DataSetInterface $dataSet): bool`, where $value and $dataSet
80
     * refer to the value validated and the data set in which context it is validated. The callable should return
81
     * a boolean value.
82
     *
83
     * The following example will enable the validator only when the country currently selected is USA:
84
     *
85
     * ```php
86
     * function ($value, DataSetInterface $dataSet) {
87
         return $dataSet->getAttributeValue('country') === Country::USA;
88
     }
89
     * ```
90
     *
91
     * @param callable $callback
92
     *
93
     * @return $this
94
     */
95 1
    public function when(callable $callback): self
96
    {
97 1
        $new = clone $this;
98 1
        $new->when = $callback;
99 1
        return $new;
100
    }
101
102 3
    public function skipOnError(bool $value): self
103
    {
104 3
        $new = clone $this;
105 3
        $new->skipOnError = $value;
106 3
        return $new;
107
    }
108
109
    /**
110
     * @param bool $value if validation should be skipped if value validated is empty
111
     *
112
     * @return self
113
     */
114 1
    public function skipOnEmpty(bool $value): self
115
    {
116 1
        $new = clone $this;
117 1
        $new->skipOnEmpty = $value;
118 1
        return $new;
119
    }
120
121
    /**
122
     * Checks if the given value is empty.
123
     * A value is considered empty if it is null, an empty array, or an empty string.
124
     * Note that this method is different from PHP empty(). It will return false when the value is 0.
125
     *
126
     * @param mixed $value the value to be checked
127
     *
128
     * @return bool whether the value is empty
129
     */
130 10
    protected function isEmpty($value): bool
131
    {
132 10
        return $value === null || $value === [] || $value === '';
133
    }
134
135
    /**
136
     * Get name of the rule to be used when rule is converted to array.
137
     * By default it returns base name of the class, first letter in lowercase.
138
     *
139
     * @return string
140
     */
141 19
    public function getName(): string
142
    {
143 19
        $className = static::class;
144 19
        return lcfirst(substr($className, strrpos($className, '\\') + 1));
145
    }
146
147
    /**
148
     * Returns rule options as array.
149
     *
150
     * @return array
151
     */
152 56
    public function getOptions(): array
153
    {
154
        return [
155 56
            'skipOnEmpty' => $this->skipOnEmpty,
156 56
            'skipOnError' => $this->skipOnError,
157
        ];
158
    }
159
}
160