Completed
Push — master ( d00506...f4b834 )
by Jared
02:33
created

Errors::push()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 6
rs 9.4286
cc 1
eloc 3
nc 1
nop 1
1
<?php
2
3
/**
4
 * @author Jared King <[email protected]>
5
 *
6
 * @link http://jaredtking.com
7
 *
8
 * @copyright 2015 Jared King
9
 * @license MIT
10
 */
11
namespace Pulsar;
12
13
use Pimple\Container;
14
15
class Errors implements \Iterator, \Countable, \ArrayAccess
16
{
17
    /**
18
     * @var array
19
     */
20
    private $stack;
21
22
    /**
23
     * @var string
24
     */
25
    private $context;
26
27
    /**
28
     * @var \Pimple\Container
29
     */
30
    private $app;
31
32
    /**
33
     * @var int
34
     */
35
    private $pointer;
36
37
    public function __construct(Container $app)
38
    {
39
        $this->stack = [];
40
        $this->context = '';
41
        $this->app = $app;
42
        $this->pointer = 0;
43
    }
44
45
    /**
46
     * Adds an error message to the stack.
47
     *
48
     * @param array|string $error
49
     *                            - error: error code
50
     *                            - params: array of parameters to be passed to message
51
     *                            - context: (optional) the context which the error message occured in
52
     *                            - class: (optional) the class invoking the error
53
     *                            - function: (optional) the function invoking the error
54
     *
55
     * @return self
56
     */
57
    public function push($error)
58
    {
59
        $this->stack[] = $this->sanitize($error);
60
61
        return $this;
62
    }
63
64
    /**
65
     * Sets the current default error context.
66
     *
67
     * @param string $context
68
     *
69
     * @return self
70
     */
71
    public function setCurrentContext($context = '')
72
    {
73
        $this->context = $context;
74
75
        return $this;
76
    }
77
78
    /**
79
     * Clears the current default error context.
80
     *
81
     * @return self
82
     */
83
    public function clearCurrentContext()
84
    {
85
        $this->context = '';
86
87
        return $this;
88
    }
89
90
    /**
91
     * Gets all of the errors on the stack and also attempts
92
     * translation using the Locale class.
93
     *
94
     * @param string $context optional context
95
     * @param string $locale  optional locale
96
     *
97
     * @return array errors
98
     */
99
    public function errors($context = '', $locale = '')
100
    {
101
        $errors = [];
102
        foreach ($this->stack as $error) {
103
            if (!$context || $error['context'] == $context) {
104
                $errors[] = $this->parse($error, $locale);
105
            }
106
        }
107
108
        return $errors;
109
    }
110
111
    /**
112
     * Gets the messages of errors on the stack.
113
     *
114
     * @param string $context optional context
115
     * @param string $locale  optional locale
116
     *
117
     * @return array errors
118
     */
119
    public function messages($context = '', $locale = '')
120
    {
121
        $messages = [];
122
        foreach ($this->errors($context, $locale) as $error) {
123
            $messages[] = $error['message'];
124
        }
125
126
        return $messages;
127
    }
128
129
    /**
130
     * Gets an error for a specific parameter on the stack.
131
     *
132
     * @param string $value value we are searching for
133
     * @param string $param parameter name
134
     *
135
     * @return array|bool
136
     */
137
    public function find($value, $param = 'field')
138
    {
139
        foreach ($this->errors() as $error) {
140
            if (array_value($error['params'], $param) === $value) {
141
                return $error;
142
            }
143
        }
144
145
        return false;
146
    }
147
148
    /**
149
     * Checks if an error exists with a specific parameter on the stack.
150
     *
151
     * @param string $value value we are searching for
152
     * @param string $param parameter name
153
     *
154
     * @return bool
155
     */
156
    public function has($value, $param = 'field')
157
    {
158
        return $this->find($value, $param) !== false;
159
    }
160
161
    /**
162
     * Clears the error stack.
163
     *
164
     * @return self
165
     */
166
    public function clear()
167
    {
168
        $this->stack = [];
169
170
        return $this;
171
    }
172
173
    /**
174
     * Formats an incoming error message.
175
     *
176
     * @param array|string $error
177
     *
178
     * @return array
179
     */
180
    private function sanitize($error)
181
    {
182
        if (!is_array($error)) {
183
            $error = ['error' => $error];
184
        }
185
186
        if (!isset($error['context'])) {
187
            $error['context'] = $this->context;
188
        }
189
190
        if (!isset($error['params'])) {
191
            $error['params'] = [];
192
        }
193
194
        return $error;
195
    }
196
197
    /**
198
     * Parses an error message before displaying it.
199
     *
200
     * @param array  $error
201
     * @param string $locale
202
     *
203
     * @return array
204
     */
205
    private function parse(array $error, $locale = '')
206
    {
207
        // attempt to translate error into a message
208
        if (!isset($error['message'])) {
209
            $error['message'] = $this->app['locale']->t($error['error'], $error['params'], $locale);
210
        }
211
212
        return $error;
213
    }
214
215
    //////////////////////////
216
    // Iterator Interface
217
    //////////////////////////
218
219
    /**
220
     * Rewind the Iterator to the first element.
221
     */
222
    public function rewind()
223
    {
224
        $this->pointer = 0;
225
    }
226
227
    /**
228
     * Returns the current element.
229
     *
230
     * @return array|null
231
     */
232
    public function current()
233
    {
234
        if ($this->pointer >= $this->count()) {
235
            return;
236
        }
237
238
        $errors = $this->errors();
239
240
        return $errors[$this->pointer];
241
    }
242
243
    /**
244
     * Return the key of the current element.
245
     *
246
     * @return int
247
     */
248
    public function key()
249
    {
250
        return $this->pointer;
251
    }
252
253
    /**
254
     * Move forward to the next element.
255
     */
256
    public function next()
257
    {
258
        ++$this->pointer;
259
    }
260
261
    /**
262
     * Checks if current position is valid.
263
     *
264
     * @return bool
265
     */
266
    public function valid()
267
    {
268
        return $this->pointer < $this->count();
269
    }
270
271
    //////////////////////////
272
    // Countable Interface
273
    //////////////////////////
274
275
    /**
276
     * Get total number of models matching query.
277
     *
278
     * @return int
279
     */
280
    public function count()
281
    {
282
        return count($this->stack);
283
    }
284
285
    /////////////////////////////
286
    // ArrayAccess Interface
287
    /////////////////////////////
288
289
    public function offsetExists($offset)
290
    {
291
        return isset($this->stack[$offset]);
292
    }
293
294 View Code Duplication
    public function offsetGet($offset)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
295
    {
296
        if (!$this->offsetExists($offset)) {
297
            throw new \OutOfBoundsException("$offset does not exist on this ErrorStack");
298
        }
299
300
        $this->pointer = $offset;
301
302
        return $this->current();
303
    }
304
305
    public function offsetSet($offset, $error)
306
    {
307
        if (!is_numeric($offset)) {
308
            throw new \Exception('Can only perform set on numeric indices');
309
        }
310
311
        $this->stack[$offset] = $this->sanitize($error);
312
    }
313
314
    public function offsetUnset($offset)
315
    {
316
        unset($this->stack[$offset]);
317
    }
318
}
319