Completed
Pull Request — master (#175)
by Alexander
02:53 queued 02:53
created

Rule   A

Complexity

Total Complexity 15

Size/Duplication

Total Lines 116
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 6
Bugs 0 Features 0
Metric Value
eloc 16
c 6
b 0
f 0
dl 0
loc 116
ccs 21
cts 21
cp 1
rs 10
wmc 15

6 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 36 1
A formatMessage() 0 7 2
A getOptions() 0 5 1
A isEmpty() 0 3 3
B validate() 0 15 7
A getName() 0 4 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Validator;
6
7
use function is_callable;
8
9
/**
10
 * Rule represents a single value validation rule.
11
 */
12
abstract class Rule implements ParametrizedRuleInterface
13
{
14 185
    public function __construct(
15
        private ?FormatterInterface $formatter = null,
16
        /**
17
         * @var bool if validation should be skipped if value validated is empty
18
         */
19
        private bool $skipOnEmpty = false,
20
        private bool $skipOnError = false,
21
        /**
22
         * @var callable|null
23
         *
24
         * Add a PHP callable whose return value determines whether this rule should be applied.
25
         * By default, rule will always be applied.
26
         *
27
         * The signature of the callable should be `function ($value, ValidationContext $context): bool`,
28
         * where `$value` and `$context` refer to the value validated and the validation context.
29
         * The callable should return a boolean value.
30
         *
31
         * The following example will enable the validator only when the country currently selected is USA:
32
         *
33
         * ```php
34
         * function ($value, ValidationContext $context)) {
35
         *     if ($context === null) {
36
         *         return false;
37
         *     }
38
         *
39
         *     $dataSet = $context->getDataSet();
40
         *     if ($dataSet === null) {
41
         *         return false;
42
         *     }
43
         *
44
         *     return $dataSet->getAttributeValue('country') === Country::USA;
45
         * }
46
         * ```
47
         */
48
        private $when = null,
49
    ) {
50
    }
51
52
    /**
53
     * Validates the value
54
     *
55
     * @param mixed $value Value to be validated.
56
     * @param ValidationContext|null $context Optional validation context.
57
     *
58
     * @return Result
59
     */
60 171
    final public function validate($value, ?ValidationContext $context = null): Result
61
    {
62 171
        if ($this->skipOnEmpty && $this->isEmpty($value)) {
63 1
            return new Result();
64
        }
65
66 171
        if ($this->skipOnError && $context?->getParameter(RuleSet::PARAMETER_PREVIOUS_RULES_ERRORED) === true) {
67 1
            return new Result();
68
        }
69
70 171
        if (is_callable($this->when) && !($this->when)($value, $context)) {
71 1
            return new Result();
72
        }
73
74 171
        return $this->validateValue($value, $context);
75
    }
76
77
    /**
78
     * Validates the value. The method should be implemented by concrete validation rules.
79
     *
80
     * @param mixed $value Value to be validated.
81
     * @param ValidationContext|null $context Optional validation context.
82
     *
83
     * @return Result
84
     */
85
    abstract protected function validateValue($value, ?ValidationContext $context = null): Result;
86
87 185
    protected function formatMessage(string $message, array $parameters = []): string
88
    {
89 185
        if ($this->formatter === null) {
90 185
            $this->formatter = new Formatter();
91
        }
92
93 185
        return $this->formatter->format($message, $parameters);
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

93
        return $this->formatter->/** @scrutinizer ignore-call */ format($message, $parameters);

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...
94
    }
95
96
    /**
97
     * Checks if the given value is empty.
98
     * A value is considered empty if it is null, an empty array, or an empty string.
99
     * Note that this method is different from PHP empty(). It will return false when the value is 0.
100
     *
101
     * @param mixed $value the value to be checked
102
     *
103
     * @return bool whether the value is empty
104
     */
105 18
    protected function isEmpty($value): bool
106
    {
107 18
        return $value === null || $value === [] || $value === '';
108
    }
109
110
    /**
111
     * Get name of the rule to be used when rule is converted to array.
112
     * By default, it returns base name of the class, first letter in lowercase.
113
     */
114 21
    public function getName(): string
115
    {
116 21
        $className = static::class;
117 21
        return lcfirst(substr($className, strrpos($className, '\\') + 1));
118
    }
119
120
    /**
121
     * Returns rule options as array.
122
     */
123 54
    public function getOptions(): array
124
    {
125
        return [
126 54
            'skipOnEmpty' => $this->skipOnEmpty,
127 54
            'skipOnError' => $this->skipOnError,
128
        ];
129
    }
130
}
131