PluginProbe
Debug Log Manager – Conveniently Monitor and Inspect Errors / 2.4.2
Debug Log Manager – Conveniently Monitor and Inspect Errors v2.4.2
2.5.2 2.5.1 trunk 1.0.0 1.0.1 1.1.0 1.2.0 1.3.0 1.3.1 1.3.3 1.4.0 1.5.0 1.5.1 1.5.2 1.5.3 1.6.0 1.6.1 1.6.2 1.6.3 1.6.4 1.7.0 1.8.0 1.8.2 1.8.3 1.8.4 All 49 releases
debug-log-manager / classes / class-debug-log.php

class-debug-log.php in Debug Log Manager – Conveniently Monitor and Inspect Errors 2.4.2, at classes/class-debug-log.php

1,984 lines 57.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace DLM\Classes;
4
5 /**
6 * Class related to the debug log file and entries
7 *
8 * @since 1.0.0
9 */
10 class Debug_Log {
11
12 // The wp_config object
13 private $wp_config;
14
15 /**
16 * Class constructor
17 */
18 public function __construct() {
19
20 $this->wp_config = new WP_Config_Transformer; // already in the DLM\Classes namespace, so, no need to repeat
21
22 }
23
24 /**
25 * Get status of WP_DEBUG
26 *
27 * @since 1.0.0
28 */
29 public function get_status() {
30
31 // If non-existent, create an empty index to prevent directory browsing and download of the debug log file
32 $uploads_path = wp_upload_dir()['basedir'] . '/debug-log-manager';
33 if ( ! is_file( $uploads_path . '/index.php' ) ) {
34 file_put_contents( $uploads_path . '/index.php', '<?php // Nothing to show here' );
35 }
36
37 $value = get_option( 'debug_log_manager' );
38 $status = $value['status'];
39
40 if ( function_exists( 'wp_date' ) ) {
41 $date_time = wp_date( 'M j, Y - H:i:s', strtotime( $value['on'] ) );
42 } else {
43 $date_time = date_i18n( 'M j, Y - H:i:s', strtotime( $value['on'] ) );
44 }
45
46 if ( 'enabled' == $status ) {
47
48 return '<div id="debug-log-status" class="dlm-log-status"><strong>' . esc_html__( 'Error Logging', 'debug-log-manager' ) . '</strong>: ' . ucfirst( esc_html__( 'enabled', 'debug-log-manager' ) ) . ' ' . esc_html__( 'on', 'debug-log-manager' ) . ' ' . esc_html( $date_time ) . '</div>';
49
50 } elseif ( 'disabled' == $status ) {
51
52 return '<div id="debug-log-status" class="dlm-log-status"><strong>' . esc_html__( 'Error Logging', 'debug-log-manager' ) . '</strong>: ' . ucfirst( esc_html__( 'disabled', 'debug-log-manager' ) ) . ' ' . esc_html__( 'on', 'debug-log-manager' ) . ' ' . esc_html( $date_time ) . '</div>';
53
54 } else {}
55
56 }
57
58 /**
59 * Get log auto-refresh status
60 *
61 * @since 1.3.0
62 */
63 public function get_autorefresh_status() {
64
65 if ( false !== get_option( 'debug_log_manager_autorefresh' ) ) {
66
67 $autorefresh_status = get_option( 'debug_log_manager_autorefresh' );
68
69 } else {
70
71 $autorefresh_status = 'disabled';
72 update_option( 'debug_log_manager_autorefresh', $autorefresh_status, false );
73
74 }
75
76 if ( 'enabled' == $autorefresh_status ) {
77
78 return '<div id="debug-autorefresh-status" class="dlm-autorefresh-status"><strong>Auto-Refresh</strong>: ' . ucfirst( esc_html__( 'enabled', 'debug-log-manager' ) ) . '</div>';
79
80 } elseif ( 'disabled' == $autorefresh_status ) {
81
82 return '<div id="debug-autorefresh-status" class="dlm-autorefresh-status"><strong>Auto-Refresh</strong>: ' . ucfirst( esc_html__( 'disabled', 'debug-log-manager' ) ) . '</div>';
83
84 }
85
86 }
87
88 /**
89 * Enable / disable WP_DEBUG
90 *
91 * @since 1.0.0
92 */
93 public function toggle_debugging() {
94
95 if ( isset( $_REQUEST ) && current_user_can( 'manage_options' ) ) {
96 if ( wp_verify_nonce( sanitize_text_field( $_REQUEST['nonce'] ), 'dlm-app' . get_current_user_id() ) ) {
97
98 $log_info = get_option( 'debug_log_manager' );
99 $dlm_debug_log_file_path = get_option( 'debug_log_manager_file_path' );
100 $modify_script_debug_status = get_option( 'debug_log_manager_modify_script_debug', 'enabled' );
101
102 if ( function_exists( 'wp_date' ) ) {
103 $date_time = wp_date( 'M j, Y - H:i:s' ); // Localized according to WP timezone settings
104 } else {
105 $date_time = date_i18n( 'M j, Y - H:i:s' );
106
107 }
108 $date_time_for_option = date( 'M j, Y H:i:s' ); // in UTC
109
110 if ( 'disabled' == $log_info['status'] ) {
111
112 $option_value = array(
113 'status' => 'enabled',
114 'on' => $date_time_for_option,
115 );
116
117 update_option( 'debug_log_manager', $option_value, false );
118
119 // If WP_DEBUG_LOG is defined, copy content of existing debug.log file into the log file created by this plugin
120
121 if ( $this->wp_config->exists( 'constant', 'WP_DEBUG_LOG' ) ) {
122
123 $wp_debug_log_const = $this->wp_config->get_value( 'constant', 'WP_DEBUG_LOG' );
124
125 if ( in_array( $wp_debug_log_const, array( 'true', 'false' ), true ) ) {
126 $wp_debug_log_const = (bool) $wp_debug_log_const;
127 }
128
129 if ( is_bool( $wp_debug_log_const ) ) {
130 // WP_DEBUG_LOG is true or false. Log file is in default location of /wp-content/debug.log.
131
132 if ( is_file( WP_CONTENT_DIR . '/debug.log' ) ) {
133 // Copy existing debug log content to this plugin's debug log.
134 $default_debug_log_content = file_get_contents( WP_CONTENT_DIR . '/debug.log' );
135 file_put_contents( $dlm_debug_log_file_path, $default_debug_log_content );
136 unlink( realpath( WP_CONTENT_DIR . '/debug.log' ) ); // delete existing debug log
137 }
138
139 } elseif ( is_string( $wp_debug_log_const ) ) {
140 // WP_DEBUG_LOG is custom path to log file. Copy existing debug log content to this plugin's debug log.
141
142 if ( is_file( $wp_debug_log_const ) && ( $wp_debug_log_const != $dlm_debug_log_file_path ) ) {
143 $custom_debug_log_content = file_get_contents( $wp_debug_log_const );
144 file_put_contents( $dlm_debug_log_file_path, $custom_debug_log_content );
145 unlink( $wp_debug_log_const ); // delete existing debug log
146 }
147
148 }
149
150 $copy = true; // existing debug.log file's entries are copied to this plugin's debug.log file
151
152 } else {
153
154 $copy = false; // existing debug.log file's entries are NOT copied to this plugin's debug.log file
155
156 }
157
158 // Define Debug constants in wp-config.php
159
160 $options = array(
161 'add' => true, // Add the config if missing.
162 'raw' => true, // Display value in raw format without quotes.
163 'normalize' => false, // Normalize config output using WP Coding Standards.
164 );
165
166 $this->wp_config->update( 'constant', 'WP_DEBUG', 'true', $options );
167
168 if ( 'enabled' == $modify_script_debug_status ) {
169 $options = array(
170 'add' => true, // Add the config if missing.
171 'raw' => true, // Display value in raw format without quotes.
172 'normalize' => false, // Normalize config output using WP Coding Standards.
173 );
174
175 $this->wp_config->update( 'constant', 'SCRIPT_DEBUG', 'true', $options );
176 }
177
178 $options = array(
179 'add' => true, // Add the config if missing.
180 'raw' => false, // Display value in raw format without quotes.
181 'normalize' => false, // Normalize config output using WP Coding Standards.
182 );
183
184 $this->wp_config->update( 'constant', 'WP_DEBUG_LOG', get_option( 'debug_log_manager_file_path' ), $options );
185
186 $options = array(
187 'add' => true, // Add the config if missing.
188 'raw' => true, // Display value in raw format without quotes.
189 'normalize' => false, // Normalize config output using WP Coding Standards.
190 );
191
192 $this->wp_config->update( 'constant', 'WP_DEBUG_DISPLAY', 'false', $options );
193
194 $options = array(
195 'add' => true, // Add the config if missing.
196 'raw' => true, // Display value in raw format without quotes.
197 'normalize' => false, // Normalize config output using WP Coding Standards.
198 );
199
200 $this->wp_config->update( 'constant', 'DISALLOW_FILE_EDIT', 'false', $options );
201
202 // Get the debug.log file size
203
204 $log_file_path = get_option( 'debug_log_manager_file_path' );
205 $log_file_shortpath = str_replace( sanitize_text_field( $_SERVER['DOCUMENT_ROOT'] ), "", $log_file_path );
206 $file_size = size_format( (int) filesize( $log_file_path ) );
207
208 // Prepare entries from the debug log for the data table
209
210 $errors_master_list = json_decode( $this->get_processed_entries(), true );
211
212 $n = 1;
213 $entries = array();
214
215 foreach ( $errors_master_list as $error ) {
216
217 if ( function_exists( 'wp_date' ) ) {
218 $localized_timestamp = wp_date( 'M j, Y - H:i:s', strtotime( $error['occurrences'][0] ) ); // last occurrence
219 } else {
220 $localized_timestamp = date_i18n( 'M j, Y - H:i:s', strtotime( $error['occurrences'][0] ) );
221 }
222
223 $occurrence_count = count( $error['occurrences'] );
224
225 $entry = array(
226 $n,
227 $error['type'],
228 $error['details'],
229 $localized_timestamp . '<br /><span class="dlm-faint">(' . sprintf( _n( '%s occurrence logged', '%s occurrences logged', $occurrence_count, 'debug-log-manager' ), number_format_i18n( $occurrence_count ) ) . ')<span>',
230 );
231
232 $entries[] = $entry;
233
234 $n++;
235
236 }
237
238 // Assemble data to return
239
240 $data = array(
241 'status' => 'enabled',
242 'copy' => $copy,
243 'message' => '<strong>' . esc_html__( 'Error Logging', 'debug-log-manager' ) . '</strong>: ' . esc_html__( 'Enabled on', 'debug-log-manager' ) . ' ' . esc_html( $date_time ),
244 'entries' => $entries,
245 'size' => $file_size,
246 );
247
248 echo json_encode( $data );
249
250 } elseif ( 'enabled' == $log_info['status'] ) {
251
252 $option_value = array(
253 'status' => 'disabled',
254 'on' => $date_time_for_option,
255 );
256
257 update_option( 'debug_log_manager', $option_value, false );
258
259 // Remove Debug constants in wp-config.php
260
261 $this->wp_config->remove( 'constant', 'WP_DEBUG' );
262 if ( 'enabled' == $modify_script_debug_status ) {
263 $this->wp_config->remove( 'constant', 'SCRIPT_DEBUG' );
264 }
265 $this->wp_config->remove( 'constant', 'WP_DEBUG_LOG' );
266 $this->wp_config->remove( 'constant', 'WP_DEBUG_DISPLAY' );
267 $this->wp_config->remove( 'constant', 'DISALLOW_FILE_EDIT' );
268
269 // Assemble data to return
270
271 $data = array(
272 'status' => 'disabled',
273 'copy' => false,
274 'message' => '<strong>' . esc_html__( 'Error Logging', 'debug-log-manager' ) . '</strong>: ' . esc_html__( 'Disabled on', 'debug-log-manager' ) . ' ' . esc_html( $date_time ),
275 'entries' => '',
276 'size' => '',
277 );
278
279 echo json_encode( $data );
280
281 } else {}
282
283 }
284 }
285
286 }
287
288 /**
289 * Toggle auto-refresh of entries table
290 *
291 * @since 1.3.0
292 */
293 public function toggle_autorefresh() {
294
295 if ( isset( $_REQUEST ) && current_user_can( 'manage_options' ) ) {
296 if ( wp_verify_nonce( sanitize_text_field( $_REQUEST['nonce'] ), 'dlm-app' . get_current_user_id() ) ) {
297
298 $autorefresh_status = get_option( 'debug_log_manager_autorefresh' );
299
300 if ( $autorefresh_status == 'disabled' ) {
301
302 update_option( 'debug_log_manager_autorefresh', 'enabled', false );
303
304 $data = array(
305 'status' => 'enabled',
306 'message' => '<strong>' . esc_html__( 'Auto-Refresh', 'debug-log-manager' ) . '</strong>: ' . esc_html__( 'Enabled', 'debug-log-manager' ),
307 );
308
309 echo json_encode( $data );
310
311 } elseif ( $autorefresh_status == 'enabled' ) {
312
313 update_option( 'debug_log_manager_autorefresh', 'disabled', false );
314
315 $data = array(
316 'status' => 'disabled',
317 'message' => '<strong>' . esc_html__( 'Auto-Refresh', 'debug-log-manager' ) . '</strong>: ' . esc_html__( 'Disabled', 'debug-log-manager' ),
318 );
319
320 echo json_encode( $data );
321
322 } else {}
323
324 }
325 }
326
327 }
328
329 /**
330 * Toggle JS error logging status
331 *
332 * @since 1.3.0
333 */
334 public function toggle_js_error_logging() {
335
336 if ( isset( $_REQUEST ) && current_user_can( 'manage_options' ) ) {
337 if ( wp_verify_nonce( sanitize_text_field( $_REQUEST['nonce'] ), 'dlm-app' . get_current_user_id() ) ) {
338
339 $js_error_logging_status = get_option( 'debug_log_manager_js_error_logging', 'enabled' );
340
341 if ( $js_error_logging_status == 'disabled' ) {
342
343 update_option( 'debug_log_manager_js_error_logging', 'enabled', false );
344
345 $data = array(
346 'status' => 'enabled',
347 );
348
349 echo json_encode( $data );
350
351 } elseif ( $js_error_logging_status == 'enabled' ) {
352
353 update_option( 'debug_log_manager_js_error_logging', 'disabled', false );
354
355 $data = array(
356 'status' => 'disabled',
357 );
358
359 echo json_encode( $data );
360
361 } else {}
362
363 }
364 }
365
366 }
367
368 /**
369 * Toggle SCRIPT_DEBUG modification status
370 *
371 * @since 1.3.0
372 */
373 public function toggle_script_debug_modification_status() {
374
375 if ( isset( $_REQUEST ) && current_user_can( 'manage_options' ) ) {
376 if ( wp_verify_nonce( sanitize_text_field( $_REQUEST['nonce'] ), 'dlm-app' . get_current_user_id() ) ) {
377
378 $modify_script_debug_status = get_option( 'debug_log_manager_modify_script_debug', 'enabled' );
379
380 if ( $modify_script_debug_status == 'disabled' ) {
381
382 update_option( 'debug_log_manager_modify_script_debug', 'enabled', false );
383
384 $data = array(
385 'status' => 'enabled',
386 );
387
388 echo json_encode( $data );
389
390 } elseif ( $modify_script_debug_status == 'enabled' ) {
391
392 update_option( 'debug_log_manager_modify_script_debug', 'disabled', false );
393
394 $data = array(
395 'status' => 'disabled',
396 );
397
398 echo json_encode( $data );
399
400 } else {}
401
402 }
403 }
404
405 }
406
407 /**
408 * Toggle processing non-UTC timezones status
409 *
410 * @since 1.3.0
411 */
412 public function toggle_process_non_utc_timezones_status() {
413
414 if ( isset( $_REQUEST ) && current_user_can( 'manage_options' ) ) {
415 if ( wp_verify_nonce( sanitize_text_field( $_REQUEST['nonce'] ), 'dlm-app' . get_current_user_id() ) ) {
416
417 $process_non_utc_timezones_status = get_option( 'debug_log_manager_process_non_utc_timezones', 'enabled' );
418
419 if ( $process_non_utc_timezones_status == 'disabled' ) {
420
421 update_option( 'debug_log_manager_process_non_utc_timezones', 'enabled', false );
422
423 $data = array(
424 'status' => 'enabled',
425 );
426
427 echo json_encode( $data );
428
429 } elseif ( $process_non_utc_timezones_status == 'enabled' ) {
430
431 update_option( 'debug_log_manager_process_non_utc_timezones', 'disabled', false );
432
433 $data = array(
434 'status' => 'disabled',
435 );
436
437 echo json_encode( $data );
438
439 } else {}
440
441 }
442 }
443
444
445 }
446 /**
447 * Get the processed debug log data
448 *
449 * @return string $errors_master_list The processed error log entries
450 * @since 1.2.0
451 */
452 public function get_processed_entries() {
453
454 // Paths with no trailing slash (/)
455 $wp_admin_path = ABSPATH . 'wp-admin';
456 $wp_includes_path = ABSPATH . 'wp-includes';
457 $theme_dir_path = get_theme_root();
458 $wp_plugin_dir_path = WP_PLUGIN_DIR;
459
460 $debug_log_file_path = get_option( 'debug_log_manager_file_path' );
461 $process_non_utc_timezones_status = get_option( 'debug_log_manager_process_non_utc_timezones', 'enabled' );
462
463 // Read the errors log file
464 $log = file_get_contents( $debug_log_file_path );
465
466 // Ignore words between square brackets,
467 // e.g. [DEBUG], [INFO], [WARNING], [ERROR] may come after timestamp [29-Nov-2023 01:30:03 UTC]
468 // This regex will extract DEBUG, INFO, WARNING, ERROR
469 // Prevents log entry with two bracket sets e.g. [timestamp] [someinfo] Details....
470 // from being returned as "No error message specified"
471 $log = preg_replace("/\[([a-zA-Z\s\-]+)\]/", "$1", $log);
472
473 $log = str_replace( "[\\", "^\\", $log ); // certain error message contains the '[\' string, which will make the following split via explode() to split lines at places in the message it's not supposed to. So, we temporarily replace those with '^\'
474
475 $log = str_replace( "[\"", "^\"", $log ); // certain error message contains the '["' string, which will make the following split via explode() to split lines at places in the message it's not supposed to. So, we temporarily replace those with '^"'
476
477 $log = str_replace( ":[", ":^", $log ); // certain error message contains the ':[' string, which will make the following split via explode() to split lines at places in the message it's not supposed to. So, we temporarily replace those with '^"'
478
479 $log = str_replace( "[internal function]", "^internal function^", $log );
480
481 // We are splitting the log file not using PHP_EOL to preserve the stack traces for PHP Fatal Errors among other things
482 $lines = explode("[", $log);
483 $prepended_lines = array();
484
485 // Pluck out the last 100k entries, the newest entry is last
486 // To pluck out the first 100000 entries, use array_slice( $lines, 0, 100000 )
487 $lines = array_slice( $lines, -100000 );
488
489 foreach ( $lines as $line ) {
490 if ( ! empty( $line ) ) {
491 $timezone_strings_to_replace = array(
492 'UTC]',
493 'Abidjan]',
494 'Accra]',
495 'Addis_Ababa]',
496 'Algiers]',
497 'Asmara]',
498 'Bamako]',
499 'Bangui]',
500 'Banjul]',
501 'Bissau]',
502 'Blantyre]',
503 'Brazzaville]',
504 'Bujumbura]',
505 'Cairo]',
506 'Casablanca]',
507 'Ceuta]',
508 'Conakry]',
509 'Dakar]',
510 'Dar_es_Salaam]',
511 'Djibouti]',
512 'Douala]',
513 'El_Aaiun]',
514 'Freetown]',
515 'Gaborone]',
516 'Harare]',
517 'Johannesburg]',
518 'Juba]',
519 'Kampala]',
520 'Khartoum]',
521 'Kigali]',
522 'Kinshasa]',
523 'Lagos]',
524 'Libreville]',
525 'Lome]',
526 'Luanda]',
527 'Lubumbashi]',
528 'Lusaka]',
529 'Malabo]',
530 'Maputo]',
531 'Maseru]',
532 'Mbabane]',
533 'Mogadishu]',
534 'Monrovia]',
535 'Nairobi]',
536 'Ndjamena]',
537 'Niamey]',
538 'Nouakchott]',
539 'Ouagadougou]',
540 'Porto-Novo]',
541 'Sao_Tome]',
542 'Tripoli]',
543 'Tunis]',
544 'Windhoek]',
545 'Adak]',
546 'Anchorage]',
547 'Anguilla]',
548 'Antigua]',
549 'Araguaina]',
550 'Argentina/Buenos_Aires]',
551 'Argentina/Catamarca]',
552 'Argentina/Cordoba]',
553 'Argentina/Jujuy]',
554 'Argentina/La_Rioja]',
555 'Argentina/Mendoza]',
556 'Argentina/Rio_Gallegos]',
557 'Argentina/Salta]',
558 'Argentina/San_Juan]',
559 'Argentina/San_Luis]',
560 'Argentina/Tucuman]',
561 'Argentina/Ushuaia]',
562 'Aruba]',
563 'Asuncion]',
564 'Atikokan]',
565 'Bahia]',
566 'Bahia_Banderas]',
567 'Barbados]',
568 'Belem]',
569 'Belize]',
570 'Blanc-Sablon]',
571 'Boa_Vista]',
572 'Bogota]',
573 'Boise]',
574 'Cambridge_Bay]',
575 'Campo_Grande]',
576 'Cancun]',
577 'Caracas]',
578 'Cayenne]',
579 'Cayman]',
580 'Chicago]',
581 'Chihuahua]',
582 'Ciudad_Juarez]',
583 'Costa_Rica]',
584 'Coyhaique]',
585 'Creston]',
586 'Cuiaba]',
587 'Curacao]',
588 'Danmarkshavn]',
589 'Dawson]',
590 'Dawson_Creek]',
591 'Denver]',
592 'Detroit]',
593 'Dominica]',
594 'Edmonton]',
595 'Eirunepe]',
596 'El_Salvador]',
597 'Fort_Nelson]',
598 'Fortaleza]',
599 'Glace_Bay]',
600 'Goose_Bay]',
601 'Grand_Turk]',
602 'Grenada]',
603 'Guadeloupe]',
604 'Guatemala]',
605 'Guayaquil]',
606 'Guyana]',
607 'Halifax]',
608 'Havana]',
609 'Hermosillo]',
610 'Indiana/Indianapolis]',
611 'Indiana/Knox]',
612 'Indiana/Marengo]',
613 'Indiana/Petersburg]',
614 'Indiana/Tell_City]',
615 'Indiana/Vevay]',
616 'Indiana/Vincennes]',
617 'Indiana/Winamac]',
618 'Inuvik]',
619 'Iqaluit]',
620 'Jamaica]',
621 'Juneau]',
622 'Kentucky/Louisville]',
623 'Kentucky/Monticello]',
624 'Kralendijk]',
625 'La_Paz]',
626 'Lima]',
627 'Los_Angeles]',
628 'Lower_Princes]',
629 'Maceio]',
630 'Managua]',
631 'Manaus]',
632 'Marigot]',
633 'Martinique]',
634 'Matamoros]',
635 'Mazatlan]',
636 'Menominee]',
637 'Merida]',
638 'Metlakatla]',
639 'Mexico_City]',
640 'Miquelon]',
641 'Moncton]',
642 'Monterrey]',
643 'Montevideo]',
644 'Montserrat]',
645 'Nassau]',
646 'New_York]',
647 'Nome]',
648 'Noronha]',
649 'North_Dakota/Beulah]',
650 'North_Dakota/Center]',
651 'North_Dakota/New_Salem]',
652 'Nuuk]',
653 'Ojinaga]',
654 'Panama]',
655 'Paramaribo]',
656 'Phoenix]',
657 'Port-au-Prince]',
658 'Port_of_Spain]',
659 'Porto_Velho]',
660 'Puerto_Rico]',
661 'Punta_Arenas]',
662 'Rankin_Inlet]',
663 'Recife]',
664 'Regina]',
665 'Resolute]',
666 'Rio_Branco]',
667 'Santarem]',
668 'Santiago]',
669 'Santo_Domingo]',
670 'Sao_Paulo]',
671 'Scoresbysund]',
672 'Sitka]',
673 'St_Barthelemy]',
674 'St_Johns]',
675 'St_Kitts]',
676 'St_Lucia]',
677 'St_Thomas]',
678 'St_Vincent]',
679 'Swift_Current]',
680 'Tegucigalpa]',
681 'Thule]',
682 'Tijuana]',
683 'Toronto]',
684 'Tortola]',
685 'Vancouver]',
686 'Whitehorse]',
687 'Winnipeg]',
688 'Yakutat]',
689 'Casey]',
690 'Davis]',
691 'DumontDUrville]',
692 'Macquarie]',
693 'Mawson]',
694 'McMurdo]',
695 'Palmer]',
696 'Rothera]',
697 'Syowa]',
698 'Troll]',
699 'Vostok]',
700 'Longyearbyen]',
701 'Aden]',
702 'Almaty]',
703 'Amman]',
704 'Anadyr]',
705 'Aqtau]',
706 'Aqtobe]',
707 'Ashgabat]',
708 'Atyrau]',
709 'Baghdad]',
710 'Bahrain]',
711 'Baku]',
712 'Bangkok]',
713 'Barnaul]',
714 'Beirut]',
715 'Bishkek]',
716 'Brunei]',
717 'Chita]',
718 'Colombo]',
719 'Damascus]',
720 'Dhaka]',
721 'Dili]',
722 'Dubai]',
723 'Dushanbe]',
724 'Famagusta]',
725 'Gaza]',
726 'Hebron]',
727 'Ho_Chi_Minh]',
728 'Hong_Kong]',
729 'Hovd]',
730 'Irkutsk]',
731 'Jakarta]',
732 'Jayapura]',
733 'Jerusalem]',
734 'Kabul]',
735 'Kamchatka]',
736 'Karachi]',
737 'Kathmandu]',
738 'Khandyga]',
739 'Kolkata]',
740 'Krasnoyarsk]',
741 'Kuala_Lumpur]',
742 'Kuching]',
743 'Kuwait]',
744 'Macau]',
745 'Magadan]',
746 'Makassar]',
747 'Manila]',
748 'Muscat]',
749 'Nicosia]',
750 'Novokuznetsk]',
751 'Novosibirsk]',
752 'Omsk]',
753 'Oral]',
754 'Phnom_Penh]',
755 'Pontianak]',
756 'Pyongyang]',
757 'Qatar]',
758 'Qostanay]',
759 'Qyzylorda]',
760 'Riyadh]',
761 'Sakhalin]',
762 'Samarkand]',
763 'Seoul]',
764 'Shanghai]',
765 'Singapore]',
766 'Srednekolymsk]',
767 'Taipei]',
768 'Tashkent]',
769 'Tbilisi]',
770 'Tehran]',
771 'Thimphu]',
772 'Tokyo]',
773 'Tomsk]',
774 'Ulaanbaatar]',
775 'Urumqi]',
776 'Ust-Nera]',
777 'Vientiane]',
778 'Vladivostok]',
779 'Yakutsk]',
780 'Yangon]',
781 'Yekaterinburg]',
782 'Yerevan]',
783 'Atlantic/Azores]',
784 'Atlantic/Bermuda]',
785 'Atlantic/Canary]',
786 'Atlantic/Cape_Verde]',
787 'Atlantic/Faroe]',
788 'Atlantic/Madeira]',
789 'Atlantic/Reykjavik]',
790 'Atlantic/South_Georgia]',
791 'Atlantic/St_Helena]',
792 'Atlantic/Stanley]',
793 'Australia/Adelaide]',
794 'Australia/Brisbane]',
795 'Australia/Broken_Hill]',
796 'Australia/Darwin]',
797 'Australia/Eucla]',
798 'Australia/Hobart]',
799 'Australia/Lindeman]',
800 'Australia/Lord_Howe]',
801 'Australia/Melbourne]',
802 'Australia/Perth]',
803 'Australia/Sydney]',
804 'Amsterdam]',
805 'Andorra]',
806 'Astrakhan]',
807 'Athens]',
808 'Belgrade]',
809 'Berlin]',
810 'Bratislava]',
811 'Brussels]',
812 'Bucharest]',
813 'Budapest]',
814 'Busingen]',
815 'Chisinau]',
816 'Copenhagen]',
817 'Dublin]',
818 'Gibraltar]',
819 'Guernsey]',
820 'Helsinki]',
821 'Isle_of_Man]',
822 'Istanbul]',
823 'Jersey]',
824 'Kaliningrad]',
825 'Kirov]',
826 'Kyiv]',
827 'Lisbon]',
828 'Ljubljana]',
829 'London]',
830 'Luxembourg]',
831 'Madrid]',
832 'Malta]',
833 'Mariehamn]',
834 'Minsk]',
835 'Monaco]',
836 'Moscow]',
837 'Oslo]',
838 'Paris]',
839 'Podgorica]',
840 'Prague]',
841 'Riga]',
842 'Rome]',
843 'Samara]',
844 'San_Marino]',
845 'Sarajevo]',
846 'Saratov]',
847 'Simferopol]',
848 'Skopje]',
849 'Sofia]',
850 'Stockholm]',
851 'Tallinn]',
852 'Tirane]',
853 'Ulyanovsk]',
854 'Vaduz]',
855 'Vatican]',
856 'Vienna]',
857 'Vilnius]',
858 'Volgograd]',
859 'Warsaw]',
860 'Zagreb]',
861 'Zurich]',
862 'Antananarivo]',
863 'Chagos]',
864 'Christmas]',
865 'Cocos]',
866 'Comoro]',
867 'Kerguelen]',
868 'Mahe]',
869 'Maldives]',
870 'Mauritius]',
871 'Mayotte]',
872 'Reunion]',
873 'Apia]',
874 'Auckland]',
875 'Bougainville]',
876 'Chatham]',
877 'Chuuk]',
878 'Easter]',
879 'Efate]',
880 'Fakaofo]',
881 'Fiji]',
882 'Funafuti]',
883 'Galapagos]',
884 'Gambier]',
885 'Guadalcanal]',
886 'Guam]',
887 'Honolulu]',
888 'Kanton]',
889 'Kiritimati]',
890 'Kosrae]',
891 'Kwajalein]',
892 'Majuro]',
893 'Marquesas]',
894 'Midway]',
895 'Nauru]',
896 'Niue]',
897 'Norfolk]',
898 'Noumea]',
899 'Pago_Pago]',
900 'Palau]',
901 'Pitcairn]',
902 'Pohnpei]',
903 'Port_Moresby]',
904 'Rarotonga]',
905 'Saipan]',
906 'Tahiti]',
907 'Tarawa]',
908 'Tongatapu]',
909 'Wake]',
910 'Wallis]',
911 );
912 $timezone_replacement_strings = array(
913 'UTC]@@@',
914 'Abidjan]@@@',
915 'Accra]@@@',
916 'Addis_Ababa]@@@',
917 'Algiers]@@@',
918 'Asmara]@@@',
919 'Bamako]@@@',
920 'Bangui]@@@',
921 'Banjul]@@@',
922 'Bissau]@@@',
923 'Blantyre]@@@',
924 'Brazzaville]@@@',
925 'Bujumbura]@@@',
926 'Cairo]@@@',
927 'Casablanca]@@@',
928 'Ceuta]@@@',
929 'Conakry]@@@',
930 'Dakar]@@@',
931 'Dar_es_Salaam]@@@',
932 'Djibouti]@@@',
933 'Douala]@@@',
934 'El_Aaiun]@@@',
935 'Freetown]@@@',
936 'Gaborone]@@@',
937 'Harare]@@@',
938 'Johannesburg]@@@',
939 'Juba]@@@',
940 'Kampala]@@@',
941 'Khartoum]@@@',
942 'Kigali]@@@',
943 'Kinshasa]@@@',
944 'Lagos]@@@',
945 'Libreville]@@@',
946 'Lome]@@@',
947 'Luanda]@@@',
948 'Lubumbashi]@@@',
949 'Lusaka]@@@',
950 'Malabo]@@@',
951 'Maputo]@@@',
952 'Maseru]@@@',
953 'Mbabane]@@@',
954 'Mogadishu]@@@',
955 'Monrovia]@@@',
956 'Nairobi]@@@',
957 'Ndjamena]@@@',
958 'Niamey]@@@',
959 'Nouakchott]@@@',
960 'Ouagadougou]@@@',
961 'Porto-Novo]@@@',
962 'Sao_Tome]@@@',
963 'Tripoli]@@@',
964 'Tunis]@@@',
965 'Windhoek]@@@',
966 'Adak]@@@',
967 'Anchorage]@@@',
968 'Anguilla]@@@',
969 'Antigua]@@@',
970 'Araguaina]@@@',
971 'Argentina/Buenos_Aires]@@@',
972 'Argentina/Catamarca]@@@',
973 'Argentina/Cordoba]@@@',
974 'Argentina/Jujuy]@@@',
975 'Argentina/La_Rioja]@@@',
976 'Argentina/Mendoza]@@@',
977 'Argentina/Rio_Gallegos]@@@',
978 'Argentina/Salta]@@@',
979 'Argentina/San_Juan]@@@',
980 'Argentina/San_Luis]@@@',
981 'Argentina/Tucuman]@@@',
982 'Argentina/Ushuaia]@@@',
983 'Aruba]@@@',
984 'Asuncion]@@@',
985 'Atikokan]@@@',
986 'Bahia]@@@',
987 'Bahia_Banderas]@@@',
988 'Barbados]@@@',
989 'Belem]@@@',
990 'Belize]@@@',
991 'Blanc-Sablon]@@@',
992 'Boa_Vista]@@@',
993 'Bogota]@@@',
994 'Boise]@@@',
995 'Cambridge_Bay]@@@',
996 'Campo_Grande]@@@',
997 'Cancun]@@@',
998 'Caracas]@@@',
999 'Cayenne]@@@',
1000 'Cayman]@@@',
1001 'Chicago]@@@',
1002 'Chihuahua]@@@',
1003 'Ciudad_Juarez]@@@',
1004 'Costa_Rica]@@@',
1005 'Coyhaique]@@@',
1006 'Creston]@@@',
1007 'Cuiaba]@@@',
1008 'Curacao]@@@',
1009 'Danmarkshavn]@@@',
1010 'Dawson]@@@',
1011 'Dawson_Creek]@@@',
1012 'Denver]@@@',
1013 'Detroit]@@@',
1014 'Dominica]@@@',
1015 'Edmonton]@@@',
1016 'Eirunepe]@@@',
1017 'El_Salvador]@@@',
1018 'Fort_Nelson]@@@',
1019 'Fortaleza]@@@',
1020 'Glace_Bay]@@@',
1021 'Goose_Bay]@@@',
1022 'Grand_Turk]@@@',
1023 'Grenada]@@@',
1024 'Guadeloupe]@@@',
1025 'Guatemala]@@@',
1026 'Guayaquil]@@@',
1027 'Guyana]@@@',
1028 'Halifax]@@@',
1029 'Havana]@@@',
1030 'Hermosillo]@@@',
1031 'Indiana/Indianapolis]@@@',
1032 'Indiana/Knox]@@@',
1033 'Indiana/Marengo]@@@',
1034 'Indiana/Petersburg]@@@',
1035 'Indiana/Tell_City]@@@',
1036 'Indiana/Vevay]@@@',
1037 'Indiana/Vincennes]@@@',
1038 'Indiana/Winamac]@@@',
1039 'Inuvik]@@@',
1040 'Iqaluit]@@@',
1041 'Jamaica]@@@',
1042 'Juneau]@@@',
1043 'Kentucky/Louisville]@@@',
1044 'Kentucky/Monticello]@@@',
1045 'Kralendijk]@@@',
1046 'La_Paz]@@@',
1047 'Lima]@@@',
1048 'Los_Angeles]@@@',
1049 'Lower_Princes]@@@',
1050 'Maceio]@@@',
1051 'Managua]@@@',
1052 'Manaus]@@@',
1053 'Marigot]@@@',
1054 'Martinique]@@@',
1055 'Matamoros]@@@',
1056 'Mazatlan]@@@',
1057 'Menominee]@@@',
1058 'Merida]@@@',
1059 'Metlakatla]@@@',
1060 'Mexico_City]@@@',
1061 'Miquelon]@@@',
1062 'Moncton]@@@',
1063 'Monterrey]@@@',
1064 'Montevideo]@@@',
1065 'Montserrat]@@@',
1066 'Nassau]@@@',
1067 'New_York]@@@',
1068 'Nome]@@@',
1069 'Noronha]@@@',
1070 'North_Dakota/Beulah]@@@',
1071 'North_Dakota/Center]@@@',
1072 'North_Dakota/New_Salem]@@@',
1073 'Nuuk]@@@',
1074 'Ojinaga]@@@',
1075 'Panama]@@@',
1076 'Paramaribo]@@@',
1077 'Phoenix]@@@',
1078 'Port-au-Prince]@@@',
1079 'Port_of_Spain]@@@',
1080 'Porto_Velho]@@@',
1081 'Puerto_Rico]@@@',
1082 'Punta_Arenas]@@@',
1083 'Rankin_Inlet]@@@',
1084 'Recife]@@@',
1085 'Regina]@@@',
1086 'Resolute]@@@',
1087 'Rio_Branco]@@@',
1088 'Santarem]@@@',
1089 'Santiago]@@@',
1090 'Santo_Domingo]@@@',
1091 'Sao_Paulo]@@@',
1092 'Scoresbysund]@@@',
1093 'Sitka]@@@',
1094 'St_Barthelemy]@@@',
1095 'St_Johns]@@@',
1096 'St_Kitts]@@@',
1097 'St_Lucia]@@@',
1098 'St_Thomas]@@@',
1099 'St_Vincent]@@@',
1100 'Swift_Current]@@@',
1101 'Tegucigalpa]@@@',
1102 'Thule]@@@',
1103 'Tijuana]@@@',
1104 'Toronto]@@@',
1105 'Tortola]@@@',
1106 'Vancouver]@@@',
1107 'Whitehorse]@@@',
1108 'Winnipeg]@@@',
1109 'Yakutat]@@@',
1110 'Casey]@@@',
1111 'Davis]@@@',
1112 'DumontDUrville]@@@',
1113 'Macquarie]@@@',
1114 'Mawson]@@@',
1115 'McMurdo]@@@',
1116 'Palmer]@@@',
1117 'Rothera]@@@',
1118 'Syowa]@@@',
1119 'Troll]@@@',
1120 'Vostok]@@@',
1121 'Longyearbyen]@@@',
1122 'Aden]@@@',
1123 'Almaty]@@@',
1124 'Amman]@@@',
1125 'Anadyr]@@@',
1126 'Aqtau]@@@',
1127 'Aqtobe]@@@',
1128 'Ashgabat]@@@',
1129 'Atyrau]@@@',
1130 'Baghdad]@@@',
1131 'Bahrain]@@@',
1132 'Baku]@@@',
1133 'Bangkok]@@@',
1134 'Barnaul]@@@',
1135 'Beirut]@@@',
1136 'Bishkek]@@@',
1137 'Brunei]@@@',
1138 'Chita]@@@',
1139 'Colombo]@@@',
1140 'Damascus]@@@',
1141 'Dhaka]@@@',
1142 'Dili]@@@',
1143 'Dubai]@@@',
1144 'Dushanbe]@@@',
1145 'Famagusta]@@@',
1146 'Gaza]@@@',
1147 'Hebron]@@@',
1148 'Ho_Chi_Minh]@@@',
1149 'Hong_Kong]@@@',
1150 'Hovd]@@@',
1151 'Irkutsk]@@@',
1152 'Jakarta]@@@',
1153 'Jayapura]@@@',
1154 'Jerusalem]@@@',
1155 'Kabul]@@@',
1156 'Kamchatka]@@@',
1157 'Karachi]@@@',
1158 'Kathmandu]@@@',
1159 'Khandyga]@@@',
1160 'Kolkata]@@@',
1161 'Krasnoyarsk]@@@',
1162 'Kuala_Lumpur]@@@',
1163 'Kuching]@@@',
1164 'Kuwait]@@@',
1165 'Macau]@@@',
1166 'Magadan]@@@',
1167 'Makassar]@@@',
1168 'Manila]@@@',
1169 'Muscat]@@@',
1170 'Nicosia]@@@',
1171 'Novokuznetsk]@@@',
1172 'Novosibirsk]@@@',
1173 'Omsk]@@@',
1174 'Oral]@@@',
1175 'Phnom_Penh]@@@',
1176 'Pontianak]@@@',
1177 'Pyongyang]@@@',
1178 'Qatar]@@@',
1179 'Qostanay]@@@',
1180 'Qyzylorda]@@@',
1181 'Riyadh]@@@',
1182 'Sakhalin]@@@',
1183 'Samarkand]@@@',
1184 'Seoul]@@@',
1185 'Shanghai]@@@',
1186 'Singapore]@@@',
1187 'Srednekolymsk]@@@',
1188 'Taipei]@@@',
1189 'Tashkent]@@@',
1190 'Tbilisi]@@@',
1191 'Tehran]@@@',
1192 'Thimphu]@@@',
1193 'Tokyo]@@@',
1194 'Tomsk]@@@',
1195 'Ulaanbaatar]@@@',
1196 'Urumqi]@@@',
1197 'Ust-Nera]@@@',
1198 'Vientiane]@@@',
1199 'Vladivostok]@@@',
1200 'Yakutsk]@@@',
1201 'Yangon]@@@',
1202 'Yekaterinburg]@@@',
1203 'Yerevan]@@@',
1204 'Atlantic/Azores]@@@',
1205 'Atlantic/Bermuda]@@@',
1206 'Atlantic/Canary]@@@',
1207 'Atlantic/Cape_Verde]@@@',
1208 'Atlantic/Faroe]@@@',
1209 'Atlantic/Madeira]@@@',
1210 'Atlantic/Reykjavik]@@@',
1211 'Atlantic/South_Georgia]@@@',
1212 'Atlantic/St_Helena]@@@',
1213 'Atlantic/Stanley]@@@',
1214 'Australia/Adelaide]@@@',
1215 'Australia/Brisbane]@@@',
1216 'Australia/Broken_Hill]@@@',
1217 'Australia/Darwin]@@@',
1218 'Australia/Eucla]@@@',
1219 'Australia/Hobart]@@@',
1220 'Australia/Lindeman]@@@',
1221 'Australia/Lord_Howe]@@@',
1222 'Australia/Melbourne]@@@',
1223 'Australia/Perth]@@@',
1224 'Australia/Sydney]@@@',
1225 'Amsterdam]@@@',
1226 'Andorra]@@@',
1227 'Astrakhan]@@@',
1228 'Athens]@@@',
1229 'Belgrade]@@@',
1230 'Berlin]@@@',
1231 'Bratislava]@@@',
1232 'Brussels]@@@',
1233 'Bucharest]@@@',
1234 'Budapest]@@@',
1235 'Busingen]@@@',
1236 'Chisinau]@@@',
1237 'Copenhagen]@@@',
1238 'Dublin]@@@',
1239 'Gibraltar]@@@',
1240 'Guernsey]@@@',
1241 'Helsinki]@@@',
1242 'Isle_of_Man]@@@',
1243 'Istanbul]@@@',
1244 'Jersey]@@@',
1245 'Kaliningrad]@@@',
1246 'Kirov]@@@',
1247 'Kyiv]@@@',
1248 'Lisbon]@@@',
1249 'Ljubljana]@@@',
1250 'London]@@@',
1251 'Luxembourg]@@@',
1252 'Madrid]@@@',
1253 'Malta]@@@',
1254 'Mariehamn]@@@',
1255 'Minsk]@@@',
1256 'Monaco]@@@',
1257 'Moscow]@@@',
1258 'Oslo]@@@',
1259 'Paris]@@@',
1260 'Podgorica]@@@',
1261 'Prague]@@@',
1262 'Riga]@@@',
1263 'Rome]@@@',
1264 'Samara]@@@',
1265 'San_Marino]@@@',
1266 'Sarajevo]@@@',
1267 'Saratov]@@@',
1268 'Simferopol]@@@',
1269 'Skopje]@@@',
1270 'Sofia]@@@',
1271 'Stockholm]@@@',
1272 'Tallinn]@@@',
1273 'Tirane]@@@',
1274 'Ulyanovsk]@@@',
1275 'Vaduz]@@@',
1276 'Vatican]@@@',
1277 'Vienna]@@@',
1278 'Vilnius]@@@',
1279 'Volgograd]@@@',
1280 'Warsaw]@@@',
1281 'Zagreb]@@@',
1282 'Zurich]@@@',
1283 'Antananarivo]@@@',
1284 'Chagos]@@@',
1285 'Christmas]@@@',
1286 'Cocos]@@@',
1287 'Comoro]@@@',
1288 'Kerguelen]@@@',
1289 'Mahe]@@@',
1290 'Maldives]@@@',
1291 'Mauritius]@@@',
1292 'Mayotte]@@@',
1293 'Reunion]@@@',
1294 'Apia]@@@',
1295 'Auckland]@@@',
1296 'Bougainville]@@@',
1297 'Chatham]@@@',
1298 'Chuuk]@@@',
1299 'Easter]@@@',
1300 'Efate]@@@',
1301 'Fakaofo]@@@',
1302 'Fiji]@@@',
1303 'Funafuti]@@@',
1304 'Galapagos]@@@',
1305 'Gambier]@@@',
1306 'Guadalcanal]@@@',
1307 'Guam]@@@',
1308 'Honolulu]@@@',
1309 'Kanton]@@@',
1310 'Kiritimati]@@@',
1311 'Kosrae]@@@',
1312 'Kwajalein]@@@',
1313 'Majuro]@@@',
1314 'Marquesas]@@@',
1315 'Midway]@@@',
1316 'Nauru]@@@',
1317 'Niue]@@@',
1318 'Norfolk]@@@',
1319 'Noumea]@@@',
1320 'Pago_Pago]@@@',
1321 'Palau]@@@',
1322 'Pitcairn]@@@',
1323 'Pohnpei]@@@',
1324 'Port_Moresby]@@@',
1325 'Rarotonga]@@@',
1326 'Saipan]@@@',
1327 'Tahiti]@@@',
1328 'Tarawa]@@@',
1329 'Tongatapu]@@@',
1330 'Wake]@@@',
1331 'Wallis]@@@',
1332 );
1333 if ( 'enabled' == $process_non_utc_timezones_status ) {
1334 $line = str_replace( $timezone_strings_to_replace, $timezone_replacement_strings, $line ); // add '@@@' as marker/separator after time stamp
1335 } else {
1336 $line = str_replace( 'UTC]', 'UTC]@@@', $line ); // add '@@@' as marker/separator after time stamp
1337 }
1338
1339 $line = str_replace( "Stack trace:", "<hr />Stack trace:", $line ); // add line break for stack trace section
1340 if ( strpos( $line, 'PHP Fatal' ) !== false ) {
1341 $line = str_replace( "#", "<hr />#", $line ); // add line break on PHP Fatal error's stack trace lines
1342 }
1343 $line = str_replace( "Argument <hr />#", "Argument #", $line ); // remove hr on certain error message
1344 $line = str_replace( "parameter <hr />#", "parameter #", $line ); // remove hr on certain error message
1345 $line = str_replace( "the <hr />#", "the #", $line ); // remove hr on certain error message
1346 $line = str_replace( "^\\", "[\\", $line ); // reverse the temporary replacement of '[\' with '^\'
1347 $line = str_replace( "^\"", "[\"", $line ); // reverse the temporary replacement of '["' with '^"'
1348 $line = str_replace( ":^", ":[", $line ); // reverse the temporary replacement of '[]' with '$#'
1349 $line = str_replace( "^internal function^", "[internal function]", $line );
1350 $prepended_line = '[' . $line; // Put back the missing '[' after explode operation
1351 $prepended_lines[] = $prepended_line;
1352 }
1353 }
1354
1355 // Reverse the order of the entries, so the newest entry is first
1356 $latest_lines = array_reverse( $prepended_lines );
1357
1358 // Will hold error details types
1359 $errors_master_list = array();
1360
1361 foreach( $latest_lines as $line ) {
1362 $line = wp_kses_post( $line );
1363
1364 if ( false !== strpos( $line, '@@@' ) ) {
1365 $line = explode("@@@ ", trim( $line ) ); // split the line using the '@@@' marker/separator defined earlier. '@@@' will be deleted by explode().
1366 }
1367
1368 if ( is_array( $line ) && isset( $line[0] ) ) {
1369 $timestamp = str_replace( [ "[", "]" ], "", $line[0] );
1370 } else {
1371 $timestamp = '';
1372 }
1373
1374 $wp_version = get_bloginfo( 'version' );
1375
1376 // Initialize error-related variables
1377 $error = '';
1378 $error_source = '';
1379 $error_file = '';
1380 $error_file_path = '';
1381 $error_file_line = '';
1382
1383 if ( is_array( $line ) && isset( $line[1] ) ) {
1384 $error = $line[1];
1385
1386 // Check if there is a file path to pluck out of the error line
1387 if ( false !== strpos( $error, ABSPATH ) ) {
1388
1389 // Separata file path and error line from error message
1390
1391 // Handling for PHP Fatal errors with stack trace included
1392 if ( false !== strpos( $error, 'Stack trace:' ) ) {
1393 $error_parts = explode( 'Stack trace:', $error );
1394 $error_message = str_replace( '<hr />', '', $error_parts[0] );
1395 if ( isset( $error_parts[1] ) ) {
1396 $error_stack_trace = ' ' . $error_parts[1];
1397 }
1398
1399 $error_message_parts = explode( ' in /', $error_message );
1400
1401 // Reconstruct the error details without error file path and line info
1402 $error = $error_message_parts[0] . '<hr />Stack trace:' . $error_stack_trace;
1403 // Shorten the file path in the error details
1404 $error = str_replace( ABSPATH, '/', $error );
1405 if ( isset( $error_message_parts[1] ) ) {
1406 $error_file = '/' . $error_message_parts[1];
1407 $error_file_info = explode ( ':', $error_file );
1408 $error_file_path = $error_file_info[0];
1409 if ( array_key_exists('1', $error_file_info) ) {
1410 $error_file_line = $error_file_info[1];
1411 }
1412 }
1413 } else {
1414 $error_message_parts = explode( ' in /', $error );
1415
1416 $error = $error_message_parts[0];
1417 if ( isset( $error_message_parts[1] ) ) {
1418 $error_file = '/' . $error_message_parts[1];
1419
1420 $error_file_info = explode ( ' on line ', $error_file );
1421 $error_file_path = $error_file_info[0];
1422 if ( array_key_exists('1', $error_file_info) ) {
1423 $error_file_line = $error_file_info[1];
1424 }
1425 }
1426 }
1427
1428 // Define whether source of error is WP Core, Theme, Plugin or Other
1429
1430 if ( ( false !== strpos( $error_file_path, $wp_admin_path ) ) ||
1431 ( false !== strpos( $error_file_path, $wp_includes_path ) ) ) {
1432 $error_source = __( 'WordPress core', 'debug-log-manager' );
1433 $error_file_path_for_url = str_replace( ABSPATH, '', $error_file_path );
1434 $error_file_path = str_replace( array( $wp_admin_path, $wp_includes_path ), '', $error_file_path ); // e.g. /post.php
1435 $error_file_path_final = str_replace( ABSPATH, '/', $wp_admin_path ) . str_replace( array( $wp_admin_path, $wp_includes_path ), '/', $error_file_path ); // e.g. /post.php
1436 } elseif ( ( false !== strpos( $error_file_path, $theme_dir_path ) ) ) {
1437 $error_source = __( 'Theme', 'debug-log-manager' );
1438 $error_file_path = str_replace( $theme_dir_path, '', $error_file_path ); // e.g. /twentytwentyfive/functions.php
1439 $error_file_path_final = str_replace( ABSPATH, '/', $theme_dir_path ) . str_replace( $theme_dir_path, '', $error_file_path ); // e.g. /wp-content/themes/twentytwentyfive/functions.php
1440 } elseif ( ( false !== strpos( $error_file_path, $wp_plugin_dir_path ) ) ) {
1441 $error_source = __( 'Plugin', 'debug-log-manager' );
1442 $error_file_path = str_replace( $wp_plugin_dir_path, '', $error_file_path ); // e.g. /debug-log-manager/bootstrap.php
1443 $error_file_path_final = str_replace( ABSPATH, '/', $wp_plugin_dir_path ) . str_replace( $wp_plugin_dir_path, '', $error_file_path ); // e.g. /wp-content/plugins/debug-log-manager/bootstrap.php
1444 } else {
1445 $error_source = '';
1446 $error_file_path = '';
1447 $error_file_path_final = '';
1448 }
1449
1450 // Get plugin/theme directory name of error file when error source is plugin or theme
1451
1452 if ( ( 'Plugin' == $error_source ) || ( 'Theme' == $error_source ) ) {
1453 $error_file_path_parts = explode( '/', $error_file_path );
1454 $error_file_directory = $error_file_path_parts[1]; // e.g. post.php, debug-log-manager or twentytwentyfive
1455 }
1456
1457 // Get plugin name
1458
1459 $plugins = get_plugins();
1460
1461 if ( 'Plugin' == $error_source ) {
1462 foreach ( $plugins as $plugin_path_file => $plugin_info ) {
1463 if ( false !== strpos( $plugin_path_file, $error_file_directory ) ) {
1464 $error_source_plugin_path_file = $plugin_path_file;
1465 $error_source_plugin_name = $plugin_info['Name'];
1466 $error_source_plugin_uri = $plugin_info['PluginURI'];
1467 // $error_source_plugin_version = $plugin_info['Version'];
1468 }
1469 }
1470 }
1471
1472 // Get theme name
1473
1474 if ( 'Theme' == $error_source ) {
1475 $theme = wp_get_theme( $error_file_directory );
1476 if ( $theme->exists() ) {
1477 $error_source_theme_dir = $error_file_directory;
1478 $error_source_theme_name = $theme->get( 'Name' );
1479 $error_source_theme_uri = $theme->get( 'ThemeURI' );
1480 // $error_source_theme_version = $theme->get( 'Version' );
1481 } else {
1482 $error_source_theme_name = $error_file_directory;
1483 }
1484 }
1485
1486 }
1487
1488 } else {
1489
1490 // $error = __( 'No error message specified...', 'debug-log-manager' );
1491 $error = $line; // Raw log entry
1492
1493 }
1494
1495 // Stopgap measure to prevent fatal error in strpos() beneath, which expects $error to be a string
1496 if ( is_array( $error ) ) {
1497 $error = maybe_serialize( $error );
1498 }
1499
1500 if ( ( false !== strpos( $error, 'PHP Fatal' ) )
1501 || ( false !== strpos( $error, 'FATAL' ) )
1502 || ( false !== strpos( $error, 'E_ERROR' ) ) )
1503 {
1504 $error_type = __( 'PHP Fatal', 'debug-log-manager' );
1505 $error_details = str_replace( "PHP Fatal error: ", "", $error );
1506 $error_details = str_replace( "PHP Fatal: ", "", $error_details );
1507 $error_details = str_replace( "FATAL ", "", $error_details );
1508 $error_details = str_replace( "E_ERROR: ", "", $error_details );
1509 } elseif ( ( false !== strpos( $error, 'PHP Warning' ) )
1510 || ( false !== strpos( $error, 'E_WARNING' ) ) )
1511 {
1512 $error_type = __( 'PHP Warning', 'debug-log-manager' );
1513 $error_details = str_replace( "PHP Warning: ", "", $error );
1514 $error_details = str_replace( "E_WARNING: ", "", $error_details );
1515 } elseif ( ( false !== strpos( $error, 'PHP Notice' ) )
1516 || ( false !== strpos( $error, 'E_NOTICE' ) ) )
1517 {
1518 $error_type = __( 'PHP Notice', 'debug-log-manager' );
1519 $error_details = str_replace( "PHP Notice: ", "", $error );
1520 $error_details = str_replace( "E_NOTICE: ", "", $error_details );
1521 } elseif ( false !== strpos( $error, 'PHP Deprecated' ) ) {
1522 $error_type = __( 'PHP Deprecated', 'debug-log-manager' );
1523 $error_details = str_replace( "PHP Deprecated: ", "", $error );
1524 } elseif ( ( false !== strpos( $error, 'PHP Parse' ) )
1525 || ( false !== strpos( $error, 'E_PARSE' ) ) )
1526 {
1527 $error_type = __( 'PHP Parse', 'debug-log-manager' );
1528 $error_details = str_replace( "PHP Parse error: ", "", $error );
1529 $error_details = str_replace( "E_PARSE: ", "", $error_details );
1530 } elseif ( false !== strpos( $error, 'EXCEPTION:' ) ) {
1531 $error_type = __( 'PHP Exception', 'debug-log-manager' );
1532 $error_details = str_replace( "EXCEPTION: ", "", $error );
1533 } elseif ( false !== strpos( $error, 'WordPress database error' ) ) {
1534 $error_type = __( 'Database', 'debug-log-manager' );
1535 $error_details = str_replace( "WordPress database error ", "", $error );
1536 } elseif ( false !== strpos( $error, 'JavaScript Error' ) ) {
1537 $error_type = __( 'JavaScript', 'debug-log-manager' );
1538 $error_details = str_replace( "JavaScript Error: ", "", $error );
1539 } else {
1540 $error_type = __( 'Other', 'debug-log-manager' );
1541 $error_details = $error;
1542 if ( $this->is_json( $error_details ) ) {
1543 // For JSON string in error message, originally added via error_log( json_encode( $variable ) )
1544 // This will output said JSON string as well-formated array in the log entries table
1545 $error_details = '<pre>' . print_r( json_decode( $error_details, true ), true ) . '</pre>';
1546 }
1547 }
1548
1549 // Append error source, file path and line number info to error details. If core plugin/theme editor is not disabled, link file path to the editor view.
1550
1551 if ( ! empty( $error_source ) ) {
1552 if ( 'WordPress core' == $error_source ) {
1553 $file_viewer_url = 'https://github.com/WordPress/wordpress-develop/blob/' . $wp_version . '/src/' . $error_file_path_for_url . '#L' . $error_file_line;
1554 $error_details = '<span class="error-details">' . $error_details . '</span><hr />' . $error_source . '<br />' . __( 'File', 'debug-log-manager' ) . ': <a href="' . $file_viewer_url . '" target="_blank" class="error-source-link">' . $error_file_path_final . '<span class="dashicons dashicons-visibility offset-down"></span></a><br />' . __( 'Line', 'debug-log-manager' ) . ': ' . $error_file_line;
1555 } elseif ( 'Theme' == $error_source ) {
1556 if ( ! defined( 'DISALLOW_FILE_EDIT' ) || ( false === constant( 'DISALLOW_FILE_EDIT' ) ) ) {
1557 $file_viewer_url = get_admin_url() . 'theme-editor.php?file=' . urlencode( str_replace( '/' . $error_source_theme_dir . '/', '', $error_file_path ) ) . '&theme=' . $error_source_theme_dir;
1558 $error_details = '<span class="error-details">' . $error_details . '</span><hr />' . $error_source . ': <a href="' . $error_source_theme_uri . '" target="_blank" class="error-source-link">' . $error_source_theme_name . '<span class="dashicons dashicons-external offset-up"></span></a><br />' . __( 'File', 'debug-log-manager' ) . ': <a href="' . $file_viewer_url . '" target="_blank" class="error-source-link">' . $error_file_path_final . '<span class="dashicons dashicons-visibility offset-down"></span></a><br />' . __( 'Line', 'debug-log-manager' ) . ': ' . $error_file_line;
1559 }
1560 if ( defined( 'DISALLOW_FILE_EDIT' ) && ( true === constant( 'DISALLOW_FILE_EDIT' ) ) ) {
1561 $error_details = '<span class="error-details">' . $error_details . '</span><hr />' . $error_source . ': <a href="' . $error_source_theme_uri . '" target="_blank" class="error-source-link">' . $error_source_theme_name . '<span class="dashicons dashicons-external offset-up"></span></a><br />' . __( 'File', 'debug-log-manager' ) . ': ' . $error_file_path_final . '<br />' . __( 'Line', 'debug-log-manager' ) . ': ' . $error_file_line;
1562 }
1563 } elseif ( 'Plugin' == $error_source ) {
1564 if ( ! defined( 'DISALLOW_FILE_EDIT' ) || ( false === constant( 'DISALLOW_FILE_EDIT' ) ) ) {
1565 $file_viewer_url = get_admin_url() . 'plugin-editor.php?file=' . urlencode( substr( $error_file_path, 1 ) ) . '&plugin=' . urlencode( $error_source_plugin_path_file );
1566 $error_details = '<span class="error-details">' . $error_details . '</span><hr />' . $error_source . ': <a href="' . $error_source_plugin_uri . '" target="_blank" class="error-source-link">' . $error_source_plugin_name . '<span class="dashicons dashicons-external offset-up"></span></a><br />' . __( 'File', 'debug-log-manager' ) . ': <a href="' . $file_viewer_url . '" target="_blank" class="error-source-link">' . $error_file_path_final . '<span class="dashicons dashicons-visibility offset-down"></span></a><br />' . __( 'Line', 'debug-log-manager' ) . ': ' . $error_file_line;
1567 }
1568 if ( defined( 'DISALLOW_FILE_EDIT' ) && ( true === constant( 'DISALLOW_FILE_EDIT' ) ) ) {
1569 $error_details = '<span class="error-details">' . $error_details . '</span><hr />' . $error_source . ': <a href="' . $error_source_plugin_uri . '" target="_blank" class="error-source-link">' . $error_source_plugin_name . '<span class="dashicons dashicons-external offset-up"></span></a><br />' . __( 'File', 'debug-log-manager' ) . ': ' . $error_file_path_final . '<br />' . __( 'Line', 'debug-log-manager' ) . ': ' . $error_file_line;
1570 }
1571 }
1572 }
1573
1574 // https://www.php.net/manual/en/function.array-search.php#120784
1575 if ( array_search( trim( $error_details ), array_column( $errors_master_list, 'details' ) ) === false ) {
1576
1577 $errors_master_list[] = array(
1578 'type' => $error_type,
1579 'details' => trim( $error_details ),
1580 'occurrences' => array( $timestamp ),
1581 );
1582
1583 } else {
1584
1585 $error_position = array_search( trim( $error_details ), array_column( $errors_master_list, 'details' ) ); // integer
1586
1587 array_push( $errors_master_list[$error_position]['occurrences'], $timestamp );
1588
1589 }
1590
1591 }
1592
1593 return json_encode( $errors_master_list );
1594
1595 }
1596
1597 /**
1598 * Get the latest entries for auto-refresh feature
1599 *
1600 * @since 1.0.0
1601 */
1602 public function get_latest_entries() {
1603
1604 if ( isset( $_REQUEST ) && current_user_can( 'manage_options' ) ) {
1605
1606 if ( wp_verify_nonce( sanitize_text_field( $_REQUEST['nonce'] ), 'dlm-app' . get_current_user_id() ) ) {
1607
1608 $errors_master_list = json_decode( $this->get_processed_entries(), true );
1609
1610 $n = 1;
1611 $entries = array();
1612
1613 foreach ( $errors_master_list as $error ) {
1614
1615 if ( function_exists( 'wp_date' ) ) {
1616 $localized_timestamp = wp_date( 'M j, Y - H:i:s', strtotime( $error['occurrences'][0] ) ); // last occurrence
1617 } else {
1618 $localized_timestamp = date_i18n( 'M j, Y - H:i:s', strtotime( $error['occurrences'][0] ) );
1619 }
1620
1621 $occurrence_count = count( $error['occurrences'] );
1622
1623 $entry = array(
1624 $n,
1625 $error['type'],
1626 $error['details'],
1627 $localized_timestamp . '<br /><span class="dlm-faint">(' . sprintf( _n( '%s occurrence logged', '%s occurrences logged', $occurrence_count, 'debug-log-manager' ), number_format_i18n( $occurrence_count ) ) . ')<span>',
1628 );
1629
1630 $entries[] = $entry;
1631
1632 $n++;
1633
1634 }
1635
1636 $data = array(
1637 'entries' => $entries,
1638 );
1639
1640 }
1641
1642 } else {
1643
1644 $data = array();
1645
1646 }
1647
1648 echo json_encode( $data );
1649
1650 }
1651
1652 /**
1653 * Get debug log in data table format
1654 *
1655 * @since 1.0.0
1656 */
1657 public function get_entries_datatable() {
1658
1659 ?>
1660 <div>
1661 <select id="errorTypeFilter" class="dlm-error-type-filter">
1662 <option value=""><?php esc_html_e( 'All Types', 'debug-log-manager' ); ?></option>
1663 <option value="<?php esc_attr_e( 'PHP Fatal', 'debug-log-manager' ); ?>"><?php esc_html_e( 'PHP Fatal', 'debug-log-manager' ); ?></option>
1664 <option value="<?php esc_attr_e( 'PHP Warning', 'debug-log-manager' ); ?>"><?php esc_html_e( 'PHP Warning', 'debug-log-manager' ); ?></option>
1665 <option value="<?php esc_attr_e( 'PHP Notice', 'debug-log-manager' ); ?>"><?php esc_html_e( 'PHP Notice', 'debug-log-manager' ); ?></option>
1666 <option value="<?php esc_attr_e( 'PHP Deprecated', 'debug-log-manager' ); ?>"><?php esc_html_e( 'PHP Deprecated', 'debug-log-manager' ); ?></option>
1667 <option value="<?php esc_attr_e( 'PHP Parse', 'debug-log-manager' ); ?>"><?php esc_html_e( 'PHP Parse', 'debug-log-manager' ); ?></option>
1668 <option value="<?php esc_attr_e( 'PHP Exception', 'debug-log-manager' ); ?>"><?php esc_html_e( 'PHP Exception', 'debug-log-manager' ); ?></option>
1669 <option value="<?php esc_attr_e( 'Database', 'debug-log-manager' ); ?>"><?php esc_html_e( 'Database', 'debug-log-manager' ); ?></option>
1670 <option value="<?php esc_attr_e( 'JavaScript', 'debug-log-manager' ); ?>"><?php esc_html_e( 'JavaScript', 'debug-log-manager' ); ?></option>
1671 <option value="<?php esc_attr_e( 'Other', 'debug-log-manager' ); ?>"><?php esc_html_e( 'Other', 'debug-log-manager' ); ?></option>
1672 </select>
1673 </div>
1674 <table id="debug-log" class="wp-list-table widefat striped">
1675 <thead>
1676 <tr>
1677 <th class="dlm-entry-no">#</th>
1678 <th class="dlm-entry-type"><?php esc_html_e( 'Type', 'debug-log-manager' ); ?></th>
1679 <th class="dlm-entry-details"><?php esc_html_e( 'Details', 'debug-log-manager' ); ?></th>
1680 <th class="dlm-entry-datetime"><?php esc_html_e( 'Last Occurrence', 'debug-log-manager' ); ?></th>
1681 </tr>
1682 </thead>
1683 <tbody>
1684 <?php
1685
1686 $errors_master_list = json_decode( $this->get_processed_entries(), true );
1687
1688 $n = 1;
1689
1690 foreach ( $errors_master_list as $error ) {
1691
1692 if ( function_exists( 'wp_date' ) ) {
1693 $localized_timestamp = wp_date( 'M j, Y - H:i:s', strtotime( $error['occurrences'][0] ) ); // last occurrence
1694 } else {
1695 $localized_timestamp = date_i18n( 'M j, Y - H:i:s', strtotime( $error['occurrences'][0] ) );
1696 }
1697
1698 $occurrence_count = count( $error['occurrences'] );
1699 ?>
1700
1701 <tr>
1702 <td class="dlm-entry-no"><?php echo esc_html( $n ); ?></td>
1703 <td class="dlm-entry-type"><?php echo esc_html( $error['type'] ); ?></td>
1704 <td class="dlm-entry-details"><?php echo wp_kses( $error['details'], 'post' ); ?></td>
1705 <td class="dlm-entry-datetime"><?php echo esc_html( $localized_timestamp ); ?><br /><span class="dlm-faint">(<?php printf( esc_html( _n( '%s occurrence logged', '%s occurrences logged', $occurrence_count, 'debug-log-manager' ) ), esc_html( number_format_i18n( $occurrence_count ) ) ); ?>)<span></td>
1706 </tr>
1707
1708 <?php
1709 $n++;
1710
1711 }
1712
1713 ?>
1714 </tbody>
1715 </table>
1716 <?php
1717
1718 }
1719
1720 /**
1721 * Get entries for dashboard widget
1722 *
1723 * @since 1.8.0
1724 */
1725 public function get_dashboard_widget_entries() {
1726
1727 $errors_master_list = json_decode( $this->get_processed_entries(), true );
1728
1729 $n = 1;
1730 $entries_to_show = 5;
1731
1732 ?>
1733 <style>
1734
1735 #debug_log_manager_widget.postbox .inside {
1736 margin: 0;
1737 padding: 0;
1738 }
1739
1740 .dlm-dashboard-widget-entry {
1741 padding: 12px;
1742 border-bottom: 1px solid #e6e7e7;
1743 word-wrap: break-word; /* All browsers since IE 5.5+ */
1744 overflow-wrap: break-word; /* Renamed property in CSS3 draft spec */
1745 }
1746
1747 .dlm-dashboard-widget-entry:nth-child(odd) {
1748 background-color: #f6f7f7;
1749 }
1750
1751 .dlm-dashboard-widget-entry-message a.error-source-link {
1752 color: #50575e;
1753 text-decoration: none;
1754 }
1755
1756 .dlm-dashboard-widget-entry-message a.error-source-link span {
1757 position: relative;
1758 margin-left: 2px;
1759 color: #777;
1760 font-size: 18px;
1761 width: 18px;
1762 height: 18px;
1763 transition: .25s;
1764 text-decoration: none;
1765 }
1766
1767 .dlm-dashboard-widget-entry-message a.error-source-link span.offset-up {
1768 top: -1px;
1769 }
1770
1771 .dlm-dashboard-widget-entry-message a.error-source-link span.offset-down {
1772 top: 1px;
1773 }
1774
1775 .dlm-dashboard-widget-entry-message a.error-source-link:hover {
1776 color: #2271b1;
1777 text-decoration: underline;
1778 }
1779
1780 #debug-log .dlm-entry-details a.error-source-link:hover span {
1781 color: #2271b1;
1782 text-decoration: none;
1783 }
1784
1785 .dlm-dashboard-widget-entry-meta {
1786 display: flex;
1787 }
1788
1789 .dlm-dashboard-widget-entry-type {
1790 margin-right: 4px;
1791 font-weight: 600;
1792 }
1793
1794 .dlm-dashboard-widget-footer {
1795 display: flex;
1796 justify-content: space-between;
1797 align-items: center;
1798 width: 100%;
1799 box-sizing: border-box;
1800 padding: 12px;
1801 background-color: #f6f7f7;
1802 }
1803
1804 </style>
1805 <div class="dlm-dashboard-widget-entries">
1806 <?php
1807
1808 foreach ( $errors_master_list as $error ) {
1809
1810 if ( $n <= $entries_to_show ) {
1811
1812 if ( function_exists( 'wp_date' ) ) {
1813 $localized_timestamp = wp_date( 'M j, Y, H:i:s', strtotime( $error['occurrences'][0] ) ); // last occurrence
1814 } else {
1815 $localized_timestamp = date_i18n( 'M j, Y - H:i:s', strtotime( $error['occurrences'][0] ) );
1816 }
1817
1818 $occurrence_count = count( $error['occurrences'] );
1819
1820 ?>
1821 <div class="dlm-dashboard-widget-entry">
1822 <div class="dlm-dashboard-widget-entry-meta">
1823 <div class="dlm-dashboard-widget-entry-type">
1824 <?php echo esc_html( $error['type'] ); ?>
1825 </div>
1826 <div class="dlm-dashboard-widget-entry-datetime">
1827 | <?php echo esc_html( $localized_timestamp ); ?>
1828 </div>
1829 </div>
1830 <div class="dlm-dashboard-widget-entry-message">
1831 <?php echo wp_kses( $error['details'], 'post' ); ?>
1832 </div>
1833 </div>
1834 <?php
1835
1836 }
1837
1838 $n++;
1839
1840 }
1841
1842 ?>
1843 </div>
1844 <div class="dlm-dashboard-widget-footer">
1845 <div class="dlm-dashboard-widget-logging-status">
1846 <?php echo wp_kses_post( $this->get_status() ); ?>
1847 </div>
1848 <a href="<?php echo esc_html( get_dashboard_url() ); ?>tools.php?page=debug-log-manager" class="button"><?php esc_html_e( 'Go to Debug Log Manager', 'debug-log-manager' ); ?></a>
1849 </div>
1850 <?php
1851
1852 }
1853
1854 /**
1855 * Clear log file
1856 *
1857 * @since 1.0.0
1858 */
1859 public function clear_log() {
1860
1861 if ( isset( $_REQUEST ) && current_user_can( 'manage_options' ) ) {
1862
1863 if ( wp_verify_nonce( sanitize_text_field( $_REQUEST['nonce'] ), 'dlm-app' . get_current_user_id() ) ) {
1864
1865 $debug_log_file_path = get_option( 'debug_log_manager_file_path' );
1866
1867 file_put_contents( $debug_log_file_path, '' );
1868
1869 echo true;
1870
1871 }
1872
1873 }
1874
1875 }
1876
1877 /**
1878 * Disable WP core's plugin/theme editor
1879 *
1880 * @since 2.0.0
1881 */
1882 public function disable_wp_file_editor() {
1883
1884 if ( isset( $_REQUEST ) && current_user_can( 'manage_options' ) ) {
1885 if ( wp_verify_nonce( sanitize_text_field( $_REQUEST['nonce'] ), 'dlm-app' . get_current_user_id() ) ) {
1886
1887 $options = array(
1888 'add' => true, // Add the config if missing.
1889 'raw' => true, // Display value in raw format without quotes.
1890 'normalize' => false, // Normalize config output using WP Coding Standards.
1891 );
1892
1893 $this->wp_config->update( 'constant', 'DISALLOW_FILE_EDIT', 'true', $options );
1894
1895 // Prepare entries from the debug log for the data table
1896
1897 $errors_master_list = json_decode( $this->get_processed_entries(), true );
1898
1899 $n = 1;
1900 $entries = array();
1901
1902 foreach ( $errors_master_list as $error ) {
1903
1904 if ( function_exists( 'wp_date' ) ) {
1905 $localized_timestamp = wp_date( 'M j, Y - H:i:s', strtotime( $error['occurrences'][0] ) ); // last occurrence
1906 } else {
1907 $localized_timestamp = date_i18n( 'M j, Y - H:i:s', strtotime( $error['occurrences'][0] ) );
1908 }
1909
1910 $occurrence_count = count( $error['occurrences'] );
1911
1912 $entry = array(
1913 $n,
1914 $error['type'],
1915 $error['details'],
1916 $localized_timestamp . '<br /><span class="dlm-faint">(' . sprintf( _n( '%s occurrence logged', '%s occurrences logged', $occurrence_count, 'debug-log-manager' ), number_format_i18n( $occurrence_count ) ) . ')<span>',
1917 );
1918
1919 $entries[] = $entry;
1920
1921 $n++;
1922
1923 }
1924
1925 // Assemble data to return
1926
1927 $data = array(
1928 'status' => 'disabled', // Plugin/theme editor
1929 'entries' => $entries, // To parse data table with unlinked plugin/theme file paths
1930 );
1931
1932 echo json_encode( $data );
1933
1934 }
1935 }
1936
1937 }
1938
1939 /**
1940 * Log javascript errors
1941 *
1942 * @since 1.4.0
1943 */
1944 public function log_js_errors() {
1945
1946 // Since we are using XHR for the js error logging, JSON data comes in via php://input
1947 $request = json_decode(urldecode(file_get_contents('php://input')), true); // an array
1948
1949 // Verify error content and nonce and then log the JS error
1950 // Source: https://plugins.svn.wordpress.org/lh-javascript-error-log/trunk/lh-javascript-error-log.php
1951 if ( isset( $request['message'] ) && isset( $request['script'] ) && isset( $request['lineNo'] ) && isset( $request['columnNo'] ) && ! empty( $request['nonce'] ) && wp_verify_nonce( $request['nonce'], DLM_SLUG ) ) {
1952
1953 // Sanitize all input data
1954 $message = sanitize_text_field( $request['message'] );
1955 $script = sanitize_text_field( $request['script'] );
1956 $line_number = sanitize_text_field( $request['lineNo'] );
1957 $column_number = sanitize_text_field( $request['columnNo'] );
1958 $page_url = sanitize_text_field( $request['pageUrl'] );
1959
1960 // The following entry will then be output with wp_kses()
1961 error_log( 'JavaScript Error: ' . $message . ' in ' . $script . ' on line ' . $line_number . ' column ' . $column_number . ' at ' . get_site_url() . $page_url );
1962
1963 } else {
1964
1965 wp_die();
1966
1967 }
1968
1969 }
1970
1971 /**
1972 * Check if a string is valid JSON
1973 *
1974 * @link https://stackoverflow.com/a/6041773
1975 * @since 2.1.0
1976 */
1977 public function is_json( $string ) {
1978
1979 json_decode( $string );
1980 return json_last_error() === JSON_ERROR_NONE;
1981
1982 }
1983
1984 }