Completed
Push — development ( 84535f...6fa0bd )
by Stephen
16s
created

ErrorContext::getErrorValue()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 19
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 0
Metric Value
cc 3
eloc 9
nc 3
nop 1
dl 0
loc 19
ccs 0
cts 9
cp 0
crap 12
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * This does the job of handling user errors in their many forms
5
 *
6
 * @name      ElkArte Forum
7
 * @copyright ElkArte Forum contributors
8
 * @license   BSD http://opensource.org/licenses/BSD-3-Clause
9
 *
10
 * @version 1.1 Release Candidate 2
11
 *
12
 */
13
14
namespace ElkArte\Errors;
15
16
/**
17
 *  This class is an experiment for the job of handling errors.
18
 */
19
final class ErrorContext
20
{
21
	/**
22
	 * Holds the unique identifier of the error (a name).
23
	 *
24
	 * @var string
25
	 */
26
	private $_name = null;
27
28
	/**
29
	 * An array that holds all the errors occurred separated by severity.
30
	 *
31
	 * @var array
32
	 */
33
	private $_errors = null;
34
35
	/**
36
	 * The default severity code.
37
	 *
38
	 * @var mixed
39
	 */
40
	private $_default_severity = 0;
41
42
	/**
43
	 * A list of all severity code from the less important to the most serious.
44
	 *
45
	 * @var array|mixed
46
	 */
47
	private $_severity_levels = array(0);
48
49
	/**
50
	 * Certain errors may need some specific language file...
51
	 *
52
	 * @var array
53
	 */
54
	private $_language_files = array();
55
56
	/**
57
	 * Multiton. This is an array of instances of ErrorContext.
58
	 * All callers use an error context ('post', 'attach', or 'default' if none chosen).
59
	 *
60
	 * @var array of ErrorContext
61
	 */
62
	private static $_contexts = null;
63
64
	const MINOR = 0;
65
	const SERIOUS = 1;
66
67
	/**
68
	 * Create and initialize an instance of the class
69
	 *
70
	 * @param string $id the error identifier
71
	 * @param int|null $default_severity the default error severity level
72
	 */
73 2
	private function __construct($id = 'default', $default_severity = null)
74
	{
75 2
		if (!empty($id))
76 2
			$this->_name = $id;
77
78
		// Initialize severity levels... waiting for details!
79 2
		$this->_severity_levels = array(self::MINOR, self::SERIOUS);
80
81
		// Initialize default severity (not sure this is needed)
82 2
		if ($default_severity === null || !in_array($default_severity, $this->_severity_levels))
83 2
			$this->_default_severity = self::MINOR;
84
		else
85 1
			$this->_default_severity = $default_severity;
86
87 2
		$this->_errors = array();
88 2
	}
89
90
	/**
91
	 * Add an error to the list
92
	 *
93
	 * @param mixed[]|mixed $error error code
94
	 * @param string|int|null $severity error severity
95
	 * @param string|null $lang_file lang_file
96
	 */
97 1
	public function addError($error, $severity = null, $lang_file = null)
98
	{
99 1
		$severity = $severity !== null && in_array($severity, $this->_severity_levels) ? $severity : $this->_default_severity;
100
101 1
		if (!empty($error))
102 1
		{
103 1
			$name = $this->getErrorName($error);
104 1
			$this->_errors[$severity][$name] = $error;
105 1
		}
106
107 1
		if (!empty($lang_file) && !isset($this->_language_files[$lang_file]))
108 1
			$this->_language_files[$lang_file] = false;
109 1
	}
110
111
	/**
112
	 * Remove an error from the list
113
	 *
114
	 * @param mixed[]|mixed $error error code
115
	 */
116 1
	public function removeError($error)
117
	{
118 1
		if (!empty($error))
119 1
		{
120 1
			$name = $this->getErrorName($error);
121
122 1
			foreach ($this->_errors as $severity => $errors)
123
			{
124 1
				if (array_key_exists($name, $errors))
125 1
					unset($this->_errors[$severity][$name]);
126 1
				if (empty($this->_errors[$severity]))
127 1
					unset($this->_errors[$severity]);
128 1
			}
129 1
		}
130 1
	}
131
132
	/**
133
	 * Finds the "name" of the error (either the string, the first element
134
	 * of the array, or the result of getName)
135
	 *
136
	 * @param mixed|mixed[] $error error code
137
	 */
138 1
	protected function getErrorName($error)
139
	{
140 1
		if (is_array($error))
141 1
		{
142
			$first_error = array_values($error);
143
			if (is_object($first_error[0]))
144
			{
145
				return $this->getErrorName($first_error[0]);
146
			}
147
			else
148
			{
149
				return $first_error[0];
150
			}
151
		}
152 1
		elseif (is_object($error))
153
		{
154
			return $error->getName();
155
		}
156
		else
157
		{
158 1
			return $error;
159
		}
160
	}
161
162
	/**
163
	 * Finds the "value" of the error (Usually applicable only to
164
	 * array of strings, being the second element of the array)
165
	 *
166
	 * @param mixed|mixed[] $error error code
167
	 */
168
	protected function getErrorValue($error)
169
	{
170
		if (is_array($error))
171
		{
172
			$first_error = array_values($error);
173
			if (is_object($first_error[0]))
174
			{
175
				return null;
176
			}
177
			else
178
			{
179
				return $first_error[1];
180
			}
181
		}
182
		else
183
		{
184
			return null;
185
		}
186
	}
187
188
	/**
189
	 * Return an array of errors of a certain severity.
190
	 *
191
	 * @todo is it needed at all?
192
	 * @param string|int|null $severity the severity level wanted. If null returns all the errors
193
	 */
194 1
	public function getErrors($severity = null)
195
	{
196 1
		if ($severity !== null && in_array($severity, $this->_severity_levels) && !empty($this->_errors[$severity]))
197 1
			return $this->_errors[$severity];
198 1
		elseif ($severity === null && !empty($this->_errors))
199
			return $this->_errors;
200
		else
201 1
			return false;
202
	}
203
204
	/**
205
	 * Return an error based on the id of the error set when adding the error itself.
206
	 *
207
	 * @param mixed|mixed[] $error error code
208
	 * @return null|mixed whatever the error is (string, object, array), noll if not found
209
	 */
210
	public function getError($error = null)
211
	{
212
		$name = $this->getErrorName($error);
213
		if (isset($this->_errors[$name]))
214
			return $this->_errors[$name];
215
		else
216
			return null;
217
	}
218
219
	/**
220
	 * Returns if there are errors or not.
221
	 *
222
	 * @param string|null $severity the severity level wanted. If null returns all the errors
223
	 * @return bool
224
	 */
225 2
	public function hasErrors($severity = null)
226
	{
227 2
		if ($severity !== null && in_array($severity, $this->_severity_levels))
228 2
			return !empty($this->_errors[$severity]);
229 2
		elseif ($severity === null)
230 2
			return !empty($this->_errors);
231
		else
232
			return false;
233
	}
234
235
	/**
236
	 * Check if a particular error exists.
237
	 *
238
	 * @param string $errors the error
239
	 */
240 1
	public function hasError($errors)
241
	{
242 1
		if (!empty($errors))
243 1
		{
244 1
			$errors = (array) $errors;
245 1
			foreach ($errors as $error)
246
			{
247 1
				$name = $this->getErrorName($error);
248 1
				foreach ($this->_errors as $current_errors)
249
				{
250 1
					if (isset($current_errors[$name]))
251 1
					{
252 1
						return true;
253
					}
254 1
				}
255 1
			}
256 1
		}
257
258 1
		return false;
259
	}
260
261
	/**
262
	 * Return the code of the highest error level encountered
263
	 */
264 1
	public function getErrorType()
265
	{
266 1
		$levels = array_reverse($this->_severity_levels);
267 1
		$level = null;
268
269 1
		foreach ($levels as $level)
270
		{
271 1
			if (!empty($this->_errors[$level]))
272 1
				return $level;
273 1
		}
274
275
		return $level;
276
	}
277
278
	/**
279
	 * Return an array containing the error strings
280
	 *
281
	 * - If severity is null the function returns all the errors
282
	 *
283
	 * @param string|null $severity the severity level wanted
284
	 */
285
	public function prepareErrors($severity = null)
286
	{
287
		global $txt;
288
289
		if (empty($this->_errors))
290
			return array();
291
292
		$this->_loadLang();
293
294
		call_integration_hook('integrate_' . $this->_name . '_errors', array(&$this->_errors, &$this->_severity_levels));
295
296
		$errors = array();
297
		$returns = array();
298
		if ($severity === null)
299
		{
300
			foreach ($this->_errors as $err)
301
				$errors = array_merge($errors, $err);
302
		}
303
		elseif (in_array($severity, $this->_severity_levels) && !empty($this->_errors[$severity]))
304
			$errors = $this->_errors[$severity];
305
306
		foreach ($errors as $error_val)
307
		{
308
			if (is_array($error_val))
309
			{
310
				$name = $this->getErrorName($error_val);
311
				$value = $this->getErrorValue($error_val);
312
				if ($value === null)
313
				{
314
					continue;
315
				}
316
				$returns[$name] = vsprintf(isset($txt['error_' . $name]) ? $txt['error_' . $name] : (isset($txt[$name]) ? $txt[$name] : $name), $value);
317
			}
318
			elseif (is_object($error_val))
319
			{
320
				continue;
321
			}
322
			else
323
			{
324
				$returns[$error_val] = isset($txt['error_' . $error_val]) ? $txt['error_' . $error_val] : (isset($txt[$error_val]) ? $txt[$error_val] : $error_val);
325
			}
326
		}
327
328
		return $returns;
329
	}
330
331
	/**
332
	 * Load the default error language and any other language file needed
333
	 */
334
	private function _loadLang()
335
	{
336
		// Errors is always needed
337
		loadLanguage('Errors');
338
339
		// Any custom one?
340
		if (!empty($this->_language_files))
341
			foreach ($this->_language_files as $language => $loaded)
342
				if (!$loaded)
343
				{
344
					loadLanguage($language);
345
346
					// Remember this file has been loaded already
347
					$this->_language_files[$language] = true;
348
				}
349
	}
350
351
	/**
352
	 * Find and return ErrorContext instance if it exists,
353
	 * or create a new instance for $id if it didn't already exist.
354
	 *
355
	 * @param string $id
356
	 * @param int|null $default_severity
357
	 * @return ErrorContext
358
	 */
359 2
	public static function context($id = 'default', $default_severity = null)
360
	{
361 2
		if (self::$_contexts === null)
362 2
			self::$_contexts = array();
363
364 2
		if (!array_key_exists($id, self::$_contexts))
365 2
			self::$_contexts[$id] = new self($id, $default_severity);
366
367 2
		return self::$_contexts[$id];
368
	}
369
}
370