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
code-profiler / lib / class-troubleshooter.php

class-troubleshooter.php in Code Profiler – WordPress Performance Profiling and Debugging Made Easy 1.7.4, at lib/class-troubleshooter.php

411 lines 11.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 +=====================================================================+
4 | ____ _ ____ __ _ _ |
5 | / ___|___ __| | ___ | _ \ _ __ ___ / _(_) | ___ _ __ |
6 | | | / _ \ / _` |/ _ \ | |_) | '__/ _ \| |_| | |/ _ \ '__| |
7 | | |__| (_) | (_| | __/ | __/| | | (_) | _| | | __/ | |
8 | \____\___/ \__,_|\___| |_| |_| \___/|_| |_|_|\___|_| |
9 | |
10 | (c) Jerome Bruandet ~ https://nintechnet.com/codeprofiler/ |
11 +=====================================================================+ 2024-08-14
12 */
13
14 if (! defined('ABSPATH') ) {
15 die('Forbidden');
16 }
17
18 // =====================================================================
19
20 class CP_Troubleshooter {
21
22 /**
23 * Array to handle all results
24 */
25 private $buffer = [];
26
27 /**
28 * Initialize.
29 */
30 public function __construct() {
31
32 $this->get_system_info('sysinfo');
33 $this->test_admin_ajax('admin-ajax');
34 $this->cp_info('code-profiler');
35 $this->function_exists('code-profiler');
36 $this->check_wpdb('wpdb');
37 $this->check_cache('cache');
38 $this->check_proxy('proxy');
39 $this->is_multisite('multisite');
40 $this->get_all_plugins('plugins');
41 $this->get_theme('themes');
42 $this->get_cp_config();
43
44 echo esc_textarea( print_r( $this->buffer, true ) );
45 }
46
47 /**
48 * Retrieve system info:
49 * * PHP version
50 * * PHP SAPI
51 * * HTTP server
52 * * Opcode cache
53 * * PHP directives (time limit, memory available, temp dir etc)
54 * * PHP last error
55 * * WordPress
56 */
57 private function get_system_info( $key ) {
58
59 $this->buffer[ $key ]['OS'] = php_uname();
60
61 if (! empty( $_SERVER['SERVER_NAME'] ) ) {
62 $this->buffer[ $key ]['SERVER_NAME'] = $_SERVER['SERVER_NAME'];
63 } else {
64 $this->buffer[ $key ]['SERVER_NAME'] = 'N/A';
65 }
66
67 if (! empty( $_SERVER['SERVER_SOFTWARE'] ) ) {
68 $this->buffer[ $key ]['HTTP server'] = $_SERVER['SERVER_SOFTWARE'];
69 } else {
70 $this->buffer[ $key ]['HTTP server'] = 'N/A';
71 }
72
73 $this->buffer[ $key ]['PHP'] = strtoupper( PHP_SAPI ) .' '. PHP_VERSION;
74
75 if ( extension_loaded('Zend OPcache') ) {
76 $this->buffer[ $key ]['Opcode cache'] = sprintf(
77 'Zend OPcache (%s)', ini_get('opcache.enable') ? 'enabled':'disabled'
78 );
79 } elseif ( extension_loaded('wincache') ) {
80 $this->buffer[ $key ]['Opcode cache'] = sprintf(
81 'wincache (%s)', ini_get('wincache.fcenabled') ? 'enabled':'disabled'
82 );
83 }
84
85 $this->buffer[ $key ]['Memory limit'] = ini_get('memory_limit');
86 $this->buffer[ $key ]['Peak limit'] = number_format( memory_get_peak_usage() );
87 $this->buffer[ $key ]['Max execution time'] = ini_get('max_execution_time') .'s';
88 $this->buffer[ $key ]['Disabled functions'] = ini_get('disable_functions');
89 $this->buffer[ $key ]['Display errors'] = ini_get('display_errors');
90
91 $tmp = ini_get('sys_temp_dir');
92 if (! empty( $tmp ) ) {
93 if ( is_writable( $tmp ) ) {
94 $tmp .= ' (writable)';
95 } else {
96 $tmp .= ' (not writable!)';
97 }
98 }
99 $tmp = $this->shorten_path( $tmp );
100 $this->buffer[ $key ]['Temp directory'] = $tmp;
101 $this->buffer[ $key ]['Log errors'] = ini_get('log_errors');
102
103 $error_log = ini_get('error_log');
104 $filesize = 0;
105 if ( is_file( $error_log ) ) {
106 $filesize = filesize( $error_log );
107 }
108 $this->buffer[ $key ]['Error log'] = "$error_log (". number_format( $filesize ) ." bytes)";
109
110 $this->buffer[ $key ]['Last error'] = error_get_last();
111 if ( isset( $this->buffer[ $key ]['Last error']['file'] ) ) {
112 $this->buffer[ $key ]['Last error']['file'] = $this->shorten_path( $this->buffer[ $key ]['Last error']['file'] );
113 }
114
115 // WordPress
116 if ( defined('WP_MEMORY_LIMIT') ) {
117 $this->buffer[ $key ]['WordPress']['WP_MEMORY_LIMIT'] = WP_MEMORY_LIMIT;
118 } else {
119 $this->buffer[ $key ]['WordPress']['WP_MEMORY_LIMIT'] = 'N/A';
120 }
121 if ( defined('WP_MAX_MEMORY_LIMIT') ) {
122 $this->buffer[ $key ]['WordPress']['WP_MAX_MEMORY_LIMIT'] = WP_MAX_MEMORY_LIMIT;
123 } else {
124 $this->buffer[ $key ]['WordPress']['WP_MAX_MEMORY_LIMIT'] = 'N/A';
125 }
126 global $wp_version;
127 $this->buffer[ $key ]['WordPress']['version'] = $wp_version;
128 $wp_debug = '';
129 if ( defined('WP_DEBUG') ) {
130 $wp_debug = WP_DEBUG;
131 }
132 $this->buffer[ $key ]['WordPress']['WP_DEBUG'] = $wp_debug;
133 $wp_debug = '';
134 $filesize = 0;
135 if ( defined('WP_DEBUG_LOG') ) {
136 $wp_debug = WP_DEBUG_LOG;
137 }
138 if ( is_file( $wp_debug ) ) {
139 $filesize = filesize( $error_log );
140 $wp_debug = $this->shorten_path( $wp_debug ) ." (". number_format( $filesize ) ." bytes)";
141 }
142 $this->buffer[ $key ]['WordPress']['WP_DEBUG_LOG'] = $wp_debug;
143
144 /**
145 * WPMU plugins directory.
146 */
147 $this->buffer[ $key ]['WordPress']['WPMU_PLUGIN_DIR']['DIR'] =
148 $this->shorten_path( WPMU_PLUGIN_DIR );
149 $this->buffer[ $key ]['WordPress']['WPMU_PLUGIN_DIR']['writable'] =
150 is_writable( WPMU_PLUGIN_DIR );
151 }
152
153 /**
154 * Verify if some important PHP functions are available.
155 */
156 private function function_exists( $key ) {
157
158 $required_functions = [
159 'register_shutdown_function' => 'shutdown',
160 'register_tick_function' => 'tick',
161 'stream_wrapper_unregister' => 'unregister',
162 'stream_wrapper_register' => 'register',
163 'stream_wrapper_restore' => 'restore',
164 'hrtime' => 'hrtime'
165 ];
166
167 foreach ( $required_functions as $function => $value ) {
168 $this->buffer[ $key ]['function'][ $value ] = function_exists( $function );
169 }
170
171 $required_methods = [
172 'PhpToken' => 'tokenize'
173 ];
174 foreach ( $required_methods as $class => $value ) {
175 $this->buffer[ $key ]['method'][ $value ] = method_exists( $class, $value );
176 }
177 }
178
179
180 /**
181 * Return the version and type (free/pro) of Code Profiler.
182 */
183 private function cp_info( $key ) {
184
185 if ( defined('CODE_PROFILER_PRO_VERSION') ) {
186 $this->buffer[ $key ]['slug'] = 'code-profiler-pro';
187 $this->buffer[ $key ]['version'] = CODE_PROFILER_PRO_VERSION;
188
189 } elseif ( defined('CODE_PROFILER_VERSION') ) {
190 $this->buffer[ $key ]['slug'] = 'code-profiler';
191 $this->buffer[ $key ]['version'] = CODE_PROFILER_VERSION;
192
193 } else {
194 exit('Error: Code Profiler is not active. Please activate it and run this script again.');
195
196 }
197
198 // Data folder must be writable
199 $upload_dir = wp_upload_dir();
200 $dir = $upload_dir['basedir'] .'/'. $this->buffer[ $key ]['slug'];
201
202 $this->buffer[ $key ]['data_dir']['path'] = $this->shorten_path( $dir );
203 $this->buffer[ $key ]['data_dir']['exists'] = file_exists( $dir );
204 $this->buffer[ $key ]['data_dir']['writable'] = is_writable( $dir );
205 }
206
207
208 /**
209 * Check if there are subclasses of the wpdb class and
210 * look for wp-content/db.php
211 */
212 function check_wpdb( $key ) {
213
214 foreach( get_declared_classes() as $class ) {
215 $reflected = new ReflectionClass( $class );
216 if ( $reflected->isSubclassOf('wpdb') ) {
217 $script = $reflected->getFileName();
218 $this->buffer[ $key ]['extends'][$class] = $this->shorten_path( $script );
219 }
220 }
221 $db_php = $this->shorten_path( WP_CONTENT_DIR .'/db.php');
222 $this->buffer[ $key ][ $db_php ] = file_exists( WP_CONTENT_DIR .'/db.php');
223 }
224
225
226 /**
227 * Check for advanced cache
228 */
229 private function check_cache( $key ) {
230
231 $this->buffer[ $key ] = [];
232 if ( defined('WP_CACHE') && file_exists( WP_CONTENT_DIR . '/advanced-cache.php') ) {
233 $this->buffer[ $key ][ $this->shorten_path( WP_CONTENT_DIR . '/advanced-cache.php') ] = 1;
234 }
235 }
236
237
238 /**
239 * Check for reverse proxy or CDN
240 */
241 private function check_proxy( $key ) {
242
243 $this->buffer[ $key ] = [];
244 $proxies = [
245 'HTTP_X_FORWARDED_FOR',
246 'HTTP_CF_CONNECTING_IP',
247 'HTTP_INCAP_CLIENT_IP'
248 ];
249
250 foreach( $proxies as $proxy ) {
251 if (! empty( $_SERVER[ $proxy ] ) ) {
252 $this->buffer[ $key ][ $proxy ] = 1;
253 }
254 }
255
256 }
257
258
259 /**
260 * Check if that is a multisite installation.
261 */
262 private function is_multisite( $key ) {
263
264 if ( is_multisite() ) {
265 global $current_blog;
266 $this->buffer[ $key ] = "site: {$current_blog->site_id}, blog: {$current_blog->blog_id}";
267 return;
268 }
269
270 $this->buffer[ $key ] = 0;
271 }
272
273
274 /**
275 * Retrieve the list of all plugins and sort them
276 * (active or disabled).
277 */
278 private function get_all_plugins( $key ) {
279
280 if (! function_exists('get_plugins') ) {
281 require_once ABSPATH .'wp-admin/includes/plugin.php';
282 }
283 $plugins = get_plugins();
284 foreach( $plugins as $k => $v ) {
285 if ( $slug = substr( $k, 0, strpos( $k, '/') ) ) {
286 $name = 'N/A'; $version = 'N/A'; $uri = 'N/A';
287 if (! empty( $v['Name'] ) ) {
288 $name = $v['Name'];
289 }
290 if (! empty( $v['Version'] ) ) {
291 $version = $v['Version'];
292 }
293 if (! empty( $v['PluginURI'] ) ) {
294 $uri = $v['PluginURI'];
295 }
296 if ( is_plugin_active( $k ) ) {
297 $this->buffer[ $key ]['active'][ $slug ] = "$name - $version - $uri";
298
299 } else {
300 $this->buffer[ $key ]['inactive'][ $slug ] = "$name - $version - $uri";
301 }
302 }
303 }
304
305 $mu_plugins = get_mu_plugins();
306 foreach( $mu_plugins as $k => $v ) {
307 $name = 'N/A'; $version = 'N/A'; $uri = 'N/A';
308 if (! empty( $v['Name'] ) ) {
309 $name = $v['Name'];
310 }
311 if (! empty( $v['Version'] ) ) {
312 $version = $v['Version'];
313 }
314 if (! empty( $v['PluginURI'] ) ) {
315 $uri = $v['PluginURI'];
316 }
317 $this->buffer[ $key ]['mu-plugins'][ $k ] = "$name - $version - $uri";
318 }
319
320 }
321
322
323 /**
324 * Retrieve the active theme.
325 */
326 private function get_theme( $key ) {
327
328 $themes = wp_get_themes();
329 $active = get_option('template');
330 foreach( $themes as $k => $v ) {
331 $name = 'N/A'; $version = 'N/A';
332 if ( $v->Name ) {
333 $name = $v->Name;
334 }
335 if ( $v->Version ) {
336 $version = $v->Version;
337 }
338 if ( $k == $active ) {
339 $this->buffer[ $key ]['active'][ $k ] = "$name - $version";
340 } else {
341 $this->buffer[ $key ]['inactive'][ $k ] = "$name - $version";
342 }
343 }
344 }
345
346
347 /**
348 * Retrieve Code Profiler's configuration
349 */
350 private function get_cp_config() {
351
352 $cp_options = get_option('code-profiler');
353
354 $list = [
355 'hide_empty_value',
356 'warn_composer',
357 'enable_wpcli',
358 'disable_wpcron',
359 // 'disable_db-php',
360 'http_response',
361 // 'backtrace_limit',
362 'accuracy',
363 'buffer',
364 'exclusions'
365 ];
366 foreach( $list as $element ) {
367 $this->buffer['options'][ $element ] = isset( $cp_options[ $element ] )? $cp_options[ $element ]:0;
368 }
369 }
370
371 /**
372 * Remove the ABSPATH from a path
373 */
374 private function shorten_path( $path ) {
375
376 return str_replace( ABSPATH, '', $path );
377 }
378
379
380 /**
381 * Test if admin-ajax is accessible.
382 */
383 private function test_admin_ajax( $key ) {
384
385 $headers = [
386 // Devs must be allowed to use it on localhost over TLS too
387 'sslverify' => apply_filters('https_local_ssl_verify', false )
388 ];
389 $res = wp_safe_remote_get( admin_url('admin-ajax.php?action=generate-password'), $headers );
390
391 /* Translators: Error message */
392 $error = __('Error: %s', 'code-profiler');
393
394 // Connection error
395 if ( is_wp_error( $res ) ) {
396 $msg = sprintf( $error, $res->get_error_message() );
397
398 } elseif ( $res['response']['code'] != 200 ) {
399 $msg = sprintf( $error, $res['response']['code'] ." ". $res['response']['message'] );
400
401 } else {
402 $msg = "OK";
403 }
404 $this->buffer[ $key ]['access'] = $msg;
405 }
406
407 }
408
409 // =====================================================================
410 // EOF
411