Issues (6)

src/Validator.php (3 issues)

1
<?php
2
3
declare(strict_types=1);
4
5
namespace jin2chen\YiiValidator;
6
7
use Closure;
8
use Yiisoft\Validator\DataSet\ArrayDataSet;
9
use Yiisoft\Validator\DataSet\ScalarDataSet;
10
use Yiisoft\Validator\DataSetInterface;
11
use Yiisoft\Validator\FormatterInterface;
12
use Yiisoft\Validator\PostValidationHookInterface;
13
use Yiisoft\Validator\ResultSet;
14
use Yiisoft\Validator\RuleInterface;
15
use Yiisoft\Validator\Rules;
16
use Yiisoft\Validator\RulesProviderInterface;
17
use Yiisoft\Validator\ValidationContext;
18
use Yiisoft\Validator\ValidatorInterface;
19
20
use function is_array;
21
use function is_object;
22
23
/**
24
 * Validator validates {@link DataSetInterface} against rules set for data set attributes.
25
 *
26
 * @psalm-type AggregateRule = iterable<string, iterable<array-key, RuleInterface|callable>>
27
 */
28
final class Validator implements ValidatorInterface
29
{
30
    private bool $isSubValidator = false;
31
    private ?FormatterInterface $formatter;
32
33 2
    public function __construct(?FormatterInterface $formatter = null)
34
    {
35 2
        $this->formatter = $formatter;
36 2
    }
37
38
    /**
39
     * @inheritdoc
40
     */
41 2
    public function validate($data, $rules = []): ResultSet
42
    {
43 2
        $data = $this->normalizeDataSet($data);
44
45 2
        if ($data instanceof RulesProviderInterface) {
46 1
            $rules = $data->getRules();
47
        }
48
49 2
        $context = new ValidationContext($data);
50 2
        $results = new ResultSet();
51
52 2
        foreach ($rules as $attribute => $attributeRules) {
53 2
            $ruleSet = new Rules($this->addValidatorForNestRule($attributeRules));
54 2
            if ($this->formatter !== null) {
55 1
                $ruleSet = $ruleSet->withFormatter($this->formatter);
56
            }
57 2
            $results->addResult(
58 2
                $attribute,
59 2
                $ruleSet->validate(
60 2
                    $data->getAttributeValue($attribute),
61 2
                    $context->withAttribute($attribute)
62
                )
63
            );
64
65 2
            $this->addNestRuleErrors($ruleSet, $results);
66
        }
67
68 2
        if (!$this->isSubValidator && $data instanceof PostValidationHookInterface) {
69 1
            $data->processValidationResult($results);
70
        }
71
72 2
        return $results;
73
    }
74
75
    /**
76
     * @param iterable<array-key, RuleInterface|callable> $rules
77
     * @return list<RuleInterface|callable>
0 ignored issues
show
The type jin2chen\YiiValidator\list was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
78
     */
79 2
    private function addValidatorForNestRule(iterable $rules): array
80
    {
81 2
        $results = [];
82 2
        foreach ($rules as $rule) {
83 2
            if ($rule instanceof NestRuleInterface) {
84 2
                $results[] = $rule->setValidator($this->withSubValidator());
85
            } else {
86 2
                $results[] = $rule;
87
            }
88
        }
89
90 2
        return $results;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $results returns the type array|jin2chen\YiiValidator\NestRuleInterface[] which is incompatible with the documented return type jin2chen\YiiValidator\list.
Loading history...
91
    }
92
93
    /**
94
     * @psalm-suppress InaccessibleProperty
95
     * @param Rules $ruleSet
96
     * @param ResultSet $resultSet
97
     */
98 2
    private function addNestRuleErrors(Rules $ruleSet, ResultSet $resultSet): void
99
    {
100
        /** @psalm-var callable(): RuleInterface[] $getRules */
101 2
        $getRules = Closure::bind(function () {
102
            /** @var Rules $this */
103 2
            return $this->rules;
0 ignored issues
show
The property rules is declared private in Yiisoft\Validator\Rules and cannot be accessed from this context.
Loading history...
104 2
        }, $ruleSet, Rules::class);
105 2
        $rules = $getRules();
106
107 2
        foreach ($rules as $rule) {
108 2
            if (!$rule instanceof NestRuleInterface) {
109 2
                continue;
110
            }
111
112 2
            foreach ($rule->getResultSet() as $attribute => $result) {
113 2
                $resultSet->addResult($attribute, $result);
114
            }
115
        }
116 2
    }
117
118 1
    public function withFormatter(?FormatterInterface $formatter): self
119
    {
120 1
        $new = clone $this;
121 1
        $new->formatter = $formatter;
122 1
        return $new;
123
    }
124
125 2
    private function withSubValidator(): self
126
    {
127 2
        $new = clone $this;
128 2
        $new->isSubValidator = true;
129 2
        return $new;
130
    }
131
132
    /**
133
     * @param mixed $data
134
     * @return DataSetInterface
135
     */
136 2
    private function normalizeDataSet($data): DataSetInterface
137
    {
138 2
        if ($data instanceof DataSetInterface) {
139 1
            return $data;
140
        }
141
142 1
        if (is_object($data) || is_array($data)) {
143 1
            return new ArrayDataSet((array)$data);
144
        }
145
146
        return new ScalarDataSet($data);
147
    }
148
}
149