Completed
Push — master ( e311cb...18f318 )
by Jared
11:52
created

Errors::clearTranslator()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
1
<?php
2
3
/**
4
 * @author Jared King <[email protected]>
5
 *
6
 * @see http://jaredtking.com
7
 *
8
 * @copyright 2015 Jared King
9
 * @license MIT
10
 */
11
12
namespace Pulsar;
13
14
use ArrayAccess;
15
use ArrayIterator;
16
use Countable;
17
use IteratorAggregate;
18
use Pulsar\Interfaces\TranslatorInterface;
19
20
/**
21
 * Holds error messages generated by models, like validation errors.
22
 */
23
final class Errors implements IteratorAggregate, Countable, ArrayAccess
24
{
25
    /**
26
     * @var TranslatorInterface|null
27
     */
28
    private static $translator;
29
30
    /**
31
     * @var Error[]
32
     */
33
    private $stack = [];
34
35
    /**
36
     * Sets the global translator instance.
37
     */
38
    public static function setTranslator(TranslatorInterface $translator)
39
    {
40
        self::$translator = $translator;
41
    }
42
43
    /**
44
     * Clears the global translator instance.
45
     */
46
    public static function clearTranslator(): void
47
    {
48
        self::$translator = null;
49
    }
50
51
    /**
52
     * Gets the translator.
53
     */
54
    public function getTranslator(): TranslatorInterface
55
    {
56
        if (!self::$translator) {
57
            self::$translator = new Translator();
58
        }
59
60
        return self::$translator;
61
    }
62
63
    /**
64
     * Adds an error message to the stack.
65
     *
66
     * @param $error
67
     *
68
     * @return $this
69
     */
70
    public function add(string $error, array $context = [])
71
    {
72
        $message = $this->parse($error, $context);
73
        $this->stack[] = new Error($error, $context, $message);
74
75
        return $this;
76
    }
77
78
    /**
79
     * Gets all of the error messages on the stack.
80
     *
81
     * @return string[]
82
     */
83
    public function all(): array
84
    {
85
        $messages = [];
86
        foreach ($this->stack as $error) {
87
            $messages[] = $error->getMessage();
88
        }
89
90
        return $messages;
91
    }
92
93
    /**
94
     * Gets an error for a specific parameter on the stack.
95
     *
96
     * @param string $value value we are searching for
97
     * @param string $param parameter name
98
     */
99
    public function find($value, $param = 'field'): ?Error
100
    {
101
        foreach ($this->stack as $error) {
102
            $stackValue = $error->getContext()[$param] ?? null;
103
            if ($stackValue === $value) {
104
                return $error;
105
            }
106
        }
107
108
        return null;
109
    }
110
111
    /**
112
     * Checks if an error exists with a specific parameter on the stack.
113
     *
114
     * @param string $value value we are searching for
115
     * @param string $param parameter name
116
     */
117
    public function has($value, $param = 'field'): bool
118
    {
119
        foreach ($this->stack as $error) {
120
            $stackValue = $error->getContext()[$param] ?? null;
121
            if ($stackValue !== $value) {
122
                continue;
123
            }
124
125
            return true;
126
        }
127
128
        return false;
129
    }
130
131
    /**
132
     * Clears the error stack.
133
     *
134
     * @return $this
135
     */
136
    public function clear()
137
    {
138
        $this->stack = [];
139
140
        return $this;
141
    }
142
143
    public function __toString()
144
    {
145
        return implode("\n", $this->all());
146
    }
147
148
    //////////////////////////
149
    // Helpers
150
    //////////////////////////
151
152
    /**
153
     * Formats an incoming error message.
154
     *
155
     * @param array|string $input
156
     */
157
    private function sanitize($input): Error
158
    {
159
        $error = is_array($input) ? $input['error'] : $input;
160
        $context = $input['context'] ?? [];
161
        $message = $this->parse($error, $context);
162
163
        return new Error($error, $context, $message);
164
    }
165
166
    /**
167
     * Parses an error message before displaying it.
168
     */
169
    private function parse(string $error, array $context): string
170
    {
171
        return $this->getTranslator()->translate($error, $context, null);
172
    }
173
174
    //////////////////////////
175
    // IteratorAggregate Interface
176
    //////////////////////////
177
178
    public function getIterator()
179
    {
180
        return new ArrayIterator($this->stack);
181
    }
182
183
    //////////////////////////
184
    // Countable Interface
185
    //////////////////////////
186
187
    /**
188
     * Get total number of models matching query.
189
     *
190
     * @return int
191
     */
192
    public function count()
193
    {
194
        return count($this->stack);
195
    }
196
197
    /////////////////////////////
198
    // ArrayAccess Interface
199
    /////////////////////////////
200
201
    public function offsetExists($offset)
202
    {
203
        return isset($this->stack[$offset]);
204
    }
205
206
    public function offsetGet($offset)
207
    {
208
        if (!$this->offsetExists($offset)) {
209
            throw new \OutOfBoundsException("$offset does not exist on this error stack");
210
        }
211
212
        return $this->stack[$offset];
213
    }
214
215
    public function offsetSet($offset, $error)
216
    {
217
        if (!is_numeric($offset)) {
218
            throw new \Exception('Can only perform set on numeric indices');
219
        }
220
221
        $this->stack[$offset] = $this->sanitize($error);
222
    }
223
224
    public function offsetUnset($offset)
225
    {
226
        unset($this->stack[$offset]);
227
    }
228
}
229