| @@ -1,6 +1,6 @@ | ||
| 1 | 1 | <?php |
| 2 | -/* | |
| 2 | +/** | |
| 3 | 3 | +=====================================================================+ |
| 4 | 4 | | ____ _ ____ __ _ _ | |
| 5 | 5 | | / ___|___ __| | ___ | _ \ _ __ ___ / _(_) | ___ _ __ | |
| 6 | 6 | | | | / _ \ / _` |/ _ \ | |_) | '__/ _ \| |_| | |/ _ \ '__| | |
| @@ -6,13 +6,15 @@ | ||
| 6 | 6 | | | | / _ \ / _` |/ _ \ | |_) | '__/ _ \| |_| | |/ _ \ '__| | |
| 7 | 7 | | | |__| (_) | (_| | __/ | __/| | | (_) | _| | | __/ | | |
| 8 | 8 | | \____\___/ \__,_|\___| |_| |_| \___/|_| |_|_|\___|_| | |
| 9 | 9 | | | |
| 10 | - | (c) Jerome Bruandet ~ https://code-profiler.com/ | | |
| 11 | - +=====================================================================+ | |
| 10 | + | (c) Jerome Bruandet ~ https://nintechnet.com/codeprofiler/ | | |
| 11 | + +=====================================================================+ 2024-08-14 | |
| 12 | 12 | */ |
| 13 | 13 | |
| 14 | -if (! defined('ABSPATH') ) { die('Forbidden'); } | |
| 14 | +if (! defined('ABSPATH') ) { | |
| 15 | + die('Forbidden'); | |
| 16 | +} | |
| 15 | 17 | |
| 16 | 18 | // ===================================================================== |
| 17 | 19 | |
| 18 | 20 | class CP_Troubleshooter { |
| @@ -27,12 +29,15 @@ | ||
| 27 | 29 | */ |
| 28 | 30 | public function __construct() { |
| 29 | 31 | |
| 30 | 32 | $this->get_system_info('sysinfo'); |
| 33 | + $this->test_admin_ajax('admin-ajax'); | |
| 31 | 34 | $this->cp_info('code-profiler'); |
| 32 | - $this->function_exists('functions'); | |
| 35 | + $this->function_exists('code-profiler'); | |
| 33 | 36 | $this->check_wpdb('wpdb'); |
| 37 | + $this->check_cache('cache'); | |
| 34 | 38 | $this->check_proxy('proxy'); |
| 39 | + $this->is_multisite('multisite'); | |
| 35 | 40 | $this->get_all_plugins('plugins'); |
| 36 | 41 | $this->get_theme('themes'); |
| 37 | 42 | $this->get_cp_config(); |
| 38 | 43 | |
| @@ -46,13 +51,20 @@ | ||
| 46 | 51 | * * HTTP server |
| 47 | 52 | * * Opcode cache |
| 48 | 53 | * * PHP directives (time limit, memory available, temp dir etc) |
| 49 | 54 | * * PHP last error |
| 55 | + * * WordPress | |
| 50 | 56 | */ |
| 51 | 57 | private function get_system_info( $key ) { |
| 52 | 58 | |
| 53 | 59 | $this->buffer[ $key ]['OS'] = php_uname(); |
| 54 | 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 | + | |
| 55 | 67 | if (! empty( $_SERVER['SERVER_SOFTWARE'] ) ) { |
| 56 | 68 | $this->buffer[ $key ]['HTTP server'] = $_SERVER['SERVER_SOFTWARE']; |
| 57 | 69 | } else { |
| 58 | 70 | $this->buffer[ $key ]['HTTP server'] = 'N/A'; |
| @@ -80,19 +92,85 @@ | ||
| 80 | 92 | if (! empty( $tmp ) ) { |
| 81 | 93 | if ( is_writable( $tmp ) ) { |
| 82 | 94 | $tmp .= ' (writable)'; |
| 83 | 95 | } else { |
| 84 | - $tmp .= ' (not writable!)'; | |
| 96 | + $tmp .= ' (not writable!)' .' ⚠️'; | |
| 85 | 97 | } |
| 86 | 98 | } |
| 87 | 99 | $tmp = $this->shorten_path( $tmp ); |
| 88 | 100 | $this->buffer[ $key ]['Temp directory'] = $tmp; |
| 89 | 101 | $this->buffer[ $key ]['Log errors'] = ini_get('log_errors'); |
| 90 | - $this->buffer[ $key ]['Error log'] = ini_get('error_log'); | |
| 91 | - $this->buffer[ $key ]['Last error'] = error_get_last(); | |
| 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(); | |
| 92 | 111 | if ( isset( $this->buffer[ $key ]['Last error']['file'] ) ) { |
| 93 | 112 | $this->buffer[ $key ]['Last error']['file'] = $this->shorten_path( $this->buffer[ $key ]['Last error']['file'] ); |
| 94 | 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 | + * SAVEQUERIES: make sure it is not set to false. | |
| 154 | + */ | |
| 155 | + if ( defined('SAVEQUERIES') ) { | |
| 156 | + if ( SAVEQUERIES === false ) { | |
| 157 | + $this->buffer[ $key ]['WordPress']['SAVEQUERIES'] = 'FALSE' .' ⚠️'; | |
| 158 | + } else { | |
| 159 | + $this->buffer[ $key ]['WordPress']['SAVEQUERIES'] = SAVEQUERIES; | |
| 160 | + } | |
| 161 | + } else { | |
| 162 | + $this->buffer[ $key ]['WordPress']['SAVEQUERIES'] = 'N/A'; | |
| 163 | + } | |
| 164 | + | |
| 165 | + /** | |
| 166 | + * xdebug. | |
| 167 | + */ | |
| 168 | + if ( extension_loaded('xdebug') ) { | |
| 169 | + $this->buffer[ $key ]['Xdebug'] = esc_html__('Extension is loaded', 'code-profiler') .' ⚠️'; | |
| 170 | + } else { | |
| 171 | + $this->buffer[ $key ]['Xdebug'] = '0'; | |
| 172 | + } | |
| 95 | 173 | } |
| 96 | 174 | |
| 97 | 175 | |
| 98 | 176 | /** |
| @@ -104,14 +182,22 @@ | ||
| 104 | 182 | 'register_shutdown_function' => 'shutdown', |
| 105 | 183 | 'register_tick_function' => 'tick', |
| 106 | 184 | 'stream_wrapper_unregister' => 'unregister', |
| 107 | 185 | 'stream_wrapper_register' => 'register', |
| 108 | - 'stream_wrapper_restore' => 'restore' | |
| 186 | + 'stream_wrapper_restore' => 'restore', | |
| 187 | + 'hrtime' => 'hrtime' | |
| 109 | 188 | ]; |
| 110 | 189 | |
| 111 | 190 | foreach ( $required_functions as $function => $value ) { |
| 112 | - $this->buffer[ $key ][ $value ] = function_exists( $function ); | |
| 191 | + $this->buffer[ $key ]['function'][ $value ] = function_exists( $function ); | |
| 113 | 192 | } |
| 193 | + | |
| 194 | + $required_methods = [ | |
| 195 | + 'PhpToken' => 'tokenize' | |
| 196 | + ]; | |
| 197 | + foreach ( $required_methods as $class => $value ) { | |
| 198 | + $this->buffer[ $key ]['method'][ $value ] = method_exists( $class, $value ); | |
| 199 | + } | |
| 114 | 200 | } |
| 115 | 201 | |
| 116 | 202 | |
| 117 | 203 | /** |
| @@ -164,9 +250,12 @@ | ||
| 164 | 250 | * Check for advanced cache |
| 165 | 251 | */ |
| 166 | 252 | private function check_cache( $key ) { |
| 167 | 253 | |
| 168 | - $this->buffer[ $key ]['cache'] = defined('WP_CACHE') && file_exists(WP_CONTENT_DIR . '/advanced-cache.php'); | |
| 254 | + $this->buffer[ $key ] = []; | |
| 255 | + if ( defined('WP_CACHE') && file_exists( WP_CONTENT_DIR . '/advanced-cache.php') ) { | |
| 256 | + $this->buffer[ $key ][ $this->shorten_path( WP_CONTENT_DIR . '/advanced-cache.php') ] = 1; | |
| 257 | + } | |
| 169 | 258 | } |
| 170 | 259 | |
| 171 | 260 | |
| 172 | 261 | /** |
| @@ -190,8 +279,23 @@ | ||
| 190 | 279 | } |
| 191 | 280 | |
| 192 | 281 | |
| 193 | 282 | /** |
| 283 | + * Check if that is a multisite installation. | |
| 284 | + */ | |
| 285 | + private function is_multisite( $key ) { | |
| 286 | + | |
| 287 | + if ( is_multisite() ) { | |
| 288 | + global $current_blog; | |
| 289 | + $this->buffer[ $key ] = "site: {$current_blog->site_id}, blog: {$current_blog->blog_id}"; | |
| 290 | + return; | |
| 291 | + } | |
| 292 | + | |
| 293 | + $this->buffer[ $key ] = 0; | |
| 294 | + } | |
| 295 | + | |
| 296 | + | |
| 297 | + /** | |
| 194 | 298 | * Retrieve the list of all plugins and sort them |
| 195 | 299 | * (active or disabled). |
| 196 | 300 | */ |
| 197 | 301 | private function get_all_plugins( $key ) { |
| @@ -201,15 +305,40 @@ | ||
| 201 | 305 | } |
| 202 | 306 | $plugins = get_plugins(); |
| 203 | 307 | foreach( $plugins as $k => $v ) { |
| 204 | 308 | if ( $slug = substr( $k, 0, strpos( $k, '/') ) ) { |
| 205 | - $this->buffer[ $key ][ $slug ] = "{$v['Name']} - {$v['Version']}"; | |
| 309 | + $name = 'N/A'; $version = 'N/A'; $uri = 'N/A'; | |
| 310 | + if (! empty( $v['Name'] ) ) { | |
| 311 | + $name = $v['Name']; | |
| 312 | + } | |
| 313 | + if (! empty( $v['Version'] ) ) { | |
| 314 | + $version = $v['Version']; | |
| 315 | + } | |
| 316 | + if (! empty( $v['PluginURI'] ) ) { | |
| 317 | + $uri = $v['PluginURI']; | |
| 318 | + } | |
| 319 | + if ( is_plugin_active( $k ) ) { | |
| 320 | + $this->buffer[ $key ]['active'][ $slug ] = "$name - $version - $uri"; | |
| 321 | + | |
| 322 | + } else { | |
| 323 | + $this->buffer[ $key ]['inactive'][ $slug ] = "$name - $version - $uri"; | |
| 324 | + } | |
| 206 | 325 | } |
| 207 | 326 | } |
| 208 | 327 | |
| 209 | 328 | $mu_plugins = get_mu_plugins(); |
| 210 | 329 | foreach( $mu_plugins as $k => $v ) { |
| 211 | - $this->buffer[ $key ]['mu-plugins'][ $k ] = "{$v['Name']} - {$v['Version']}"; | |
| 330 | + $name = 'N/A'; $version = 'N/A'; $uri = 'N/A'; | |
| 331 | + if (! empty( $v['Name'] ) ) { | |
| 332 | + $name = $v['Name']; | |
| 333 | + } | |
| 334 | + if (! empty( $v['Version'] ) ) { | |
| 335 | + $version = $v['Version']; | |
| 336 | + } | |
| 337 | + if (! empty( $v['PluginURI'] ) ) { | |
| 338 | + $uri = $v['PluginURI']; | |
| 339 | + } | |
| 340 | + $this->buffer[ $key ]['mu-plugins'][ $k ] = "$name - $version - $uri"; | |
| 212 | 341 | } |
| 213 | 342 | |
| 214 | 343 | } |
| 215 | 344 | |
| @@ -221,13 +350,20 @@ | ||
| 221 | 350 | |
| 222 | 351 | $themes = wp_get_themes(); |
| 223 | 352 | $active = get_option('template'); |
| 224 | 353 | foreach( $themes as $k => $v ) { |
| 225 | - $version = $v->Version; | |
| 354 | + $name = 'N/A'; $version = 'N/A'; | |
| 355 | + if ( $v->Name ) { | |
| 356 | + $name = $v->Name; | |
| 357 | + } | |
| 358 | + if ( $v->Version ) { | |
| 359 | + $version = $v->Version; | |
| 360 | + } | |
| 226 | 361 | if ( $k == $active ) { |
| 227 | - $version .= ' (active)'; | |
| 362 | + $this->buffer[ $key ]['active'][ $k ] = "$name - $version"; | |
| 363 | + } else { | |
| 364 | + $this->buffer[ $key ]['inactive'][ $k ] = "$name - $version"; | |
| 228 | 365 | } |
| 229 | - $this->buffer[ $key ][ $k ] = "{$v->Name} - $version"; | |
| 230 | 366 | } |
| 231 | 367 | } |
| 232 | 368 | |
| 233 | 369 | |
| @@ -239,13 +375,16 @@ | ||
| 239 | 375 | $cp_options = get_option('code-profiler'); |
| 240 | 376 | |
| 241 | 377 | $list = [ |
| 242 | 378 | 'hide_empty_value', |
| 243 | - 'warn_composer', | |
| 244 | 379 | 'enable_wpcli', |
| 245 | 380 | 'disable_wpcron', |
| 246 | - // 'disable_db-php', | |
| 247 | - 'http_response' | |
| 381 | + // 'disable_db-php', | |
| 382 | + 'http_response', | |
| 383 | + // 'backtrace_limit', | |
| 384 | + 'accuracy', | |
| 385 | + 'buffer', | |
| 386 | + 'exclusions' | |
| 248 | 387 | ]; |
| 249 | 388 | foreach( $list as $element ) { |
| 250 | 389 | $this->buffer['options'][ $element ] = isset( $cp_options[ $element ] )? $cp_options[ $element ]:0; |
| 251 | 390 | } |
| @@ -256,8 +395,36 @@ | ||
| 256 | 395 | */ |
| 257 | 396 | private function shorten_path( $path ) { |
| 258 | 397 | |
| 259 | 398 | return str_replace( ABSPATH, '', $path ); |
| 399 | + } | |
| 400 | + | |
| 401 | + | |
| 402 | + /** | |
| 403 | + * Test if admin-ajax is accessible. | |
| 404 | + */ | |
| 405 | + private function test_admin_ajax( $key ) { | |
| 406 | + | |
| 407 | + $headers = [ | |
| 408 | + // Devs must be allowed to use it on localhost over TLS too | |
| 409 | + 'sslverify' => apply_filters('https_local_ssl_verify', false ) | |
| 410 | + ]; | |
| 411 | + $res = wp_safe_remote_get( admin_url('admin-ajax.php?action=generate-password'), $headers ); | |
| 412 | + | |
| 413 | + /* Translators: Error message */ | |
| 414 | + $error = __('Error: %s', 'code-profiler'); | |
| 415 | + | |
| 416 | + // Connection error | |
| 417 | + if ( is_wp_error( $res ) ) { | |
| 418 | + $msg = sprintf( $error, $res->get_error_message() ); | |
| 419 | + | |
| 420 | + } elseif ( $res['response']['code'] != 200 ) { | |
| 421 | + $msg = sprintf( $error, $res['response']['code'] ." ". $res['response']['message'] ); | |
| 422 | + | |
| 423 | + } else { | |
| 424 | + $msg = "OK"; | |
| 425 | + } | |
| 426 | + $this->buffer[ $key ]['access'] = $msg; | |
| 260 | 427 | } |
| 261 | 428 | |
| 262 | 429 | } |
| 263 | 430 | |