PluginProbe
Code Profiler – WordPress Performance Profiling and Debugging Made Easy / 1.7.4
Code Profiler – WordPress Performance Profiling and Debugging Made Easy v1.7.4
1.9.5 1.9.4 1.9.3 trunk 1.4 1.4.1 1.4.2 1.4.3 1.4.4 1.5 1.5.1 1.5.2 1.5.3 1.5.4 1.5.5 1.6 1.6.1 1.6.10 1.6.2 1.6.3 1.6.4 1.6.5 1.6.6 1.6.7 1.6.8 All 40 releases
← All changes | lib/helper.php +313 -89 1.5.51.7.4 View file →
@@ -1,6 +1,6 @@
1 1 <?php
2 -/*
2 +/**
3 3 +=====================================================================+
4 4 | ____ _ ____ __ _ _ |
5 5 | / ___|___ __| | ___ | _ \ _ __ ___ / _(_) | ___ _ __ |
6 6 | | | / _ \ / _` |/ _ \ | |_) | '__/ _ \| |_| | |/ _ \ '__| |
@@ -6,66 +6,125 @@
6 6 | | | / _ \ / _` |/ _ \ | |_) | '__/ _ \| |_| | |/ _ \ '__| |
7 7 | | |__| (_) | (_| | __/ | __/| | | (_) | _| | | __/ | |
8 8 | \____\___/ \__,_|\___| |_| |_| \___/|_| |_|_|\___|_| |
9 9 | |
10 - | (c) Jerome Bruandet ~ https://code-profiler.com/ |
10 + | (c) Jerome Bruandet ~ https://nintechnet.com/codeprofiler/ |
11 11 +=====================================================================+
12 12 */
13 13
14 -if (! defined('ABSPATH') ) { die('Forbidden'); }
14 +if (! defined('ABSPATH') ) {
15 + die('Forbidden');
16 +}
15 17
16 18 // =====================================================================
17 19 // Various constants
18 20
19 -$upload_dir = wp_upload_dir();
20 -define('CODE_PROFILER_UPLOAD_DIR', $upload_dir['basedir'] .'/code-profiler');
21 +// The profiles directory can be defined in the wp-config.php script
22 +if (! defined('CODE_PROFILER_UPLOAD_DIR') ) {
23 + // When running Code Profiler via WP CLI on a child site of a multisite installation,
24 + // we need to get the main site upload folder otherwise wp_upload_dir will return
25 + // the child site's
26 + if ( is_multisite() && ! ( is_main_network() && is_main_site() && defined('MULTISITE') ) ) {
27 + $upload_dir = code_profiler_upload_dir();
28 + } else {
29 + $upload_dir = wp_upload_dir();
30 + }
31 + define('CODE_PROFILER_UPLOAD_DIR', $upload_dir['basedir'] .'/code-profiler');
32 +}
21 33 define('CODE_PROFILER_LOG', CODE_PROFILER_UPLOAD_DIR .'/log.php');
22 34 define('CODE_PROFILER_TMP_IOSTATS_LOG', 'iostats.tmp');
23 35 define('CODE_PROFILER_TMP_SUMMARY_LOG', 'summary.tmp');
24 -define('CODE_PROFILER_TMP_TICKS_LOG', 'ticks.tmp');
36 +define('CODE_PROFILER_TMP_CALLS_LOG', 'calls.tmp');
25 37 define('CODE_PROFILER_TMP_DISKIO_LOG', 'diskio.tmp');
38 +define('CODE_PROFILER_TMP_CONNECTIONS_LOG', 'connections.tmp');
26 39 define('CODE_PROFILER_UPDATE_NOTICE', '<div class="updated notice is-dismissible"><p>%s</p></div>');
27 40 define('CODE_PROFILER_ERROR_NOTICE', '<div class="error notice is-dismissible"><p>%s</p></div>');
28 -global $wp_version;
29 -if (! defined('CODE_PROFILER_UA') ) { // UA signatures can be user-defined in the wp-config.php
30 - define ('CODE_PROFILER_UA', [
31 - esc_html__('Desktop', 'code-profiler') => [
32 - 'Firefox' => 'Mozilla/5.0 (Linux x86_64; rv:104.0) Gecko/20100101 Firefox/104.0',
33 - 'Chrome' => 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko)'.
34 - ' Chrome/105.0.0.0 Safari/537.36',
35 - 'Edge' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML,'.
36 - ' like Gecko) Chrome/105.0.0.0 Safari/537.36 Edg/105.0.1343.27'
37 - ],
38 - esc_html__('Mobile', 'code-profiler') => [
39 - 'Android Phone' => 'Mozilla/5.0 (Android 12; Mobile; rv:68.0) Gecko/68.0 Firefox/104.0',
40 - 'Android Tablet' => 'Mozilla/5.0 (Linux; Android 12.0; SAMSUNG-SM-T377A Build/NMF26X)'.
41 - ' AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Mobile Safari/537.36',
42 - 'iPhone' => 'Mozilla/5.0 (iPhone; CPU iPhone OS 15_5 like Mac OS X) AppleWebKit/605.1.15'.
43 - ' (KHTML, like Gecko) Version/15.4 Mobile/15E148 Safari/604.1',
44 - 'iPad' => 'Mozilla/5.0 (iPad; CPU OS 15_5 like Mac OS X) AppleWebKit/605.1.15'.
45 - ' (KHTML, like Gecko) GSA/213.0.449417121 Mobile/15E148 Safari/604.1'
46 - ],
47 - esc_html__('Bot', 'code-profiler') => [
48 - 'Google Bot' => 'Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)',
49 - 'WordPress' => 'Mozilla/5.0 (compatible; CodeProfiler for WordPress/'. $wp_version .
50 - '; https://code-profiler.com/)'
51 - ]
41 +if (! defined('CODE_PROFILER_MUPLUGIN') ) {
42 + // MU plugin's name can be defined in the wp-config.php
43 + define('CODE_PROFILER_MUPLUGIN', '0----code-profiler.php');
44 +}
52 45
53 - ] );
46 +/**
47 + * Since WP 6.7, translation loading must not be triggered too early.
48 + */
49 +add_action('init', 'code_profiler_i18n_constants');
50 +function code_profiler_i18n_constants() {
51 +
52 + global $wp_version;
53 + if (! defined('CODE_PROFILER_UA') ) { // UA signatures can be user-defined in the wp-config.php
54 + define ('CODE_PROFILER_UA', [
55 + esc_html__('Desktop', 'code-profiler') => [
56 + 'Firefox' => 'Mozilla/5.0 (Linux x86_64; rv:135.0) Gecko/20100101 Firefox/135.0',
57 + 'Chrome' => 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML,'.
58 + ' like Gecko) Chrome/133.0.0.0 Safari/537.36',
59 + 'Edge' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML,'.
60 + ' like Gecko) Chrome/133.0.0.0 Safari/537.36 Edg/131.0.2903.86'
61 + ],
62 + esc_html__('Mobile', 'code-profiler') => [
63 + 'Android Phone' => 'Mozilla/5.0 (Android 15; Mobile; rv:68.0) Gecko/68.0 Firefox/135.0',
64 + 'Android Tablet' => 'Mozilla/5.0 (Linux; Android 15.0; SAMSUNG-SM-T377A Build/NMF26X)'.
65 + ' AppleWebKit/537.36 (KHTML, like Gecko) Chrome/150.0.0.0 Mobile Safari/537.36',
66 + 'iPhone' => 'Mozilla/5.0 (iPhone; CPU iPhone OS 17_7_2 like Mac OS X) AppleWebKit/605.1.15'.
67 + ' (KHTML, like Gecko) Version/17_7_2 Mobile/15E148 Safari/604.1',
68 + 'iPad' => 'Mozilla/5.0 (iPad; CPU OS 17_7_2 like Mac OS X) AppleWebKit/605.1.15'.
69 + ' (KHTML, like Gecko) GSA/213.0.449417121 Mobile/15E148 Safari/605.1.15'
70 + ],
71 + esc_html__('Bot', 'code-profiler') => [
72 + 'Google Bot' => 'Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)',
73 + 'WordPress' => 'Mozilla/5.0 (compatible; CodeProfiler for WordPress/'. $wp_version .
74 + '; https://nintechnet.com/codeprofiler/)'
75 + ]
76 +
77 + ] );
78 + }
79 + define('CODE_PROFILER_ACCURACY', [
80 + 1 => __('Highest', 'code-profiler'),
81 + 5 => __('High', 'code-profiler'),
82 + 10 => __('Moderate', 'code-profiler'),
83 + 15 => __('Low', 'code-profiler'),
84 + 20 => __('Lowest', 'code-profiler')
85 + ]);
54 86 }
55 87
56 -if (! defined('CODE_PROFILER_MUPLUGIN') ) {
57 - // MU plugin's name can be defined in the wp-config.php
58 - define('CODE_PROFILER_MUPLUGIN', '0----code-profiler.php');
88 +// =====================================================================
89 +// Find the main site upload dir on a multisite installation.
90 +// Used when running the profiler via WP CLI.
91 +// This code is based on the WP private _wp_upload_dir function.
92 +
93 +function code_profiler_upload_dir() {
94 +
95 + $upload_path = trim( get_option('upload_path') );
96 + if ( empty( $upload_path ) || 'wp-content/uploads' === $upload_path ) {
97 + $basedir = WP_CONTENT_DIR . '/uploads';
98 + } elseif ( strpos( $upload_path, ABSPATH ) !== 0 ) {
99 + // $basedir is absolute, $upload_path is (maybe) relative to ABSPATH.
100 + $basedir = path_join( ABSPATH, $upload_path );
101 + } else {
102 + $basedir = $upload_path;
103 + }
104 +
105 + if ( defined('UPLOADS') && ! ( is_multisite() && get_site_option('ms_files_rewriting') ) ) {
106 + $basedir = ABSPATH . UPLOADS;
107 + }
108 +
109 + return ['basedir' => $basedir];
59 110 }
60 -define('CODE_PROFILER_ACCURACY', [
61 - 1 => __('Highest (default)', 'code-profiler'),
62 - 5 => __('High', 'code-profiler'),
63 - 10 => __('Moderate', 'code-profiler'),
64 - 15 => __('Low', 'code-profiler'),
65 - 20 => __('Lowest', 'code-profiler')
66 -]);
111 +
67 112 // =====================================================================
113 +// Prevent cURL timeout if a plugin changes its timeout options.
114 +
115 +function code_profiler_curl_timeout( $handle, $parsed_args, $url ) {
116 +
117 + if ( isset( $_REQUEST['action'] ) &&
118 + $_REQUEST['action'] == 'codeprofiler_start_profiler') {
119 +
120 + curl_setopt( $handle, CURLOPT_CONNECTTIMEOUT, 300 );
121 + curl_setopt( $handle, CURLOPT_TIMEOUT, 300 );
122 + }
123 +}
124 +add_action('http_api_curl', 'code_profiler_curl_timeout', 1000, 3 );
125 +
126 +// =====================================================================
68 127 // Update version in the DB and check if options must be updated.
69 128
70 129 function code_profiler_init_update() {
71 130
@@ -110,8 +169,12 @@
110 169
111 170 if (! file_exists( CODE_PROFILER_UPLOAD_DIR ) ) {
112 171 mkdir( CODE_PROFILER_UPLOAD_DIR, 0755 );
113 172 }
173 + if (! is_writable( CODE_PROFILER_UPLOAD_DIR ) ) {
174 + // PHP running as an Apache module?
175 + chmod( CODE_PROFILER_UPLOAD_DIR, 0777 );
176 + }
114 177 if (! file_exists( CODE_PROFILER_UPLOAD_DIR .'/index.html') ) {
115 178 touch( CODE_PROFILER_UPLOAD_DIR .'/index.html');
116 179 }
117 180 // For Apache & Litespeed
@@ -166,12 +229,59 @@
166 229
167 230 }
168 231
169 232 // =====================================================================
233 +// Check the PHP memory limit and return a suggested size
234 +// for the profiler's buffer.
235 +
236 +function code_profiler_suggested_memory() {
237 +
238 + $memory_limit = ini_get('memory_limit');
239 +
240 + if ('-1' == $memory_limit ) {
241 + // Return max size
242 + return 10;
243 + }
244 +
245 + if ( preg_match('/^(\d+)([PTGMK])$/i', $memory_limit, $match ) ) {
246 + $bytes = (int) $match[1];
247 + switch ( strtoupper( $match[2] ) ) {
248 + case 'P':
249 + $bytes *= 1024;
250 + case 'T':
251 + $bytes *= 1024;
252 + case 'G':
253 + $bytes *= 1024;
254 + case 'M':
255 + $bytes *= 1024;
256 + case 'K':
257 + $bytes *= 1024;
258 + }
259 + // 256 MB
260 + if ( $bytes >= 268435456 ) {
261 + return 10;
262 + // 128 MB
263 + } elseif ( $bytes >= 134217728 ) {
264 + return 7;
265 + // 64 MB
266 + } elseif ( $bytes >= 67108864 ) {
267 + return 4;
268 + // <64 MB
269 + } else {
270 + return 1;
271 + }
272 + }
273 + // Don't know :/
274 + return 5;
275 +}
276 +
277 +// =====================================================================
170 278 // Create the default options.
171 279
172 280 function code_profiler_default_options() {
173 281
282 + $buffer = code_profiler_suggested_memory();
283 +
174 284 $cp_options = [
175 285 'show_paths' => 'relative',
176 286 'display_name' => 'full',
177 287 'truncate_name' => 30,
@@ -182,9 +292,10 @@
182 292 'warn_composer' => 1,
183 293 'enable_wpcli' => 1,
184 294 'disable_wpcron' => 1,
185 295 'http_response' => '^(?:3|4|5)\d{2}$',
186 - 'accuracy' => 1
296 + 'accuracy' => 1,
297 + 'buffer' => (int) $buffer
187 298 ];
188 299
189 300 update_option('code-profiler', $cp_options );
190 301
@@ -189,15 +300,23 @@
189 300 update_option('code-profiler', $cp_options );
190 301
191 302 }
192 303
193 -// =====================================================================
304 +// ===================================================================== 2023-06-14
194 305 // Create a profile name.
195 306
196 307 function code_profiler_profile_name() {
197 308
198 309 return date('Y-m-d_') . substr( time(), 4 );
310 +}
199 311
312 +// ===================================================================== 2023-06-14
313 +// Disable PHP display_errors so that notice, warning and error messages
314 +// don't show up in the AJAX response.
315 +
316 +function code_profiler_hide_errors() {
317 +
318 + ini_set('display_errors', 0 );
200 319 }
201 320
202 321 // =====================================================================
203 322 // Disable opcode cache.
@@ -204,14 +323,15 @@
204 323
205 324 function code_profiler_disable_opcode() {
206 325
207 326 try {
208 - if (extension_loaded('Zend OPcache')) {
327 + if ( extension_loaded('Zend OPcache') ) {
209 328 ini_set('opcache.enable', 0);
210 329 } elseif ( extension_loaded('wincache') ) {
211 330 ini_set('wincache.fcenabled', 0);
212 331 }
213 332 set_time_limit(0);
333 + ini_set('memory_limit', -1);
214 334
215 335 } catch ( Exception $e ) { }
216 336
217 337 $cp_options = get_option('code-profiler');
@@ -219,36 +339,32 @@
219 339 if (! defined('DISABLE_WP_CRON') ) {
220 340 define('DISABLE_WP_CRON', true );
221 341 }
222 342 }
343 +}
223 344
224 -}
225 345 // =====================================================================
226 -// Verify the security key when running the profile.
346 +// Verify the security key when running the profiler.
227 347
228 348 function code_profiler_verify_key() {
229 349
230 350 $response = [
231 351 'status' => 'error',
232 - 'message' => __('Security keys do not match. Reload the page and try again (%s)', 'code-profiler')
352 + 'message' => __('Security keys do not match. Reload the page and try again (%s)',
353 + 'code-profiler')
233 354 ];
234 355
235 - $cp_options = get_option('code-profiler');
356 + if ( empty( $_REQUEST['profiler_key'] ) ) {
357 + $response['message'] = sprintf( $response['message'], '001');
236 358
237 - if ( empty( $cp_options['hash'] ) ) {
238 - $response['message'] = sprintf( $response['message'], '#1');
239 -
240 359 } else {
241 - if ( empty( $_REQUEST['profiler_key'] ) ) {
242 - $response['message'] = sprintf( $response['message'], '#2');
243 -
244 - } else {
245 - if ( $cp_options['hash'] == sha1( $_REQUEST['profiler_key'] ) ) {
246 - return;
247 - } else {
248 - $response['message'] = sprintf( $response['message'], '#3');
249 - }
360 + $file = CODE_PROFILER_UPLOAD_DIR .'/key_'. sha1( $_REQUEST['profiler_key'] ) .'.tmp';
361 + if ( file_exists( $file ) ) {
362 + // Delete it and accept the request
363 + unlink( $file );
364 + return;
250 365 }
366 + $response['message'] = sprintf( $response['message'], '002');
251 367 }
252 368 wp_send_json( $response );
253 369
254 370 }
@@ -260,30 +376,64 @@
260 376
261 377 function code_profiler_write2log( $message, $level, $create ) {
262 378
263 379 if ( empty( $create ) ) {
264 - file_put_contents( CODE_PROFILER_LOG, time() ."~~$level~~$message\n", FILE_APPEND );
380 + file_put_contents(
381 + CODE_PROFILER_LOG,
382 + time() ."~~$level~~$message\n",
383 + FILE_APPEND
384 + );
265 385 } else {
266 - file_put_contents( CODE_PROFILER_LOG, time() ."~~$level~~$message\n");
386 + file_put_contents(
387 + CODE_PROFILER_LOG,
388 + time() ."~~$level~~$message\n"
389 + );
267 390 }
268 391 }
269 392
270 -function code_profiler_log_info( $string, $create = 0 ) { code_profiler_write2log( $string, 1, $create ); }
271 -function code_profiler_log_warn( $string, $create = 0 ) { code_profiler_write2log( $string, 2, $create ); }
272 -function code_profiler_log_error( $string, $create = 0 ) { code_profiler_write2log( $string, 4, $create ); }
273 -function code_profiler_log_debug( $string, $create = 0 ) { code_profiler_write2log( $string, 8, $create ); }
393 +function code_profiler_log_info( $string, $create = 0 ) {
394 + code_profiler_write2log( $string, 1, $create );
395 +}
396 +function code_profiler_log_warn( $string, $create = 0 ) {
397 + code_profiler_write2log( $string, 2, $create );
398 +}
399 +function code_profiler_log_error( $string, $create = 0 ) {
400 + code_profiler_write2log( $string, 4, $create );
401 +}
402 +function code_profiler_log_debug( $string, $create = 0 ) {
403 + code_profiler_write2log( $string, 8, $create );
404 +}
274 405
275 406 // =====================================================================
407 +// Retrieve and return matching files from a directory.
408 +
409 +function code_profiler_glob( $directory, $regex, $pathname = false ) {
410 +
411 + $list = [];
412 +
413 + foreach ( new DirectoryIterator( $directory ) as $finfo ) {
414 + if (! $finfo->isDot() && preg_match("`$regex`", $finfo->getFilename() ) ) {
415 + if ( $pathname ) {
416 + $list[] = $finfo->getPathname();
417 + } else {
418 + $list[] = $finfo->getFilename();
419 + }
420 + }
421 + }
422 + return $list;
423 +}
424 +
425 +// =====================================================================
276 426 // Verify if a profile exists and return its full path.
277 427
278 428 function code_profiler_get_profile_path( $id, $type = 'slugs') {
279 429
280 - $return = false;
430 + if (! empty( $id ) && preg_match('/^\d{10}\.\d+$/', $id ) ) {
281 431
282 - if (! empty( $id ) && preg_match('/^\d{10}\.\d+$/', $id ) ) {
283 - $glob = glob( CODE_PROFILER_UPLOAD_DIR ."/$id.*.$type.profile" );
432 + $glob = code_profiler_glob(CODE_PROFILER_UPLOAD_DIR, "$id\..+\.$type\.profile$", true);
433 +
284 434 if ( is_array( $glob ) && ! empty( $glob[0] ) ) {
285 - if ( preg_match( "`/$id\.(.+?).$type.profile$`", $glob[0], $match ) ) {
435 + if ( preg_match( "`$id\.(.+?).$type.profile$`", $glob[0], $match ) ) {
286 436
287 437 return CODE_PROFILER_UPLOAD_DIR. "/$id.{$match[1]}";
288 438 }
289 439 }
@@ -311,10 +461,17 @@
311 461 $buffer['error'] = $err;
312 462 return $buffer;
313 463 }
314 464
465 + /**
466 + * We don't use fgetcsv() as it requires the $escape parameter since PHP 8.4
467 + */
315 468 while (! feof( $fh ) ) {
316 - $buffer[] = fgetcsv( $fh, 1000, "\t" );
469 + $tmp = trim( fgets( $fh, 1000 ) );
470 + if (! $tmp ) {
471 + continue;
472 + }
473 + $buffer[] = explode( "\t", $tmp );
317 474 }
318 475
319 476 fclose( $fh );
320 477
@@ -369,9 +526,9 @@
369 526
370 527 $string = $open;
371 528
372 529 if ( empty( $decode->items ) ) {
373 - $tmp = 'N/A';
530 + $tmp = __('N/A', 'code-profiler');
374 531 } else {
375 532 $tmp = (int) --$decode->items;
376 533 }
377 534 $string .= sprintf(
@@ -381,9 +538,9 @@
381 538
382 539 $string .= $div;
383 540
384 541 if ( empty( $decode->time ) ) {
385 - $tmp = 'N/A';
542 + $tmp = __('N/A', 'code-profiler');
386 543 } else {
387 544 $tmp = number_format( $decode->time, 4 );
388 545 }
389 546 $string .= sprintf(
@@ -393,9 +550,9 @@
393 550
394 551 $string .= $div;
395 552
396 553 if ( empty( $decode->memory ) ) {
397 - $tmp = 'N/A';
554 + $tmp = __('N/A', 'code-profiler');
398 555 } else {
399 556 $tmp = number_format( $decode->memory, 2);
400 557 }
401 558 $string .= sprintf(
@@ -405,11 +562,11 @@
405 562
406 563 $string .= $div;
407 564
408 565 if ( empty( $decode->io ) ) {
409 - $tmp = 'N/A';
566 + $tmp = __('N/A', 'code-profiler');
410 567 } else {
411 - $tmp = number_format( $decode->io );
568 + $tmp = number_format( (int) $decode->io );
412 569 }
413 570 $string .= sprintf(
414 571 __('File I/O operations: %s', 'code-profiler'),
415 572 $tmp
@@ -417,11 +574,11 @@
417 574
418 575 $string .= $div;
419 576
420 577 if ( empty( $decode->queries ) ) {
421 - $tmp = 'N/A';
578 + $tmp = __('N/A', 'code-profiler');
422 579 } else {
423 - $tmp = number_format( $decode->queries );
580 + $tmp = number_format( (int) $decode->queries );
424 581 }
425 582 $string .= sprintf(
426 583 __('SQL queries: %s', 'code-profiler'),
427 584 $tmp
@@ -426,8 +583,20 @@
426 583 __('SQL queries: %s', 'code-profiler'),
427 584 $tmp
428 585 );
429 586
587 + $string .= $div;
588 +
589 + if ( empty( CODE_PROFILER_ACCURACY[ $decode->precision ] ) ) {
590 + $tmp = __('N/A', 'code-profiler');
591 + } else {
592 + $tmp = CODE_PROFILER_ACCURACY[ $decode->precision ];
593 + }
594 + $string .= sprintf(
595 + __('Accuracy: %s', 'code-profiler'),
596 + $tmp
597 + );
598 +
430 599 $string .= $close;
431 600
432 601 return $string;
433 602 }
@@ -432,29 +601,30 @@
432 601 return $string;
433 602 }
434 603
435 604 // =====================================================================
436 -// Remove *tmp files left after an HTTP error (4xx or 5xx).
605 +// Remove *tmp files left in the profiles folder.
437 606
438 607 function code_profiler_cleantmpfiles() {
439 608
440 - $glob = glob( CODE_PROFILER_UPLOAD_DIR .'/*.tmp');
609 + $glob = code_profiler_glob( CODE_PROFILER_UPLOAD_DIR, '\.tmp$', true );
610 +
441 611 if ( is_array( $glob ) ) {
442 - $count = 0;
443 612 foreach( $glob as $file ) {
444 - $count++;
445 613 unlink( $file );
446 614 }
447 - if ( $count ) {
448 - code_profiler_log_info( sprintf(
449 - __('Deleting %s temporary files found in the profiles folder', 'code-profiler'),
450 - (int) $count
451 - ) );
452 - }
453 615 }
454 616 }
455 617
456 618 // =====================================================================
619 +// Remove non-ASCII characters from a string.
620 +
621 +function code_profiler_ASCII_filter( $string ) {
622 +
623 + return preg_replace('/[\x00-\x1f\x7f-\xff]/', '', $string );
624 +}
625 +
626 +// =====================================================================
457 627 // Clear the log if it's bigger than 100KB.
458 628
459 629 function code_profiler_clearlog() {
460 630
@@ -462,9 +632,9 @@
462 632 file_put_contents( CODE_PROFILER_LOG, "<?php exit; ?>\n" );
463 633 }
464 634 }
465 635
466 -// =====================================================================
636 +// ===================================================================== 2023-06-15
467 637 // We don't want to be bothered by other themes/plugins' admin notices.
468 638
469 639 add_action('admin_head', 'code_profiler_hide_admin_notices');
470 640
@@ -471,9 +641,63 @@
471 641 function code_profiler_hide_admin_notices() {
472 642 if ( isset( $_GET['page'] ) && $_GET['page'] == 'code-profiler') {
473 643 remove_all_actions('admin_notices');
474 644 remove_all_actions('all_admin_notices');
645 + add_filter('admin_footer_text', 'code_profiler_admin_footer');
475 646 }
647 +}
648 +
649 +function code_profiler_admin_footer () {
650 + echo '<span id="footer-thankyou">'.
651 + sprintf(
652 + /* Translators: %s are the '<a href="">' and '</a>' anchors */
653 + esc_html(
654 + 'Thank you for using %sCode Profiler%s.',
655 + 'code-profiler'
656 + ),
657 + '<a href="https://nintechnet.com/codeprofiler/" target="_blank">',
658 + '</a>'
659 + ).
660 + '</span>';
661 +}
662 +
663 +// =====================================================================
664 +// Display/hide an element depending on some value
665 +
666 +function code_profiler_hide( $var, $val ) {
667 +
668 + if ( $var == $val ) {
669 + echo " style='display:none'";
670 + }
671 +}
672 +
673 +// =====================================================================
674 +// Retrieve all themes.
675 +
676 +function code_profiler_get_themes() {
677 +
678 + $list = [];
679 +
680 + // Make sure the function is loaded
681 + if (! function_exists('wp_get_themes') ) {
682 + require_once ABSPATH . 'wp-includes/theme.php';
683 + }
684 + $themes = wp_get_themes();
685 + foreach( $themes as $k => $v ) {
686 + if ( $v->Name ) {
687 + $list[ $k ] = [
688 + 'n' => $v->Name,
689 +
690 + 't' => $v->Template
691 + ];
692 + } else {
693 + $list[ $k ] = [
694 + 'n' => $k,
695 + 't' => $v->Template
696 + ];
697 + }
698 + }
699 + return $list;
476 700 }
477 701
478 702 // =====================================================================
479 703 // EOF