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

Get in Touch

© 2024 Teachers Night Out. All Rights Reserved.