Completed
Push — master ( a97ce7...6f972b )
by Jan
03:17
created

Errors::raw()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 3
rs 10
1
<?php
2
3
namespace Kontrolio\Error;
4
5
use Countable;
6
use Kontrolio\Data\Attribute;
7
use Kontrolio\Rules\RuleInterface;
8
9
final class Errors implements Countable
10
{
11
    private $messages;
12
    private $errors = [];
13
14
    public function __construct(array $messages)
15
    {
16
        $this->messages = $messages;
17
    }
18
19
    public function raw()
20
    {
21
        return $this->errors;
22
    }
23
24
    public function flatten()
25
    {
26
        $list = [];
27
28
        foreach ($this->errors as $messages) {
29
            foreach ($messages as $message) {
30
                $list[] = $message;
31
            }
32
        }
33
34
        return $list;
35
    }
36
37
    /**
38
     * @param Attribute|string $attribute
39
     *
40
     * @return bool
41
     */
42
    public function has($attribute)
43
    {
44
        $attribute = $attribute instanceof Attribute ? $attribute->getName() : $attribute;
45
46
        return array_key_exists($attribute, $this->errors);
47
    }
48
49
    public function count()
50
    {
51
        return count($this->errors);
52
    }
53
54
    public function isEmpty()
55
    {
56
        return $this->count() === 0;
57
    }
58
59
    public function add(Attribute $attribute, RuleInterface $rule)
60
    {
61
        $name = $attribute->getName();
62
        $errors = $this->prepareErrors($name, $this->prepareRuleKey($name, $rule), $rule);
63
64
        if ($this->has($name)) {
65
            $this->errors[$name] = array_merge($this->errors[$name], $errors);
66
        } else {
67
            $this->errors[$name] = $errors;
68
        }
69
    }
70
71
    /**
72
     * Prepares rule key for the validation error messages array.
73
     *
74
     * @param string $attribute
75
     * @param RuleInterface $rule
76
     *
77
     * @return string
78
     */
79
    private function prepareRuleKey($attribute, RuleInterface $rule)
80
    {
81
        $name = $rule->getName();
82
83
        if ($name) {
84
            return $name;
85
        }
86
87
        if ($this->has($attribute)) {
88
            return $this->count();
89
        }
90
91
        return 0;
92
    }
93
94
    /**
95
     * Prepares validation error messages to proper format.
96
     *
97
     * @param string $attribute
98
     * @param string $ruleName
99
     * @param RuleInterface $rule
100
     *
101
     * @return array
102
     */
103
    private function prepareErrors($attribute, $ruleName, RuleInterface $rule)
104
    {
105
        $messages = $this->getMessagesByAttributeAndRuleName($attribute, $ruleName);
106
        $violations = $rule->getViolations();
107
108
        if (!count($violations)) {
109
            return [reset($messages)];
110
        }
111
112
        return $this->getMessagesForViolations($messages, $violations, $attribute . '.' . $ruleName);
113
    }
114
115
    /**
116
     * Filter all given messages by the attribute and the rule name.
117
     *
118
     * @param string $attribute
119
     * @param string $ruleName
120
     *
121
     * @return array
122
     */
123
    private function getMessagesByAttributeAndRuleName($attribute, $ruleName)
124
    {
125
        $prefix = $attribute . '.' . $ruleName;
126
127
        $messages = array_filter($this->messages, static function ($key) use ($attribute, $prefix) {
128
            return $key === $attribute || strpos($key, $prefix) === 0;
129
        }, ARRAY_FILTER_USE_KEY);
130
131
        if (empty($messages)) {
132
            $messages = [$prefix];
133
        }
134
135
        return $messages;
136
    }
137
138
    /**
139
     * Returns messages for all validation rule violations.
140
     *
141
     * @param array $messages
142
     * @param array $violations
143
     * @param string $prefix
144
     *
145
     * @return array
146
     */
147
    private function getMessagesForViolations(array $messages, array $violations, $prefix)
148
    {
149
        $result = [];
150
151
        foreach ($violations as $violation) {
152
            $keys = [
153
                $prefix,
154
                $prefix . '.' . $violation
155
            ];
156
157
            foreach ($keys as $key) {
158
                if (array_key_exists($key, $messages)) {
159
                    $result[] = $messages[$key];
160
                }
161
            }
162
        }
163
164
        return $result;
165
    }
166
}
167