Completed
Push — master ( cdcee0...01231f )
by Jared
01:38
created

ErrorStack::offsetSet()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 8
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 4
nc 2
nop 2
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 Infuse\Locale;
18
use IteratorAggregate;
19
20
/**
21
 * Holds error messages generated by models, like validation errors.
22
 */
23
class ErrorStack implements IteratorAggregate, Countable, ArrayAccess
24
{
25
    /**
26
     * @var array
27
     */
28
    private $stack;
29
30
    /**
31
     * @var Locale|null
32
     */
33
    private $locale;
34
35
    /**
36
     * @var int
37
     */
38
    private $pointer;
39
40
    public function __construct()
41
    {
42
        $this->stack = [];
43
        $this->pointer = 0;
44
    }
45
46
    /**
47
     * Sets the locale service.
48
     *
49
     * @param Locale $locale
50
     *
51
     * @return self
52
     */
53
    public function setLocale(Locale $locale)
54
    {
55
        $this->locale = $locale;
56
57
        return $this;
58
    }
59
60
    /**
61
     * Gets the locale service.
62
     *
63
     * @return Locale|null
64
     */
65
    public function getLocale()
66
    {
67
        return $this->locale;
68
    }
69
70
    /**
71
     * Adds an error message to the stack.
72
     *
73
     * @param array|string $error
74
     *                            - error: error code
75
     *                            - params: array of parameters to be passed to message
76
     *
77
     * @return self
78
     */
79
    public function push($error)
80
    {
81
        $this->stack[] = $this->sanitize($error);
82
83
        return $this;
84
    }
85
86
    /**
87
     * Gets all of the errors on the stack and also attempts
88
     * translation using the Locale class.
89
     *
90
     * @param string $locale optional locale
91
     *
92
     * @return array errors
93
     */
94
    public function errors($locale = '')
95
    {
96
        $errors = [];
97
        foreach ($this->stack as $error) {
98
            $errors[] = $this->parse($error, $locale);
99
        }
100
101
        return $errors;
102
    }
103
104
    /**
105
     * Gets the messages of errors on the stack.
106
     *
107
     * @param string $locale optional locale
108
     *
109
     * @return array errors
110
     */
111
    public function messages($locale = '')
112
    {
113
        $messages = [];
114
        foreach ($this->errors($locale) as $error) {
115
            $messages[] = $error['message'];
116
        }
117
118
        return $messages;
119
    }
120
121
    /**
122
     * Gets an error for a specific parameter on the stack.
123
     *
124
     * @param string $value value we are searching for
125
     * @param string $param parameter name
126
     *
127
     * @return array|bool
128
     */
129
    public function find($value, $param = 'field')
130
    {
131
        foreach ($this->errors() as $error) {
132
            if (array_value($error['params'], $param) === $value) {
133
                return $error;
134
            }
135
        }
136
137
        return false;
138
    }
139
140
    /**
141
     * Checks if an error exists with a specific parameter on the stack.
142
     *
143
     * @param string $value value we are searching for
144
     * @param string $param parameter name
145
     *
146
     * @return bool
147
     */
148
    public function has($value, $param = 'field')
149
    {
150
        return $this->find($value, $param) !== false;
151
    }
152
153
    /**
154
     * Clears the error stack.
155
     *
156
     * @return self
157
     */
158
    public function clear()
159
    {
160
        $this->stack = [];
161
162
        return $this;
163
    }
164
165
    /**
166
     * Formats an incoming error message.
167
     *
168
     * @param array|string $error
169
     *
170
     * @return array
171
     */
172
    private function sanitize($error)
173
    {
174
        if (!is_array($error)) {
175
            $error = ['error' => $error];
176
        }
177
178
        if (!isset($error['params'])) {
179
            $error['params'] = [];
180
        }
181
182
        return $error;
183
    }
184
185
    /**
186
     * Parses an error message before displaying it.
187
     *
188
     * @param array  $error
189
     * @param string $locale
190
     *
191
     * @return array
192
     */
193
    private function parse(array $error, $locale = '')
194
    {
195
        // attempt to translate error into a message
196
        // when the locale service is available
197
        if (!isset($error['message'])) {
198
            if ($this->locale) {
199
                $error['message'] = $this->locale->t($error['error'], $error['params'], $locale);
200
            } else {
201
                $error['message'] = $error['error'];
202
            }
203
        }
204
205
        return $error;
206
    }
207
208
    //////////////////////////
209
    // IteratorAggregate Interface
210
    //////////////////////////
211
212
    public function getIterator()
213
    {
214
        return new ArrayIterator($this->stack);
215
    }
216
217
    //////////////////////////
218
    // Countable Interface
219
    //////////////////////////
220
221
    /**
222
     * Get total number of models matching query.
223
     *
224
     * @return int
225
     */
226
    public function count()
227
    {
228
        return count($this->stack);
229
    }
230
231
    /////////////////////////////
232
    // ArrayAccess Interface
233
    /////////////////////////////
234
235
    public function offsetExists($offset)
236
    {
237
        return isset($this->stack[$offset]);
238
    }
239
240
    public function offsetGet($offset)
241
    {
242
        if (!$this->offsetExists($offset)) {
243
            throw new \OutOfBoundsException("$offset does not exist on this ErrorStack");
244
        }
245
246
        return $this->stack[$offset];
247
    }
248
249
    public function offsetSet($offset, $error)
250
    {
251
        if (!is_numeric($offset)) {
252
            throw new \Exception('Can only perform set on numeric indices');
253
        }
254
255
        $this->stack[$offset] = $this->sanitize($error);
256
    }
257
258
    public function offsetUnset($offset)
259
    {
260
        unset($this->stack[$offset]);
261
    }
262
}
263