PluginProbe
YayMail – WooCommerce Email Customizer / 4.4.5
YayMail – WooCommerce Email Customizer v4.4.5
4.4.6 4.4.5 4.4.4 4.4.3 4.4.2 4.4.1 trunk 1.9.6 2.1.4 2.1.5 3.2.2 3.2.6 3.2.7.1 3.2.8.1 3.2.9 3.3 3.3.1 3.3.4 3.3.5 3.3.6 3.3.7 3.3.8 3.3.9 3.4 3.4.1 All 57 releases
yaymail / src / Utils / Logger.php

Logger.php in YayMail – WooCommerce Email Customizer 4.4.5, at src/Utils/Logger.php

159 lines 5.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace YayMail\Utils;
4
5 /**
6 * Logger
7 */
8 class Logger {
9 private $log_directory;
10 private $wp_filesystem;
11 private $max_log_files;
12
13 private $ready = false;
14
15 /**
16 * Constructor for the Logger class.
17 *
18 * Only records the log directory and retention limit. Filesystem setup (WP_Filesystem,
19 * mkdir, old-log cleanup) is deferred to the first log() call because Logger instances
20 * are created on every request by classes that rarely log.
21 */
22 public function __construct( $log_directory = null, $max_log_files = 30 ) {
23 if ( ! $log_directory ) {
24 $log_directory = WP_CONTENT_DIR . '/yaymail-logs';
25 }
26 $this->log_directory = $log_directory;
27 $this->max_log_files = $max_log_files;
28 }
29
30 /**
31 * Initializes the filesystem, ensures the log directory exists and prunes old logs. Runs once.
32 */
33 private function ensure_ready() {
34 if ( $this->ready ) {
35 return;
36 }
37 $this->ready = true;
38 $this->initialize_filesystem();
39
40 // Ensure the log directory exists (only if filesystem is available)
41 if ( $this->wp_filesystem && ! $this->wp_filesystem->is_dir( $this->log_directory ) ) {
42 $this->wp_filesystem->mkdir( $this->log_directory, 0755 );
43 }
44
45 // Clean up old log files (only if filesystem is available)
46 if ( $this->wp_filesystem ) {
47 $this->cleanup_old_logs();
48 }
49 }
50
51 private function initialize_filesystem() {
52 global $wp_filesystem;
53
54 // Initialize the WordPress filesystem
55 require_once ABSPATH . 'wp-admin/includes/file.php';
56
57 // Try to initialize WP_Filesystem, fallback to direct method if failed
58 if ( ! WP_Filesystem() || ! $wp_filesystem ) {
59 // Fallback to direct filesystem access
60 require_once ABSPATH . 'wp-admin/includes/class-wp-filesystem-direct.php';
61 $this->wp_filesystem = new \WP_Filesystem_Direct( null );
62 } else {
63 $this->wp_filesystem = $wp_filesystem;
64 }
65 }
66
67 private function cleanup_old_logs() {
68 // Return early if filesystem is not available or log directory is not a directory
69 if ( ! $this->wp_filesystem || ! $this->wp_filesystem->is_dir( $this->log_directory ) ) {
70 return;
71 }
72
73 // Get all log files in the directory
74 $files = $this->wp_filesystem->dirlist( $this->log_directory );
75
76 if ( ! is_array( $files ) ) {
77 return;
78 }
79
80 // Filter only log files
81 $log_files = array_filter(
82 $files,
83 function( $file ) {
84 return strpos( $file['name'], '.log' ) !== false;
85 }
86 );
87
88 // Sort log files by name (assuming the name is in the format 'Y-m-d.log')
89 usort(
90 $log_files,
91 function( $a, $b ) {
92 return strcmp( $b['name'], $a['name'] );
93 }
94 );
95
96 // If there are more log files than the allowed maximum, delete the oldest
97 if ( count( $log_files ) > $this->max_log_files ) {
98 $files_to_delete = array_slice( $log_files, $this->max_log_files );
99
100 foreach ( $files_to_delete as $file ) {
101 $this->wp_filesystem->delete( $this->log_directory . '/' . $file['name'] );
102 }
103 }
104 }
105
106 public function log( $message ) {
107 $this->ensure_ready();
108
109 // Return early if filesystem is not available
110 if ( ! $this->wp_filesystem ) {
111 return;
112 }
113
114 // Get the current date to create a log file for each day, based on local time
115 $date = current_time( 'Y-m-d' );
116 $log_file = $this->log_directory . '/' . $date . '.log';
117
118 // Construct the log message with a timestamp based on local time
119 $timestamp = current_time( 'Y-m-d H:i:s' );
120 $log_message = "[$timestamp] $message" . PHP_EOL;
121
122 // Append the log message to the log file
123 if ( $this->wp_filesystem->exists( $log_file ) ) {
124 $existing_content = $this->wp_filesystem->get_contents( $log_file );
125 $log_message = $existing_content . $log_message;
126 }
127
128 $this->wp_filesystem->put_contents( $log_file, $log_message, FS_CHMOD_FILE );
129 }
130
131 /**
132 * Logs an exception message to wp-content/yaymail-logs and returns.
133 *
134 * Does not terminate the request: rendering can be triggered inside another
135 * plugin's request (e.g. WooCommerce checkout AJAX), where dying would break
136 * the host response. Callers that need to abort (YayMail's own AJAX endpoints)
137 * must call wp_send_json_error() themselves.
138 */
139 public function log_exception_message( $ex, $log_type = 'error', $additional_data = null ) {
140 $prefix = ( $log_type === 'warning' ) ? __( 'WARNING:', 'yaymail' ) : __( 'SYSTEM ERROR:', 'yaymail' );
141
142 $message = $prefix . ' ' . $ex->getCode() . ' : ' . $ex->getMessage();
143 $message .= PHP_EOL . $ex->getFile() . '(' . $ex->getLine() . ')';
144 $message .= PHP_EOL . $ex->getTraceAsString();
145
146 // Add additional data if provided
147 if ( $additional_data !== null ) {
148 $message .= PHP_EOL . 'Additional data: ';
149 if ( is_array( $additional_data ) || is_object( $additional_data ) ) {
150 $message .= PHP_EOL . print_r( $additional_data, true );
151 } else {
152 $message .= $additional_data;
153 }
154 }
155
156 $this->log( $message );
157 }
158 }
159