Completed
Branch FET-9594-attendee-mover (38558c)
by
unknown
09:29 queued 1434:43
created

BaseException::display_errors()   D

Complexity

Conditions 33
Paths 104

Size

Total Lines 159
Code Lines 105

Duplication

Lines 8
Ratio 5.03 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 33
eloc 105
c 1
b 0
f 1
nc 104
nop 0
dl 8
loc 159
rs 4.3015

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
namespace EventEspresso\Core\Exceptions;
3
4
if ( ! defined( 'EVENT_ESPRESSO_VERSION' ) ) {
5
	exit( 'No direct script access allowed' );
6
}
7
8
9
10
/**
11
 * Class BaseException
12
 * extended by other exceptions
13
 *
14
 * @package       Event Espresso
15
 * @author        Brent Christensen
16
 * @since         4.9.0
17
 */
18
class BaseException extends \Exception {
19
20
21
	/**
22
	 *    name of the file to log exceptions to
23
	 *
24
	 * @access    private
25
	 * @var string
26
	 */
27
	private static $_exception_log_file = 'espresso_error_log.txt';
0 ignored issues
show
Unused Code introduced by
The property $_exception_log_file is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
28
29
	/**
30
	 *    tracks number of errors
31
	 *
32
	 * @access    private
33
	 * @var int
34
	 */
35
	private static $_error_count = 0;
36
37
	/**
38
	 *    stores details for all exception
39
	 *
40
	 * @access    private
41
	 * @var array
42
	 */
43
	private static $_all_exceptions = array();
44
45
46
47
	/**
48
	 * @param string     $message
49
	 * @param int        $code
50
	 * @param \Exception $previous
51
	 * @throws \EventEspresso\Core\Exceptions\BaseException
52
	 */
53
	public function __construct( $message, $code = 0, \Exception $previous = null ) {
54
		parent::__construct( $message, $code, $previous );
55
		if ( WP_DEBUG ) {
56
			$this->get_error();
57
		}
58
	}
59
60
61
62
	/**
63
	 * @access public
64
	 * @throws \EventEspresso\Core\Exceptions\BaseException
65
	 */
66 View Code Duplication
	public function get_error() {
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...
67
		if ( apply_filters( 'FHEE__BaseException__get_error__show_normal_exceptions', false ) ) {
68
			throw $this;
69
		}
70
		// get separate user and developer messages if they exist
71
		$msg = explode( '||', $this->getMessage() );
72
		$user_msg = $msg[0];
73
		$dev_msg = isset( $msg[1] ) ? $msg[1] : $msg[0];
74
		$msg = WP_DEBUG ? $dev_msg : $user_msg;
75
		// add details to _all_exceptions array
76
		$x_time = time();
77
		self::$_all_exceptions[ $x_time ]['name'] = get_class( $this );
78
		self::$_all_exceptions[ $x_time ]['file'] = $this->getFile();
79
		self::$_all_exceptions[ $x_time ]['line'] = $this->getLine();
80
		self::$_all_exceptions[ $x_time ]['msg'] = $msg;
81
		self::$_all_exceptions[ $x_time ]['code'] = $this->getCode();
82
		self::$_all_exceptions[ $x_time ]['trace'] = $this->getTrace();
83
		self::$_all_exceptions[ $x_time ]['string'] = $this->getTraceAsString();
84
		self::$_error_count++;
85
		$this->display_errors();
86
	}
87
88
89
90
	/**
91
	 *    display_errors
92
	 *
93
	 * @access public
94
	 * @echo   string
95
	 */
96
	public function display_errors() {
97
		$error_code = '';
98
		$trace_details = '';
99
		$output = BaseException::_exception_styles();
100
		$output .= '
101
<div id="ee-error-message" class="error">';
102
		if ( ! WP_DEBUG ) {
103
			$output .= '
104
	<p>';
105
		}
106
		// cycle thru errors
107
		foreach ( self::$_all_exceptions as $time => $ex ) {
108
			// process trace info
109
			if ( empty( $ex['trace'] ) ) {
110
				$trace_details .= __(
111
					'Sorry, but no trace information was available for this exception.',
112
					'event_espresso'
113
				);
114
			} else {
115
				$trace_details .= '
116
			<div id="ee-trace-details">
117
			<table width="100%" border="0" cellpadding="5" cellspacing="0">
118
				<tr>
119
					<th scope="col" align="right" style="width:2.5%;">#</th>
120
					<th scope="col" align="right" style="width:3.5%;">Line</th>
121
					<th scope="col" align="left" style="width:40%;">File</th>
122
					<th scope="col" align="left">' . __( 'Class', 'event_espresso' ) . '->' . __( 'Method( arguments )', 'event_espresso' ) . '</th>
123
				</tr>';
124
				$last_on_stack = count( $ex['trace'] ) - 1;
125
				// reverse array so that stack is in proper chronological order
126
				$sorted_trace = array_reverse( $ex['trace'] );
127
				foreach ( $sorted_trace as $nmbr => $trace ) {
128
					$file = isset( $trace['file'] ) ? $trace['file'] : '';
129
					$class = isset( $trace['class'] ) ? $trace['class'] : '';
130
					$type = isset( $trace['type'] ) ? $trace['type'] : '';
131
					$function = isset( $trace['function'] ) ? $trace['function'] : '';
132
					$args = isset( $trace['args'] ) ? $this->_convert_args_to_string( $trace['args'] ) : '';
133
					$args = isset( $trace['args'] ) && count( $trace['args'] ) > 4  ? ' <br />' . $args . '<br />' : $args;
134
					$line = isset( $trace['line'] ) ? $trace['line'] : '';
135
					$zebra = $nmbr % 2 !== 0 ? ' odd' : '';
136 View Code Duplication
					if ( empty( $file ) && ! empty( $class ) ) {
137
						$a = new \ReflectionClass( $class );
138
						$file = $a->getFileName();
139
						if ( empty( $line ) && ! empty( $function ) ) {
140
							$b = new \ReflectionMethod( $class, $function );
141
							$line = $b->getStartLine();
142
						}
143
					}
144
					if ( $nmbr === $last_on_stack ) {
145
						$file = $ex['file'] !== '' ? $ex['file'] : $file;
146
						$line = $ex['line'] !== '' ? $ex['line'] : $line;
147
						$error_code = self::generate_error_code( $file, $trace['function'], $line );
148
					}
149
					$file = \EEH_File::standardise_directory_separators( $file );
150
					$nmbr = ! empty( $nmbr ) ? $nmbr : '&nbsp;';
151
					$line = ! empty( $line ) ? $line : '&nbsp;';
152
					$file = ! empty( $file ) ? $file : '&nbsp;';
153
					$class_display = ! empty( $class ) ? $class : '';
154
					$type = ! empty( $type ) ? $type : '';
155
					$function = ! empty( $function ) ? $function : '';
156
					$args = ! empty( $args ) ? '( ' . $args . ' )' : '()';
157
					$trace_details .= '
158
					<tr>
159
						<td align="right" valign="top" class="' . $zebra . '">' . $nmbr . '</td>
160
						<td align="right" valign="top" class="' . $zebra . '">' . $line . '</td>
161
						<td align="left" valign="top" class="' . $zebra . '">' . $file . '</td>
162
						<td align="left" valign="top" class="' . $zebra . '">' . $class_display . $type . $function . $args . '</td>
163
					</tr>';
164
				}
165
				$trace_details .= '
166
			 </table>
167
			</div>';
168
			}
169
			$ex['code'] = $ex['code'] ? $ex['code'] : $error_code;
170
			// add generic non-identifying messages for non-privileged users
171
			if ( ! WP_DEBUG ) {
172
				$output .= '<span class="ee-error-user-msg-spn">'
173
				           . trim( $ex['msg'] )
174
				           . '</span> &nbsp; <sup>'
175
				           . $ex['code']
176
				           . '</sup><br />';
177
			} else {
178
				// or helpful developer messages if debugging is on
179
				$output .= '
180
		<div class="ee-error-dev-msg-dv">
181
			<p class="ee-error-dev-msg-pg">
182
				'
183
				. sprintf(
184
					__( '%1$sAn %2$s was thrown!%3$s code: %4$s', 'event_espresso' ),
185
				    '<strong class="ee-error-dev-msg-str">',
186
					$ex['name'],
187
					'</strong>  &nbsp; <span>',
188
					$ex['code'] . '</span>'
189
				)
190
				. '<br />
191
				<span class="big-text">"'
192
				           . trim( $ex['msg'] )
193
				           . '"</span><br/>
194
				<a id="display-ee-error-trace-'
195
				           . self::$_error_count
196
				           . $time
197
				           . '" class="display-ee-error-trace-lnk small-text" rel="ee-error-trace-'
198
				           . self::$_error_count
199
				           . $time
200
				           . '">
201
					'
202
				           . __( 'click to view backtrace and class/method details', 'event_espresso' )
203
				           . '
204
				</a><br />
205
				'
206
				           . $ex['file']
207
				           . sprintf(
208
					           __( '%1$s( line no: %2$s )%3$s', 'event_espresso' ),
209
					           ' &nbsp; <span class="small-text lt-grey-text">',
210
					           $ex['line'],
211
					           '</span>'
212
				           )
213
				           . '
214
			</p>
215
			<div id="ee-error-trace-'
216
				           . self::$_error_count
217
				           . $time
218
				           . '-dv" class="ee-error-trace-dv" style="display: none;">
219
				'
220
				           . $trace_details;
221
				if ( ! empty( $class ) ) {
222
					$output .= '
223
				<div style="padding:3px; margin:0 0 1em; border:1px solid #999; background:#fff; border-radius:3px;">
224
					<div style="padding:1em 2em; border:1px solid #999; background:#fcfcfc;">
225
						<h3>' . __( 'Class Details', 'event_espresso' ) . '</h3>';
226
					$a = new \ReflectionClass( $class );
227
					$output .= '
228
						<pre>' . $a . '</pre>
229
					</div>
230
				</div>';
231
				}
232
				$output .= '
233
			</div>
234
		</div>
235
		<br />';
236
			}
237
			$this->write_to_error_log( $time, $ex );
238
		}
239
		// remove last linebreak
240
		$output = substr( $output, 0, count( $output ) - 7 );
241
		if ( ! WP_DEBUG ) {
242
			$output .= '
243
	</p>';
244
		}
245
		$output .= '
246
</div>';
247
		$output .= self::_print_scripts( true );
248
		if ( defined( 'DOING_AJAX' ) ) {
249
			echo json_encode( array( 'error' => $output ) );
250
			exit();
251
		}
252
		echo $output;
253
		die();
254
	}
255
256
257
258
	/**
259
	 * generate string from exception trace args
260
	 *
261
	 * @param array $arguments
262
	 * @param int   $indent
263
	 * @param bool  $array
264
	 * @return string
265
	 */
266
	private function _convert_args_to_string( $arguments = array(), $indent = 0, $array = false ) {
267
		$args = array();
268
		$args_count = count( $arguments );
269
		if ( $args_count > 2 ) {
270
			$indent++;
271
			$args[] = '<br />';
272
		}
273
		$x = 0;
274
		foreach ( $arguments as $arg ) {
275
			$x++;
276
			for( $i = 0; $i < $indent; $i++ ) {
277
				$args[] = ' &nbsp;&nbsp; ';
278
			}
279
			if ( is_string( $arg ) ) {
280
				if ( ! $array && strlen( $arg ) > 75 ) {
281
					$args[] = "<br />";
282
					for ( $i = 0; $i <= $indent; $i++ ) {
283
						$args[] = ' &nbsp;&nbsp; ';
284
					}
285
					$args[] = "'" . $arg . "'<br />";
286
				} else {
287
					$args[] = " '" . $arg . "'";
288
				}
289
			} elseif ( is_array( $arg ) ) {
290
				$arg_count = count( $arg );
291
				if ( $arg_count > 2 ) {
292
					$indent++;
293
					$args[] = " array(" . $this->_convert_args_to_string( $arg, $indent, true ) . ")";
294
					$indent--;
295
				} else if ( $arg_count === 0 ) {
296
					$args[] = " array()";
297
				} else {
298
					$args[] = " array( " . $this->_convert_args_to_string( $arg ) . " )";
299
				}
300
			} elseif ( $arg === null ) {
301
				$args[] = ' null';
302
			} elseif ( is_bool( $arg ) ) {
303
				$args[] = $arg ? ' true' : ' false';
304
			} elseif ( is_object( $arg ) ) {
305
				$args[] = get_class( $arg );
306
			} elseif ( is_resource( $arg ) ) {
307
				$args[] = get_resource_type( $arg );
308
			} else {
309
				$args[] = $arg;
310
			}
311
			if ( $x === $args_count ) {
312
				if ( $args_count > 2 ) {
313
					$args[] = "<br />";
314
					$indent--;
315
					for ( $i = 1; $i < $indent; $i++ ) {
316
						$args[] = ' &nbsp;&nbsp; ';
317
					}
318
				}
319
			} else {
320
				$args[] = $args_count > 2 ? ",<br />" : ', ';
321
			}
322
		}
323
		return implode( '', $args );
324
	}
325
326
327
328
	/**
329
	 * create error code from filepath, function name,
330
	 * and line number where exception or error was thrown
331
	 *
332
	 * @access public
333
	 * @param string $file
334
	 * @param string $func
335
	 * @param string $line
336
	 * @return string
337
	 */
338 View Code Duplication
	public static function generate_error_code( $file = '', $func = '', $line = '' ) {
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...
339
		$file_bits = explode( '.', basename( $file ) );
340
		$error_code = ! empty( $file_bits[0] ) ? $file_bits[0] : '';
341
		$error_code .= ! empty( $func ) ? ' - ' . $func : '';
342
		$error_code .= ! empty( $line ) ? ' - ' . $line : '';
343
		return $error_code;
344
	}
345
346
347
348
	/**
349
	 * write exception details to log file
350
	 *
351
	 * @param int   $time
352
	 * @param array $ex
353
	 * @param bool  $clear
354
	 */
355
	public function write_to_error_log( $time = 0, $ex = array(), $clear = false ) {
356
		if ( empty( $ex ) ) {
357
			return;
358
		}
359
		if ( ! $time ) {
360
			$time = time();
361
		}
362
		$exception_log = '----------------------------------------------------------------------------------------'
363
		                 . PHP_EOL;
364
		$exception_log .= '[' . date( 'Y-m-d H:i:s', $time ) . ']  Exception Details' . PHP_EOL;
365
		$exception_log .= 'Message: ' . $ex['msg'] . PHP_EOL;
366
		$exception_log .= 'Code: ' . $ex['code'] . PHP_EOL;
367
		$exception_log .= 'File: ' . $ex['file'] . PHP_EOL;
368
		$exception_log .= 'Line No: ' . $ex['line'] . PHP_EOL;
369
		$exception_log .= 'Stack trace: ' . PHP_EOL;
370
		$exception_log .= $ex['string'] . PHP_EOL;
371
		$exception_log .= '----------------------------------------------------------------------------------------'
372
		                  . PHP_EOL;
373
		try {
374
			\EEH_File::ensure_file_exists_and_is_writable(
375
				EVENT_ESPRESSO_UPLOAD_DIR . 'logs' . DS . BaseException::$_exception_log_file
376
			);
377
			\EEH_File::add_htaccess_deny_from_all( EVENT_ESPRESSO_UPLOAD_DIR . 'logs' );
378 View Code Duplication
			if ( ! $clear ) {
379
				//get existing log file and append new log info
380
				$exception_log = \EEH_File::get_file_contents(
381
						EVENT_ESPRESSO_UPLOAD_DIR . 'logs' . DS . BaseException::$_exception_log_file
382
					) . $exception_log;
383
			}
384
			\EEH_File::write_to_file(
385
				EVENT_ESPRESSO_UPLOAD_DIR . 'logs' . DS . BaseException::$_exception_log_file,
386
				$exception_log
387
			);
388
		} catch ( \Exception $e ) {
389
			\EE_Error::add_error(
390
				sprintf(
391
					__( 'Event Espresso error logging could not be setup because: %s', 'event_espresso' ),
392
					$e->getMessage()
393
				)
394
			);
395
			return;
396
		}
397
	}
398
399
400
401
402
	/**
403
	 * _exception_styles
404
	 *
405
	 * @return string
406
	 */
407
	private static function _exception_styles() {
408
		return '
409
<style type="text/css">
410
	#ee-error-message {
411
		max-width:90% !important;
412
		margin: 0 5%;
413
	}
414
	.ee-error-dev-msg-pg,
415
	.error .ee-error-dev-msg-pg {
416
		padding:1em;
417
		margin:0 0 1em;
418
		border:2px solid #E44064;
419
		background:#fff;
420
		border-radius:3px;
421
		line-height: 1.5em;;
422
	}
423
	#ee-trace-details {
424
		padding:3px;
425
		margin:0 0 1em;
426
		border:1px solid #999;
427
		background:#f9f9f9;
428
		border-radius:3px;
429
	}
