PluginProbe
Debug Log Manager – Conveniently Monitor and Inspect Errors / 2.5.0
Debug Log Manager – Conveniently Monitor and Inspect Errors v2.5.0
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.5.0, at classes/class-debug-log.php

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