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 / bootstrap.php

bootstrap.php in Debug Log Manager – Conveniently Monitor and Inspect Errors 2.4.2, at bootstrap.php

567 lines 19.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 // We're using the singleton design pattern
4 // https://code.tutsplus.com/articles/design-patterns-in-wordpress-the-singleton-pattern--wp-31621
5 // https://carlalexander.ca/singletons-in-wordpress/
6 // https://torquemag.io/2016/11/singletons-wordpress-good-evil/
7
8 /**
9 * Main class of the plugin used to add functionalities
10 *
11 * @since 1.0.0
12 */
13 class Debug_Log_Manager {
14
15 // Refers to a single instance of this class
16 private static $instance = null;
17
18 // For the debug log object
19 private $debug_log;
20
21 // For the wp-config object
22 private $wp_config;
23
24 /**
25 * Creates or returns a single instance of this class
26 *
27 * @return Debug_Log_Manager a single instance of this class.
28 */
29 public static function get_instance() {
30
31 if ( null == self::$instance ) {
32 self::$instance = new self;
33 }
34
35 return self::$instance;
36
37 }
38
39 /**
40 * Initialize plugin functionalities
41 */
42 private function __construct() {
43
44 global $pagenow;
45
46 // Register admin menu and subsequently the main admin page
47 add_action( 'admin_menu', [ $this, 'register_admin_menu' ] );
48
49 // Do not display any admin notices while viewing logs.
50 add_action( 'admin_notices', [ $this, 'suppress_admin_notices' ], 0 );
51 add_action( 'all_admin_notices', [ $this, 'suppress_generic_notices' ], 0 );
52
53 // Add action links
54 add_filter( 'plugin_action_links_'.DLM_SLUG.'/'.DLM_SLUG.'.php', [ $this, 'action_links' ] );
55
56 if ( is_admin() ) {
57
58 if ( $this->is_dlm() ) {
59
60 // Update footer text
61 add_filter( 'admin_footer_text', [ $this, 'footer_text' ] );
62
63 // Replace WP version text in footer
64 add_filter( 'update_footer', [ $this, 'footer_version_text' ], 20 );
65
66
67 // Enqueue admin scripts and styles only on the plugin's main page
68 add_action( 'admin_enqueue_scripts', [ $this, 'admin_scripts' ] );
69
70 }
71
72 }
73
74 // Enqueue admin scripts and styles on plugin editor page
75 if ( 'plugin-editor.php' === $pagenow ) {
76 add_action( 'admin_enqueue_scripts', [ $this, 'plugin_editor_scripts' ] );
77 }
78
79 // Enqueue admin scripts and styles on theme editor page
80 if ( 'theme-editor.php' === $pagenow ) {
81 add_action( 'admin_enqueue_scripts', [ $this, 'theme_editor_scripts' ] );
82 }
83
84 // Add admin bar icon if error logging is enabled and admin URL is not the plugin's main page. It will show on on the front end too (when logged-in), as we're also logging JavaScript errors.
85
86 $default_value = array(
87 'status' => 'disabled',
88 'on' => date( 'Y-m-d H:i:s' ),
89 );
90
91 $logging_info = get_option( 'debug_log_manager', $default_value );
92 $logging_status = $logging_info['status'];
93
94 if ( ( $logging_status == 'enabled' ) && ! $this->is_dlm() ) {
95
96 // https://developer.wordpress.org/reference/hooks/admin_bar_menu/
97 add_action( 'admin_bar_menu', [ $this, 'admin_bar_icon' ], 100 );
98
99 }
100
101 // Add dashboard widget
102 add_action( 'wp_dashboard_setup', [ $this, 'add_dashboard_widget' ] );
103
104 // Add inline CSS for the admin bar icon (menu item)
105 add_action( 'admin_enqueue_scripts', [ $this, 'admin_bar_icon_css' ] );
106 add_action( 'wp_enqueue_scripts', [ $this, 'admin_bar_icon_css' ] );
107
108 // Enqueue public scripts and styles
109 add_action( 'wp_enqueue_scripts', [ $this, 'public_scripts' ] );
110
111 // Register ajax calls
112 $this->debug_log = new DLM\Classes\Debug_Log;
113 $this->wp_config = new DLM\Classes\WP_Config_Transformer;
114 add_action( 'wp_ajax_toggle_debugging', [ $this->debug_log, 'toggle_debugging' ] );
115 add_action( 'wp_ajax_toggle_autorefresh', [ $this->debug_log, 'toggle_autorefresh' ] );
116 add_action( 'wp_ajax_get_latest_entries', [ $this->debug_log, 'get_latest_entries' ] );
117 add_action( 'wp_ajax_clear_log', [ $this->debug_log, 'clear_log' ] );
118 add_action( 'wp_ajax_disable_wp_file_editor', [ $this->debug_log, 'disable_wp_file_editor' ] );
119 add_action( 'wp_ajax_toggle_js_error_logging', [ $this->debug_log, 'toggle_js_error_logging' ] );
120 add_action( 'wp_ajax_toggle_script_debug_modification_status', [ $this->debug_log, 'toggle_script_debug_modification_status' ] );
121 add_action( 'wp_ajax_toggle_process_non_utc_timezones_status', [ $this->debug_log, 'toggle_process_non_utc_timezones_status' ] );
122 add_action( 'wp_ajax_log_js_errors', [ $this->debug_log, 'log_js_errors' ] );
123 add_action( 'wp_ajax_nopriv_log_js_errors', [ $this->debug_log, 'log_js_errors' ] );
124
125 }
126
127 /**
128 * Check if current screen is this plugin's main page
129 *
130 * @since 1.0.0
131 */
132 public function is_dlm() {
133
134 $request_uri = sanitize_text_field( $_SERVER['REQUEST_URI'] ); // e.g. /wp-admin/index.php?page=page-slug
135
136 if ( strpos( $request_uri, 'tools.php?page=' . DLM_SLUG ) !== false ) {
137 return true; // Yes, this is the plugin's main page
138 } else {
139 return false; // Nope, this is NOT the plugin's page
140 }
141
142 }
143
144 /**
145 * Register admin menu
146 *
147 * @since 1.0.0
148 */
149 public function register_admin_menu() {
150
151 add_submenu_page(
152 'tools.php',
153 __( 'Debug Log Manager', 'debug-log-manager' ),
154 __( 'Debug Log Manager', 'debug-log-manager' ),
155 'manage_options',
156 'debug-log-manager',
157 [ $this, 'create_main_page' ]
158 );
159
160 }
161
162 /**
163 * Register action links
164 *
165 * @since 1.0.0
166 */
167 public function action_links( $links ) {
168
169 $settings_link = '<a href="tools.php?page='.DLM_SLUG.'">' . esc_html__( 'View Debug Log', 'debug-log-manager' ) . '</a>';
170
171 array_unshift($links, $settings_link);
172
173 return $links;
174
175 }
176
177 /**
178 * Change admin footer text
179 *
180 * @since 1.0.0
181 */
182 public function footer_text() {
183 ?>
184 <a href="https://bowo.io/dotorg-dlm" target="_blank"><?php esc_html_e( 'Debug Log Manager', 'debug-log-manager' ); ?></a> is on <a href="https://bowo.io/github-dlm" target="_blank">github</a>
185 <?php
186 }
187
188 /**
189 * Replace WP version number text in footer
190 *
191 * @since 2.1.4
192 */
193 public function footer_version_text() {
194 return 'Also by Bowo &#8594; <a href="https://bowo.io/wpn-dlm" target="_blank">WordPress Newsboard</a>: The latest from 100+ sources';
195 }
196
197 /**
198 * Add debug icon in the admin bar
199 *
200 * @since 1.6.0
201 */
202 public function admin_bar_icon( WP_Admin_Bar $wp_admin_bar ) {
203
204 $current_user = wp_get_current_user();
205 $current_user_roles = array_values( $current_user->roles ); // indexed array
206
207 if ( in_array( 'administrator', $current_user_roles ) ) {
208
209 // https://developer.wordpress.org/reference/classes/wp_admin_bar/add_menu/
210 // https://developer.wordpress.org/reference/classes/wp_admin_bar/add_node/ for more examples
211 $wp_admin_bar->add_menu( array(
212 'id' => DLM_SLUG,
213 'parent' => 'top-secondary',
214 'group' => null,
215 'title' => '<span class="dashicons dashicons-warning"></span>',
216 'href' => admin_url( 'tools.php?page=' . DLM_SLUG ),
217 'meta' => array(
218 'class' => 'dlm-admin-bar-icon',
219 'title' => esc_attr__( 'Error logging is enabled. Click to access the Debug Log Manager.', 'debug-log-manager' )
220 ),
221 ) );
222
223 }
224
225 }
226
227 /**
228 * Create the main admin page of the plugin
229 *
230 * @since 1.0.0
231 */
232 public function create_main_page() {
233
234 $log_file_path = get_option( 'debug_log_manager_file_path' );
235 $log_file_shortpath = str_replace( sanitize_text_field( $_SERVER['DOCUMENT_ROOT'] ), "", $log_file_path );
236 $file_size = size_format( (int) filesize( $log_file_path ) );
237
238 ?>
239
240 <div class="wrap dlm-main-page">
241 <div id="dlm-header" class="dlm-header">
242 <div class="dlm-header-left">
243 <h1 class="dlm-heading"><?php esc_html_e( 'Debug Log Manager', 'debug-log-manager' ); ?> <small><?php esc_html_e( 'by', 'debug-log-manager' ); ?> <a href="https://bowo.io/bowoio-dlm" target="_blank">Bowo</a></small></h1>
244 </div>
245 <div class="dlm-header-right">
246 <a href="https://bowo.io/review-dlm" target="_blank" class="dlm-header-action"><span>�
247 </span> <?php esc_html_e( 'Review', 'debug-log-manager' ); ?></a>
248 <a href="https://bowo.io/feedback-dlm" target="_blank" class="dlm-header-action"> <?php esc_html_e( 'Feedback', 'debug-log-manager' ); ?></a>
249 <a href="https://bowo.io/sponsor-dlm" target="_blank" class="button button-primary plugin-sponsor">&#10084; <?php esc_html_e( 'Sponsor', 'debug-log-manager' ); ?></a>
250 </div>
251 </div>
252 <div class="dlm-body">
253 <div class="dlm-log-management">
254 <div class="dlm-logging-status">
255 <div class="dlm-log-status-toggle">
256 <input type="checkbox" id="debug-log-checkbox" class="inset-3 debug-log-checkbox"><label for="debug-log-checkbox" class="green debug-log-switcher"></label>
257 </div>
258 <?php echo wp_kses_post( $this->debug_log->get_status() ); ?>
259 </div>
260 <div class="dlm-autorefresh-status">
261 <div class="dlm-log-autorefresh-toggle">
262 <input type="checkbox" id="debug-autorefresh-checkbox" class="inset-3 debug-autorefresh-checkbox"><label for="debug-autorefresh-checkbox" class="green debug-autorefresh-switcher"></label>
263 </div>
264 <?php echo wp_kses_post( $this->debug_log->get_autorefresh_status() ); ?>
265 </div>
266 </div>
267 <?php
268 // Ref: https://docs.wpvip.com/vip-code-analysis-bot/customize-phpcs/
269 // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- already late-escaped before output here
270 $this->debug_log->get_entries_datatable();
271 ?>
272 </div>
273 <div class="dlm-footer">
274 <div id="dlm-log-file-location-section" class="dlm-footer-section">
275 <div class="dlm-log-file-location"><strong><?php esc_html_e( 'Log file', 'debug-log-manager' ); ?></strong>: <?php echo esc_html( $log_file_shortpath ); ?> (<span id="dlm-log-file-size"><?php echo esc_html( $file_size ); ?></span>)</div>
276 <button id="dlm-log-clear" class="button button-small button-secondary dlm-footer-button dlm-log-clear"><?php esc_html_e( 'Clear Log', 'debug-log-manager' ); ?></button>
277 </div>
278 <div id="dlm-disable-wp-file-editor-section" class="dlm-footer-section dlm-top-border" style="display:none;">
279 <div><?php esc_html_e( 'Once error logging is enabled, the core\'s plugin/theme editor stays enabled even if error logging has been disabled later on. This allows for viewing the files where errors occurred even when logging has been disabled. You can optionally disable the editor here once you\'re done debugging.', 'debug-log-manager' ); ?></div>
280 <button id="dlm-disable-wp-file-editor" class="button button-small button-secondary dlm-footer-button dlm-disable-wp-file-editor"><?php esc_html_e( 'Disable Editor', 'debug-log-manager' ); ?></button>
281 </div>
282 <div id="dlm-extra-settings" class="dlm-footer-section dlm-top-border">
283 <div class="dlm-extra-setting">
284 <div class="dlm-js-error-logging-status-toggle">
285 <input type="checkbox" id="js-error-logging-checkbox" class="inset-3 js-error-logging-checkbox"><label for="js-error-logging-checkbox" class="green js-error-logging-switcher"></label>
286 </div>
287 <div class="dlm-extra-setting-label">
288 <?php echo esc_html__( 'Do not log javascript errors', 'debug-log-manager' ); ?>
289 </div>
290 </div>
291 <div class="dlm-extra-setting">
292 <div class="dlm-script-debug-mod-status-toggle">
293 <input type="checkbox" id="script-debug-mod-checkbox" class="inset-3 script-debug-mod-checkbox"><label for="script-debug-mod-checkbox" class="green script-debug-mod-switcher"></label>
294 </div>
295 <div class="dlm-extra-setting-label">
296 <?php echo esc_html__( 'Do not modify SCRIPT_DEBUG value in wp-config.php', 'debug-log-manager' ); ?>
297 </div>
298 </div>
299 <div class="dlm-extra-setting">
300 <div class="dlm-process-non-utc-timezones-status-toggle">
301 <input type="checkbox" id="process-non-utc-timezones-checkbox" class="inset-3 process-non-utc-timezones-checkbox"><label for="process-non-utc-timezones-checkbox" class="green process-non-utc-timezones-switcher"></label>
302 </div>
303 <div class="dlm-extra-setting-label">
304 <?php echo esc_html__( 'Do not process entries with non-UTC timezones, which can be resource-intensive when log file size is significantly large.', 'debug-log-manager' ); ?>
305 </div>
306 </div>
307 </div>
308 <?php
309 echo wp_kses_post( $this->wp_config->wpconfig_file( 'status' ) );
310 ?>
311 </div>
312 </div>
313
314 <?php
315
316 }
317
318 /**
319 * To stop other plugins' admin notices overlaying in the Debug Log Manager UI, remove them.
320 *
321 * @hooked admin_notices
322 *
323 * @since 1.8.7
324 */
325 public function suppress_admin_notices() {
326
327 global $plugin_page;
328
329 if ( DLM_SLUG === $plugin_page ) {
330 remove_all_actions( 'admin_notices' );
331 }
332
333 }
334
335 /**
336 * Suppress all generic notices on the plugin settings page
337 *
338 * @since 1.8.8
339 */
340 public function suppress_generic_notices() {
341
342 global $plugin_page;
343
344 // Suppress all notices
345
346 if ( DLM_SLUG === $plugin_page ) {
347
348 remove_all_actions( 'all_admin_notices' );
349
350 }
351
352 }
353
354 /**
355 * Add dashboard widget with latest errors
356 *
357 * @since 1.8.0
358 */
359 public function add_dashboard_widget() {
360
361 $user = wp_get_current_user();
362 $roles = array_values( $user->roles );
363
364 if ( in_array( 'administrator', $roles ) ) {
365 wp_add_dashboard_widget(
366 'debug_log_manager_widget', // widget ID
367 __( 'Debug Log | Latest Errors', 'debug-log-manager' ), // widget title
368 array( $this, 'get_dashboard_widget_entries' ) // callback #1 to display entries
369 // array( $this, 'dashboard_widget_settings' ) // callback #2 for configuration
370 );
371 }
372
373 }
374
375 /**
376 * Load latest errors for dashboard widget
377 *
378 * @since 1.8.0
379 */
380 public function get_dashboard_widget_entries() {
381
382 $this->debug_log->get_dashboard_widget_entries();
383
384 }
385
386 /**
387 * Enqueue admin scripts
388 *
389 * @since 1.0.0
390 */
391 public function admin_scripts() {
392
393 wp_enqueue_style( 'dlm-admin', DLM_URL . 'assets/css/admin.css', array(), DLM_VERSION );
394 wp_enqueue_style( 'dlm-datatables', DLM_URL . 'assets/css/datatables.min.css', array(), DLM_VERSION );
395 wp_enqueue_style( 'dlm-toast', DLM_URL . 'assets/css/jquery.toast.min.css', array(), DLM_VERSION );
396 wp_enqueue_script( 'dlm-app', DLM_URL . 'assets/js/admin.js', array(), DLM_VERSION, false );
397 wp_enqueue_script( 'dlm-jsticky', DLM_URL . 'assets/js/jquery.jsticky.mod.min.js', array( 'jquery' ), DLM_VERSION, false );
398 wp_enqueue_script( 'dlm-datatables', DLM_URL . 'assets/js/datatables.min.js', array( 'jquery' ), DLM_VERSION, false );
399 wp_enqueue_script( 'dlm-toast', DLM_URL . 'assets/js/jquery.toast.min.js', array( 'jquery' ), DLM_VERSION, false );
400
401 // Pass on data from PHP to JS
402
403 $default_value = array(
404 'status' => 'disabled',
405 'on' => date( 'Y-m-d H:i:s' ),
406 );
407
408 $log_info = get_option( 'debug_log_manager', $default_value );
409 $log_status = $log_info['status']; // WP_DEBUG log status: enabled / disabled
410
411 if ( false !== get_option( 'debug_log_manager_autorefresh' ) ) {
412 $autorefresh_status = get_option( 'debug_log_manager_autorefresh' );
413 } else {
414 $autorefresh_status = 'disabled';
415 update_option( 'debug_log_manager_autorefresh', $autorefresh_status, false );
416 }
417
418 $js_error_logging_status = get_option( 'debug_log_manager_js_error_logging', 'enabled' );
419 $modify_script_debug_status = get_option( 'debug_log_manager_modify_script_debug', 'enabled' );
420 $process_non_utc_timezones_status = get_option( 'debug_log_manager_process_non_utc_timezones', 'enabled' );
421
422 $title_of_column_to_filter = __( 'Type', 'debug-log-manager' );
423
424 $nonce = wp_create_nonce( 'dlm-app' . get_current_user_id() );
425
426 wp_localize_script(
427 'dlm-app',
428 'dlmVars',
429 array(
430 'logStatus' => $log_status,
431 'autorefreshStatus' => $autorefresh_status,
432 'jsErrorLoggingStatus' => $js_error_logging_status,
433 'modifyScriptDebugStatus' => $modify_script_debug_status,
434 'processNonUtcTimezonesStatus' => $process_non_utc_timezones_status,
435 'titleOfColumnToFilter' => $title_of_column_to_filter,
436 'nonce' => $nonce,
437 'jsErrorLogging' => array(
438 'status' => '',
439 'url' => admin_url( 'admin-ajax.php' ),
440 'nonce' => wp_create_nonce( DLM_SLUG ),
441 'action' => 'log_js_errors',
442 ),
443 'toastMessage' => array(
444 'toggleDebugSuccess' => __( 'Error logging has been enabled and the latest entries have been loaded.', 'debug-log-manager' ),
445 'copySuccess' => __( 'Entries have been copied from an existing debug.log file.', 'debug-log-manager' ),
446 'logFileCleared' => __( 'Log file has been cleared.', 'debug-log-manager' ),
447 'editoDisabled' => __( 'WordPress plugin/theme editor has been disabled. ', 'debug-log-manager' ),
448 'paginationActive' => __( 'Pagination is active. Auto-refresh has been disabled.', 'debug-log-manager' ),
449 ),
450 'dataTable' => array(
451 'emptyTable' => __( 'No data available in table', 'debug-log-manager' ),
452 'info' => __( 'Showing _START_ to _END_ of _TOTAL_ entries', 'debug-log-manager' ),
453 'infoEmpty' => __( 'Showing 0 to 0 of 0 entries', 'debug-log-manager' ),
454 'infoFiltered' => __( '(filtered from _MAX_ total entries)', 'debug-log-manager' ),
455 'lengthMenu' => __( 'Show _MENU_ entries', 'debug-log-manager' ),
456 'search' => __( 'Search:', 'debug-log-manager' ),
457 'zeroRecords' => __( 'No matching records found', 'debug-log-manager' ),
458 'paginate' => array(
459 'first' => __( 'First', 'debug-log-manager' ),
460 'last' => __( 'Last', 'debug-log-manager' ),
461 'next' => __( 'Next', 'debug-log-manager' ),
462 'previous' => __( 'Previous', 'debug-log-manager' ),
463 ),
464 ),
465 )
466 );
467
468 }
469
470 /**
471 * Scripts for WP plugin editor page
472 *
473 * @since 2.0.0
474 */
475 public function plugin_editor_scripts() {
476
477 wp_enqueue_style( 'dlm-plugin-theme-editor', DLM_URL . 'assets/css/plugin-theme-editor.css', array(), DLM_VERSION );
478 wp_enqueue_script( 'dlm-plugin-editor', DLM_URL . 'assets/js/plugin-editor.js', array( 'jquery', 'wp-theme-plugin-editor' ), DLM_VERSION, false );
479
480 }
481
482 /**
483 * Scripts for WP theme editor page
484 *
485 * @since 2.0.0
486 */
487 public function theme_editor_scripts() {
488
489 wp_enqueue_style( 'dlm-plugin-theme-editor', DLM_URL . 'assets/css/plugin-theme-editor.css', array(), DLM_VERSION );
490 wp_enqueue_script( 'dlm-theme-editor', DLM_URL . 'assets/js/theme-editor.js', array( 'jquery', 'wp-theme-plugin-editor' ), DLM_VERSION, false );
491
492 }
493
494 /**
495 * Admin bar icon's inline css
496 *
497 * @since 1.6.0
498 */
499 public function admin_bar_icon_css() {
500
501 // https://developer.wordpress.org/reference/functions/wp_add_inline_style/
502 wp_add_inline_style( 'admin-bar', '
503
504 #wpadminbar .dlm-admin-bar-icon .dashicons {
505 font-family: dashicons;
506 font-size: 20px;
507 width: 20px;
508 height: 20px;
509 line-height: 32px;
510 }
511
512 #wpadminbar .quicklinks ul li.dlm-admin-bar-icon a {
513 background: green;
514 }
515
516 #wpadminbar:not(.mobile) .ab-top-menu>li:hover>.ab-item {
517 transition: .25s;
518 }
519
520 #wpadminbar:not(.mobile) .ab-top-menu>li.dlm-admin-bar-icon:hover>.ab-item,
521 #wpadminbar:not(.mobile) .ab-top-menu>li.dlm-admin-bar-icon>.ab-item:focus {
522 background: #006600;
523 color: #fff;
524 }
525
526 ' );
527
528 }
529
530 /**
531 * Enqueue public scripts
532 *
533 * @since 1.4.0
534 */
535 public function public_scripts() {
536 $log_info_default_value = array(
537 'status' => 'disabled',
538 'on' => date( 'Y-m-d H:i:s' ),
539 );
540
541 $log_info = get_option( 'debug_log_manager', $log_info_default_value );
542 $log_status = $log_info['status']; // WP_DEBUG log status: enabled / disabled
543
544 $js_error_logging_status = get_option( 'debug_log_manager_js_error_logging', 'enabled' ); // enabled | disabled
545
546 if ( 'enabled' == $log_status && 'enabled' == $js_error_logging_status ) {
547 wp_enqueue_script( 'dlm-public', DLM_URL . 'assets/js/public.js', array( 'jquery' ), DLM_VERSION, false );
548
549 wp_localize_script(
550 'dlm-public',
551 'dlmVars',
552 array(
553 'logStatus' => $log_status,
554 'jsErrorLogging' => array(
555 'status' => '',
556 'url' => admin_url( 'admin-ajax.php' ),
557 'nonce' => wp_create_nonce( DLM_SLUG ),
558 'action' => 'log_js_errors',
559 ),
560 )
561 );
562 }
563 }
564
565 }
566
567 Debug_Log_Manager::get_instance();