PluginProbe
Content Control – The Ultimate Content Restriction Plugin! Restrict Content, Create Conditional Blocks & More / 2.0.2
Content Control – The Ultimate Content Restriction Plugin! Restrict Content, Create Conditional Blocks & More v2.0.2
trunk 1.0.0 1.0.1 1.0.2 1.0.3 1.1.0 1.1.1 1.1.10 1.1.2 1.1.3 1.1.4 1.1.5 1.1.6 1.1.7 1.1.8 2.0.0 2.0.1 2.0.10 2.0.11 2.0.12 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 All 47 releases
content-control / classes / Plugin / Logging.php

Logging.php in Content Control – The Ultimate Content Restriction Plugin! Restrict Content, Create Conditional Blocks & More 2.0.2, at classes/Plugin/Logging.php

446 lines 9.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Logging class.
4 *
5 * @package ContentControl\Plugin
6 */
7
8 namespace ContentControl\Plugin;
9
10 /**
11 * Logging class.
12 */
13 class Logging {
14
15 /**
16 * Log file prefix.
17 */
18 const LOG_FILE_PREFIX = 'content-control-';
19
20 /**
21 * Container.
22 *
23 * @var \ContentControl\Base\Container
24 */
25 private $c;
26
27 /**
28 * Whether the log file is writable.
29 *
30 * @var bool
31 */
32 private $is_writable;
33
34 /**
35 * Log file name.
36 *
37 * @var string
38 */
39 private $filename = '';
40
41 /**
42 * Log file path.
43 *
44 * @var string
45 */
46 private $file = '';
47
48 /**
49 * File system API.
50 *
51 * @var WP_Filesystem_Base
52 */
53 private $fs;
54
55 /**
56 * Log file content.
57 *
58 * @var string
59 */
60 private $content;
61
62 /**
63 * Initialize logging.
64 *
65 * @param \ContentControl\Base\Container $c Container.
66 */
67 public function __construct( $c ) {
68 $this->c = $c;
69
70 $this->init();
71
72 $this->register_hooks();
73 }
74
75 /**
76 * Register hooks.
77 */
78 public function register_hooks() {
79 // On shutdown, save the log file.
80 add_action( 'shutdown', [ $this, 'save_logs' ] );
81 }
82
83 /**
84 * Gets the Uploads directory
85 *
86 * @return bool|array An associated array with baseurl and basedir or false on failure
87 */
88 public function get_upload_dir() {
89 if ( defined( '\IS_WPCOM' ) && \IS_WPCOM ) {
90 $wp_upload_dir = wp_get_upload_dir();
91 } else {
92 $wp_upload_dir = wp_upload_dir();
93 }
94
95 if ( isset( $wp_upload_dir['error'] ) && false !== $wp_upload_dir['error'] ) {
96 return false;
97 } else {
98 return $wp_upload_dir;
99 }
100 }
101
102 /**
103 * Gets the uploads directory URL
104 *
105 * @param string $path A path to append to end of upload directory URL.
106 * @return bool|string The uploads directory URL or false on failure
107 */
108 public function get_upload_dir_url( $path = '' ) {
109 $upload_dir = $this->get_upload_dir();
110 if ( false !== $upload_dir && isset( $upload_dir['baseurl'] ) ) {
111 $url = preg_replace( '/^https?:/', '', $upload_dir['baseurl'] );
112 if ( null === $url ) {
113 return false;
114 }
115 if ( ! empty( $path ) ) {
116 $url = trailingslashit( $url ) . $path;
117 }
118 return $url;
119 } else {
120 return false;
121 }
122 }
123
124 /**
125 * Chek if logging is enabled.
126 *
127 * @return bool
128 */
129 public function enabled() {
130 return ! defined( 'CONTENT_CONTROL_DISABLE_LOGGING' ) || ! CONTENT_CONTROL_DISABLE_LOGGING && $this->is_writable();
131 }
132
133 /**
134 * Get working WP Filesystem instance
135 *
136 * @return WP_Filesystem_Base|false
137 */
138 public function fs() {
139 if ( isset( $this->fs ) ) {
140 return $this->fs;
141 }
142
143 global $wp_filesystem;
144
145 require_once ABSPATH . 'wp-admin/includes/file.php';
146
147 // If for some reason the include doesn't work as expected just return false.
148 if ( ! function_exists( 'WP_Filesystem' ) ) {
149 return false;
150 }
151
152 $writable = WP_Filesystem( false, '', true );
153
154 // We consider the directory as writable if it uses the direct transport,
155 // otherwise credentials would be needed.
156 $this->fs = ( $writable && 'direct' === $wp_filesystem->method ) ? $wp_filesystem : false;
157
158 return $this->fs;
159 }
160
161 /**
162 * Check if the log file is writable.
163 *
164 * @return boolean
165 */
166 public function is_writable() {
167 if ( isset( $this->is_writable ) ) {
168 return $this->is_writable;
169 }
170
171 $file_system = $this->fs();
172
173 if ( false === $file_system ) {
174 $this->is_writable = false;
175 return $this->is_writable;
176 }
177
178 $this->is_writable = 'direct' === $file_system->method;
179
180 $upload_dir = $this->get_upload_dir();
181
182 if ( ! $file_system->is_writable( $upload_dir['basedir'] ) ) {
183 $this->is_writable = false;
184 }
185
186 return $this->is_writable;
187 }
188
189 /**
190 * Get things started
191 */
192 public function init() {
193 $upload_dir = $this->get_upload_dir();
194 $file_system = $this->fs();
195
196 if ( false === $upload_dir || false === $file_system ) {
197 return;
198 }
199
200 $file_token = \get_option( 'content_control_debug_log_token' );
201 if ( false === $file_token ) {
202 $file_token = uniqid( wp_rand(), true );
203 \update_option( 'content_control_debug_log_token', $file_token );
204 }
205
206 $this->filename = self::LOG_FILE_PREFIX . "debug-{$file_token}.log"; // ex. content-control-debug-5c2f6a9b9b5a3.log.
207 $this->file = trailingslashit( $upload_dir['basedir'] ) . $this->filename;
208
209 if ( ! $file_system->exists( $this->file ) ) {
210 $this->setup_new_log();
211 } else {
212 $this->content = $this->get_file( $this->file );
213 }
214
215 // Truncate long log files.
216 if ( $file_system->exists( $this->file ) && $file_system->size( $this->file ) >= 1048576 ) {
217 $this->truncate_log();
218 }
219 }
220
221 /**
222 * Get the log file path.
223 *
224 * @return string
225 */
226 public function get_file_path() {
227 return $this->file;
228 }
229
230 /**
231 * Retrieves the url to the file
232 *
233 * @returns string|bool The url to the file or false on failure
234 */
235 public function get_file_url() {
236 if ( ! $this->enabled() ) {
237 return false;
238 }
239
240 return $this->get_upload_dir_url( $this->filename );
241 }
242
243 /**
244 * Retrieve the log data
245 *
246 * @return string
247 */
248 public function get_log() {
249 return $this->get_log_content();
250 }
251
252 /**
253 * Delete the log file and token.
254 *
255 * @return void
256 */
257 public function delete_logs() {
258 $file_system = $this->fs();
259
260 if ( false === $file_system ) {
261 return;
262 }
263
264 $file_system->delete( $this->file );
265 \delete_option( 'content_control_debug_log_token' );
266 }
267
268 /**
269 * Log message to file
270 *
271 * @param string $message The message to log.
272 */
273 public function log( $message = '' ) {
274 $this->write_to_log( wp_date( 'Y-n-d H:i:s' ) . ' - ' . $message );
275 }
276
277 /**
278 * Log unique message to file.
279 *
280 * @param string $message The unique message to log.
281 */
282 public function log_unique( $message = '' ) {
283 $contents = $this->get_log_content();
284
285 if ( strpos( $contents, $message ) !== false ) {
286 return;
287 }
288
289 $this->log( $message );
290 }
291
292 /**
293 * Get the log file contents.
294 *
295 * @return string
296 */
297 public function get_log_content() {
298 if ( ! isset( $this->content ) ) {
299 $this->content = $this->get_file();
300 }
301
302 return $this->content;
303 }
304
305 /**
306 * Set the log file contents in memory.
307 *
308 * @param mixed $content The content to set.
309 * @param bool $save Whether to save the content to the file immediately.
310 * @return void
311 */
312 private function set_log_content( $content, $save = false ) {
313 $this->content = $content;
314
315 if ( $save ) {
316 $this->save_logs();
317 }
318 }
319
320 /**
321 * Retrieve the contents of a file.
322 *
323 * @param string|boolean $file File to get contents of.
324 *
325 * @return string
326 */
327 protected function get_file( $file = false ) {
328 $file = $file ? $file : $this->file;
329
330 $file_system = $this->fs();
331
332 if ( false === $file_system || ! $this->enabled() ) {
333 return '';
334 }
335
336 $content = '';
337
338 if ( $file_system->exists( $file ) ) {
339 $content = $file_system->get_contents( $file );
340 }
341
342 return $content;
343 }
344
345 /**
346 * Write the log message
347 *
348 * @param string $message The message to write.
349 */
350 protected function write_to_log( $message = '' ) {
351 if ( ! $this->enabled() ) {
352 return;
353 }
354
355 $contents = $this->get_log_content();
356
357 // If it doesn't end with a new line, add one. \r\n length is 2.
358 if ( substr( $contents, -2 ) !== "\r\n" ) {
359 $contents .= "\r\n";
360 }
361
362 $this->set_log_content( $contents . $message );
363 }
364
365 /**
366 * Save the current contents to file.
367 */
368 public function save_logs() {
369 $file_system = $this->fs();
370
371 if ( false === $file_system || ! $this->enabled() ) {
372 return;
373 }
374
375 $file_system->put_contents( $this->file, $this->content, FS_CHMOD_FILE );
376 }
377
378 /**
379 * Get a line count.
380 *
381 * @return int
382 */
383 public function count_lines() {
384 $file = $this->get_log_content();
385 $lines = explode( "\r\n", $file );
386
387 return count( $lines );
388 }
389
390 /**
391 * Truncates a log file to maximum of 250 lines.
392 */
393 public function truncate_log() {
394 $content = $this->get_log_content();
395 $lines = explode( "\r\n", $content );
396 $lines = array_slice( $lines, 0, 250 ); // 50 is how many lines you want to keep
397 $truncated_content = implode( "\r\n", $lines );
398 $this->set_log_content( $truncated_content, true );
399 }
400
401 /**
402 * Set up a new log file.
403 *
404 * @return void
405 */
406 public function setup_new_log() {
407 $this->set_log_content( "Content Control Debug Logs:\r\n" . wp_date( 'Y-n-d H:i:s' ) . " - Log file initialized\r\n", true );
408 }
409
410 /**
411 * Delete the log file.
412 */
413 public function clear_log() {
414 $file_system = $this->fs();
415
416 if ( false === $file_system ) {
417 return;
418 }
419
420 // Delete the file.
421 // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged
422 @$file_system->delete( $this->file );
423
424 if ( $this->enabled() ) {
425 $this->setup_new_log();
426 }
427 }
428
429 /**
430 * Log a deprecated notice.
431 *
432 * @param string $func_name Function name.
433 * @param string $version Versoin deprecated.
434 * @param string $replacement Replacement function (optional).
435 */
436 public function log_deprecated_notice( $func_name, $version, $replacement = null ) {
437 if ( ! is_null( $replacement ) ) {
438 $notice = sprintf( '%1$s is <strong>deprecated</strong> since version %2$s! Use %3$s instead.', $func_name, $version, $replacement );
439 } else {
440 $notice = sprintf( '%1$s is <strong>deprecated</strong> since version %2$s with no alternative available.', $func_name, $version );
441 }
442
443 $this->log_unique( $notice );
444 }
445 }
446