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 +278 -83 1.6.11.7.4 View file →
@@ -1,6 +1,6 @@
1 1 <?php
2 -/*
2 +/**
3 3 +=====================================================================+
4 4 | ____ _ ____ __ _ _ |
5 5 | / ___|___ __| | ___ | _ \ _ __ ___ / _(_) | ___ _ __ |
6 6 | | | / _ \ / _` |/ _ \ | |_) | '__/ _ \| |_| | |/ _ \ '__| |
@@ -6,65 +6,110 @@
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:110.0) Gecko/20100101 Firefox/110.0',
33 - 'Chrome' => 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko)'.
34 - ' Chrome/111.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/111.0.0.0 Safari/537.36 Edg/110.0.1587.63'
37 - ],
38 - esc_html__('Mobile', 'code-profiler') => [
39 - 'Android Phone' => 'Mozilla/5.0 (Android 13; Mobile; rv:68.0) Gecko/68.0 Firefox/110.0',
40 - 'Android Tablet' => 'Mozilla/5.0 (Linux; Android 13.0; SAMSUNG-SM-T377A Build/NMF26X)'.
41 - ' AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Mobile Safari/537.36',
42 - 'iPhone' => 'Mozilla/5.0 (iPhone; CPU iPhone OS 16_3_1 like Mac OS X) AppleWebKit/605.1.15'.
43 - ' (KHTML, like Gecko) Version/16.3 Mobile/15E148 Safari/604.1',
44 - 'iPad' => 'Mozilla/5.0 (iPad; CPU OS 16_3_1 like Mac OS X) AppleWebKit/605.1.15'.
45 - ' (KHTML, like Gecko) GSA/213.0.449417121 Mobile/15E148 Safari/605.1.15'
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 // =====================================================================
68 113 // Prevent cURL timeout if a plugin changes its timeout options.
69 114
70 115 function code_profiler_curl_timeout( $handle, $parsed_args, $url ) {
@@ -124,8 +169,12 @@
124 169
125 170 if (! file_exists( CODE_PROFILER_UPLOAD_DIR ) ) {
126 171 mkdir( CODE_PROFILER_UPLOAD_DIR, 0755 );
127 172 }
173 + if (! is_writable( CODE_PROFILER_UPLOAD_DIR ) ) {
174 + // PHP running as an Apache module?
175 + chmod( CODE_PROFILER_UPLOAD_DIR, 0777 );
176 + }
128 177 if (! file_exists( CODE_PROFILER_UPLOAD_DIR .'/index.html') ) {
129 178 touch( CODE_PROFILER_UPLOAD_DIR .'/index.html');
130 179 }
131 180 // For Apache & Litespeed
@@ -180,12 +229,59 @@
180 229
181 230 }
182 231
183 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 +// =====================================================================
184 278 // Create the default options.
185 279
186 280 function code_profiler_default_options() {
187 281
282 + $buffer = code_profiler_suggested_memory();
283 +
188 284 $cp_options = [
189 285 'show_paths' => 'relative',
190 286 'display_name' => 'full',
191 287 'truncate_name' => 30,
@@ -196,9 +292,10 @@
196 292 'warn_composer' => 1,
197 293 'enable_wpcli' => 1,
198 294 'disable_wpcron' => 1,
199 295 'http_response' => '^(?:3|4|5)\d{2}$',
200 - 'accuracy' => 1
296 + 'accuracy' => 1,
297 + 'buffer' => (int) $buffer
201 298 ];
202 299
203 300 update_option('code-profiler', $cp_options );
204 301
@@ -203,15 +300,23 @@
203 300 update_option('code-profiler', $cp_options );
204 301
205 302 }
206 303
207 -// =====================================================================
304 +// ===================================================================== 2023-06-14
208 305 // Create a profile name.
209 306
210 307 function code_profiler_profile_name() {
211 308
212 309 return date('Y-m-d_') . substr( time(), 4 );
310 +}
213 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 );
214 319 }
215 320
216 321 // =====================================================================
217 322 // Disable opcode cache.
@@ -218,14 +323,15 @@
218 323
219 324 function code_profiler_disable_opcode() {
220 325
221 326 try {
222 - if (extension_loaded('Zend OPcache')) {
327 + if ( extension_loaded('Zend OPcache') ) {
223 328 ini_set('opcache.enable', 0);
224 329 } elseif ( extension_loaded('wincache') ) {
225 330 ini_set('wincache.fcenabled', 0);
226 331 }
227 332 set_time_limit(0);
333 + ini_set('memory_limit', -1);
228 334
229 335 } catch ( Exception $e ) { }
230 336
231 337 $cp_options = get_option('code-profiler');
@@ -233,36 +339,32 @@
233 339 if (! defined('DISABLE_WP_CRON') ) {
234 340 define('DISABLE_WP_CRON', true );
235 341 }
236 342 }
343 +}
237 344
238 -}
239 345 // =====================================================================
240 -// Verify the security key when running the profile.
346 +// Verify the security key when running the profiler.
241 347
242 348 function code_profiler_verify_key() {
243 349
244 350 $response = [
245 351 'status' => 'error',
246 - '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')
247 354 ];
248 355
249 - $cp_options = get_option('code-profiler');
356 + if ( empty( $_REQUEST['profiler_key'] ) ) {
357 + $response['message'] = sprintf( $response['message'], '001');
250 358
251 - if ( empty( $cp_options['hash'] ) ) {
252 - $response['message'] = sprintf( $response['message'], '#1');
253 -
254 359 } else {
255 - if ( empty( $_REQUEST['profiler_key'] ) ) {
256 - $response['message'] = sprintf( $response['message'], '#2');
257 -
258 - } else {
259 - if ( $cp_options['hash'] == sha1( $_REQUEST['profiler_key'] ) ) {
260 - return;
261 - } else {
262 - $response['message'] = sprintf( $response['message'], '#3');
263 - }
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;
264 365 }
366 + $response['message'] = sprintf( $response['message'], '002');
265 367 }
266 368 wp_send_json( $response );
267 369
268 370 }
@@ -301,18 +403,37 @@
301 403 code_profiler_write2log( $string, 8, $create );
302 404 }
303 405
304 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 +// =====================================================================
305 426 // Verify if a profile exists and return its full path.
306 427
307 428 function code_profiler_get_profile_path( $id, $type = 'slugs') {
308 429
309 - $return = false;
430 + if (! empty( $id ) && preg_match('/^\d{10}\.\d+$/', $id ) ) {
310 431
311 - if (! empty( $id ) && preg_match('/^\d{10}\.\d+$/', $id ) ) {
312 - $glob = glob( CODE_PROFILER_UPLOAD_DIR ."/$id.*.$type.profile" );
432 + $glob = code_profiler_glob(CODE_PROFILER_UPLOAD_DIR, "$id\..+\.$type\.profile$", true);
433 +
313 434 if ( is_array( $glob ) && ! empty( $glob[0] ) ) {
314 - if ( preg_match( "`/$id\.(.+?).$type.profile$`", $glob[0], $match ) ) {
435 + if ( preg_match( "`$id\.(.+?).$type.profile$`", $glob[0], $match ) ) {
315 436
316 437 return CODE_PROFILER_UPLOAD_DIR. "/$id.{$match[1]}";
317 438 }
318 439 }
@@ -340,10 +461,17 @@
340 461 $buffer['error'] = $err;
341 462 return $buffer;
342 463 }
343 464
465 + /**
466 + * We don't use fgetcsv() as it requires the $escape parameter since PHP 8.4
467 + */
344 468 while (! feof( $fh ) ) {
345 - $buffer[] = fgetcsv( $fh, 1000, "\t" );
469 + $tmp = trim( fgets( $fh, 1000 ) );
470 + if (! $tmp ) {
471 + continue;
472 + }
473 + $buffer[] = explode( "\t", $tmp );
346 474 }
347 475
348 476 fclose( $fh );
349 477
@@ -398,9 +526,9 @@
398 526
399 527 $string = $open;
400 528
401 529 if ( empty( $decode->items ) ) {
402 - $tmp = 'N/A';
530 + $tmp = __('N/A', 'code-profiler');
403 531 } else {
404 532 $tmp = (int) --$decode->items;
405 533 }
406 534 $string .= sprintf(
@@ -410,9 +538,9 @@
410 538
411 539 $string .= $div;
412 540
413 541 if ( empty( $decode->time ) ) {
414 - $tmp = 'N/A';
542 + $tmp = __('N/A', 'code-profiler');
415 543 } else {
416 544 $tmp = number_format( $decode->time, 4 );
417 545 }
418 546 $string .= sprintf(
@@ -422,9 +550,9 @@
422 550
423 551 $string .= $div;
424 552
425 553 if ( empty( $decode->memory ) ) {
426 - $tmp = 'N/A';
554 + $tmp = __('N/A', 'code-profiler');
427 555 } else {
428 556 $tmp = number_format( $decode->memory, 2);
429 557 }
430 558 $string .= sprintf(
@@ -434,11 +562,11 @@
434 562
435 563 $string .= $div;
436 564
437 565 if ( empty( $decode->io ) ) {
438 - $tmp = 'N/A';
566 + $tmp = __('N/A', 'code-profiler');
439 567 } else {
440 - $tmp = number_format( $decode->io );
568 + $tmp = number_format( (int) $decode->io );
441 569 }
442 570 $string .= sprintf(
443 571 __('File I/O operations: %s', 'code-profiler'),
444 572 $tmp
@@ -446,11 +574,11 @@
446 574
447 575 $string .= $div;
448 576
449 577 if ( empty( $decode->queries ) ) {
450 - $tmp = 'N/A';
578 + $tmp = __('N/A', 'code-profiler');
451 579 } else {
452 - $tmp = number_format( $decode->queries );
580 + $tmp = number_format( (int) $decode->queries );
453 581 }
454 582 $string .= sprintf(
455 583 __('SQL queries: %s', 'code-profiler'),
456 584 $tmp
@@ -455,8 +583,20 @@
455 583 __('SQL queries: %s', 'code-profiler'),
456 584 $tmp
457 585 );
458 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 +
459 599 $string .= $close;
460 600
461 601 return $string;
462 602 }
@@ -461,29 +601,30 @@
461 601 return $string;
462 602 }
463 603
464 604 // =====================================================================
465 -// Remove *tmp files left after an HTTP error (4xx or 5xx).
605 +// Remove *tmp files left in the profiles folder.
466 606
467 607 function code_profiler_cleantmpfiles() {
468 608
469 - $glob = glob( CODE_PROFILER_UPLOAD_DIR .'/*.tmp');
609 + $glob = code_profiler_glob( CODE_PROFILER_UPLOAD_DIR, '\.tmp$', true );
610 +
470 611 if ( is_array( $glob ) ) {
471 - $count = 0;
472 612 foreach( $glob as $file ) {
473 - $count++;
474 613 unlink( $file );
475 614 }
476 - if ( $count ) {
477 - code_profiler_log_info( sprintf(
478 - __('Deleting %s temporary files found in the profiles folder', 'code-profiler'),
479 - (int) $count
480 - ) );
481 - }
482 615 }
483 616 }
484 617
485 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 +// =====================================================================
486 627 // Clear the log if it's bigger than 100KB.
487 628
488 629 function code_profiler_clearlog() {
489 630
@@ -491,9 +632,9 @@
491 632 file_put_contents( CODE_PROFILER_LOG, "<?php exit; ?>\n" );
492 633 }
493 634 }
494 635
495 -// =====================================================================
636 +// ===================================================================== 2023-06-15
496 637 // We don't want to be bothered by other themes/plugins' admin notices.
497 638
498 639 add_action('admin_head', 'code_profiler_hide_admin_notices');
499 640
@@ -500,9 +641,63 @@
500 641 function code_profiler_hide_admin_notices() {
501 642 if ( isset( $_GET['page'] ) && $_GET['page'] == 'code-profiler') {
502 643 remove_all_actions('admin_notices');
503 644 remove_all_actions('all_admin_notices');
645 + add_filter('admin_footer_text', 'code_profiler_admin_footer');
504 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;
505 700 }
506 701
507 702 // =====================================================================
508 703 // EOF