PluginProbe
MainWP Dashboard: Self-hosted WordPress Management for Agencies / 5.3
MainWP Dashboard: Self-hosted WordPress Management for Agencies v5.3
6.2 6.1.8 6.1.7 6.1.6 6.1.5 6.1.4 6.1.3 6.1.2 6.1.1 6.1 6.0.12 6.0.11 4.6.0.1 5.0 5.0.1 5.0.2 5.0.3 5.0.3.1 5.0.3.2 5.1 5.1.1 5.2 5.2.1 5.2.2 5.3 All 153 releases
mainwp / class / class-mainwp-logger.php

class-mainwp-logger.php in MainWP Dashboard: Self-hosted WordPress Management for Agencies 5.3, at class/class-mainwp-logger.php

960 lines 30.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * MainWP Logger
4 *
5 * For custom read/write logging file.
6 *
7 * @package MainWP/Dashboard
8 */
9
10 namespace MainWP\Dashboard;
11
12 /**
13 * Class MainWP_Logger
14 *
15 * @package MainWP\Dashboard
16 */
17 class MainWP_Logger { // phpcs:ignore Generic.Classes.OpeningBraceSameLine.ContentAfterBrace -- NOSONAR.
18
19 // phpcs:disable WordPress.WP.AlternativeFunctions -- for custom read/write logging file.
20
21 const UPDATE_CHECK_LOG_PRIORITY = 10;
22 const EXECUTION_TIME_LOG_PRIORITY = 15;
23 const LOGS_AUTO_PURGE_LOG_PRIORITY = 16;
24 const COST_TRACKER_LOG_PRIORITY = 20230112;
25 const API_BACKUPS_LOG_PRIORITY = 20240130;
26 const CONNECT_LOG_PRIORITY = 20241001;
27 const UPTIME_CHECK_LOG_PRIORITY = 20241017;
28 const UPTIME_NOTICE_LOG_PRIORITY = 202411106;
29 const DISABLED = - 1;
30 const LOG = 0;
31 const WARNING = 1;
32 const INFO = 2;
33 const DEBUG = 3;
34
35 const LOG_COLOR = '#999999';
36 const DEBUG_COLOR = '#666666';
37 const INFO_COLOR = '#276f86';
38 const WARNING_COLOR = '#9f3a38;';
39
40 /**
41 * Private variable to hold time start.
42 *
43 * @var int
44 */
45 private static $time_start = null;
46
47 /**
48 * Private varibale to hold the log file prefix.
49 *
50 * @var string Default 'mainwp'
51 */
52 private $logFileNamePrefix = 'mainwp';
53
54 /**
55 * Private varibale to hold the log file suffix.
56 *
57 * @var string Default '.log'
58 */
59 private $logFileNameSuffix = '.log';
60
61 /**
62 * Private varibale to hold the log file max size.
63 *
64 * @var int Default 0.5
65 */
66 private $logMaxMB = 0.5;
67
68 /**
69 * Private varibale to hold the log file date format.
70 *
71 * @var string Default 'Y-m-d H:i:s'
72 */
73 private $logDateFormat = 'Y-m-d H:i:s';
74
75 /**
76 * Private varibale to hold the log file output directory.
77 *
78 * @var mixed Default null
79 */
80 private $logDirectory = null;
81
82 /**
83 * Private varibale to hold the log file priotrity.
84 *
85 * @var string Disabled
86 */
87 private $logPriority = self::DISABLED;
88
89 /**
90 * Private varibale to hold the log Specific priotrity.
91 *
92 * @var string Disabled
93 */
94 private $logSpecific = 0;
95
96 /**
97 * Private varibale to hold the log Specific priotrity.
98 *
99 * @var string Disabled
100 */
101 private $autoEnableLoggingActions = array();
102
103
104 /**
105 * Private static varibale to hold the instance.
106 *
107 * @var mixed Default null
108 */
109 private static $instance = null;
110
111 /**
112 * Method instance()
113 *
114 * Returns new MainWP_Logger instance.
115 *
116 * @return self MainWP_Logger
117 *
118 * @uses \MainWP\Dashboard\MainWP_Logger
119 */
120 public static function instance() {
121 if ( null === static::$instance ) {
122 static::$instance = new self();
123 }
124 return static::$instance;
125 }
126
127 /**
128 * MainWP_Logger constructor.
129 *
130 * Run each time the class is called.
131 *
132 * @uses \MainWP\Dashboard\MainWP_System_Utility::get_mainwp_dir()
133 */
134 private function __construct() {
135
136 $enabled = $this->get_log_status();
137 $specific = $this->get_log_specific();
138
139 $enabled = apply_filters( 'mainwp_log_status', $enabled );
140 $specific = apply_filters( 'mainwp_log_specific', $specific );
141
142 $this->set_log_priority( $enabled, $specific );
143
144 $this->autoEnableLoggingActions = array(
145 static::CONNECT_LOG_PRIORITY,
146 );
147 }
148
149 /**
150 * Method set_log_priority()
151 *
152 * Sets the log priority.
153 *
154 * @param mixed $logPriority Log priority value.
155 * @param mixed $spec_log Specific log.
156 */
157 public function set_log_priority( $logPriority, $spec_log = 0 ) {
158 $this->logPriority = (int) $logPriority;
159 $this->logSpecific = (int) $spec_log; // 1 - specific log, 0 - not specific log.
160 }
161
162
163 /**
164 * Method enable_log_priority()
165 *
166 * Sets the log priority.
167 *
168 * @param mixed $logPriority Log priority value.
169 * @param mixed $spec_log Specific log.
170 */
171 public function enable_log_priority( $logPriority, $spec_log = 1 ) {
172 $spec_log = $spec_log ? 1 : 0;
173 $logPriority = intval( $logPriority );
174 MainWP_Utility::update_option( 'mainwp_specific_logs', $spec_log );
175 MainWP_Utility::update_option( 'mainwp_actionlogs', $logPriority );
176 MainWP_Utility::update_option( 'mainwp_actionlogs_enabled_timestamp', time() );
177 $this->log_action( 'Action logs set to: ' . $this->get_log_text( $logPriority ), ( $spec_log ? $logPriority : static::LOG ), 2, true );
178 $this->set_log_priority( $logPriority, $spec_log );
179 }
180
181
182 /**
183 * Method get_log_status()
184 *
185 * Get log status.
186 *
187 * @return mixed $enabled log status.
188 */
189 public function get_log_status() {
190 $enabled = get_option( 'mainwp_actionlogs' );
191
192 if ( false === $enabled ) {
193 $sites_count = MainWP_DB::instance()->get_websites_count();
194 if ( empty( $sites_count ) ) {
195 $enabled = self::DEBUG;
196 set_transient( 'mainwp_transient_action_logs', true, 2 * WEEK_IN_SECONDS );
197 } elseif ( get_transient( 'mainwp_transient_action_logs' ) ) {
198 $enabled = self::DEBUG;
199 } else {
200 $enabled = static::DISABLED;
201 }
202 }
203 return $enabled;
204 }
205
206
207 /**
208 * Method get_log_specific()
209 *
210 * Get log specific status.
211 *
212 * @return mixed $enabled log status.
213 */
214 public function get_log_specific() {
215 return get_option( 'mainwp_specific_logs', 0 );
216 }
217
218 /**
219 * Method get_log_type_info()
220 *
221 * Get log type info.
222 *
223 * @param int $type Log type value.
224 * @param int $logcolor Log color value.
225 *
226 * @return int $currentColor log color code.
227 */
228 public function get_log_type_info( $type, $logcolor ) {
229 $currentColor = '';
230 $prefix = '';
231 if ( static::DEBUG === $type || static::DEBUG === $logcolor ) {
232 $currentColor = static::DEBUG_COLOR;
233 $prefix = '[DEBUG]';
234 } elseif ( static::INFO === $type || static::INFO === $logcolor ) {
235 $currentColor = static::INFO_COLOR;
236 $prefix = '[INFO]';
237 } elseif ( static::WARNING === $type || static::WARNING === $logcolor ) {
238 $currentColor = static::WARNING_COLOR;
239 $prefix = '[WARNING]';
240 } elseif ( static::LOG === $type || static::LOG === $logcolor ) {
241 $currentColor = static::LOG_COLOR;
242 $prefix = '[LOG]';
243 }
244 return array(
245 'log_color' => $currentColor,
246 'log_prefix' => $prefix,
247 );
248 }
249
250 /**
251 * Method debug()
252 *
253 * Grab debug.
254 *
255 * @param string $text Debug message text.
256 *
257 * @return string Log debug message.
258 */
259 public function debug( $text ) {
260 return $this->log( $text, static::DEBUG );
261 }
262
263 /**
264 * Method info()
265 *
266 * Grab info.
267 *
268 * @param string $text Info message text.
269 *
270 * @return string Log info message.
271 */
272 public function info( $text ) {
273 return $this->log( $text, static::INFO );
274 }
275
276 /**
277 * Method warning()
278 *
279 * Grab warning information.
280 *
281 * @param string $text Warning message text.
282 *
283 * @return string Log warning message.
284 */
285 public function warning( $text ) {
286 return $this->log( $text, static::WARNING );
287 }
288
289 /**
290 * Method actions()
291 *
292 * Grab actions information.
293 *
294 * @param string $text Warning message text.
295 * @param int $priority priority message.
296 * @param int $log_color Set color: 0 - LOG, 1 - WARNING, 2 - INFO, 3- DEBUG.
297 * @param bool $forced forced logging.
298 *
299 * @return string Log warning message.
300 */
301 public function log_action( $text, $priority, $log_color = 0, $forced = false ) {
302 return $this->log( $text, $priority, $log_color, $forced );
303 }
304
305
306 /**
307 * Method log_update_check().
308 *
309 * @param string $text Log update check.
310 */
311 public function log_update_check( $text = '' ) {
312 $this->log_action( $text, static::UPDATE_CHECK_LOG_PRIORITY );
313 }
314
315 /**
316 * Method log_update_check().
317 *
318 * @param string $text Log update check.
319 */
320 public function log_uptime_check( $text = '' ) {
321 $this->log_action( $text, static::UPTIME_CHECK_LOG_PRIORITY );
322 }
323
324 /**
325 * Method log_uptime_notice().
326 *
327 * @param string $text Log update check.
328 */
329 public function log_uptime_notice( $text = '' ) {
330 $this->log_action( $text, static::UPTIME_NOTICE_LOG_PRIORITY );
331 }
332
333 /**
334 * Method debug_for_website()
335 *
336 * Grab website debug and info.
337 *
338 * @param object $website Child site object.
339 * @param string $action Performed action.
340 * @param string $message Debug message.
341 *
342 * @return mixed Website debug info.
343 *
344 * @uses \MainWP\Dashboard\MainWP_Utility::get_nice_url()
345 */
346 public function debug_for_website( $website, $action, $message ) {
347 if ( empty( $website ) ) {
348 return $this->log( '[-] [-] ::' . $action . ':: ' . $message, static::DEBUG );
349 }
350
351 return $this->log( '[' . $website->name . '] [' . MainWP_Utility::get_nice_url( $website->url ) . '] ::' . $action . ':: ' . $message, static::DEBUG, 0, false, $website );
352 }
353
354 /**
355 * Method info_for_website()
356 *
357 * Grab Website Info.
358 *
359 * @param object $website Child site object.
360 * @param string $action Performed action.
361 * @param string $message Info message.
362 *
363 * @return mixed Website Info.
364 *
365 * @uses \MainWP\Dashboard\MainWP_Utility::get_nice_url()
366 */
367 public function info_for_website( $website, $action, $message ) {
368 if ( empty( $website ) ) {
369 return $this->log( '[-] [-] ::' . $action . ':: ' . $message, static::INFO );
370 }
371
372 return $this->log( '[' . $website->name . '] [' . MainWP_Utility::get_nice_url( $website->url ) . '] ::' . $action . ':: ' . $message, static::INFO );
373 }
374
375 /**
376 * Method warning_for_website()
377 *
378 * Grab Website Warnings.
379 *
380 * @param object $website Child site object.
381 * @param string $action Performed action.
382 * @param string $message Warning message.
383 * @param bool $addStackTrace Add or Don't add stack trace.
384 *
385 * @return string Website warnings.
386 */
387 public function warning_for_website( $website, $action, $message, $addStackTrace = true ) {
388 $stackTrace = '';
389 if ( $addStackTrace ) {
390 ob_start();
391 // phpcs:ignore -- for debugging.
392 debug_print_backtrace( DEBUG_BACKTRACE_IGNORE_ARGS );
393 $stackTrace = "\n" . ob_get_clean();
394 }
395 if ( empty( $website ) ) {
396 return $this->log( '[-] [-] :: ' . $action . ' :: ' . $message . $stackTrace, static::WARNING );
397 }
398
399 return $this->log( '[' . $website->name . '] [' . MainWP_Utility::get_nice_url( $website->url ) . '] ::' . $action . ':: ' . $message . $stackTrace, static::WARNING );
400 }
401
402 /**
403 * Method log_to_db()
404 *
405 * Log to database.
406 *
407 * @param string $text Log record text.
408 * @param int $priority Set priority.
409 * @param int $log_color Set color.
410 * @param bool $forced forced logging.
411 * @param mixed $website website object.
412 *
413 * @return bool true|false Default is False.
414 */
415 private function log_to_db( $text, $priority, $log_color = 0, $forced = false, $website = false ) {
416
417 if ( static::DISABLED === $this->logPriority ) {
418 return false;
419 }
420
421 $priority = (int) apply_filters( 'mainwp_log_to_db_priority', $priority, $website );
422
423 $do_log = false;
424
425 if ( 1 === $this->logSpecific ) { // 1 - specific log, 0 - not specific log.
426 if ( $this->logPriority === $priority ) { // specific priority number saved setting.
427 $do_log = true;
428 }
429 } elseif ( $this->logPriority >= $priority ) {
430 $do_log = true;
431 }
432
433 $do_log = apply_filters( 'mainwp_log_do_to_db', $do_log, $website );
434
435 if ( ! $forced && ! $do_log ) {
436 return false;
437 }
438
439 $text = $this->prepare_log_info( $text );
440
441 do_action( 'mainwp_before_log_data', $text, $priority, $log_color );
442
443 if ( defined( 'DOING_CRON' ) && DOING_CRON && 'CRON' !== strtoupper( substr( $text, 0, 4 ) ) ) {
444 $text = 'CRON :: ' . $text;
445 }
446
447 /**
448 * Current user global.
449 *
450 * @global string
451 */
452 global $current_user;
453
454 $user = '';
455 if ( ! empty( $current_user ) && ! empty( $current_user->user_login ) ) {
456 $user = $current_user->user_login;
457 } elseif ( defined( 'WP_CLI' ) ) {
458 $user = 'WP_CLI';
459 } elseif ( defined( 'DOING_CRON' ) ) {
460 $user = 'DOING_CRON';
461 }
462
463 $data = array();
464
465 $data['log_content'] = $text;
466 $data['log_user'] = $user;
467 $data['log_type'] = $priority;
468 $data['log_color'] = intval( $log_color );
469 $data['log_timestamp'] = time();
470
471 $data = apply_filters( 'mainwp_log_to_db_data', $data );
472
473 MainWP_DB_Common::instance()->insert_action_log( $data );
474
475 return true;
476 }
477
478 /**
479 * Method log()
480 *
481 * Create Log File.
482 *
483 * @param string $text Log record text.
484 * @param int $priority Set priority.
485 * @param int $log_color Set color.
486 * @param bool $forced forced logging.
487 * @param mixed $website Site object.
488 *
489 * @return bool true|false Default is False.
490 */
491 private function log( $text, $priority, $log_color = 0, $forced = false, $website = false ) { // phpcs:ignore -- NOSONAR - complex function.
492
493 if ( in_array( $priority, $this->autoEnableLoggingActions ) && (int) $this->logPriority !== (int) $priority ) {
494 $this->enable_log_priority( $priority, 1 );
495 }
496
497 if ( static::DISABLED === $this->logPriority ) {
498 return;
499 }
500
501 $log_to_db = apply_filters( 'mainwp_logger_to_db', true, $website );
502
503 if ( $log_to_db ) {
504 return $this->log_to_db( $text, $priority, $log_color, $forced, $website );
505 }
506
507 $text = $this->prepare_log_info( $text );
508
509 $do_log = false;
510 if ( 1 === $this->logSpecific ) { // 1 - specific log, 0 - not specific log.
511 if ( $this->logPriority === $priority ) { // specific priority number saved setting.
512 $do_log = true;
513 }
514 } elseif ( $this->logPriority >= $priority ) {
515 $do_log = true;
516 }
517
518 if ( $do_log ) {
519 $this->logCurrentFile = $this->get_log_file();
520 $logCurrentHandle = fopen( $this->logCurrentFile, 'a+' );
521
522 if ( $logCurrentHandle ) {
523 $time = gmdate( $this->logDateFormat );
524 $prefix = '[' . $this->get_log_text( $priority ) . ']';
525
526 /**
527 * Current user global.
528 *
529 * @global string
530 */
531 global $current_user;
532
533 if ( ! empty( $current_user ) && ! empty( $current_user->user_login ) ) {
534 $prefix .= ' [administrator]';
535 }
536
537 fwrite( $logCurrentHandle, $time . ' ' . $prefix . ' ' . $text . "\n" );
538 fclose( $logCurrentHandle );
539 }
540
541 if ( filesize( $this->logCurrentFile ) > ( $this->logMaxMB * 1048576 ) ) {
542 $logCurrentHandle = fopen( $this->logCurrentFile, 'a+' );
543 if ( $logCurrentHandle ) {
544 fseek( $logCurrentHandle, 0 );
545 $newLogFile = $this->logCurrentFile . '.tmp';
546 $newLogHandle = false;
547 $chunkSize = filesize( $this->logCurrentFile ) - ( $this->logMaxMB * 1048576 );
548 while ( is_resource( $logCurrentHandle ) && ! feof( $logCurrentHandle ) && ( $chunkSize > 0 ) ) {
549 $content = fread( $logCurrentHandle, $chunkSize );
550 if ( false === $content ) {
551 break;
552 }
553 $pos = strrpos( $content, "\n" );
554 if ( $newLogHandle ) {
555 fwrite( $newLogHandle, $content );
556 } elseif ( $pos ) {
557 if ( ! $newLogHandle ) {
558 $newLogHandle = fopen( $newLogFile, 'w+' );
559 }
560 fwrite( $newLogHandle, substr( $content, $pos + 1 ) );
561 }
562 }
563
564 if ( is_resource( $logCurrentHandle ) ) {
565 fclose( $logCurrentHandle );
566 }
567
568 if ( $newLogHandle ) {
569 fclose( $newLogHandle );
570 wp_delete_file( $this->logCurrentFile );
571 if ( file_exists( $newLogFile ) ) {
572 rename( $newLogFile, $this->logCurrentFile );
573 }
574 }
575 }
576 }
577
578 return true;
579 }
580
581 return false;
582 }
583
584
585 /**
586 * Method prepare_log_info()
587 *
588 * Prepare log data.
589 *
590 * @param mixed $data Log data.
591 *
592 * @return mixed $data filtered data.
593 */
594 public function prepare_log_info( $data ) {
595 $patterns[0] = '/user=([^\&]+)\&/';
596 $replacement[0] = 'user=xxxxxx&';
597 $patterns[1] = '/alt_user=([^\&]+)\&/';
598 $replacement[1] = 'alt_user=xxxxxx&';
599 $patterns[2] = '/\&server=([^\&]+)\&/';
600 $replacement[2] = '&server=xxxxxx&';
601 $data = preg_replace( $patterns, $replacement, $data );
602 return $data;
603 }
604
605 /**
606 * Method prepend()
607 *
608 * Prepend content to log file.
609 *
610 * @param mixed $str Custom string.
611 * @param mixed $filename Filename.
612 */
613 public function prepend( $str, $filename ) {
614 $context = stream_context_create();
615 $fp = fopen( $filename, 'r', 1, $context );
616 $tmpname = md5( $str ); // NOSONAR - safe for salt file name.
617 file_put_contents( $tmpname, $str );
618 file_put_contents( $tmpname, $fp, FILE_APPEND );
619 fclose( $fp );
620 wp_delete_file( $filename );
621 rename( $tmpname, $filename );
622 }
623
624 /**
625 * Method init_execution_time().
626 *
627 * @param string $time_index index for timer.
628 *
629 * Init execution time start value.
630 */
631 public function init_execution_time( $time_index = '' ) {
632 if ( null === static::$time_start || ! is_array( static::$time_start ) ) {
633 static::$time_start = array( 'start' => microtime( true ) );
634 $this->log_action( 'execution time :: init :: [start]', static::EXECUTION_TIME_LOG_PRIORITY );
635 }
636
637 if ( ! empty( $time_index ) && is_string( $time_index ) && 'start' !== $time_index ) {
638 static::$time_start[ $time_index ] = microtime( true );
639 $this->log_action( 'execution time :: init :: [' . $time_index . ']', static::EXECUTION_TIME_LOG_PRIORITY );
640 }
641 }
642
643 /**
644 * Method log_execution_time().
645 *
646 * @param string $text Log record text.
647 *
648 * Log the execution time value.
649 */
650 public function log_execution_time( $text = '' ) {
651 $exec_time = $this->get_execution_time();
652 $this->log_action( 'execution time :: ' . ( ! empty( $text ) ? (string) $text : '<empty>' ) . ' :: [time=' . round( $exec_time, 4 ) . '](seconds)', static::EXECUTION_TIME_LOG_PRIORITY );
653 }
654
655
656 /**
657 * Method get_execution_time().
658 *
659 * Get the execution time value.
660 *
661 * @param string $time_index Index for timer.
662 *
663 * @return int execution time.
664 */
665 private function get_execution_time( $time_index = '' ) {
666
667 if ( empty( static::$time_start ) ) {
668 return 0;
669 }
670
671 $start = 0;
672 if ( ! empty( $time_index ) ) {
673 $start = is_array( static::$time_start ) && isset( static::$time_start[ $time_index ] ) ? static::$time_start[ $time_index ] : 0;
674 }
675
676 if ( empty( $start ) ) {
677 $start = is_array( static::$time_start ) && isset( static::$time_start['start'] ) ? static::$time_start['start'] : 0;
678 }
679
680 if ( empty( $start ) ) {
681 return 0;
682 }
683 return microtime( true ) - $start; // seconds.
684 }
685
686 /**
687 * Method get_log_file()
688 *
689 * Grab Log File.
690 *
691 * @return mixed Log File.
692 */
693 public function get_log_file() {
694 if ( empty( $this->logDirectory ) ) {
695 $this->logDirectory = MainWP_System_Utility::get_mainwp_dir();
696 $this->logDirectory = $this->logDirectory[0];
697 }
698 return $this->logDirectory . $this->logFileNamePrefix . $this->logFileNameSuffix;
699 }
700
701 /**
702 * Method get_log_text()
703 *
704 * Grab what type of log entry.
705 *
706 * @param mixed $priority Set priority.
707 *
708 * @return string LOG -OR- DISABLED|DEBUG|INFO|WARNING|INFO UPDATE
709 */
710 public function get_log_text( $priority ) {
711 switch ( $priority ) {
712 case static::DISABLED:
713 return 'DISABLED';
714 case static::DEBUG:
715 return 'DEBUG';
716 case static::INFO:
717 return 'INFO';
718 case static::WARNING:
719 return 'WARNING';
720 default:
721 return 'SPEC LOG';
722 }
723 }
724
725 /**
726 * Method check_log_daily()
727 *
728 * Daily checks to clear the log file.
729 */
730 public function check_log_daily() {
731 $status = (int) $this->get_log_status();
732 if ( 0 >= $status ) {
733 return;
734 }
735
736 $today_m_y = date_i18n( 'd/m/Y' ); //phpcs:ignore -- local time.
737 // one time per day.
738 if ( get_option( 'mainwp_logger_check_daily' ) !== $today_m_y ) {
739 $num_days = apply_filters( 'mainwp_logger_keep_days', 7 );
740 MainWP_DB_Common::instance()->delete_action_log( $num_days );
741 MainWP_Utility::update_option( 'mainwp_logger_check_daily', $today_m_y );
742
743 $enabled_time = get_option( 'mainwp_actionlogs_enabled_timestamp', false );
744 if ( false === $enabled_time ) {
745 MainWP_Utility::update_option( 'mainwp_actionlogs_enabled_timestamp', time() );
746 } elseif ( $enabled_time + $num_days * DAY_IN_SECONDS < time() ) {
747 MainWP_Utility::update_option( 'mainwp_actionlogs', static::DISABLED );
748 }
749 }
750 }
751
752 /**
753 * Method clear_log_db()
754 *
755 * Clear the log file.
756 */
757 public function clear_log_db() {
758 MainWP_DB_Common::instance()->delete_action_log();
759 }
760
761 /**
762 * Method clear_log()
763 *
764 * Clear the log file.
765 */
766 public function clear_log() {
767 $logFile = $this->get_log_file();
768 wp_delete_file( $logFile );
769 $fh = fopen( $logFile, 'w' );
770 if ( false === $fh ) {
771 return;
772 }
773 fclose( $fh );
774 }
775
776 /**
777 * Method show_log_db()
778 *
779 * Grab log file and build output to screen.
780 */
781 public function show_log_db() { //phpcs:ignore -- NOSONAR - complexity.
782
783 echo '<div class="ui hidden divider"></div>';
784 echo '<div class="ui divided padded relaxed list" local-datetime="' . date( 'Y-m-d H:i:s' ) . '">'; // phpcs:ignore -- local time.
785
786 $limit = 500;
787
788 //phpcs:disable WordPress.Security.NonceVerification
789 $paged = isset( $_GET['paged'] ) ? intval( $_GET['paged'] ) : 0; //phpcs:ignore -- NOSONAR -ok.
790
791 if ( $paged <= 0 ) {
792 $paged = 0;
793 } else {
794 --$paged;
795 }
796
797 $params = array();
798
799 if ( isset( $_GET['hour'] ) && ! empty( $_GET['hour'] ) ) { // phpcs:ignore -- local time.
800 $params['hour'] = intval( $_GET['hour'] ); // phpcs:ignore -- local time.
801 } else {
802 $params['hour'] = $limit;
803 }
804
805 $order = isset( $_GET['order'] ) ? sanitize_text_field( wp_unslash( $_GET['order'] ) ) : ''; //phpcs:ignore -- NOSONAR -ok.
806
807 $total = MainWP_DB::instance()->get_var_field( MainWP_DB_Common::instance()->get_sql_log( $paged, $order, array( 'count' => true ) ) );
808
809 $rows = MainWP_DB::instance()->query( MainWP_DB_Common::instance()->get_sql_log( $paged, $order, $params ) );
810
811 $count = $rows ? MainWP_DB::num_rows( $rows ) : 0;
812
813 $show_info = '';
814
815 if ( isset( $_GET['hour'] ) ) {
816 $show_info = $count . ' latest items from a total of ' . $total;
817 } elseif ( isset( $_GET['paged'] ) ) { //phpcs:ignore -- NOSONAR -ok.
818 $from = $limit * $paged;
819 $show_info = $count . ' items, from ' . $from . ' - ' . ( $from + $limit ) . ' of ' . $total . ' total.';
820 }
821
822 if ( ! empty( $show_info ) ) {
823 echo '<p><strong>' . esc_html__( 'Showing ', 'mainwp' ) . ':</strong> ' . $show_info; //phpcs:ignore -- NOSONAR ok.
824 }
825 //phpcs:enable WordPress.Security.NonceVerification
826
827 $start_wrapper = '<span class="ui mini label mainwp-action-log-show-more">Click to See Response</span><div class="mainwp-action-log-site-response" style="display: none;">';
828 $end_wrapper = '</div>';
829
830 while ( $rows && ( $row = MainWP_DB::fetch_object( $rows ) ) ) {
831 $line = $row->log_content;
832 if ( 120 * 1024 < strlen( $line ) ) {
833 $line = '[Data row too long]';
834 }
835
836 $time = gmdate( $this->logDateFormat, MainWP_Utility::get_timestamp( $row->log_timestamp ) );
837
838 $showInfo = $this->get_log_type_info( $row->log_type, $row->log_color );
839
840 $currentColor = $showInfo['log_color'];
841
842 $prefix = $time . ' ' . $showInfo['log_prefix'];
843
844 $line = htmlentities( $line );
845
846 if ( false !== strpos( $line, '[data-start]' ) ) {
847 $line = str_replace( '[data-start]', $start_wrapper, $line );
848 $line = str_replace( '[data-end]', $end_wrapper, $line );
849 }
850
851 echo '<div class="item" style="color:' . esc_html( $currentColor ) . '"><div class="mainwpactionlogsline">';
852
853 echo $prefix . ' ' . $line; // phpcs:ignore WordPress.Security.EscapeOutput
854
855 echo '</div></div>';
856 }
857
858 echo '</div></div>';
859
860 echo '</div>';
861
862 ?>
863 <div class="ui large modal" id="mainwp-action-log-response-modal">
864 <i class="close icon mainwp-reload"></i>
865 <div class="header"><?php esc_html_e( 'Child Site Response', 'mainwp' ); ?></div>
866 <div class="content">
867 <div class="ui info message"><?php esc_html_e( 'To see the response in a more readable way, you can copy it and paste it into some HTML render tool, such as Codepen.io.', 'mainwp' ); ?>
868 </div>
869 </div>
870 <div class="scrolling content content-response"></div>
871 <div class="actions">
872 <button class="ui green button mainwp-response-copy-button"><?php esc_html_e( 'Copy Response', 'mainwp' ); ?></button>
873 </div>
874 </div>
875 <?php
876 }
877
878 /**
879 * Method show_log_file()
880 *
881 * Grab log file and build output to screen.
882 */
883 public function show_log_file() { // phpcs:ignore -- NOSONAR - complex.
884 $logFile = $this->get_log_file();
885
886 if ( ! file_exists( $logFile ) ) {
887 return;
888 }
889
890 $fh = fopen( $logFile, 'r' );
891 if ( false === $fh ) {
892 return;
893 }
894
895 $previousColor = '';
896 $fontOpen = false;
897 $firstLinePassedProcessed = false;
898 echo '<div class="ui hidden divider"></div>';
899 echo '<div class="ui divided padded relaxed list">';
900 while ( false !== ( $line = fgets( $fh ) ) ) {
901 $currentColor = $previousColor;
902 if ( stristr( $line, '[DEBUG]' ) ) {
903 $currentColor = static::DEBUG_COLOR;
904 $firstLinePassed = true;
905 } elseif ( stristr( $line, '[INFO]' ) ) {
906 $currentColor = static::INFO_COLOR;
907 $firstLinePassed = true;
908 } elseif ( stristr( $line, '[WARNING]' ) ) {
909 $currentColor = static::WARNING_COLOR;
910 $firstLinePassed = true;
911 } elseif ( stristr( $line, '[LOG]' ) ) {
912 $currentColor = static::LOG_COLOR;
913 $firstLinePassed = true;
914 } else {
915 $firstLinePassed = false;
916 }
917
918 if ( $firstLinePassedProcessed && ! $firstLinePassed ) {
919 echo ' <span class="ui mini label mainwp-action-log-show-more">Click to See Response</span></div><div class="mainwp-action-log-site-response" style="display: none;">';
920 }
921
922 $firstLinePassedProcessed = $firstLinePassed;
923
924 if ( $currentColor !== $previousColor ) {
925 if ( $fontOpen ) {
926 echo '</div></div>';
927 }
928
929 echo '<div class="item" style="color:' . esc_html( $currentColor ) . '"><div class="mainwpactionlogsline">';
930 $fontOpen = true;
931 }
932
933 echo esc_html( htmlentities( $line ) );
934 }
935
936 if ( $fontOpen ) {
937 echo '</div></div>';
938 }
939
940 echo '</div>';
941
942 ?>
943 <div class="ui large modal" id="mainwp-action-log-response-modal">
944 <i class="close icon mainwp-reload"></i>
945 <div class="header"><?php esc_html_e( 'Child Site Response', 'mainwp' ); ?></div>
946 <div class="content">
947 <div class="ui info message"><?php esc_html_e( 'To see the response in a more readable way, you can copy it and paste it into some HTML render tool, such as Codepen.io.', 'mainwp' ); ?>
948 </div>
949 </div>
950 <div class="scrolling content content-response"></div>
951 <div class="actions">
952 <button class="ui green button mainwp-response-copy-button"><?php esc_html_e( 'Copy Response', 'mainwp' ); ?></button>
953 </div>
954 </div>
955 <?php
956
957 fclose( $fh );
958 }
959 }
960