Passed
Pull Request — master (#102)
by Sergei
01:57
created

Rules::withFormatter()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 4
c 0
b 0
f 0
nc 1
nop 1
dl 0
loc 6
ccs 5
cts 5
cp 1
crap 1
rs 10
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
    public const PARAM_RREVIOUS_RULES_ERRORED = 'previousRulesErrored';
17
18
    private ?FormatterInterface $formatter = null;
19
20
    /**
21
     * @var RuleInterface[]
22
     */
23
    private array $rules = [];
24
25 16
    public function __construct(iterable $rules = [])
26
    {
27 16
        foreach ($rules as $rule) {
28 15
            $this->add($rule);
29
        }
30 16
    }
31
32
    /**
33
     * @param callable|RuleInterface $rule
34
     */
35 16
    public function add($rule): void
36
    {
37 16
        $rule = $this->normalizeRule($rule);
38 16
        if ($this->formatter !== null && $rule instanceof FormattableRuleInterface) {
39
            $rule = $rule->withFormatter($this->formatter);
40
        }
41 16
        $this->rules[] = $rule;
42 16
    }
43
44 10
    public function validate($value, ValidationContext $context = null): Result
45
    {
46 10
        $context = $context ?? new ValidationContext();
47
48 10
        $compoundResult = new Result();
49 10
        foreach ($this->rules as $rule) {
50 10
            $ruleResult = $rule->validate($value, $context);
51 10
            if ($ruleResult->isValid() === false) {
52 10
                $context->setParam(self::PARAM_RREVIOUS_RULES_ERRORED, true);
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