430
	#ee-trace-details table {
431
		border:1px solid #999;
432
		border-bottom:none;
433
		background:#fff;
434
	}
435
	#ee-trace-details table th {
436
		background:#eee;
437
		border-bottom:1px solid #ccc;
438
	}
439
	#ee-trace-details table td {
440
		border-bottom:1px solid #e8e8e8;
441
		padding: 10px 5px;
442
	}
443
	#ee-trace-details table td.odd {
444
		background:#fdfdfd;
445
	}
446
	.display-ee-error-trace-lnk {
447
		color:blue;
448
		cursor:pointer;
449
	}
450
	.display-ee-error-trace-lnk:hover {
451
		text-decoration:underline;
452
	}
453
	.hidden {
454
		display:none;
455
	}
456
	.small-text {
457
		font-size: .85em;
458
		line-height: 1.4em;
459
		letter-spacing: 1px;
460
	}
461
	.lt-grey-text {
462
		color: #999;
463
	}
464
</style>';
465
	}
466
467
468
469
	/**
470
	 * _print_scripts
471
	 *
472
	 * @param bool $force_print
473
	 * @return string|void
474
	 */
475 View Code Duplication
	private static function _print_scripts( $force_print = false ) {
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...
476
		if ( ! $force_print  && ( did_action( 'admin_enqueue_scripts' ) || did_action( 'wp_enqueue_scripts' ) ) ) {
477
			if ( wp_script_is( 'ee_error_js', 'enqueued' ) ) {
478
				return '';
479
			} else if ( wp_script_is( 'ee_error_js', 'registered' ) ) {
480
				add_filter( 'FHEE_load_css', '__return_true' );
481
				add_filter( 'FHEE_load_js', '__return_true' );
482
				wp_enqueue_script( 'ee_error_js' );
483
				wp_localize_script( 'ee_error_js', 'ee_settings', array( 'wp_debug' => WP_DEBUG ) );
484
			}
485
		} else {
486
			return '
487
<script>
488
/* <![CDATA[ */
489
var ee_settings = {"wp_debug":"' . WP_DEBUG . '"};
490
/* ]]> */
491
</script>
492
<script src="' . includes_url() . 'js/jquery/jquery.js" type="text/javascript"></script>
493
<script src="' . EE_GLOBAL_ASSETS_URL . 'scripts/espresso_core.js' . '?ver=' . espresso_version() . '" type="text/javascript"></script>
494
<script src="' . EE_GLOBAL_ASSETS_URL . 'scripts/EE_Error.js' . '?ver=' . espresso_version() . '" type="text/javascript"></script>
495
';
496
		}
497
		return '';
498
	}
499
500
501
502
}
503
// End of file BaseException.php
504
// Location: /core/exceptions/BaseException.php