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