Passed
Pull Request — master (#102)
by Sergei
02:09 queued 15s
created

Rules   A

Complexity

Total Complexity 20

Size/Duplication

Total Lines 93
Duplicated Lines 0 %

Test Coverage

Coverage 88.89%

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 38
c 2
b 0
f 0
dl 0
loc 93
ccs 40
cts 45
cp 0.8889
rs 10
wmc 20

7 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 2
A add() 0 7 3
A addFormatterToRules() 0 5 3
A asArray() 0 9 3
A withFormatter() 0 6 1
A normalizeRule() 0 15 3
A validate() 0 17 5
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Validator;
6
7
use InvalidArgumentException;
8
use Yiisoft\Validator\Rule\Callback;
9
use function is_callable;
10
11
/**
12
 * Rules represents multiple rules for a single value
13
 */
14
final class Rules
15
{
16
    private ?FormatterInterface $formatter = null;
17
18
    /**
19
     * @var RuleInterface[]
20
     */
21
    private array $rules = [];
22
23 16
    public function __construct(iterable $rules = [])
24
    {
25 16
        foreach ($rules as $rule) {
26 15
            $this->add($rule);
27
        }
28 16
    }
29
30
    /**
31
     * @param callable|RuleInterface $rule
32
     */
33 16
    public function add($rule): void
34
    {
35 16
        $rule = $this->normalizeRule($rule);
36 16
        if ($this->formatter !== null && $rule instanceof FormattableRuleInterface) {
37
            $rule = $rule->withFormatter($this->formatter);
38
        }
39 16
        $this->rules[] = $rule;
40 16
    }
41
42 10
    public function validate($value, ValidationContext $context = null): Result
43
    {
44 10
        $context = $context ?? new ValidationContext();
45
46 10
        $compoundResult = new Result();
47 10
        foreach ($this->rules as $rule) {
48 10
            $ruleResult = $rule->validate($value, $context);
49 10
            if ($ruleResult->isValid() === false) {
50 10
                if (!$context->isPreviousRulesErrored()) {
51 10
                    $context = $context->withPreviousRulesErrored(true);
52
                }
53 10
                foreach ($ruleResult->getErrors() as $message) {
54 10
                    $compoundResult->addError($message);
55
                }
56
            }
57
        }
58 10
        return $compoundResult;
59
    }
60
61 16
    private function normalizeRule($rule): RuleInterface
62
    {
63 16
        if (is_callable($rule)) {
64 2
            $rule = new Callback($rule);
65
        }
66
67 16
        if (!$rule instanceof RuleInterface) {
68
            throw new InvalidArgumentException(sprintf(
69
                'Rule should be either an instance of %s or a callable, %s given.',
70
                RuleInterface::class,
71
                gettype($rule)
72
            ));
73
        }
74
75 16
        return $rule;
76
    }
77
78 1
    public function withFormatter(?FormatterInterface $formatter): self
79
    {
80 1
        $new = clone $this;
81 1
        $new->formatter = $formatter;
82 1
        $new->addFormatterToRules($formatter);
83 1
        return $new;
84
    }
85
86
    /**
87
     * Return rules as array.
88
     *
89
     * @return array
90
     */
91 5
    public function asArray(): array
92
    {
93 5
        $arrayOfRules = [];
94 5
        foreach ($this->rules as $rule) {
95 5
            if ($rule instanceof ParametrizedRuleInterface) {
96 5
                $arrayOfRules[] = array_merge([$rule->getName()], $rule->getOptions());
97
            }
98
        }
99 5
        return $arrayOfRules;
100
    }
101
102 1
    private function addFormatterToRules(?FormatterInterface $formatter): void
103
    {
104 1
        foreach ($this->rules as &$rule) {
105 1
            if ($rule instanceof FormattableRuleInterface) {
106 1
                $rule = $rule->withFormatter($formatter);
107
            }
108
        }
109 1
    }
110
}
111