PluginProbe ʕ •ᴥ•ʔ
AI Engine – The Chatbot, AI Framework & MCP for WordPress / 2.8.1
AI Engine – The Chatbot, AI Framework & MCP for WordPress v2.8.1
3.5.7 3.5.6 3.5.5 3.5.4 3.5.3 3.5.2 3.5.1 3.5.0 3.4.9 3.4.8 3.4.7 0.2.1 1.6.91 0.2.2 1.6.92 0.2.3 1.6.93 0.2.4 1.6.94 0.2.5 1.6.95 0.2.6 1.6.96 0.2.7 1.6.97 0.2.8 1.6.98 0.2.9 1.6.99 0.3.0 1.7.0 0.3.1 1.7.1 0.3.2 1.7.2 0.3.3 1.7.3 0.3.4 1.7.4 0.3.5 1.7.5 0.3.6 1.7.6 0.4.0 1.7.7 0.4.1 1.7.8 0.4.2 1.7.9 0.4.3 1.8.0 0.4.4 1.8.1 0.4.5 1.8.2 0.4.6 1.8.3 0.4.7 1.8.4 0.4.8 1.8.5 0.4.9 1.8.6 0.5.0 1.8.7 0.5.1 1.8.8 0.5.2 1.8.9 0.5.3 1.9.0 0.5.4 1.9.1 0.5.5 1.9.2 0.5.6 1.9.3 0.5.7 1.9.4 0.5.8 1.9.5 0.5.9 1.9.6 0.6.0 1.9.7 0.6.1 1.9.8 0.6.2 1.9.81 0.6.3 1.9.82 0.6.4 1.9.83 0.6.5 1.9.84 0.6.6 1.9.85 0.6.7 1.9.86 0.6.8 1.9.87 0.6.9 1.9.88 0.7.0 1.9.89 0.7.1 1.9.90 0.7.2 1.9.91 0.7.3 1.9.92 0.7.4 1.9.93 0.7.5 1.9.94 0.7.6 1.9.95 0.7.7 1.9.96 0.7.8 1.9.97 0.7.9 1.9.98 0.8.0 1.9.99 0.8.1 2.0.0 0.8.2 2.0.1 0.8.3 2.0.2 0.8.4 2.0.3 0.8.5 2.0.4 0.8.6 2.0.5 0.8.7 2.0.6 0.8.8 2.0.7 0.8.9 2.0.8 0.9.0 2.0.9 0.9.2 2.1.0 0.9.3 2.1.1 0.9.4 2.1.2 0.9.5 2.1.3 0.9.6 2.1.4 0.9.7 2.1.5 0.9.8 2.1.6 0.9.81 2.1.7 0.9.82 2.1.8 0.9.83 2.1.9 0.9.84 2.2.0 0.9.85 2.2.1 0.9.86 2.2.2 0.9.87 2.2.3 0.9.88 2.2.4 0.9.89 2.2.5 0.9.9 2.2.51 0.9.91 2.2.52 0.9.92 2.2.53 0.9.93 2.2.54 0.9.94 2.2.56 0.9.95 2.2.57 0.9.96 2.2.6 0.9.97 2.2.60 0.9.98 2.2.61 0.9.99 2.2.62 1.0.0 2.2.63 1.0.01 2.2.70 1.0.1 2.2.80 1.0.2 2.2.81 1.0.3 2.2.90 1.0.4 2.2.91 1.0.5 2.2.92 1.0.6 2.2.93 1.0.7 2.2.94 1.0.8 2.2.95 1.0.9 2.3.0 1.1.0 2.3.1 1.1.1 2.3.2 1.1.2 2.3.3 1.1.3 2.3.4 1.1.4 2.3.5 1.1.5 2.3.6 1.1.6 2.3.7 1.1.7 2.3.8 1.1.8 2.3.9 1.1.9 2.4.0 1.2.0 2.4.1 1.2.1 2.4.2 1.2.2 2.4.3 1.2.21 2.4.4 1.2.3 2.4.5 1.2.30 2.4.6 1.3.0 2.4.7 1.3.1 2.4.8 1.3.2 2.4.9 1.3.3 2.5.0 1.3.31 2.5.1 1.3.32 2.5.2 1.3.33 2.5.3 1.3.34 2.5.4 1.3.35 2.5.5 1.3.36 2.5.6 1.3.37 2.5.7 1.3.38 2.5.8 1.3.39 2.5.9 1.3.40 2.6.0 1.3.41 2.6.1 1.3.42 2.6.2 1.3.43 2.6.3 1.3.44 2.6.5 1.3.45 2.6.6 1.3.46 2.6.7 1.3.47 2.6.8 1.3.48 2.6.9 1.3.49 2.7.0 1.3.50 2.7.1 1.3.51 2.7.2 1.3.52 2.7.3 1.3.53 2.7.4 1.3.54 2.7.5 1.3.56 2.7.6 1.3.57 2.7.7 1.3.58 2.7.8 1.3.59 2.7.9 1.3.60 2.8.0 1.3.61 2.8.1 1.3.62 2.8.2 1.3.63 2.8.3 1.3.64 2.8.4 1.3.65 2.8.5 1.3.66 2.8.6 1.3.67 2.8.7 1.3.68 2.8.8 1.3.69 2.8.9 1.3.70 2.9.0 1.3.71 2.9.1 1.3.72 2.9.2 1.3.73 2.9.3 1.3.74 2.9.4 1.3.75 2.9.5 1.3.76 2.9.6 1.3.77 2.9.7 1.3.78 2.9.8 1.3.79 2.9.9 1.3.80 3.0.0 1.3.81 3.0.1 1.3.82 3.0.2 1.3.83 3.0.3 1.3.84 3.0.4 1.3.85 3.0.5 1.3.86 3.0.6 1.3.87 3.0.7 1.3.88 3.0.8 1.3.89 3.0.9 1.3.90 3.1.0 1.3.91 3.1.1 1.3.92 3.1.2 1.3.93 3.1.3 1.3.94 3.1.4 1.3.95 3.1.5 1.3.96 3.1.6 1.3.97 3.1.7 1.3.98 3.1.8 1.3.99 3.1.9 1.4.0 3.2.0 1.4.1 3.2.1 1.4.2 3.2.2 1.4.3 3.2.3 1.4.4 3.2.4 1.4.5 3.2.5 1.4.6 3.2.6 1.4.7 3.2.7 1.4.8 3.2.8 1.4.9 3.2.9 1.5.0 3.3.0 1.5.1 3.3.1 1.5.2 3.3.2 1.5.3 3.3.3 1.5.4 3.3.4 1.5.5 3.3.5 1.5.6 3.3.6 1.5.7 3.3.7 1.5.8 3.3.8 1.5.9 3.3.9 1.6.0 3.4.0 1.6.1 3.4.1 1.6.2 3.4.2 1.6.3 3.4.3 1.6.5 3.4.4 1.6.51 3.4.5 1.6.52 3.4.6 1.6.53 1.6.54 1.6.55 1.6.56 1.6.57 1.6.58 1.6.59 1.6.60 1.6.61 1.6.62 1.6.63 1.6.64 1.6.65 1.6.66 1.6.67 1.6.68 trunk 1.6.69 0.0.1 1.6.70 0.0.2 1.6.71 0.0.3 1.6.72 0.0.4 1.6.73 0.0.5 1.6.74 0.0.6 1.6.75 0.0.7 1.6.76 0.0.8 1.6.77 0.0.9 1.6.78 0.1.0 1.6.79 0.1.1 1.6.81 0.1.2 1.6.82 0.1.3 1.6.83 0.1.4 1.6.84 0.1.5 1.6.85 0.1.6 1.6.86 0.1.7 1.6.87 0.1.8 1.6.88 0.1.9 1.6.89 0.2.0 1.6.90
ai-engine / classes / logging.php
ai-engine / classes Last commit date
engines 1 year ago modules 1 year ago queries 1 year ago admin.php 1 year ago api.php 1 year ago core.php 1 year ago discussion.php 1 year ago init.php 1 year ago logging.php 1 year ago reply.php 1 year ago rest.php 1 year ago
logging.php
254 lines
1 <?php
2
3 /**
4 * Class Meow_MWAI_Logging
5 *
6 * A logging utility that uses the WordPress Filesystem API for storage,
7 * with fallback to PHP error_log when necessary.
8 */
9 class Meow_MWAI_Logging {
10 private static $plugin_name;
11 private static $option_name;
12 private static $log_file_path;
13 private static $fs;
14 private static $log_count = 0;
15 private static $rotate_check_frequency = 10;
16 private static $max_log_size = 5 * 1024 * 1024; // 5 MB
17
18 /**
19 * Initialize the logger.
20 *
21 * @param string $option_name Option key for settings.
22 * @param string $plugin_name Plugin identifier for error log prefix.
23 */
24 public static function init( $option_name, $plugin_name ) {
25 self::$plugin_name = $plugin_name;
26 self::$option_name = $option_name;
27
28 if ( ! function_exists( 'request_filesystem_credentials' ) ) {
29 require_once ABSPATH . 'wp-admin/includes/file.php';
30 }
31
32 $creds = request_filesystem_credentials( site_url(), '', false, false, [] );
33 if ( ! WP_Filesystem( $creds ) ) {
34 error_log( self::$plugin_name . " : Unable to initialize WP_Filesystem." );
35 self::$fs = null;
36 }
37 else {
38 global $wp_filesystem;
39 self::$fs = $wp_filesystem;
40 }
41
42 self::$log_file_path = self::get_logs_path( true );
43 }
44
45 /**
46 * Determine or create the log file path using WP_Filesystem.
47 *
48 * @param bool $create Whether to generate a new file if none exists.
49 * @return string|false Path to log file or false if unavailable.
50 */
51 private static function get_logs_path( $create = false ) {
52 $options = get_option( self::$option_name, null );
53 if ( is_null( $options ) ) {
54 return null;
55 }
56
57 if ( empty( self::$fs ) ) {
58 return null;
59 }
60
61 $path = empty( $options['logs_path'] ) ? '' : $options['logs_path'];
62
63 if ( $path && self::$fs->exists( $path ) ) {
64 return $path;
65 }
66
67 if ( ! $create ) {
68 return null;
69 }
70
71 $uploads = wp_upload_dir();
72 $base_dir = trailingslashit( $uploads['basedir'] );
73
74 if ( ! self::$fs->is_dir( $base_dir ) ) {
75 self::$fs->mkdir( $base_dir );
76 }
77
78 $filename = MWAI_PREFIX . '_' . self::random_ascii_chars() . '.log';
79 $new_path = $base_dir . $filename;
80
81 self::$fs->put_contents( $new_path, '', FS_CHMOD_FILE );
82
83 $options['logs_path'] = $new_path;
84 update_option( self::$option_name, $options );
85
86 return $new_path;
87 }
88
89 /**
90 * Check if logging is enabled via plugin options and FS availability.
91 *
92 * @return bool
93 */
94 private static function is_logging_enabled() {
95 $options = get_option( self::$option_name, null );
96 if ( is_null( $options ) ) {
97 return false;
98 }
99
100 $module_devtools = empty( $options['module_devtools'] ) ? false : $options['module_devtools'];
101 $server_debug_mode = empty( $options['server_debug_mode'] ) ? false : $options['server_debug_mode'];
102
103 return ( $module_devtools && $server_debug_mode && ! empty( self::$fs ) );
104 }
105
106 /**
107 * Internal log writer. Appends to file and/or error_log.
108 */
109 private static function add( $message = null, $icon = '', $error_log = false ) {
110 $date = date( 'Y-m-d H:i:s' );
111 $message = is_string( $message ) ? strip_tags( $message ) : $message;
112
113 if ( empty( $message ) ) {
114 $entry = "\n";
115 }
116 else if ( ! empty( $icon ) ) {
117 $entry = "$date: $icon $message\n";
118 }
119 else {
120 $entry = "$date: $message\n";
121 }
122
123 if ( self::is_logging_enabled() && self::$log_file_path ) {
124 if ( self::$fs->exists( self::$log_file_path ) ) {
125 $current = self::$fs->get_contents( self::$log_file_path );
126 self::$fs->put_contents( self::$log_file_path, $current . $entry, FS_CHMOD_FILE );
127 }
128 else {
129 self::$fs->put_contents( self::$log_file_path, $entry, FS_CHMOD_FILE );
130 }
131 }
132
133 if ( $error_log && ! empty( $message ) ) {
134 error_log( self::$plugin_name . " : $message" );
135 }
136
137 self::$log_count++;
138
139 if ( self::$log_count >= self::$rotate_check_frequency ) {
140 self::maybe_rotate_log();
141 self::$log_count = 0;
142 }
143 }
144
145 /**
146 * Logs a general message.
147 *
148 * @param string $message The message to log.
149 * @param string $icon Optional icon to prepend.
150 */
151 public static function log( $message = null, $icon = '' ) {
152 self::add( $message, $icon );
153 }
154
155 /**
156 * Logs a warning message.
157 *
158 * @param string $message The warning message to log.
159 * @param string $icon Optional icon to prepend (default ⚠️).
160 */
161 public static function warn( $message = null, $icon = '⚠️' ) {
162 self::add( $message, $icon );
163 }
164
165 /**
166 * Logs an error message and sends to PHP error_log.
167 *
168 * @param string $message The error message to log.
169 * @param string $icon Optional icon to prepend (default ❌).
170 */
171 public static function error( $message = null, $icon = '' ) {
172 self::add( $message, $icon, true );
173 }
174
175 /**
176 * Logs a deprecated feature notice.
177 *
178 * @param string $message The message to log.
179 */
180 public static function deprecated( $message = null ) {
181 self::add( $message, '🚨', true );
182 }
183
184 /**
185 * Clears the log file and resets the option.
186 */
187 public static function clear() {
188 if ( self::$fs && self::$log_file_path && self::$fs->exists( self::$log_file_path ) ) {
189 self::$fs->delete( self::$log_file_path );
190 $options = get_option( self::$option_name, null );
191 $options['logs_path'] = '';
192 update_option( self::$option_name, $options );
193 self::$log_file_path = '';
194 }
195 }
196
197 /**
198 * Retrieves the log contents in reverse order (newest first).
199 *
200 * @return string
201 */
202 public static function get() {
203 if ( self::$fs && self::$log_file_path && self::$fs->exists( self::$log_file_path ) ) {
204 $content = self::$fs->get_contents( self::$log_file_path );
205 $lines = explode( "\n", $content );
206 $lines = array_filter( $lines );
207 $lines = array_reverse( $lines );
208
209 return implode( "\n", $lines );
210 }
211
212 return 'Empty log file.';
213 }
214
215 /**
216 * Checks file size and rotates if exceeding maximum.
217 */
218 private static function maybe_rotate_log() {
219 if ( empty( self::$fs ) || empty( self::$log_file_path ) ) {
220 return;
221 }
222
223 if ( self::$fs->exists( self::$log_file_path ) ) {
224 $size = self::$fs->size( self::$log_file_path );
225
226 if ( $size > self::$max_log_size ) {
227
228 $info = pathinfo( self::$log_file_path );
229 $archived = $info['dirname'] . '/' . $info['filename'] . '_' . date( 'Y-m-d_H-i-s' ) . '.' . $info['extension'];
230
231 self::$fs->move( self::$log_file_path, $archived, true );
232 self::$fs->put_contents( self::$log_file_path, '', FS_CHMOD_FILE );
233 }
234 }
235 }
236
237 /**
238 * Generates a random ASCII string.
239 *
240 * @param int $length String length.
241 * @return string
242 */
243 private static function random_ascii_chars( $length = 8 ) {
244 $characters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
245 $result = '';
246
247 for ( $i = 0; $i < $length; $i++ ) {
248 $result .= $characters[ rand( 0, strlen( $characters ) - 1 ) ];
249 }
250
251 return $result;
252 }
253 }
254