PluginProbe
Content Control – The Ultimate Content Restriction Plugin! Restrict Content, Create Conditional Blocks & More / 2.0.1
Content Control – The Ultimate Content Restriction Plugin! Restrict Content, Create Conditional Blocks & More v2.0.1
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.1, at classes/Plugin/Logging.php

418 lines 8.5 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 $this->is_writable = false !== $this->fs() && 'direct' === $this->fs()->method;
172
173 $upload_dir = $this->get_upload_dir();
174
175 if ( ! $this->fs()->is_writable( $upload_dir['basedir'] ) ) {
176 $this->is_writable = false;
177 }
178
179 return $this->is_writable;
180 }
181
182 /**
183 * Get things started
184 */
185 public function init() {
186 $upload_dir = $this->get_upload_dir();
187
188 $file_token = \get_option( 'content_control_debug_log_token' );
189 if ( false === $file_token ) {
190 $file_token = uniqid( wp_rand(), true );
191 \update_option( 'content_control_debug_log_token', $file_token );
192 }
193
194 $this->filename = self::LOG_FILE_PREFIX . "debug-{$file_token}.log"; // ex. content-control-debug-5c2f6a9b9b5a3.log.
195 $this->file = trailingslashit( $upload_dir['basedir'] ) . $this->filename;
196
197 if ( ! $this->fs()->exists( $this->file ) ) {
198 $this->setup_new_log();
199 } else {
200 $this->content = $this->get_file( $this->file );
201 }
202
203 // Truncate long log files.
204 if ( $this->fs()->exists( $this->file ) && $this->fs()->size( $this->file ) >= 1048576 ) {
205 $this->truncate_log();
206 }
207 }
208
209 /**
210 * Get the log file path.
211 *
212 * @return string
213 */
214 public function get_file_path() {
215 return $this->file;
216 }
217
218 /**
219 * Retrieves the url to the file
220 *
221 * @returns string|bool The url to the file or false on failure
222 */
223 public function get_file_url() {
224 if ( ! $this->enabled() ) {
225 return false;
226 }
227
228 return $this->get_upload_dir_url( $this->filename );
229 }
230
231 /**
232 * Retrieve the log data
233 *
234 * @return string
235 */
236 public function get_log() {
237 return $this->get_log_content();
238 }
239
240 /**
241 * Delete the log file and token.
242 *
243 * @return void
244 */
245 public function delete_logs() {
246 $this->fs->delete( $this->file );
247 \delete_option( 'content_control_debug_log_token' );
248 }
249
250 /**
251 * Log message to file
252 *
253 * @param string $message The message to log.
254 */
255 public function log( $message = '' ) {
256 $this->write_to_log( wp_date( 'Y-n-d H:i:s' ) . ' - ' . $message );
257 }
258
259 /**
260 * Log unique message to file.
261 *
262 * @param string $message The unique message to log.
263 */
264 public function log_unique( $message = '' ) {
265 $contents = $this->get_log_content();
266
267 if ( strpos( $contents, $message ) !== false ) {
268 return;
269 }
270
271 $this->log( $message );
272 }
273
274 /**
275 * Get the log file contents.
276 *
277 * @return string
278 */
279 public function get_log_content() {
280 if ( ! isset( $this->content ) ) {
281 $this->content = $this->get_file();
282 }
283
284 return $this->content;
285 }
286
287 /**
288 * Set the log file contents in memory.
289 *
290 * @param mixed $content The content to set.
291 * @param bool $save Whether to save the content to the file immediately.
292 * @return void
293 */
294 private function set_log_content( $content, $save = false ) {
295 $this->content = $content;
296
297 if ( $save ) {
298 $this->save_logs();
299 }
300 }
301
302 /**
303 * Retrieve the contents of a file.
304 *
305 * @param string|boolean $file File to get contents of.
306 *
307 * @return string
308 */
309 protected function get_file( $file = false ) {
310 $file = $file ? $file : $this->file;
311
312 if ( ! $this->enabled() ) {
313 return '';
314 }
315
316 $content = '';
317
318 if ( $this->fs()->exists( $file ) ) {
319 $content = $this->fs()->get_contents( $file );
320 }
321
322 return $content;
323 }
324
325 /**
326 * Write the log message
327 *
328 * @param string $message The message to write.
329 */
330 protected function write_to_log( $message = '' ) {
331 if ( ! $this->enabled() ) {
332 return;
333 }
334
335 $contents = $this->get_log_content();
336
337 // If it doesn't end with a new line, add one. \r\n length is 2.
338 if ( substr( $contents, -2 ) !== "\r\n" ) {
339 $contents .= "\r\n";
340 }
341
342 $this->set_log_content( $contents . $message );
343 }
344
345 /**
346 * Save the current contents to file.
347 */
348 public function save_logs() {
349 if ( ! $this->enabled() ) {
350 return;
351 }
352
353 $this->fs()->put_contents( $this->file, $this->content, FS_CHMOD_FILE );
354 }
355
356 /**
357 * Get a line count.
358 *
359 * @return int
360 */
361 public function count_lines() {
362 $file = $this->get_log_content();
363 $lines = explode( "\r\n", $file );
364
365 return count( $lines );
366 }
367
368 /**
369 * Truncates a log file to maximum of 250 lines.
370 */
371 public function truncate_log() {
372 $content = $this->get_log_content();
373 $lines = explode( "\r\n", $content );
374 $lines = array_slice( $lines, 0, 250 ); // 50 is how many lines you want to keep
375 $truncated_content = implode( "\r\n", $lines );
376 $this->set_log_content( $truncated_content, true );
377 }
378
379 /**
380 * Set up a new log file.
381 *
382 * @return void
383 */
384 public function setup_new_log() {
385 $this->set_log_content( "Content Control Debug Logs:\r\n" . wp_date( 'Y-n-d H:i:s' ) . " - Log file initialized\r\n", true );
386 }
387
388 /**
389 * Delete the log file.
390 */
391 public function clear_log() {
392 // Delete the file.
393 // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged
394 @$this->fs()->delete( $this->file );
395
396 if ( $this->enabled() ) {
397 $this->setup_new_log();
398 }
399 }
400
401 /**
402 * Log a deprecated notice.
403 *
404 * @param string $func_name Function name.
405 * @param string $version Versoin deprecated.
406 * @param string $replacement Replacement function (optional).
407 */
408 public function log_deprecated_notice( $func_name, $version, $replacement = null ) {
409 if ( ! is_null( $replacement ) ) {
410 $notice = sprintf( '%1$s is <strong>deprecated</strong> since version %2$s! Use %3$s instead.', $func_name, $version, $replacement );
411 } else {
412 $notice = sprintf( '%1$s is <strong>deprecated</strong> since version %2$s with no alternative available.', $func_name, $version );
413 }
414
415 $this->log_unique( $notice );
416 }
417 }
418