PluginProbe ʕ •ᴥ•ʔ
Strong Testimonials / 3.3.6
Strong Testimonials v3.3.6
3.3.6 3.3.5 3.3.4 3.3.3 3.3.2 3.3.1 trunk 1.0.1 2.30.9 2.31.10 2.32 2.32.1 2.32.2 2.32.3 2.32.4 2.33 2.34 2.35 2.36 2.37 2.38 2.38.1 2.39 2.39.1 2.39.2 2.39.3 2.40.0 2.40.1 2.40.2 2.40.3 2.40.4 2.40.5 2.40.6 2.40.7 2.41.0 2.41.1 2.50.0 2.50.1 2.50.2 2.50.3 2.50.4 2.51.0 2.51.1 2.51.2 2.51.3 2.51.4 2.51.5 2.51.6 2.51.7 2.51.8 2.51.9 3.0.0 3.0.1 3.0.2 3.0.3 3.1.0 3.1.1 3.1.10 3.1.11 3.1.12 3.1.13 3.1.14 3.1.15 3.1.16 3.1.17 3.1.18 3.1.19 3.1.2 3.1.20 3.1.3 3.1.4 3.1.5 3.1.6 3.1.7 3.1.8 3.1.9 3.2.0 3.2.1 3.2.10 3.2.11 3.2.12 3.2.13 3.2.14 3.2.15 3.2.16 3.2.17 3.2.18 3.2.19 3.2.2 3.2.20 3.2.21 3.2.22 3.2.3 3.2.4 3.2.5 3.2.6 3.2.7 3.2.8 3.2.9 3.3.0
strong-testimonials / includes / logs / class-strong-testimonials-logger.php
strong-testimonials / includes / logs Last commit date
class-strong-testimonials-logger.php 2 months ago html-strong-testimonials-logs-viewer.php 1 year ago
class-strong-testimonials-logger.php
410 lines
1 <?php
2
3 // Exit if accessed directly
4 if ( ! defined( 'ABSPATH' ) ) {
5 exit;
6 }
7
8
9 /**
10 * Strong_File_Logging Class
11 *
12 * A general use class for logging events and errors.
13 *
14 * @since 2.51.7
15 */
16 class Strong_File_Logging {
17
18 public $is_writable = true;
19 private $filename = '';
20 private $file = '';
21 public $is_logging_enabled = false;
22 /**
23 * Holds the class object.
24 *
25 * @since 1.0.0
26 *
27 * @var object
28 */
29 public static $instance;
30
31 /**
32 * Returns the singleton instance of the class.
33 *
34 * @since 2.51.7
35 *
36 * @return object The Strong_File_Logging object.
37 */
38 public static function get_instance() {
39
40 if ( ! isset( self::$instance ) && ! ( self::$instance instanceof Strong_File_Logging ) ) {
41 self::$instance = new Strong_File_Logging();
42 }
43
44 return self::$instance;
45
46 }
47
48 public function __construct() {
49
50 $this->is_logging_enabled();
51 add_filter( 'wpmtst_submenu_pages', array( $this, 'add_submenu' ) );
52 add_action( 'admin_init', array( $this, 'handle_actions' ) );
53 }
54
55 /**
56 * Add submenu page.
57 *
58 * @param $pages
59 *
60 * @return mixed
61 *
62 * @since 2.51.7
63 */
64 public function add_submenu( $pages ) {
65 $pages[90] = $this->get_submenu();
66 return $pages;
67 }
68
69 /**
70 * Return submenu page parameters.
71 *
72 * @return array
73 *
74 * @since 2.51.7
75 */
76 public function get_submenu() {
77 return array(
78 'page_title' => esc_html__( 'Logs', 'strong-testimonials' ),
79 'menu_title' => esc_html__( 'Logs', 'strong-testimonials' ),
80 'capability' => 'strong_testimonials_options',
81 'menu_slug' => 'strong-testimonials-logs',
82 'function' => array( $this, 'status_logs_file' ),
83 );
84 }
85
86 /**
87 * Check if logging is enabled
88 *
89 * @since 2.51.7
90 */
91 public function is_logging_enabled() {
92 $options = get_option( 'strong_testimonials_advanced_settings' );
93 if ( isset( $options['debug_log'] ) && ( 'on' === $options['debug_log'] || true === $options['debug_log'] ) ) {
94 $this->is_logging_enabled = true;
95 }
96 }
97
98 /**
99 * Return the log file handle.
100 *
101 * @param string $filename Filename to get the handle for.
102 * @return string
103 *
104 * @since 2.51.7
105 */
106 public static function get_log_file_handle( $filename ) {
107 return substr( $filename, 0, strlen( $filename ) > 48 ? strlen( $filename ) - 48 : strlen( $filename ) - 4 );
108 }
109
110 /**
111 * Scan log files
112 *
113 * @param [type] $path
114 * @return void
115 *
116 * @since 2.51.7
117 */
118 public static function scan_log_files( $path ) {
119 return @scandir( $path ); // @codingStandardsIgnoreLine
120 }
121
122 /**
123 * Get all log files in the log directory.
124 *
125 * @return array
126 *
127 * @since 2.51.7
128 */
129 public function get_log_files() {
130 $files = self::scan_log_files( WPMTST_LOGS );
131 $result = array();
132
133 if ( ! empty( $files ) ) {
134 foreach ( $files as $key => $value ) {
135 if ( ! in_array( $value, array( '.', '..' ), true ) ) {
136 if ( ! is_dir( $value ) && strstr( $value, '.log' ) ) {
137 $result[ sanitize_title( $value ) ] = $value;
138 } elseif ( is_dir( WPMTST_LOGS . $value ) ) {
139 $subfiles = self::scan_log_files( WPMTST_LOGS . $value );
140 if ( ! empty( $subfiles ) ) {
141 foreach ( $subfiles as $key => $subvalue ) {
142 if ( ! in_array( $subvalue, array( '.', '..' ), true ) ) {
143 if ( ! is_dir( $subvalue ) && strstr( $subvalue, '.log' ) ) {
144 $result[ sanitize_title( $subvalue ) ] = $value . '/' . $subvalue;
145 }
146 }
147 }
148 }
149 }
150 }
151 }
152 }
153
154 return $result;
155 }
156
157 /**
158 * Handles the delete log and download log actions.
159 *
160 * @since 2.51.7
161 */
162 public function handle_actions() {
163
164 if( isset( $_GET['post_type'] ) && isset( $_GET['page'] ) && 'wpm-testimonial' === $_GET['post_type'] && 'strong-testimonials-logs' === $_GET['page']){
165
166 if ( ! empty( $_REQUEST['st_log_remove'] ) ) { // phpcs:ignore input var ok, CSRF ok.
167 $this->remove_log();
168 }
169
170 if ( ! empty( $_REQUEST['st_log_download'] ) ) { // phpcs:ignore input var ok, CSRF ok.
171 $this->download_log();
172 }
173 }
174 }
175
176 /**
177 * Show the log page contents for file log handler.
178 *
179 * @since 2.51.7
180 */
181 public function status_logs_file() {
182 $logs = $this->get_log_files();
183
184 if ( ! empty( $_REQUEST['log_file'] ) && isset( $logs[ sanitize_title( wp_unslash( $_REQUEST['log_file'] ) ) ] ) ) { // phpcs:ignore input var ok, CSRF ok.
185 $viewed_log = $logs[ sanitize_title( wp_unslash( $_REQUEST['log_file'] ) ) ]; // phpcs:ignore input var ok, CSRF ok.
186 } elseif ( ! empty( $logs ) ) {
187 $viewed_log = current( $logs );
188 }
189
190 $handle = ! empty( $viewed_log ) ? self::get_log_file_handle( $viewed_log ) : '';
191
192 include_once __DIR__ . '/html-strong-testimonials-logs-viewer.php';
193 }
194
195 /**
196 * Remove/delete the chosen file and it's directory.
197 *
198 * @since 2.51.7
199 */
200 public function remove_log() {
201
202 if( !isset( $_REQUEST['st_log_remove'] ) || !isset( $_REQUEST['subdir'] ) ){
203 wp_die( esc_html__( 'Action failed. Please refresh the page and retry.', 'strong-testimonials' ) );
204 }
205
206 if ( empty( $_REQUEST['_wpnonce'] ) || ! wp_verify_nonce( wp_unslash( $_REQUEST['_wpnonce'] ), 'remove_log' ) ) { // phpcs:ignore input var ok, sanitization ok.
207 wp_die( esc_html__( 'Action failed. Please refresh the page and retry.', 'strong-testimonials' ) );
208 }
209
210 if ( ! empty( $_REQUEST['st_log_remove'] ) ) { // phpcs:ignore input var ok.
211 $this->remove( wp_unslash( $_REQUEST['st_log_remove'] ), wp_unslash( $_REQUEST['subdir'] ) ); // phpcs:ignore input var ok, sanitization ok.
212 }
213
214 wp_safe_redirect( esc_url_raw( admin_url( 'edit.php?post_type=wpm-testimonial&page=strong-testimonials-logs' ) ) );
215 exit();
216 }
217
218 /**
219 * Remove/delete the chosen file and it's directory.
220 *
221 * @param string $handle Log handle.
222 *
223 * @return bool
224 *
225 * @since 2.51.7
226 */
227 public function remove( $handle, $subdir ) {
228 $removed = false;
229 $logs = $this->get_log_files();
230 $handle = sanitize_title( $handle );
231 $subdir = sanitize_title( $subdir );
232
233 if ( isset( $logs[ $handle ] ) && $logs[ $handle ] ) {
234 $file = realpath( trailingslashit( WPMTST_LOGS ) . $logs[ $handle ] );
235 if ( 0 === stripos( $file, realpath( trailingslashit( WPMTST_LOGS ) ) ) && is_file( $file ) && is_writable( $file ) ) { // phpcs:ignore WordPress.VIP.FileSystemWritesDisallow.file_ops_is_writable
236 $removed = unlink( $file ); // phpcs:ignore WordPress.VIP.FileSystemWritesDisallow.file_ops_unlink
237 if ( $subdir != '' ) {
238 rmdir( dirname( $file ) );
239 }
240 }
241 }
242 return $removed;
243 }
244
245 /**
246 * Download the chosen file.
247 *
248 * @since 2.51.7
249 */
250 public function download_log() {
251 if ( empty( $_REQUEST['_wpnonce'] ) || ! wp_verify_nonce( wp_unslash( $_REQUEST['_wpnonce'] ), 'download_log' ) ) { // phpcs:ignore input var ok, sanitization ok.
252 wp_die( esc_html__( 'Action failed. Please refresh the page and retry.', 'strong-testimonials' ) );
253 }
254
255 if ( ! empty( $_REQUEST['st_log_download'] ) && ! empty( $_REQUEST['subdir'] ) ) { // phpcs:ignore input var ok.
256 $this->download( wp_unslash( $_REQUEST['st_log_download'] ), wp_unslash( $_REQUEST['subdir'] ) ); // phpcs:ignore input var ok, sanitization ok.
257 }
258
259 }
260
261 /**
262 * Download the chosen file.
263 *
264 * @param string $handle Log handle.
265 *
266 * @return void
267 *
268 * @since 2.51.7
269 */
270 public function download( $handle, $subdir ) {
271 $logs = $this->get_log_files();
272 $handle = sanitize_title( $handle );
273 $subdir = sanitize_title( $subdir );
274 if ( isset( $logs[ $handle ] ) && $logs[ $handle ] ) {
275 $file = realpath( trailingslashit( WPMTST_LOGS ) . $logs[ $handle ] );
276 if ( 0 === stripos( $file, realpath( trailingslashit( WPMTST_LOGS ) ) ) && is_file( $file ) && is_writable( $file ) ) { // phpcs:ignore WordPress.VIP.FileSystemWritesDisallow.file_ops_is_writable
277 header( 'Content-Description: File Transfer' );
278 header( 'Content-Type: application/octet-stream' );
279 header( 'Content-Disposition: attachment; filename="' . basename( $file ) . '"' );
280 header( 'Expires: 0' );
281 header( 'Cache-Control: must-revalidate' );
282 header( 'Pragma: public' );
283 header( 'Content-Length: ' . filesize( $file ) );
284 ob_clean();
285 flush();
286 readfile( $file );
287 exit();
288 }
289 }
290
291 }
292
293 /**
294 * Sets up the log file if it is writable
295 *
296 * @return void
297 *
298 * @since 2.51.7
299 */
300 public function setup_log_file( $importer ) {
301 $basedir = trailingslashit( WPMTST_LOGS ) . $importer;
302 if ( ! is_dir( $basedir ) ) {
303 mkdir( $basedir, 0777, true );
304 }
305 $this->filename = wp_hash( home_url( '/' ) ) . '-' . $importer . '-st_debug.log';
306 $this->file = $basedir . '/' . $this->filename;
307 if ( ! is_writeable( WPMTST_LOGS ) ) {
308 $this->is_writable = false;
309 }
310
311 }
312
313 /**
314 * Retrieve the log data
315 *
316 * @return string
317 *
318 * @since 2.51.7
319 */
320 public function get_file_contents() {
321 return $this->get_file();
322 }
323
324 /**
325 * Log message to file
326 *
327 * @return void
328 *
329 * @since 2.51.7
330 */
331 public function log_to_file( $message = '' ) {
332 $message = wp_date( 'd-n-Y H:i:s' ) . ' - ' . $message . "\r\n";
333 $this->write_to_log( $message );
334
335 }
336
337 /**
338 * Retrieve the file data is written to
339 *
340 * @return string
341 *
342 * @since 2.51.7
343 */
344 protected function get_file() {
345
346 $file = '';
347
348 if ( @file_exists( $this->file ) ) {
349
350 if ( ! is_writeable( $this->file ) ) {
351 $this->is_writable = false;
352 }
353
354 $file = @file_get_contents( $this->file );
355 } else {
356 @file_put_contents( $this->file, '' );
357 @chmod( $this->file, 0664 );
358
359 }
360
361 return $file;
362 }
363
364 /**
365 * Write the log message
366 *
367 * @return void
368 *
369 * @since 2.51.7
370 */
371 protected function write_to_log( $message = '' ) {
372 $file = $this->get_file();
373 $file .= $message;
374 @file_put_contents( $this->file, $file );
375 }
376
377 /**
378 * Return the location of the log file that Strong_File_Logging will use.
379 *
380 * @return string
381 *
382 * @since 2.51.7
383 */
384 public function get_log_file_path() {
385 return $this->file;
386 }
387
388 }
389
390 $GLOBALS['strong_logs'] = Strong_File_Logging::get_instance();
391
392
393 /**
394 * Logs a message to the debug log file
395 *
396 * @param string $message
397 * @global $strong_logs Strong_File_Logging Object
398 * @return void
399 *
400 * @since 2.51.7
401 */
402 function ST_debug_log( $importer = '', $message = '' ) {
403 global $strong_logs;
404 if ( $strong_logs->is_logging_enabled ) {
405 $strong_logs->setup_log_file( $importer );
406 $strong_logs->log_to_file( $message );
407 }
408
409 }
410