[ Index ] |
PHP Cross Reference of WordPress |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * Class for providing debug data based on a users WordPress environment. 4 * 5 * @package WordPress 6 * @subpackage Site_Health 7 * @since 5.2.0 8 */ 9 10 class WP_Debug_Data { 11 /** 12 * Calls all core functions to check for updates. 13 * 14 * @since 5.2.0 15 */ 16 public static function check_for_updates() { 17 wp_version_check(); 18 wp_update_plugins(); 19 wp_update_themes(); 20 } 21 22 /** 23 * Static function for generating site debug data when required. 24 * 25 * @since 5.2.0 26 * @since 5.3.0 Added database charset, database collation, 27 * and timezone information. 28 * @since 5.5.0 Added pretty permalinks support information. 29 * 30 * @throws ImagickException 31 * @global wpdb $wpdb WordPress database abstraction object. 32 * 33 * @return array The debug data for the site. 34 */ 35 public static function debug_data() { 36 global $wpdb; 37 38 // Save few function calls. 39 $upload_dir = wp_upload_dir(); 40 $permalink_structure = get_option( 'permalink_structure' ); 41 $is_ssl = is_ssl(); 42 $is_multisite = is_multisite(); 43 $users_can_register = get_option( 'users_can_register' ); 44 $blog_public = get_option( 'blog_public' ); 45 $default_comment_status = get_option( 'default_comment_status' ); 46 $environment_type = wp_get_environment_type(); 47 $core_version = get_bloginfo( 'version' ); 48 $core_updates = get_core_updates(); 49 $core_update_needed = ''; 50 51 if ( is_array( $core_updates ) ) { 52 foreach ( $core_updates as $core => $update ) { 53 if ( 'upgrade' === $update->response ) { 54 /* translators: %s: Latest WordPress version number. */ 55 $core_update_needed = ' ' . sprintf( __( '(Latest version: %s)' ), $update->version ); 56 } else { 57 $core_update_needed = ''; 58 } 59 } 60 } 61 62 // Set up the array that holds all debug information. 63 $info = array(); 64 65 $info['wp-core'] = array( 66 'label' => __( 'WordPress' ), 67 'fields' => array( 68 'version' => array( 69 'label' => __( 'Version' ), 70 'value' => $core_version . $core_update_needed, 71 'debug' => $core_version, 72 ), 73 'site_language' => array( 74 'label' => __( 'Site Language' ), 75 'value' => get_locale(), 76 ), 77 'user_language' => array( 78 'label' => __( 'User Language' ), 79 'value' => get_user_locale(), 80 ), 81 'timezone' => array( 82 'label' => __( 'Timezone' ), 83 'value' => wp_timezone_string(), 84 ), 85 'home_url' => array( 86 'label' => __( 'Home URL' ), 87 'value' => get_bloginfo( 'url' ), 88 'private' => true, 89 ), 90 'site_url' => array( 91 'label' => __( 'Site URL' ), 92 'value' => get_bloginfo( 'wpurl' ), 93 'private' => true, 94 ), 95 'permalink' => array( 96 'label' => __( 'Permalink structure' ), 97 'value' => $permalink_structure ? $permalink_structure : __( 'No permalink structure set' ), 98 'debug' => $permalink_structure, 99 ), 100 'https_status' => array( 101 'label' => __( 'Is this site using HTTPS?' ), 102 'value' => $is_ssl ? __( 'Yes' ) : __( 'No' ), 103 'debug' => $is_ssl, 104 ), 105 'multisite' => array( 106 'label' => __( 'Is this a multisite?' ), 107 'value' => $is_multisite ? __( 'Yes' ) : __( 'No' ), 108 'debug' => $is_multisite, 109 ), 110 'user_registration' => array( 111 'label' => __( 'Can anyone register on this site?' ), 112 'value' => $users_can_register ? __( 'Yes' ) : __( 'No' ), 113 'debug' => $users_can_register, 114 ), 115 'blog_public' => array( 116 'label' => __( 'Is this site discouraging search engines?' ), 117 'value' => $blog_public ? __( 'No' ) : __( 'Yes' ), 118 'debug' => $blog_public, 119 ), 120 'default_comment_status' => array( 121 'label' => __( 'Default comment status' ), 122 'value' => 'open' === $default_comment_status ? _x( 'Open', 'comment status' ) : _x( 'Closed', 'comment status' ), 123 'debug' => $default_comment_status, 124 ), 125 'environment_type' => array( 126 'label' => __( 'Environment type' ), 127 'value' => $environment_type, 128 'debug' => $environment_type, 129 ), 130 ), 131 ); 132 133 if ( ! $is_multisite ) { 134 $info['wp-paths-sizes'] = array( 135 'label' => __( 'Directories and Sizes' ), 136 'fields' => array(), 137 ); 138 } 139 140 $info['wp-dropins'] = array( 141 'label' => __( 'Drop-ins' ), 142 'show_count' => true, 143 'description' => sprintf( 144 /* translators: %s: wp-content directory name. */ 145 __( 'Drop-ins are single files, found in the %s directory, that replace or enhance WordPress features in ways that are not possible for traditional plugins.' ), 146 '<code>' . str_replace( ABSPATH, '', WP_CONTENT_DIR ) . '</code>' 147 ), 148 'fields' => array(), 149 ); 150 151 $info['wp-active-theme'] = array( 152 'label' => __( 'Active Theme' ), 153 'fields' => array(), 154 ); 155 156 $info['wp-parent-theme'] = array( 157 'label' => __( 'Parent Theme' ), 158 'fields' => array(), 159 ); 160 161 $info['wp-themes-inactive'] = array( 162 'label' => __( 'Inactive Themes' ), 163 'show_count' => true, 164 'fields' => array(), 165 ); 166 167 $info['wp-mu-plugins'] = array( 168 'label' => __( 'Must Use Plugins' ), 169 'show_count' => true, 170 'fields' => array(), 171 ); 172 173 $info['wp-plugins-active'] = array( 174 'label' => __( 'Active Plugins' ), 175 'show_count' => true, 176 'fields' => array(), 177 ); 178 179 $info['wp-plugins-inactive'] = array( 180 'label' => __( 'Inactive Plugins' ), 181 'show_count' => true, 182 'fields' => array(), 183 ); 184 185 $info['wp-media'] = array( 186 'label' => __( 'Media Handling' ), 187 'fields' => array(), 188 ); 189 190 $info['wp-server'] = array( 191 'label' => __( 'Server' ), 192 'description' => __( 'The options shown below relate to your server setup. If changes are required, you may need your web host’s assistance.' ), 193 'fields' => array(), 194 ); 195 196 $info['wp-database'] = array( 197 'label' => __( 'Database' ), 198 'fields' => array(), 199 ); 200 201 // Check if WP_DEBUG_LOG is set. 202 $wp_debug_log_value = __( 'Disabled' ); 203 204 if ( is_string( WP_DEBUG_LOG ) ) { 205 $wp_debug_log_value = WP_DEBUG_LOG; 206 } elseif ( WP_DEBUG_LOG ) { 207 $wp_debug_log_value = __( 'Enabled' ); 208 } 209 210 // Check CONCATENATE_SCRIPTS. 211 if ( defined( 'CONCATENATE_SCRIPTS' ) ) { 212 $concatenate_scripts = CONCATENATE_SCRIPTS ? __( 'Enabled' ) : __( 'Disabled' ); 213 $concatenate_scripts_debug = CONCATENATE_SCRIPTS ? 'true' : 'false'; 214 } else { 215 $concatenate_scripts = __( 'Undefined' ); 216 $concatenate_scripts_debug = 'undefined'; 217 } 218 219 // Check COMPRESS_SCRIPTS. 220 if ( defined( 'COMPRESS_SCRIPTS' ) ) { 221 $compress_scripts = COMPRESS_SCRIPTS ? __( 'Enabled' ) : __( 'Disabled' ); 222 $compress_scripts_debug = COMPRESS_SCRIPTS ? 'true' : 'false'; 223 } else { 224 $compress_scripts = __( 'Undefined' ); 225 $compress_scripts_debug = 'undefined'; 226 } 227 228 // Check COMPRESS_CSS. 229 if ( defined( 'COMPRESS_CSS' ) ) { 230 $compress_css = COMPRESS_CSS ? __( 'Enabled' ) : __( 'Disabled' ); 231 $compress_css_debug = COMPRESS_CSS ? 'true' : 'false'; 232 } else { 233 $compress_css = __( 'Undefined' ); 234 $compress_css_debug = 'undefined'; 235 } 236 237 // Check WP_ENVIRONMENT_TYPE. 238 if ( defined( 'WP_ENVIRONMENT_TYPE' ) ) { 239 $wp_environment_type = WP_ENVIRONMENT_TYPE; 240 } else { 241 $wp_environment_type = __( 'Undefined' ); 242 } 243 244 $info['wp-constants'] = array( 245 'label' => __( 'WordPress Constants' ), 246 'description' => __( 'These settings alter where and how parts of WordPress are loaded.' ), 247 'fields' => array( 248 'ABSPATH' => array( 249 'label' => 'ABSPATH', 250 'value' => ABSPATH, 251 'private' => true, 252 ), 253 'WP_HOME' => array( 254 'label' => 'WP_HOME', 255 'value' => ( defined( 'WP_HOME' ) ? WP_HOME : __( 'Undefined' ) ), 256 'debug' => ( defined( 'WP_HOME' ) ? WP_HOME : 'undefined' ), 257 ), 258 'WP_SITEURL' => array( 259 'label' => 'WP_SITEURL', 260 'value' => ( defined( 'WP_SITEURL' ) ? WP_SITEURL : __( 'Undefined' ) ), 261 'debug' => ( defined( 'WP_SITEURL' ) ? WP_SITEURL : 'undefined' ), 262 ), 263 'WP_CONTENT_DIR' => array( 264 'label' => 'WP_CONTENT_DIR', 265 'value' => WP_CONTENT_DIR, 266 ), 267 'WP_PLUGIN_DIR' => array( 268 'label' => 'WP_PLUGIN_DIR', 269 'value' => WP_PLUGIN_DIR, 270 ), 271 'WP_MEMORY_LIMIT' => array( 272 'label' => 'WP_MEMORY_LIMIT', 273 'value' => WP_MEMORY_LIMIT, 274 ), 275 'WP_MAX_MEMORY_LIMIT' => array( 276 'label' => 'WP_MAX_MEMORY_LIMIT', 277 'value' => WP_MAX_MEMORY_LIMIT, 278 ), 279 'WP_DEBUG' => array( 280 'label' => 'WP_DEBUG', 281 'value' => WP_DEBUG ? __( 'Enabled' ) : __( 'Disabled' ), 282 'debug' => WP_DEBUG, 283 ), 284 'WP_DEBUG_DISPLAY' => array( 285 'label' => 'WP_DEBUG_DISPLAY', 286 'value' => WP_DEBUG_DISPLAY ? __( 'Enabled' ) : __( 'Disabled' ), 287 'debug' => WP_DEBUG_DISPLAY, 288 ), 289 'WP_DEBUG_LOG' => array( 290 'label' => 'WP_DEBUG_LOG', 291 'value' => $wp_debug_log_value, 292 'debug' => WP_DEBUG_LOG, 293 ), 294 'SCRIPT_DEBUG' => array( 295 'label' => 'SCRIPT_DEBUG', 296 'value' => SCRIPT_DEBUG ? __( 'Enabled' ) : __( 'Disabled' ), 297 'debug' => SCRIPT_DEBUG, 298 ), 299 'WP_CACHE' => array( 300 'label' => 'WP_CACHE', 301 'value' => WP_CACHE ? __( 'Enabled' ) : __( 'Disabled' ), 302 'debug' => WP_CACHE, 303 ), 304 'CONCATENATE_SCRIPTS' => array( 305 'label' => 'CONCATENATE_SCRIPTS', 306 'value' => $concatenate_scripts, 307 'debug' => $concatenate_scripts_debug, 308 ), 309 'COMPRESS_SCRIPTS' => array( 310 'label' => 'COMPRESS_SCRIPTS', 311 'value' => $compress_scripts, 312 'debug' => $compress_scripts_debug, 313 ), 314 'COMPRESS_CSS' => array( 315 'label' => 'COMPRESS_CSS', 316 'value' => $compress_css, 317 'debug' => $compress_css_debug, 318 ), 319 'WP_ENVIRONMENT_TYPE' => array( 320 'label' => 'WP_ENVIRONMENT_TYPE', 321 'value' => $wp_environment_type, 322 'debug' => $wp_environment_type, 323 ), 324 'DB_CHARSET' => array( 325 'label' => 'DB_CHARSET', 326 'value' => ( defined( 'DB_CHARSET' ) ? DB_CHARSET : __( 'Undefined' ) ), 327 'debug' => ( defined( 'DB_CHARSET' ) ? DB_CHARSET : 'undefined' ), 328 ), 329 'DB_COLLATE' => array( 330 'label' => 'DB_COLLATE', 331 'value' => ( defined( 'DB_COLLATE' ) ? DB_COLLATE : __( 'Undefined' ) ), 332 'debug' => ( defined( 'DB_COLLATE' ) ? DB_COLLATE : 'undefined' ), 333 ), 334 ), 335 ); 336 337 $is_writable_abspath = wp_is_writable( ABSPATH ); 338 $is_writable_wp_content_dir = wp_is_writable( WP_CONTENT_DIR ); 339 $is_writable_upload_dir = wp_is_writable( $upload_dir['basedir'] ); 340 $is_writable_wp_plugin_dir = wp_is_writable( WP_PLUGIN_DIR ); 341 $is_writable_template_directory = wp_is_writable( get_theme_root( get_template() ) ); 342 343 $info['wp-filesystem'] = array( 344 'label' => __( 'Filesystem Permissions' ), 345 'description' => __( 'Shows whether WordPress is able to write to the directories it needs access to.' ), 346 'fields' => array( 347 'wordpress' => array( 348 'label' => __( 'The main WordPress directory' ), 349 'value' => ( $is_writable_abspath ? __( 'Writable' ) : __( 'Not writable' ) ), 350 'debug' => ( $is_writable_abspath ? 'writable' : 'not writable' ), 351 ), 352 'wp-content' => array( 353 'label' => __( 'The wp-content directory' ), 354 'value' => ( $is_writable_wp_content_dir ? __( 'Writable' ) : __( 'Not writable' ) ), 355 'debug' => ( $is_writable_wp_content_dir ? 'writable' : 'not writable' ), 356 ), 357 'uploads' => array( 358 'label' => __( 'The uploads directory' ), 359 'value' => ( $is_writable_upload_dir ? __( 'Writable' ) : __( 'Not writable' ) ), 360 'debug' => ( $is_writable_upload_dir ? 'writable' : 'not writable' ), 361 ), 362 'plugins' => array( 363 'label' => __( 'The plugins directory' ), 364 'value' => ( $is_writable_wp_plugin_dir ? __( 'Writable' ) : __( 'Not writable' ) ), 365 'debug' => ( $is_writable_wp_plugin_dir ? 'writable' : 'not writable' ), 366 ), 367 'themes' => array( 368 'label' => __( 'The themes directory' ), 369 'value' => ( $is_writable_template_directory ? __( 'Writable' ) : __( 'Not writable' ) ), 370 'debug' => ( $is_writable_template_directory ? 'writable' : 'not writable' ), 371 ), 372 ), 373 ); 374 375 // Conditionally add debug information for multisite setups. 376 if ( is_multisite() ) { 377 $network_query = new WP_Network_Query(); 378 $network_ids = $network_query->query( 379 array( 380 'fields' => 'ids', 381 'number' => 100, 382 'no_found_rows' => false, 383 ) 384 ); 385 386 $site_count = 0; 387 foreach ( $network_ids as $network_id ) { 388 $site_count += get_blog_count( $network_id ); 389 } 390 391 $info['wp-core']['fields']['site_count'] = array( 392 'label' => __( 'Site count' ), 393 'value' => $site_count, 394 ); 395 396 $info['wp-core']['fields']['network_count'] = array( 397 'label' => __( 'Network count' ), 398 'value' => $network_query->found_networks, 399 ); 400 } 401 402 $info['wp-core']['fields']['user_count'] = array( 403 'label' => __( 'User count' ), 404 'value' => get_user_count(), 405 ); 406 407 // WordPress features requiring processing. 408 $wp_dotorg = wp_remote_get( 'https://wordpress.org', array( 'timeout' => 10 ) ); 409 410 if ( ! is_wp_error( $wp_dotorg ) ) { 411 $info['wp-core']['fields']['dotorg_communication'] = array( 412 'label' => __( 'Communication with WordPress.org' ), 413 'value' => __( 'WordPress.org is reachable' ), 414 'debug' => 'true', 415 ); 416 } else { 417 $info['wp-core']['fields']['dotorg_communication'] = array( 418 'label' => __( 'Communication with WordPress.org' ), 419 'value' => sprintf( 420 /* translators: 1: The IP address WordPress.org resolves to. 2: The error returned by the lookup. */ 421 __( 'Unable to reach WordPress.org at %1$s: %2$s' ), 422 gethostbyname( 'wordpress.org' ), 423 $wp_dotorg->get_error_message() 424 ), 425 'debug' => $wp_dotorg->get_error_message(), 426 ); 427 } 428 429 // Remove accordion for Directories and Sizes if in Multisite. 430 if ( ! $is_multisite ) { 431 $loading = __( 'Loading…' ); 432 433 $info['wp-paths-sizes']['fields'] = array( 434 'wordpress_path' => array( 435 'label' => __( 'WordPress directory location' ), 436 'value' => untrailingslashit( ABSPATH ), 437 ), 438 'wordpress_size' => array( 439 'label' => __( 'WordPress directory size' ), 440 'value' => $loading, 441 'debug' => 'loading...', 442 ), 443 'uploads_path' => array( 444 'label' => __( 'Uploads directory location' ), 445 'value' => $upload_dir['basedir'], 446 ), 447 'uploads_size' => array( 448 'label' => __( 'Uploads directory size' ), 449 'value' => $loading, 450 'debug' => 'loading...', 451 ), 452 'themes_path' => array( 453 'label' => __( 'Themes directory location' ), 454 'value' => get_theme_root(), 455 ), 456 'themes_size' => array( 457 'label' => __( 'Themes directory size' ), 458 'value' => $loading, 459 'debug' => 'loading...', 460 ), 461 'plugins_path' => array( 462 'label' => __( 'Plugins directory location' ), 463 'value' => WP_PLUGIN_DIR, 464 ), 465 'plugins_size' => array( 466 'label' => __( 'Plugins directory size' ), 467 'value' => $loading, 468 'debug' => 'loading...', 469 ), 470 'database_size' => array( 471 'label' => __( 'Database size' ), 472 'value' => $loading, 473 'debug' => 'loading...', 474 ), 475 'total_size' => array( 476 'label' => __( 'Total installation size' ), 477 'value' => $loading, 478 'debug' => 'loading...', 479 ), 480 ); 481 } 482 483 // Get a list of all drop-in replacements. 484 $dropins = get_dropins(); 485 486 // Get dropins descriptions. 487 $dropin_descriptions = _get_dropins(); 488 489 // Spare few function calls. 490 $not_available = __( 'Not available' ); 491 492 foreach ( $dropins as $dropin_key => $dropin ) { 493 $info['wp-dropins']['fields'][ sanitize_text_field( $dropin_key ) ] = array( 494 'label' => $dropin_key, 495 'value' => $dropin_descriptions[ $dropin_key ][0], 496 'debug' => 'true', 497 ); 498 } 499 500 // Populate the media fields. 501 $info['wp-media']['fields']['image_editor'] = array( 502 'label' => __( 'Active editor' ), 503 'value' => _wp_image_editor_choose(), 504 ); 505 506 // Get ImageMagic information, if available. 507 if ( class_exists( 'Imagick' ) ) { 508 // Save the Imagick instance for later use. 509 $imagick = new Imagick(); 510 $imagemagick_version = $imagick->getVersion(); 511 } else { 512 $imagemagick_version = __( 'Not available' ); 513 } 514 515 $info['wp-media']['fields']['imagick_module_version'] = array( 516 'label' => __( 'ImageMagick version number' ), 517 'value' => ( is_array( $imagemagick_version ) ? $imagemagick_version['versionNumber'] : $imagemagick_version ), 518 ); 519 520 $info['wp-media']['fields']['imagemagick_version'] = array( 521 'label' => __( 'ImageMagick version string' ), 522 'value' => ( is_array( $imagemagick_version ) ? $imagemagick_version['versionString'] : $imagemagick_version ), 523 ); 524 525 $imagick_version = phpversion( 'imagick' ); 526 527 $info['wp-media']['fields']['imagick_version'] = array( 528 'label' => __( 'Imagick version' ), 529 'value' => ( $imagick_version ) ? $imagick_version : __( 'Not available' ), 530 ); 531 532 if ( ! function_exists( 'ini_get' ) ) { 533 $info['wp-media']['fields']['ini_get'] = array( 534 'label' => __( 'File upload settings' ), 535 'value' => sprintf( 536 /* translators: %s: ini_get() */ 537 __( 'Unable to determine some settings, as the %s function has been disabled.' ), 538 'ini_get()' 539 ), 540 'debug' => 'ini_get() is disabled', 541 ); 542 } else { 543 // Get the PHP ini directive values. 544 $post_max_size = ini_get( 'post_max_size' ); 545 $upload_max_filesize = ini_get( 'upload_max_filesize' ); 546 $max_file_uploads = ini_get( 'max_file_uploads' ); 547 $effective = min( wp_convert_hr_to_bytes( $post_max_size ), wp_convert_hr_to_bytes( $upload_max_filesize ) ); 548 549 // Add info in Media section. 550 $info['wp-media']['fields']['file_uploads'] = array( 551 'label' => __( 'File uploads' ), 552 'value' => empty( ini_get( 'file_uploads' ) ) ? __( 'Disabled' ) : __( 'Enabled' ), 553 'debug' => 'File uploads is turned off', 554 ); 555 $info['wp-media']['fields']['post_max_size'] = array( 556 'label' => __( 'Max size of post data allowed' ), 557 'value' => $post_max_size, 558 ); 559 $info['wp-media']['fields']['upload_max_filesize'] = array( 560 'label' => __( 'Max size of an uploaded file' ), 561 'value' => $upload_max_filesize, 562 ); 563 $info['wp-media']['fields']['max_effective_size'] = array( 564 'label' => __( 'Max effective file size' ), 565 'value' => size_format( $effective ), 566 ); 567 $info['wp-media']['fields']['max_file_uploads'] = array( 568 'label' => __( 'Max number of files allowed' ), 569 'value' => number_format( $max_file_uploads ), 570 ); 571 } 572 573 // If Imagick is used as our editor, provide some more information about its limitations. 574 if ( 'WP_Image_Editor_Imagick' === _wp_image_editor_choose() && isset( $imagick ) && $imagick instanceof Imagick ) { 575 $limits = array( 576 'area' => ( defined( 'imagick::RESOURCETYPE_AREA' ) ? size_format( $imagick->getResourceLimit( imagick::RESOURCETYPE_AREA ) ) : $not_available ), 577 'disk' => ( defined( 'imagick::RESOURCETYPE_DISK' ) ? $imagick->getResourceLimit( imagick::RESOURCETYPE_DISK ) : $not_available ), 578 'file' => ( defined( 'imagick::RESOURCETYPE_FILE' ) ? $imagick->getResourceLimit( imagick::RESOURCETYPE_FILE ) : $not_available ), 579 'map' => ( defined( 'imagick::RESOURCETYPE_MAP' ) ? size_format( $imagick->getResourceLimit( imagick::RESOURCETYPE_MAP ) ) : $not_available ), 580 'memory' => ( defined( 'imagick::RESOURCETYPE_MEMORY' ) ? size_format( $imagick->getResourceLimit( imagick::RESOURCETYPE_MEMORY ) ) : $not_available ), 581 'thread' => ( defined( 'imagick::RESOURCETYPE_THREAD' ) ? $imagick->getResourceLimit( imagick::RESOURCETYPE_THREAD ) : $not_available ), 582 ); 583 584 $limits_debug = array( 585 'imagick::RESOURCETYPE_AREA' => ( defined( 'imagick::RESOURCETYPE_AREA' ) ? size_format( $imagick->getResourceLimit( imagick::RESOURCETYPE_AREA ) ) : 'not available' ), 586 'imagick::RESOURCETYPE_DISK' => ( defined( 'imagick::RESOURCETYPE_DISK' ) ? $imagick->getResourceLimit( imagick::RESOURCETYPE_DISK ) : 'not available' ), 587 'imagick::RESOURCETYPE_FILE' => ( defined( 'imagick::RESOURCETYPE_FILE' ) ? $imagick->getResourceLimit( imagick::RESOURCETYPE_FILE ) : 'not available' ), 588 'imagick::RESOURCETYPE_MAP' => ( defined( 'imagick::RESOURCETYPE_MAP' ) ? size_format( $imagick->getResourceLimit( imagick::RESOURCETYPE_MAP ) ) : 'not available' ), 589 'imagick::RESOURCETYPE_MEMORY' => ( defined( 'imagick::RESOURCETYPE_MEMORY' ) ? size_format( $imagick->getResourceLimit( imagick::RESOURCETYPE_MEMORY ) ) : 'not available' ), 590 'imagick::RESOURCETYPE_THREAD' => ( defined( 'imagick::RESOURCETYPE_THREAD' ) ? $imagick->getResourceLimit( imagick::RESOURCETYPE_THREAD ) : 'not available' ), 591 ); 592 593 $info['wp-media']['fields']['imagick_limits'] = array( 594 'label' => __( 'Imagick Resource Limits' ), 595 'value' => $limits, 596 'debug' => $limits_debug, 597 ); 598 599 try { 600 $formats = Imagick::queryFormats( '*' ); 601 } catch ( Exception $e ) { 602 $formats = array(); 603 } 604 605 $info['wp-media']['fields']['imagemagick_file_formats'] = array( 606 'label' => __( 'ImageMagick supported file formats' ), 607 'value' => ( empty( $formats ) ) ? __( 'Unable to determine' ) : implode( ', ', $formats ), 608 'debug' => ( empty( $formats ) ) ? 'Unable to determine' : implode( ', ', $formats ), 609 ); 610 } 611 612 // Get GD information, if available. 613 if ( function_exists( 'gd_info' ) ) { 614 $gd = gd_info(); 615 } else { 616 $gd = false; 617 } 618 619 $info['wp-media']['fields']['gd_version'] = array( 620 'label' => __( 'GD version' ), 621 'value' => ( is_array( $gd ) ? $gd['GD Version'] : $not_available ), 622 'debug' => ( is_array( $gd ) ? $gd['GD Version'] : 'not available' ), 623 ); 624 625 $gd_image_formats = array(); 626 $gd_supported_formats = array( 627 'GIF Create' => 'GIF', 628 'JPEG' => 'JPEG', 629 'PNG' => 'PNG', 630 'WebP' => 'WebP', 631 'BMP' => 'BMP', 632 'AVIF' => 'AVIF', 633 'HEIF' => 'HEIF', 634 'TIFF' => 'TIFF', 635 'XPM' => 'XPM', 636 ); 637 638 foreach ( $gd_supported_formats as $format_key => $format ) { 639 $index = $format_key . ' Support'; 640 if ( isset( $gd[ $index ] ) && $gd[ $index ] ) { 641 array_push( $gd_image_formats, $format ); 642 } 643 } 644 645 if ( ! empty( $gd_image_formats ) ) { 646 $info['wp-media']['fields']['gd_formats'] = array( 647 'label' => __( 'GD supported file formats' ), 648 'value' => implode( ', ', $gd_image_formats ), 649 ); 650 } 651 652 // Get Ghostscript information, if available. 653 if ( function_exists( 'exec' ) ) { 654 $gs = exec( 'gs --version' ); 655 656 if ( empty( $gs ) ) { 657 $gs = $not_available; 658 $gs_debug = 'not available'; 659 } else { 660 $gs_debug = $gs; 661 } 662 } else { 663 $gs = __( 'Unable to determine if Ghostscript is installed' ); 664 $gs_debug = 'unknown'; 665 } 666 667 $info['wp-media']['fields']['ghostscript_version'] = array( 668 'label' => __( 'Ghostscript version' ), 669 'value' => $gs, 670 'debug' => $gs_debug, 671 ); 672 673 // Populate the server debug fields. 674 if ( function_exists( 'php_uname' ) ) { 675 $server_architecture = sprintf( '%s %s %s', php_uname( 's' ), php_uname( 'r' ), php_uname( 'm' ) ); 676 } else { 677 $server_architecture = 'unknown'; 678 } 679 680 if ( function_exists( 'phpversion' ) ) { 681 $php_version_debug = phpversion(); 682 // Whether PHP supports 64-bit. 683 $php64bit = ( PHP_INT_SIZE * 8 === 64 ); 684 685 $php_version = sprintf( 686 '%s %s', 687 $php_version_debug, 688 ( $php64bit ? __( '(Supports 64bit values)' ) : __( '(Does not support 64bit values)' ) ) 689 ); 690 691 if ( $php64bit ) { 692 $php_version_debug .= ' 64bit'; 693 } 694 } else { 695 $php_version = __( 'Unable to determine PHP version' ); 696 $php_version_debug = 'unknown'; 697 } 698 699 if ( function_exists( 'php_sapi_name' ) ) { 700 $php_sapi = php_sapi_name(); 701 } else { 702 $php_sapi = 'unknown'; 703 } 704 705 $info['wp-server']['fields']['server_architecture'] = array( 706 'label' => __( 'Server architecture' ), 707 'value' => ( 'unknown' !== $server_architecture ? $server_architecture : __( 'Unable to determine server architecture' ) ), 708 'debug' => $server_architecture, 709 ); 710 $info['wp-server']['fields']['httpd_software'] = array( 711 'label' => __( 'Web server' ), 712 'value' => ( isset( $_SERVER['SERVER_SOFTWARE'] ) ? $_SERVER['SERVER_SOFTWARE'] : __( 'Unable to determine what web server software is used' ) ), 713 'debug' => ( isset( $_SERVER['SERVER_SOFTWARE'] ) ? $_SERVER['SERVER_SOFTWARE'] : 'unknown' ), 714 ); 715 $info['wp-server']['fields']['php_version'] = array( 716 'label' => __( 'PHP version' ), 717 'value' => $php_version, 718 'debug' => $php_version_debug, 719 ); 720 $info['wp-server']['fields']['php_sapi'] = array( 721 'label' => __( 'PHP SAPI' ), 722 'value' => ( 'unknown' !== $php_sapi ? $php_sapi : __( 'Unable to determine PHP SAPI' ) ), 723 'debug' => $php_sapi, 724 ); 725 726 // Some servers disable `ini_set()` and `ini_get()`, we check this before trying to get configuration values. 727 if ( ! function_exists( 'ini_get' ) ) { 728 $info['wp-server']['fields']['ini_get'] = array( 729 'label' => __( 'Server settings' ), 730 'value' => sprintf( 731 /* translators: %s: ini_get() */ 732 __( 'Unable to determine some settings, as the %s function has been disabled.' ), 733 'ini_get()' 734 ), 735 'debug' => 'ini_get() is disabled', 736 ); 737 } else { 738 $info['wp-server']['fields']['max_input_variables'] = array( 739 'label' => __( 'PHP max input variables' ), 740 'value' => ini_get( 'max_input_vars' ), 741 ); 742 $info['wp-server']['fields']['time_limit'] = array( 743 'label' => __( 'PHP time limit' ), 744 'value' => ini_get( 'max_execution_time' ), 745 ); 746 747 if ( WP_Site_Health::get_instance()->php_memory_limit !== ini_get( 'memory_limit' ) ) { 748 $info['wp-server']['fields']['memory_limit'] = array( 749 'label' => __( 'PHP memory limit' ), 750 'value' => WP_Site_Health::get_instance()->php_memory_limit, 751 ); 752 $info['wp-server']['fields']['admin_memory_limit'] = array( 753 'label' => __( 'PHP memory limit (only for admin screens)' ), 754 'value' => ini_get( 'memory_limit' ), 755 ); 756 } else { 757 $info['wp-server']['fields']['memory_limit'] = array( 758 'label' => __( 'PHP memory limit' ), 759 'value' => ini_get( 'memory_limit' ), 760 ); 761 } 762 763 $info['wp-server']['fields']['max_input_time'] = array( 764 'label' => __( 'Max input time' ), 765 'value' => ini_get( 'max_input_time' ), 766 ); 767 $info['wp-server']['fields']['upload_max_filesize'] = array( 768 'label' => __( 'Upload max filesize' ), 769 'value' => ini_get( 'upload_max_filesize' ), 770 ); 771 $info['wp-server']['fields']['php_post_max_size'] = array( 772 'label' => __( 'PHP post max size' ), 773 'value' => ini_get( 'post_max_size' ), 774 ); 775 } 776 777 if ( function_exists( 'curl_version' ) ) { 778 $curl = curl_version(); 779 780 $info['wp-server']['fields']['curl_version'] = array( 781 'label' => __( 'cURL version' ), 782 'value' => sprintf( '%s %s', $curl['version'], $curl['ssl_version'] ), 783 ); 784 } else { 785 $info['wp-server']['fields']['curl_version'] = array( 786 'label' => __( 'cURL version' ), 787 'value' => $not_available, 788 'debug' => 'not available', 789 ); 790 } 791 792 // SUHOSIN. 793 $suhosin_loaded = ( extension_loaded( 'suhosin' ) || ( defined( 'SUHOSIN_PATCH' ) && constant( 'SUHOSIN_PATCH' ) ) ); 794 795 $info['wp-server']['fields']['suhosin'] = array( 796 'label' => __( 'Is SUHOSIN installed?' ), 797 'value' => ( $suhosin_loaded ? __( 'Yes' ) : __( 'No' ) ), 798 'debug' => $suhosin_loaded, 799 ); 800 801 // Imagick. 802 $imagick_loaded = extension_loaded( 'imagick' ); 803 804 $info['wp-server']['fields']['imagick_availability'] = array( 805 'label' => __( 'Is the Imagick library available?' ), 806 'value' => ( $imagick_loaded ? __( 'Yes' ) : __( 'No' ) ), 807 'debug' => $imagick_loaded, 808 ); 809 810 // Pretty permalinks. 811 $pretty_permalinks_supported = got_url_rewrite(); 812 813 $info['wp-server']['fields']['pretty_permalinks'] = array( 814 'label' => __( 'Are pretty permalinks supported?' ), 815 'value' => ( $pretty_permalinks_supported ? __( 'Yes' ) : __( 'No' ) ), 816 'debug' => $pretty_permalinks_supported, 817 ); 818 819 // Check if a .htaccess file exists. 820 if ( is_file( ABSPATH . '.htaccess' ) ) { 821 // If the file exists, grab the content of it. 822 $htaccess_content = file_get_contents( ABSPATH . '.htaccess' ); 823 824 // Filter away the core WordPress rules. 825 $filtered_htaccess_content = trim( preg_replace( '/\# BEGIN WordPress[\s\S]+?# END WordPress/si', '', $htaccess_content ) ); 826 $filtered_htaccess_content = ! empty( $filtered_htaccess_content ); 827 828 if ( $filtered_htaccess_content ) { 829 /* translators: %s: .htaccess */ 830 $htaccess_rules_string = sprintf( __( 'Custom rules have been added to your %s file.' ), '.htaccess' ); 831 } else { 832 /* translators: %s: .htaccess */ 833 $htaccess_rules_string = sprintf( __( 'Your %s file contains only core WordPress features.' ), '.htaccess' ); 834 } 835 836 $info['wp-server']['fields']['htaccess_extra_rules'] = array( 837 'label' => __( '.htaccess rules' ), 838 'value' => $htaccess_rules_string, 839 'debug' => $filtered_htaccess_content, 840 ); 841 } 842 843 // Populate the database debug fields. 844 if ( is_resource( $wpdb->dbh ) ) { 845 // Old mysql extension. 846 $extension = 'mysql'; 847 } elseif ( is_object( $wpdb->dbh ) ) { 848 // mysqli or PDO. 849 $extension = get_class( $wpdb->dbh ); 850 } else { 851 // Unknown sql extension. 852 $extension = null; 853 } 854 855 $server = $wpdb->get_var( 'SELECT VERSION()' ); 856 857 if ( isset( $wpdb->use_mysqli ) && $wpdb->use_mysqli ) { 858 $client_version = $wpdb->dbh->client_info; 859 } else { 860 // phpcs:ignore WordPress.DB.RestrictedFunctions.mysql_mysql_get_client_info,PHPCompatibility.Extensions.RemovedExtensions.mysql_DeprecatedRemoved 861 if ( preg_match( '|[0-9]{1,2}\.[0-9]{1,2}\.[0-9]{1,2}|', mysql_get_client_info(), $matches ) ) { 862 $client_version = $matches[0]; 863 } else { 864 $client_version = null; 865 } 866 } 867 868 $info['wp-database']['fields']['extension'] = array( 869 'label' => __( 'Extension' ), 870 'value' => $extension, 871 ); 872 873 $info['wp-database']['fields']['server_version'] = array( 874 'label' => __( 'Server version' ), 875 'value' => $server, 876 ); 877 878 $info['wp-database']['fields']['client_version'] = array( 879 'label' => __( 'Client version' ), 880 'value' => $client_version, 881 ); 882 883 $info['wp-database']['fields']['database_user'] = array( 884 'label' => __( 'Database username' ), 885 'value' => $wpdb->dbuser, 886 'private' => true, 887 ); 888 889 $info['wp-database']['fields']['database_host'] = array( 890 'label' => __( 'Database host' ), 891 'value' => $wpdb->dbhost, 892 'private' => true, 893 ); 894 895 $info['wp-database']['fields']['database_name'] = array( 896 'label' => __( 'Database name' ), 897 'value' => $wpdb->dbname, 898 'private' => true, 899 ); 900 901 $info['wp-database']['fields']['database_prefix'] = array( 902 'label' => __( 'Table prefix' ), 903 'value' => $wpdb->prefix, 904 'private' => true, 905 ); 906 907 $info['wp-database']['fields']['database_charset'] = array( 908 'label' => __( 'Database charset' ), 909 'value' => $wpdb->charset, 910 'private' => true, 911 ); 912 913 $info['wp-database']['fields']['database_collate'] = array( 914 'label' => __( 'Database collation' ), 915 'value' => $wpdb->collate, 916 'private' => true, 917 ); 918 919 $info['wp-database']['fields']['max_allowed_packet'] = array( 920 'label' => __( 'Max allowed packet size' ), 921 'value' => self::get_mysql_var( 'max_allowed_packet' ), 922 ); 923 924 $info['wp-database']['fields']['max_connections'] = array( 925 'label' => __( 'Max connections number' ), 926 'value' => self::get_mysql_var( 'max_connections' ), 927 ); 928 929 // List must use plugins if there are any. 930 $mu_plugins = get_mu_plugins(); 931 932 foreach ( $mu_plugins as $plugin_path => $plugin ) { 933 $plugin_version = $plugin['Version']; 934 $plugin_author = $plugin['Author']; 935 936 $plugin_version_string = __( 'No version or author information is available.' ); 937 $plugin_version_string_debug = 'author: (undefined), version: (undefined)'; 938 939 if ( ! empty( $plugin_version ) && ! empty( $plugin_author ) ) { 940 /* translators: 1: Plugin version number. 2: Plugin author name. */ 941 $plugin_version_string = sprintf( __( 'Version %1$s by %2$s' ), $plugin_version, $plugin_author ); 942 $plugin_version_string_debug = sprintf( 'version: %s, author: %s', $plugin_version, $plugin_author ); 943 } else { 944 if ( ! empty( $plugin_author ) ) { 945 /* translators: %s: Plugin author name. */ 946 $plugin_version_string = sprintf( __( 'By %s' ), $plugin_author ); 947 $plugin_version_string_debug = sprintf( 'author: %s, version: (undefined)', $plugin_author ); 948 } 949 950 if ( ! empty( $plugin_version ) ) { 951 /* translators: %s: Plugin version number. */ 952 $plugin_version_string = sprintf( __( 'Version %s' ), $plugin_version ); 953 $plugin_version_string_debug = sprintf( 'author: (undefined), version: %s', $plugin_version ); 954 } 955 } 956 957 $info['wp-mu-plugins']['fields'][ sanitize_text_field( $plugin['Name'] ) ] = array( 958 'label' => $plugin['Name'], 959 'value' => $plugin_version_string, 960 'debug' => $plugin_version_string_debug, 961 ); 962 } 963 964 // List all available plugins. 965 $plugins = get_plugins(); 966 $plugin_updates = get_plugin_updates(); 967 $transient = get_site_transient( 'update_plugins' ); 968 969 $auto_updates = array(); 970 971 $auto_updates_enabled = wp_is_auto_update_enabled_for_type( 'plugin' ); 972 973 if ( $auto_updates_enabled ) { 974 $auto_updates = (array) get_site_option( 'auto_update_plugins', array() ); 975 } 976 977 foreach ( $plugins as $plugin_path => $plugin ) { 978 $plugin_part = ( is_plugin_active( $plugin_path ) ) ? 'wp-plugins-active' : 'wp-plugins-inactive'; 979 980 $plugin_version = $plugin['Version']; 981 $plugin_author = $plugin['Author']; 982 983 $plugin_version_string = __( 'No version or author information is available.' ); 984 $plugin_version_string_debug = 'author: (undefined), version: (undefined)'; 985 986 if ( ! empty( $plugin_version ) && ! empty( $plugin_author ) ) { 987 /* translators: 1: Plugin version number. 2: Plugin author name. */ 988 $plugin_version_string = sprintf( __( 'Version %1$s by %2$s' ), $plugin_version, $plugin_author ); 989 $plugin_version_string_debug = sprintf( 'version: %s, author: %s', $plugin_version, $plugin_author ); 990 } else { 991 if ( ! empty( $plugin_author ) ) { 992 /* translators: %s: Plugin author name. */ 993 $plugin_version_string = sprintf( __( 'By %s' ), $plugin_author ); 994 $plugin_version_string_debug = sprintf( 'author: %s, version: (undefined)', $plugin_author ); 995 } 996 997 if ( ! empty( $plugin_version ) ) { 998 /* translators: %s: Plugin version number. */ 999 $plugin_version_string = sprintf( __( 'Version %s' ), $plugin_version ); 1000 $plugin_version_string_debug = sprintf( 'author: (undefined), version: %s', $plugin_version ); 1001 } 1002 } 1003 1004 if ( array_key_exists( $plugin_path, $plugin_updates ) ) { 1005 /* translators: %s: Latest plugin version number. */ 1006 $plugin_version_string .= ' ' . sprintf( __( '(Latest version: %s)' ), $plugin_updates[ $plugin_path ]->update->new_version ); 1007 $plugin_version_string_debug .= sprintf( ' (latest version: %s)', $plugin_updates[ $plugin_path ]->update->new_version ); 1008 } 1009 1010 if ( $auto_updates_enabled ) { 1011 if ( isset( $transient->response[ $plugin_path ] ) ) { 1012 $item = $transient->response[ $plugin_path ]; 1013 } elseif ( isset( $transient->no_update[ $plugin_path ] ) ) { 1014 $item = $transient->no_update[ $plugin_path ]; 1015 } else { 1016 $item = array( 1017 'id' => $plugin_path, 1018 'slug' => '', 1019 'plugin' => $plugin_path, 1020 'new_version' => '', 1021 'url' => '', 1022 'package' => '', 1023 'icons' => array(), 1024 'banners' => array(), 1025 'banners_rtl' => array(), 1026 'tested' => '', 1027 'requires_php' => '', 1028 'compatibility' => new stdClass(), 1029 ); 1030 $item = wp_parse_args( $plugin, $item ); 1031 } 1032 1033 $auto_update_forced = wp_is_auto_update_forced_for_item( 'plugin', null, (object) $item ); 1034 1035 if ( ! is_null( $auto_update_forced ) ) { 1036 $enabled = $auto_update_forced; 1037 } else { 1038 $enabled = in_array( $plugin_path, $auto_updates, true ); 1039 } 1040 1041 if ( $enabled ) { 1042 $auto_updates_string = __( 'Auto-updates enabled' ); 1043 } else { 1044 $auto_updates_string = __( 'Auto-updates disabled' ); 1045 } 1046 1047 /** 1048 * Filters the text string of the auto-updates setting for each plugin in the Site Health debug data. 1049 * 1050 * @since 5.5.0 1051 * 1052 * @param string $auto_updates_string The string output for the auto-updates column. 1053 * @param string $plugin_path The path to the plugin file. 1054 * @param array $plugin An array of plugin data. 1055 * @param bool $enabled Whether auto-updates are enabled for this item. 1056 */ 1057 $auto_updates_string = apply_filters( 'plugin_auto_update_debug_string', $auto_updates_string, $plugin_path, $plugin, $enabled ); 1058 1059 $plugin_version_string .= ' | ' . $auto_updates_string; 1060 $plugin_version_string_debug .= ', ' . $auto_updates_string; 1061 } 1062 1063 $info[ $plugin_part ]['fields'][ sanitize_text_field( $plugin['Name'] ) ] = array( 1064 'label' => $plugin['Name'], 1065 'value' => $plugin_version_string, 1066 'debug' => $plugin_version_string_debug, 1067 ); 1068 } 1069 1070 // Populate the section for the currently active theme. 1071 global $_wp_theme_features; 1072 $theme_features = array(); 1073 1074 if ( ! empty( $_wp_theme_features ) ) { 1075 foreach ( $_wp_theme_features as $feature => $options ) { 1076 $theme_features[] = $feature; 1077 } 1078 } 1079 1080 $active_theme = wp_get_theme(); 1081 $theme_updates = get_theme_updates(); 1082 $transient = get_site_transient( 'update_themes' ); 1083 1084 $active_theme_version = $active_theme->version; 1085 $active_theme_version_debug = $active_theme_version; 1086 1087 $auto_updates = array(); 1088 $auto_updates_enabled = wp_is_auto_update_enabled_for_type( 'theme' ); 1089 if ( $auto_updates_enabled ) { 1090 $auto_updates = (array) get_site_option( 'auto_update_themes', array() ); 1091 } 1092 1093 if ( array_key_exists( $active_theme->stylesheet, $theme_updates ) ) { 1094 $theme_update_new_version = $theme_updates[ $active_theme->stylesheet ]->update['new_version']; 1095 1096 /* translators: %s: Latest theme version number. */ 1097 $active_theme_version .= ' ' . sprintf( __( '(Latest version: %s)' ), $theme_update_new_version ); 1098 $active_theme_version_debug .= sprintf( ' (latest version: %s)', $theme_update_new_version ); 1099 } 1100 1101 $active_theme_author_uri = $active_theme->display( 'AuthorURI' ); 1102 1103 if ( $active_theme->parent_theme ) { 1104 $active_theme_parent_theme = sprintf( 1105 /* translators: 1: Theme name. 2: Theme slug. */ 1106 __( '%1$s (%2$s)' ), 1107 $active_theme->parent_theme, 1108 $active_theme->template 1109 ); 1110 $active_theme_parent_theme_debug = sprintf( 1111 '%s (%s)', 1112 $active_theme->parent_theme, 1113 $active_theme->template 1114 ); 1115 } else { 1116 $active_theme_parent_theme = __( 'None' ); 1117 $active_theme_parent_theme_debug = 'none'; 1118 } 1119 1120 $info['wp-active-theme']['fields'] = array( 1121 'name' => array( 1122 'label' => __( 'Name' ), 1123 'value' => sprintf( 1124 /* translators: 1: Theme name. 2: Theme slug. */ 1125 __( '%1$s (%2$s)' ), 1126 $active_theme->name, 1127 $active_theme->stylesheet 1128 ), 1129 ), 1130 'version' => array( 1131 'label' => __( 'Version' ), 1132 'value' => $active_theme_version, 1133 'debug' => $active_theme_version_debug, 1134 ), 1135 'author' => array( 1136 'label' => __( 'Author' ), 1137 'value' => wp_kses( $active_theme->author, array() ), 1138 ), 1139 'author_website' => array( 1140 'label' => __( 'Author website' ), 1141 'value' => ( $active_theme_author_uri ? $active_theme_author_uri : __( 'Undefined' ) ), 1142 'debug' => ( $active_theme_author_uri ? $active_theme_author_uri : '(undefined)' ), 1143 ), 1144 'parent_theme' => array( 1145 'label' => __( 'Parent theme' ), 1146 'value' => $active_theme_parent_theme, 1147 'debug' => $active_theme_parent_theme_debug, 1148 ), 1149 'theme_features' => array( 1150 'label' => __( 'Theme features' ), 1151 'value' => implode( ', ', $theme_features ), 1152 ), 1153 'theme_path' => array( 1154 'label' => __( 'Theme directory location' ), 1155 'value' => get_stylesheet_directory(), 1156 ), 1157 ); 1158 1159 if ( $auto_updates_enabled ) { 1160 if ( isset( $transient->response[ $active_theme->stylesheet ] ) ) { 1161 $item = $transient->response[ $active_theme->stylesheet ]; 1162 } elseif ( isset( $transient->no_update[ $active_theme->stylesheet ] ) ) { 1163 $item = $transient->no_update[ $active_theme->stylesheet ]; 1164 } else { 1165 $item = array( 1166 'theme' => $active_theme->stylesheet, 1167 'new_version' => $active_theme->version, 1168 'url' => '', 1169 'package' => '', 1170 'requires' => '', 1171 'requires_php' => '', 1172 ); 1173 } 1174 1175 $auto_update_forced = wp_is_auto_update_forced_for_item( 'theme', null, (object) $item ); 1176 1177 if ( ! is_null( $auto_update_forced ) ) { 1178 $enabled = $auto_update_forced; 1179 } else { 1180 $enabled = in_array( $active_theme->stylesheet, $auto_updates, true ); 1181 } 1182 1183 if ( $enabled ) { 1184 $auto_updates_string = __( 'Enabled' ); 1185 } else { 1186 $auto_updates_string = __( 'Disabled' ); 1187 } 1188 1189 /** This filter is documented in wp-admin/includes/class-wp-debug-data.php */ 1190 $auto_updates_string = apply_filters( 'theme_auto_update_debug_string', $auto_updates_string, $active_theme, $enabled ); 1191 1192 $info['wp-active-theme']['fields']['auto_update'] = array( 1193 'label' => __( 'Auto-updates' ), 1194 'value' => $auto_updates_string, 1195 'debug' => $auto_updates_string, 1196 ); 1197 } 1198 1199 $parent_theme = $active_theme->parent(); 1200 1201 if ( $parent_theme ) { 1202 $parent_theme_version = $parent_theme->version; 1203 $parent_theme_version_debug = $parent_theme_version; 1204 1205 if ( array_key_exists( $parent_theme->stylesheet, $theme_updates ) ) { 1206 $parent_theme_update_new_version = $theme_updates[ $parent_theme->stylesheet ]->update['new_version']; 1207 1208 /* translators: %s: Latest theme version number. */ 1209 $parent_theme_version .= ' ' . sprintf( __( '(Latest version: %s)' ), $parent_theme_update_new_version ); 1210 $parent_theme_version_debug .= sprintf( ' (latest version: %s)', $parent_theme_update_new_version ); 1211 } 1212 1213 $parent_theme_author_uri = $parent_theme->display( 'AuthorURI' ); 1214 1215 $info['wp-parent-theme']['fields'] = array( 1216 'name' => array( 1217 'label' => __( 'Name' ), 1218 'value' => sprintf( 1219 /* translators: 1: Theme name. 2: Theme slug. */ 1220 __( '%1$s (%2$s)' ), 1221 $parent_theme->name, 1222 $parent_theme->stylesheet 1223 ), 1224 ), 1225 'version' => array( 1226 'label' => __( 'Version' ), 1227 'value' => $parent_theme_version, 1228 'debug' => $parent_theme_version_debug, 1229 ), 1230 'author' => array( 1231 'label' => __( 'Author' ), 1232 'value' => wp_kses( $parent_theme->author, array() ), 1233 ), 1234 'author_website' => array( 1235 'label' => __( 'Author website' ), 1236 'value' => ( $parent_theme_author_uri ? $parent_theme_author_uri : __( 'Undefined' ) ), 1237 'debug' => ( $parent_theme_author_uri ? $parent_theme_author_uri : '(undefined)' ), 1238 ), 1239 'theme_path' => array( 1240 'label' => __( 'Theme directory location' ), 1241 'value' => get_template_directory(), 1242 ), 1243 ); 1244 1245 if ( $auto_updates_enabled ) { 1246 if ( isset( $transient->response[ $parent_theme->stylesheet ] ) ) { 1247 $item = $transient->response[ $parent_theme->stylesheet ]; 1248 } elseif ( isset( $transient->no_update[ $parent_theme->stylesheet ] ) ) { 1249 $item = $transient->no_update[ $parent_theme->stylesheet ]; 1250 } else { 1251 $item = array( 1252 'theme' => $parent_theme->stylesheet, 1253 'new_version' => $parent_theme->version, 1254 'url' => '', 1255 'package' => '', 1256 'requires' => '', 1257 'requires_php' => '', 1258 ); 1259 } 1260 1261 $auto_update_forced = wp_is_auto_update_forced_for_item( 'theme', null, (object) $item ); 1262 1263 if ( ! is_null( $auto_update_forced ) ) { 1264 $enabled = $auto_update_forced; 1265 } else { 1266 $enabled = in_array( $parent_theme->stylesheet, $auto_updates, true ); 1267 } 1268 1269 if ( $enabled ) { 1270 $parent_theme_auto_update_string = __( 'Enabled' ); 1271 } else { 1272 $parent_theme_auto_update_string = __( 'Disabled' ); 1273 } 1274 1275 /** This filter is documented in wp-admin/includes/class-wp-debug-data.php */ 1276 $parent_theme_auto_update_string = apply_filters( 'theme_auto_update_debug_string', $auto_updates_string, $parent_theme, $enabled ); 1277 1278 $info['wp-parent-theme']['fields']['auto_update'] = array( 1279 'label' => __( 'Auto-update' ), 1280 'value' => $parent_theme_auto_update_string, 1281 'debug' => $parent_theme_auto_update_string, 1282 ); 1283 } 1284 } 1285 1286 // Populate a list of all themes available in the install. 1287 $all_themes = wp_get_themes(); 1288 1289 foreach ( $all_themes as $theme_slug => $theme ) { 1290 // Exclude the currently active theme from the list of all themes. 1291 if ( $active_theme->stylesheet === $theme_slug ) { 1292 continue; 1293 } 1294 1295 // Exclude the currently active parent theme from the list of all themes. 1296 if ( ! empty( $parent_theme ) && $parent_theme->stylesheet === $theme_slug ) { 1297 continue; 1298 } 1299 1300 $theme_version = $theme->version; 1301 $theme_author = $theme->author; 1302 1303 // Sanitize. 1304 $theme_author = wp_kses( $theme_author, array() ); 1305 1306 $theme_version_string = __( 'No version or author information is available.' ); 1307 $theme_version_string_debug = 'undefined'; 1308 1309 if ( ! empty( $theme_version ) && ! empty( $theme_author ) ) { 1310 /* translators: 1: Theme version number. 2: Theme author name. */ 1311 $theme_version_string = sprintf( __( 'Version %1$s by %2$s' ), $theme_version, $theme_author ); 1312 $theme_version_string_debug = sprintf( 'version: %s, author: %s', $theme_version, $theme_author ); 1313 } else { 1314 if ( ! empty( $theme_author ) ) { 1315 /* translators: %s: Theme author name. */ 1316 $theme_version_string = sprintf( __( 'By %s' ), $theme_author ); 1317 $theme_version_string_debug = sprintf( 'author: %s, version: (undefined)', $theme_author ); 1318 } 1319 1320 if ( ! empty( $theme_version ) ) { 1321 /* translators: %s: Theme version number. */ 1322 $theme_version_string = sprintf( __( 'Version %s' ), $theme_version ); 1323 $theme_version_string_debug = sprintf( 'author: (undefined), version: %s', $theme_version ); 1324 } 1325 } 1326 1327 if ( array_key_exists( $theme_slug, $theme_updates ) ) { 1328 /* translators: %s: Latest theme version number. */ 1329 $theme_version_string .= ' ' . sprintf( __( '(Latest version: %s)' ), $theme_updates[ $theme_slug ]->update['new_version'] ); 1330 $theme_version_string_debug .= sprintf( ' (latest version: %s)', $theme_updates[ $theme_slug ]->update['new_version'] ); 1331 } 1332 1333 if ( $auto_updates_enabled ) { 1334 if ( isset( $transient->response[ $theme_slug ] ) ) { 1335 $item = $transient->response[ $theme_slug ]; 1336 } elseif ( isset( $transient->no_update[ $theme_slug ] ) ) { 1337 $item = $transient->no_update[ $theme_slug ]; 1338 } else { 1339 $item = array( 1340 'theme' => $theme_slug, 1341 'new_version' => $theme->version, 1342 'url' => '', 1343 'package' => '', 1344 'requires' => '', 1345 'requires_php' => '', 1346 ); 1347 } 1348 1349 $auto_update_forced = wp_is_auto_update_forced_for_item( 'theme', null, (object) $item ); 1350 1351 if ( ! is_null( $auto_update_forced ) ) { 1352 $enabled = $auto_update_forced; 1353 } else { 1354 $enabled = in_array( $theme_slug, $auto_updates, true ); 1355 } 1356 1357 if ( $enabled ) { 1358 $auto_updates_string = __( 'Auto-updates enabled' ); 1359 } else { 1360 $auto_updates_string = __( 'Auto-updates disabled' ); 1361 } 1362 1363 /** 1364 * Filters the text string of the auto-updates setting for each theme in the Site Health debug data. 1365 * 1366 * @since 5.5.0 1367 * 1368 * @param string $auto_updates_string The string output for the auto-updates column. 1369 * @param WP_Theme $theme An object of theme data. 1370 * @param bool $enabled Whether auto-updates are enabled for this item. 1371 */ 1372 $auto_updates_string = apply_filters( 'theme_auto_update_debug_string', $auto_updates_string, $theme, $enabled ); 1373 1374 $theme_version_string .= ' | ' . $auto_updates_string; 1375 $theme_version_string_debug .= ', ' . $auto_updates_string; 1376 } 1377 1378 $info['wp-themes-inactive']['fields'][ sanitize_text_field( $theme->name ) ] = array( 1379 'label' => sprintf( 1380 /* translators: 1: Theme name. 2: Theme slug. */ 1381 __( '%1$s (%2$s)' ), 1382 $theme->name, 1383 $theme_slug 1384 ), 1385 'value' => $theme_version_string, 1386 'debug' => $theme_version_string_debug, 1387 ); 1388 } 1389 1390 // Add more filesystem checks. 1391 if ( defined( 'WPMU_PLUGIN_DIR' ) && is_dir( WPMU_PLUGIN_DIR ) ) { 1392 $is_writable_wpmu_plugin_dir = wp_is_writable( WPMU_PLUGIN_DIR ); 1393 1394 $info['wp-filesystem']['fields']['mu-plugins'] = array( 1395 'label' => __( 'The must use plugins directory' ), 1396 'value' => ( $is_writable_wpmu_plugin_dir ? __( 'Writable' ) : __( 'Not writable' ) ), 1397 'debug' => ( $is_writable_wpmu_plugin_dir ? 'writable' : 'not writable' ), 1398 ); 1399 } 1400 1401 /** 1402 * Add to or modify the debug information shown on the Tools -> Site Health -> Info screen. 1403 * 1404 * Plugin or themes may wish to introduce their own debug information without creating 1405 * additional admin pages. They can utilize this filter to introduce their own sections 1406 * or add more data to existing sections. 1407 * 1408 * Array keys for sections added by core are all prefixed with `wp-`. Plugins and themes 1409 * should use their own slug as a prefix, both for consistency as well as avoiding 1410 * key collisions. Note that the array keys are used as labels for the copied data. 1411 * 1412 * All strings are expected to be plain text except `$description` that can contain 1413 * inline HTML tags (see below). 1414 * 1415 * @since 5.2.0 1416 * 1417 * @param array $args { 1418 * The debug information to be added to the core information page. 1419 * 1420 * This is an associative multi-dimensional array, up to three levels deep. 1421 * The topmost array holds the sections, keyed by section ID. 1422 * 1423 * @type array ...$0 { 1424 * Each section has a `$fields` associative array (see below), and each `$value` in `$fields` 1425 * can be another associative array of name/value pairs when there is more structured data 1426 * to display. 1427 * 1428 * @type string $label Required. The title for this section of the debug output. 1429 * @type string $description Optional. A description for your information section which 1430 * may contain basic HTML markup, inline tags only as it is 1431 * outputted in a paragraph. 1432 * @type bool $show_count Optional. If set to `true`, the amount of fields will be included 1433 * in the title for this section. Default false. 1434 * @type bool $private Optional. If set to `true`, the section and all associated fields 1435 * will be excluded from the copied data. Default false. 1436 * @type array $fields { 1437 * Required. An associative array containing the fields to be displayed in the section, 1438 * keyed by field ID. 1439 * 1440 * @type array ...$0 { 1441 * An associative array containing the data to be displayed for the field. 1442 * 1443 * @type string $label Required. The label for this piece of information. 1444 * @type mixed $value Required. The output that is displayed for this field. 1445 * Text should be translated. Can be an associative array 1446 * that is displayed as name/value pairs. 1447 * Accepted types: `string|int|float|(string|int|float)[]`. 1448 * @type string $debug Optional. The output that is used for this field when 1449 * the user copies the data. It should be more concise and 1450 * not translated. If not set, the content of `$value` 1451 * is used. Note that the array keys are used as labels 1452 * for the copied data. 1453 * @type bool $private Optional. If set to `true`, the field will be excluded 1454 * from the copied data, allowing you to show, for example, 1455 * API keys here. Default false. 1456 * } 1457 * } 1458 * } 1459 * } 1460 */ 1461 $info = apply_filters( 'debug_information', $info ); 1462 1463 return $info; 1464 } 1465 1466 /** 1467 * Returns the value of a MySQL system variable. 1468 * 1469 * @since 5.9.0 1470 * 1471 * @global wpdb $wpdb WordPress database abstraction object. 1472 * 1473 * @param string $mysql_var Name of the MySQL system variable. 1474 * @return string|null The variable value on success. Null if the variable does not exist. 1475 */ 1476 public static function get_mysql_var( $mysql_var ) { 1477 global $wpdb; 1478 1479 $result = $wpdb->get_row( 1480 $wpdb->prepare( 'SHOW VARIABLES LIKE %s', $mysql_var ), 1481 ARRAY_A 1482 ); 1483 1484 if ( ! empty( $result ) && array_key_exists( 'Value', $result ) ) { 1485 return $result['Value']; 1486 } 1487 1488 return null; 1489 } 1490 1491 /** 1492 * Format the information gathered for debugging, in a manner suitable for copying to a forum or support ticket. 1493 * 1494 * @since 5.2.0 1495 * 1496 * @param array $info_array Information gathered from the `WP_Debug_Data::debug_data()` function. 1497 * @param string $data_type The data type to return, either 'info' or 'debug'. 1498 * @return string The formatted data. 1499 */ 1500 public static function format( $info_array, $data_type ) { 1501 $return = "`\n"; 1502 1503 foreach ( $info_array as $section => $details ) { 1504 // Skip this section if there are no fields, or the section has been declared as private. 1505 if ( empty( $details['fields'] ) || ( isset( $details['private'] ) && $details['private'] ) ) { 1506 continue; 1507 } 1508 1509 $section_label = 'debug' === $data_type ? $section : $details['label']; 1510 1511 $return .= sprintf( 1512 "### %s%s ###\n\n", 1513 $section_label, 1514 ( isset( $details['show_count'] ) && $details['show_count'] ? sprintf( ' (%d)', count( $details['fields'] ) ) : '' ) 1515 ); 1516 1517 foreach ( $details['fields'] as $field_name => $field ) { 1518 if ( isset( $field['private'] ) && true === $field['private'] ) { 1519 continue; 1520 } 1521 1522 if ( 'debug' === $data_type && isset( $field['debug'] ) ) { 1523 $debug_data = $field['debug']; 1524 } else { 1525 $debug_data = $field['value']; 1526 } 1527 1528 // Can be array, one level deep only. 1529 if ( is_array( $debug_data ) ) { 1530 $value = ''; 1531 1532 foreach ( $debug_data as $sub_field_name => $sub_field_value ) { 1533 $value .= sprintf( "\n\t%s: %s", $sub_field_name, $sub_field_value ); 1534 } 1535 } elseif ( is_bool( $debug_data ) ) { 1536 $value = $debug_data ? 'true' : 'false'; 1537 } elseif ( empty( $debug_data ) && '0' !== $debug_data ) { 1538 $value = 'undefined'; 1539 } else { 1540 $value = $debug_data; 1541 } 1542 1543 if ( 'debug' === $data_type ) { 1544 $label = $field_name; 1545 } else { 1546 $label = $field['label']; 1547 } 1548 1549 $return .= sprintf( "%s: %s\n", $label, $value ); 1550 } 1551 1552 $return .= "\n"; 1553 } 1554 1555 $return .= '`'; 1556 1557 return $return; 1558 } 1559 1560 /** 1561 * Fetch the total size of all the database tables for the active database user. 1562 * 1563 * @since 5.2.0 1564 * 1565 * @return int The size of the database, in bytes. 1566 */ 1567 public static function get_database_size() { 1568 global $wpdb; 1569 $size = 0; 1570 $rows = $wpdb->get_results( 'SHOW TABLE STATUS', ARRAY_A ); 1571 1572 if ( $wpdb->num_rows > 0 ) { 1573 foreach ( $rows as $row ) { 1574 $size += $row['Data_length'] + $row['Index_length']; 1575 } 1576 } 1577 1578 return (int) $size; 1579 } 1580 1581 /** 1582 * Fetch the sizes of the WordPress directories: `wordpress` (ABSPATH), `plugins`, `themes`, and `uploads`. 1583 * Intended to supplement the array returned by `WP_Debug_Data::debug_data()`. 1584 * 1585 * @since 5.2.0 1586 * 1587 * @return array The sizes of the directories, also the database size and total installation size. 1588 */ 1589 public static function get_sizes() { 1590 $size_db = self::get_database_size(); 1591 $upload_dir = wp_get_upload_dir(); 1592 1593 /* 1594 * We will be using the PHP max execution time to prevent the size calculations 1595 * from causing a timeout. The default value is 30 seconds, and some 1596 * hosts do not allow you to read configuration values. 1597 */ 1598 if ( function_exists( 'ini_get' ) ) { 1599 $max_execution_time = ini_get( 'max_execution_time' ); 1600 } 1601 1602 // The max_execution_time defaults to 0 when PHP runs from cli. 1603 // We still want to limit it below. 1604 if ( empty( $max_execution_time ) ) { 1605 $max_execution_time = 30; 1606 } 1607 1608 if ( $max_execution_time > 20 ) { 1609 // If the max_execution_time is set to lower than 20 seconds, reduce it a bit to prevent 1610 // edge-case timeouts that may happen after the size loop has finished running. 1611 $max_execution_time -= 2; 1612 } 1613 1614 // Go through the various installation directories and calculate their sizes. 1615 // No trailing slashes. 1616 $paths = array( 1617 'wordpress_size' => untrailingslashit( ABSPATH ), 1618 'themes_size' => get_theme_root(), 1619 'plugins_size' => WP_PLUGIN_DIR, 1620 'uploads_size' => $upload_dir['basedir'], 1621 ); 1622 1623 $exclude = $paths; 1624 unset( $exclude['wordpress_size'] ); 1625 $exclude = array_values( $exclude ); 1626 1627 $size_total = 0; 1628 $all_sizes = array(); 1629 1630 // Loop over all the directories we want to gather the sizes for. 1631 foreach ( $paths as $name => $path ) { 1632 $dir_size = null; // Default to timeout. 1633 $results = array( 1634 'path' => $path, 1635 'raw' => 0, 1636 ); 1637 1638 if ( microtime( true ) - WP_START_TIMESTAMP < $max_execution_time ) { 1639 if ( 'wordpress_size' === $name ) { 1640 $dir_size = recurse_dirsize( $path, $exclude, $max_execution_time ); 1641 } else { 1642 $dir_size = recurse_dirsize( $path, null, $max_execution_time ); 1643 } 1644 } 1645 1646 if ( false === $dir_size ) { 1647 // Error reading. 1648 $results['size'] = __( 'The size cannot be calculated. The directory is not accessible. Usually caused by invalid permissions.' ); 1649 $results['debug'] = 'not accessible'; 1650 1651 // Stop total size calculation. 1652 $size_total = null; 1653 } elseif ( null === $dir_size ) { 1654 // Timeout. 1655 $results['size'] = __( 'The directory size calculation has timed out. Usually caused by a very large number of sub-directories and files.' ); 1656 $results['debug'] = 'timeout while calculating size'; 1657 1658 // Stop total size calculation. 1659 $size_total = null; 1660 } else { 1661 if ( null !== $size_total ) { 1662 $size_total += $dir_size; 1663 } 1664 1665 $results['raw'] = $dir_size; 1666 $results['size'] = size_format( $dir_size, 2 ); 1667 $results['debug'] = $results['size'] . " ({$dir_size} bytes)"; 1668 } 1669 1670 $all_sizes[ $name ] = $results; 1671 } 1672 1673 if ( $size_db > 0 ) { 1674 $database_size = size_format( $size_db, 2 ); 1675 1676 $all_sizes['database_size'] = array( 1677 'raw' => $size_db, 1678 'size' => $database_size, 1679 'debug' => $database_size . " ({$size_db} bytes)", 1680 ); 1681 } else { 1682 $all_sizes['database_size'] = array( 1683 'size' => __( 'Not available' ), 1684 'debug' => 'not available', 1685 ); 1686 } 1687 1688 if ( null !== $size_total && $size_db > 0 ) { 1689 $total_size = $size_total + $size_db; 1690 $total_size_mb = size_format( $total_size, 2 ); 1691 1692 $all_sizes['total_size'] = array( 1693 'raw' => $total_size, 1694 'size' => $total_size_mb, 1695 'debug' => $total_size_mb . " ({$total_size} bytes)", 1696 ); 1697 } else { 1698 $all_sizes['total_size'] = array( 1699 'size' => __( 'Total size is not available. Some errors were encountered when determining the size of your installation.' ), 1700 'debug' => 'not available', 1701 ); 1702 } 1703 1704 return $all_sizes; 1705 } 1706 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Thu Nov 21 01:00:03 2024 | Cross-referenced by PHPXref 0.7.1 |