WordPress.org

Make WordPress Core

Changeset 45176


Ignore:
Timestamp:
04/12/2019 07:23:13 PM (5 months ago)
Author:
azaozz
Message:

Site health: Load the "Info" tab immediately and notify the user while gathering site data. Changes the Info tab to work similarly to the Status tab: it does separate request to fetch the directories sizes and doesn't "block" the loading of the page.

Props xkon, afercia, Clorith, azaozz.
See #46707.

Location:
trunk/src
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/js/_enqueues/admin/site-health.js

    r45071 r45176  
    1010
    1111    var data;
    12 
    1312    var clipboard = new ClipboardJS( '.site-health-copy-buttons .copy-button' );
     13    var isDebugTab = $( '.health-check-body.health-check-debug-tab' ).length;
    1414
    1515    // Debug information copy section.
     
    119119        $progressCount.text( val + '%' );
    120120
    121         $.post(
    122             ajaxurl,
    123             {
    124                 'action': 'health-check-site-status-result',
    125                 '_wpnonce': SiteHealth.nonce.site_status_result,
    126                 'counts': SiteHealth.site_status.issues
    127             }
    128         );
    129 
    130         wp.a11y.speak( SiteHealth.string.site_health_complete_screen_reader.replace( '%s', val + '%' ) );
     121        if ( ! isDebugTab ) {
     122            $.post(
     123                ajaxurl,
     124                {
     125                    'action': 'health-check-site-status-result',
     126                    '_wpnonce': SiteHealth.nonce.site_status_result,
     127                    'counts': SiteHealth.site_status.issues
     128                }
     129            );
     130
     131            wp.a11y.speak( SiteHealth.string.site_health_complete_screen_reader.replace( '%s', val + '%' ) );
     132        }
    131133    }
    132134
     
    172174    }
    173175
    174     if ( 'undefined' !== typeof SiteHealth ) {
     176    if ( 'undefined' !== typeof SiteHealth && ! isDebugTab ) {
    175177        if ( 0 === SiteHealth.site_status.direct.length && 0 === SiteHealth.site_status.async.length ) {
    176178            RecalculateProgression();
     
    210212    }
    211213
     214    function getDirectorySizes() {
     215        var data = {
     216            action: 'health-check-get-sizes',
     217            _wpnonce: SiteHealth.nonce.site_status_result
     218        };
     219
     220        var timestamp = ( new Date().getTime() );
     221
     222        // After 3 seconds announce that we're still waiting for directory sizes.
     223        var timeout = window.setTimeout( function() {
     224            wp.a11y.speak( SiteHealth.string.please_wait );
     225        }, 3000 );
     226
     227        $.post( {
     228            type: 'POST',
     229            url: ajaxurl,
     230            data: data,
     231            dataType: 'json'
     232        } ).done( function( response ) {
     233            updateDirSizes( response.data || {} );
     234        } ).always( function() {
     235            var delay = ( new Date().getTime() ) - timestamp;
     236
     237            $( '.health-check-wp-paths-sizes.spinner' ).css( 'visibility', 'hidden' );
     238            RecalculateProgression();
     239
     240            if ( delay > 3000  ) {
     241                // We have announced that we're waiting.
     242                // Announce that we're ready after giving at least 3 seconds for the first announcement
     243                // to be read out, or the two may collide.
     244                if ( delay > 6000 ) {
     245                    delay = 0;
     246                } else {
     247                    delay = 6500 - delay;
     248                }
     249
     250                window.setTimeout( function() {
     251                    wp.a11y.speak( SiteHealth.string.site_health_complete );
     252                }, delay );
     253            } else {
     254                // Cancel the announcement.
     255                window.clearTimeout( timeout );
     256            }
     257        } );
     258    }
     259
     260    function updateDirSizes( data ) {
     261        var copyButton = $( 'button.button.copy-button' );
     262        var clipdoardText = copyButton.attr( 'data-clipboard-text' );
     263
     264        $.each( data, function( name, value ) {
     265            var text = value.debug || value.size;
     266
     267            if ( typeof text !== 'undefined' ) {
     268                clipdoardText = clipdoardText.replace( name + ': not calculated', name + ': ' + text );
     269            }
     270        } );
     271
     272        copyButton.attr( 'data-clipboard-text', clipdoardText );
     273
     274        $( '#health-check-accordion-block-wp-paths-sizes' ).find( 'td[class]' ).each( function( i, element ) {
     275            var td = $( element );
     276            var name = td.attr( 'class' );
     277
     278            if ( data.hasOwnProperty( name ) && data[ name ].size ) {
     279                td.text( data[ name ].size );
     280            }
     281        } );
     282    }
     283
     284    if ( isDebugTab ) {
     285        getDirectorySizes();
     286    }
    212287} );
  • trunk/src/wp-admin/admin-ajax.php

    r44986 r45176  
    137137    'health-check-background-updates',
    138138    'health-check-loopback-requests',
     139    'health-check-get-sizes',
    139140);
    140141
  • trunk/src/wp-admin/css/site-health.css

    r45170 r45176  
    378378}
    379379
     380.health-check-wp-paths-sizes.spinner {
     381    position: absolute;
     382    visibility: visible;
     383    float: none;
     384    margin: 0 4px;
     385}
     386
    380387@media screen and (max-width: 782px) {
    381388    .health-check-body {
  • trunk/src/wp-admin/includes/ajax-actions.php

    r45034 r45176  
    49594959    wp_send_json_success();
    49604960}
     4961
     4962/**
     4963 * Ajax handler for site health check to get directories and database sizes.
     4964 *
     4965 * @since 5.2.0
     4966 */
     4967function wp_ajax_health_check_get_sizes() {
     4968    check_ajax_referer( 'health-check-site-status-result' );
     4969
     4970    if ( ! current_user_can( 'install_plugins' ) ) {
     4971        wp_send_json_error();
     4972    }
     4973
     4974    if ( ! class_exists( 'WP_Debug_Data' ) ) {
     4975        require_once( ABSPATH . 'wp-admin/includes/class-wp-debug-data.php' );
     4976    }
     4977
     4978    $sizes_data = WP_Debug_Data::get_sizes();
     4979    $all_sizes  = array();
     4980
     4981    foreach ( $sizes_data as $name => $value ) {
     4982        $name = sanitize_text_field( $name );
     4983        $data = array();
     4984
     4985        if ( isset( $value['size'] ) ) {
     4986            if ( is_string( $value['size'] ) ) {
     4987                $data['size'] = sanitize_text_field( $value['size'] );
     4988            } else {
     4989                $data['size'] = (int) $value['size'];
     4990            }
     4991        }
     4992
     4993        if ( isset( $value['debug'] ) ) {
     4994            if ( is_string( $value['debug'] ) ) {
     4995                $data['debug'] = sanitize_text_field( $value['debug'] );
     4996            } else {
     4997                $data['debug'] = (int) $value['debug'];
     4998            }
     4999        }
     5000
     5001        $all_sizes[ $name ] = $data;
     5002    }
     5003
     5004    if ( isset( $all_sizes['total_size']['debug'] ) && 'not available' === $all_sizes['total_size']['debug'] ) {
     5005        wp_send_json_error( $all_sizes );
     5006    }
     5007
     5008    wp_send_json_success( $all_sizes );
     5009}
  • trunk/src/wp-admin/includes/class-wp-debug-data.php

    r45171 r45176  
    388388        }
    389389
    390         $size_db = WP_Debug_Data::get_database_size();
    391 
    392         /*
    393          * We will be using the PHP max execution time to prevent the size calculations
    394          * from causing a timeout. The default value is 30 seconds, and some
    395          * hosts do not allow you to read configuration values.
    396          */
    397         if ( function_exists( 'ini_get' ) ) {
    398             $max_execution_time = ini_get( 'max_execution_time' );
    399         }
    400 
    401         // The max_execution_time defaults to 0 when PHP runs from cli.
    402         // We still want to limit it below.
    403         if ( empty( $max_execution_time ) ) {
    404             $max_execution_time = 30;
    405         }
    406 
    407         // Here 20 seconds is a "sensible default" for how long to make the user wait for the directory size calculation.
    408         // When testing 20 seconds seem enough in nearly all cases. The remaining edge cases are likely testing or development sites
    409         // that have very large number of files, for example `node_modules` in plugins or themes, etc.
    410         if ( $max_execution_time > 20 ) {
    411             $max_execution_time = 20;
    412         } elseif ( $max_execution_time > 10 ) {
    413             // If the max_execution_time is set to lower than 20 seconds, reduce it a bit to prevent
    414             // edge-case timeouts that may happen after the size loop has finished running.
    415             $max_execution_time -= 1;
    416         }
    417 
    418         // Go through the various installation directories and calculate their sizes.
    419         $size_directories = array(
    420             'wordpress' => array(
    421                 'path' => ABSPATH,
    422                 'size' => 0,
    423             ),
    424             'themes'    => array(
    425                 'path' => trailingslashit( get_theme_root() ),
    426                 'size' => 0,
    427             ),
    428             'plugins'   => array(
    429                 'path' => trailingslashit( WP_PLUGIN_DIR ),
    430                 'size' => 0,
    431             ),
    432             'uploads'   => array(
    433                 'path' => $upload_dir['basedir'],
    434                 'size' => 0,
    435             ),
    436         );
    437 
    438         $size_total = 0;
    439 
    440         // Loop over all the directories we want to gather the sizes for.
    441         foreach ( $size_directories as $size => $attributes ) {
    442             $dir_size = null; // Default to timeout.
    443 
    444             if ( microtime( true ) - WP_START_TIMESTAMP < $max_execution_time ) {
    445                 $dir_size = get_dirsize( $attributes['path'], $max_execution_time );
    446             }
    447 
    448             if ( false === $dir_size ) {
    449                 // Error reading.
    450                 $size_directories[ $size ]['size']  = __( 'The size cannot be calculated. The directory is not accessible. Usually caused by invalid permissions.' );
    451                 $size_directories[ $size ]['debug'] = 'not accessible';
    452 
    453                 // Stop total size calculation.
    454                 $size_total = null;
    455             } elseif ( null === $dir_size ) {
    456                 // Timeout.
    457                 $size_directories[ $size ]['size']  = __( 'The directory size calculation has timed out. Usually caused by a very large number of sub-directories and files.' );
    458                 $size_directories[ $size ]['debug'] = 'timeout while calculating size';
    459 
    460                 // Stop total size calculation.
    461                 $size_total = null;
    462             } else {
    463                 $is_subdir = ( strpos( $size_directories[ $size ]['path'], ABSPATH ) === 0 );
    464 
    465                 // phpcs:ignore WordPress.WP.CapitalPDangit.Misspelled
    466                 if ( null !== $size_total && ( 'wordpress' === $size || ! $is_subdir ) ) {
    467                     $size_total += $dir_size;
    468                 }
    469 
    470                 $size_directories[ $size ]['size']  = size_format( $dir_size, 2 );
    471                 $size_directories[ $size ]['debug'] = $size_directories[ $size ]['size'];
    472             }
    473         }
    474 
    475         if ( null !== $size_total && $size_db > 0 ) {
    476             $size_total = size_format( $size_total + $size_db, 2 );
    477         } else {
    478             $size_total = 0;
    479         }
     390        $not_calculated = __( 'Not calculated' );
    480391
    481392        $info['wp-paths-sizes']['fields'] = array(
    482393            'uploads_path'       => array(
    483394                'label' => __( 'Uploads Directory Location' ),
    484                 'value' => $size_directories['uploads']['path'],
     395                'value' => $upload_dir['basedir'],
    485396            ),
    486397            'uploads_size'       => array(
    487398                'label' => __( 'Uploads Directory Size' ),
    488                 'value' => $size_directories['uploads']['size'],
    489                 'debug' => $size_directories['uploads']['debug'],
     399                'value' => $not_calculated,
     400                'debug' => 'not calculated',
    490401            ),
    491402            'themes_path'        => array(
    492403                'label' => __( 'Themes Directory Location' ),
    493                 'value' => $size_directories['themes']['path'],
     404                'value' => trailingslashit( get_theme_root() ),
    494405            ),
    495406            'current_theme_path' => array(
     
    499410            'themes_size'        => array(
    500411                'label' => __( 'Themes Directory Size' ),
    501                 'value' => $size_directories['themes']['size'],
    502                 'debug' => $size_directories['themes']['debug'],
     412                'value' => $not_calculated,
     413                'debug' => 'not calculated',
    503414            ),
    504415            'plugins_path'       => array(
    505416                'label' => __( 'Plugins Directory Location' ),
    506                 'value' => $size_directories['plugins']['path'],
     417                'value' => trailingslashit( WP_PLUGIN_DIR ),
    507418            ),
    508419            'plugins_size'       => array(
    509420                'label' => __( 'Plugins Directory Size' ),
    510                 'value' => $size_directories['plugins']['size'],
    511                 'debug' => $size_directories['plugins']['debug'],
     421                'value' => $not_calculated,
     422                'debug' => 'not calculated',
    512423            ),
    513424            'wordpress_path'     => array(
    514425                'label' => __( 'WordPress Directory Location' ),
    515                 'value' => $size_directories['wordpress']['path'],
     426                'value' => ABSPATH,
    516427            ),
    517428            'wordpress_size'     => array(
    518429                'label' => __( 'WordPress Directory Size' ),
    519                 'value' => $size_directories['wordpress']['size'],
    520                 'debug' => $size_directories['wordpress']['debug'],
     430                'value' => $not_calculated,
     431                'debug' => 'not calculated',
    521432            ),
    522433            'database_size'      => array(
    523434                'label' => __( 'Database size' ),
    524                 'value' => size_format( $size_db, 2 ),
     435                'value' => $not_calculated,
     436                'debug' => 'not calculated',
    525437            ),
    526438            'total_size'         => array(
    527439                'label' => __( 'Total installation size' ),
    528                 'value' => $size_total > 0 ? $size_total : __( 'Total size is not available. Some errors were encountered when determining the size of your installation.' ),
    529                 'debug' => $size_total > 0 ? $size_total : 'not available',
     440                'value' => $not_calculated,
     441                'debug' => 'not calculated',
    530442            ),
    531443        );
     
    11891101        return (int) $size;
    11901102    }
     1103
     1104    /**
     1105     * Fetch the sizes of the WordPress directories: `wordpress` (ABSPATH), `plugins`, `themes`, and `uploads`.
     1106     * Intended to supplement the array returned by `WP_Debug_Data::debug_data()`.
     1107     *
     1108     * @since 5.2.0
     1109     *
     1110     * @return array The sizes of the directories, also the database size and total installation size.
     1111     */
     1112    public static function get_sizes() {
     1113        $size_db    = self::get_database_size();
     1114        $upload_dir = wp_get_upload_dir();
     1115
     1116        /*
     1117         * We will be using the PHP max execution time to prevent the size calculations
     1118         * from causing a timeout. The default value is 30 seconds, and some
     1119         * hosts do not allow you to read configuration values.
     1120         */
     1121        if ( function_exists( 'ini_get' ) ) {
     1122            $max_execution_time = ini_get( 'max_execution_time' );
     1123        }
     1124
     1125        // The max_execution_time defaults to 0 when PHP runs from cli.
     1126        // We still want to limit it below.
     1127        if ( empty( $max_execution_time ) ) {
     1128            $max_execution_time = 30;
     1129        }
     1130
     1131        if ( $max_execution_time > 20 ) {
     1132            // If the max_execution_time is set to lower than 20 seconds, reduce it a bit to prevent
     1133            // edge-case timeouts that may happen after the size loop has finished running.
     1134            $max_execution_time -= 2;
     1135        }
     1136
     1137        // Go through the various installation directories and calculate their sizes.
     1138        $all_sizes = array(
     1139            'wordpress_size' => array(
     1140                'path' => ABSPATH,
     1141                'size' => 0,
     1142            ),
     1143            'themes_size'    => array(
     1144                'path' => trailingslashit( get_theme_root() ),
     1145                'size' => 0,
     1146            ),
     1147            'plugins_size'   => array(
     1148                'path' => trailingslashit( WP_PLUGIN_DIR ),
     1149                'size' => 0,
     1150            ),
     1151            'uploads_size'   => array(
     1152                'path' => $upload_dir['basedir'],
     1153                'size' => 0,
     1154            ),
     1155        );
     1156
     1157        $size_total = 0;
     1158
     1159        // Loop over all the directories we want to gather the sizes for.
     1160        foreach ( $all_sizes as $name => $attributes ) {
     1161            $dir_size = null; // Default to timeout.
     1162
     1163            if ( microtime( true ) - WP_START_TIMESTAMP < $max_execution_time ) {
     1164                $dir_size = recurse_dirsize( $attributes['path'], null, $max_execution_time );
     1165            }
     1166
     1167            if ( false === $dir_size ) {
     1168                // Error reading.
     1169                $all_sizes[ $name ]['size']  = __( 'The size cannot be calculated. The directory is not accessible. Usually caused by invalid permissions.' );
     1170                $all_sizes[ $name ]['debug'] = 'not accessible';
     1171
     1172                // Stop total size calculation.
     1173                $size_total = null;
     1174            } elseif ( null === $dir_size ) {
     1175                // Timeout.
     1176                $all_sizes[ $name ]['size']  = __( 'The directory size calculation has timed out. Usually caused by a very large number of sub-directories and files.' );
     1177                $all_sizes[ $name ]['debug'] = 'timeout while calculating size';
     1178
     1179                // Stop total size calculation.
     1180                $size_total = null;
     1181            } else {
     1182                $is_subdir = ( strpos( $attributes['path'], ABSPATH ) === 0 );
     1183
     1184                // phpcs:ignore WordPress.WP.CapitalPDangit.Misspelled
     1185                if ( null !== $size_total && ( 'wordpress_size' === $name || ! $is_subdir ) ) {
     1186                    $size_total += $dir_size;
     1187                }
     1188
     1189                $all_sizes[ $name ]['size']  = size_format( $dir_size, 2 );
     1190                $all_sizes[ $name ]['debug'] = $all_sizes[ $name ]['size'];
     1191            }
     1192        }
     1193
     1194        if ( $size_db > 0 ) {
     1195            $database_size = size_format( $size_db, 2 );
     1196
     1197            $all_sizes['database_size'] = array(
     1198                'size'  => $database_size,
     1199                'debug' => $database_size,
     1200            );
     1201        } else {
     1202            $all_sizes['database_size'] = array(
     1203                'size'  => __( 'Not available' ),
     1204                'debug' => 'not available',
     1205            );
     1206        }
     1207
     1208        if ( null !== $size_total && $size_db > 0 ) {
     1209            $total_size = size_format( $size_total + $size_db, 2 );
     1210
     1211            $all_sizes['total_size'] = array(
     1212                'size'  => $total_size,
     1213                'debug' => $total_size,
     1214            );
     1215        } else {
     1216            $all_sizes['total_size'] = array(
     1217                'size'  => __( 'Total size is not available. Some errors were encountered when determining the size of your installation.' ),
     1218                'debug' => 'not available',
     1219            );
     1220        }
     1221
     1222        return $all_sizes;
     1223    }
    11911224}
  • trunk/src/wp-admin/site-health-info.php

    r45156 r45176  
    6363</div>
    6464
    65 <div class="health-check-body hide-if-no-js">
     65<div class="health-check-body health-check-debug-tab hide-if-no-js">
    6666    <?php
     67
    6768    WP_Debug_Data::check_for_updates();
    6869
     
    9495
    9596        <?php
     97
     98        $sizes_fields = array( 'uploads_size', 'themes_size', 'plugins_size', 'wordpress_size', 'database_size', 'total_size' );
     99
    96100        foreach ( $info as $section => $details ) {
    97101            if ( ! isset( $details['fields'] ) || empty( $details['fields'] ) ) {
    98102                continue;
    99103            }
     104
    100105            ?>
    101106            <h3 class="health-check-accordion-heading">
     
    103108                    <span class="title">
    104109                        <?php echo esc_html( $details['label'] ); ?>
     110                        <?php
    105111
    106                         <?php if ( isset( $details['show_count'] ) && $details['show_count'] ) : ?>
    107                             <?php printf( '(%d)', count( $details['fields'] ) ); ?>
    108                         <?php endif; ?>
     112                        if ( isset( $details['show_count'] ) && $details['show_count'] ) {
     113                            printf( '(%d)', count( $details['fields'] ) );
     114                        }
     115
     116                        ?>
    109117                    </span>
     118                    <?php
     119
     120                    if ( 'wp-paths-sizes' === $section ) {
     121                        ?>
     122                        <span class="health-check-wp-paths-sizes spinner" title="<?php esc_attr_e( 'Calculating directory sizes. This may take a while&hellip;' ); ?>"></span>
     123                        <?php
     124                    }
     125
     126                    ?>
    110127                    <span class="icon"></span>
    111128                </button>
     
    114131            <div id="health-check-accordion-block-<?php echo esc_attr( $section ); ?>" class="health-check-accordion-panel" hidden="hidden">
    115132                <?php
     133
     134                $kses_settings = array(
     135                    'a'      => array(
     136                        'href' => true,
     137                    ),
     138                    'strong' => true,
     139                    'em'     => true,
     140                );
     141
    116142                if ( isset( $details['description'] ) && ! empty( $details['description'] ) ) {
    117                     printf(
    118                         '<p>%s</p>',
    119                         wp_kses(
    120                             $details['description'],
    121                             array(
    122                                 'a'      => array(
    123                                     'href' => true,
    124                                 ),
    125                                 'strong' => true,
    126                                 'em'     => true,
    127                             )
    128                         )
    129                     );
     143                    printf( '<p>%s</p>', wp_kses( $details['description'], $kses_settings ) );
    130144                }
     145
    131146                ?>
    132147                <table class="widefat striped health-check-table" role="presentation">
    133148                    <tbody>
    134149                    <?php
    135                     foreach ( $details['fields'] as $field ) {
     150
     151                    foreach ( $details['fields'] as $field_name => $field ) {
    136152                        if ( is_array( $field['value'] ) ) {
    137153                            $values = '<ul>';
     154
    138155                            foreach ( $field['value'] as $name => $value ) {
    139                                 $values .= sprintf(
    140                                     '<li>%s: %s</li>',
    141                                     esc_html( $name ),
    142                                     esc_html( $value )
    143                                 );
     156                                $values .= sprintf( '<li>%s: %s</li>', esc_html( $name ), esc_html( $value ) );
    144157                            }
     158
    145159                            $values .= '</ul>';
    146160                        } else {
     
    148162                        }
    149163
    150                         printf(
    151                             '<tr><td>%s</td><td>%s</td></tr>',
    152                             esc_html( $field['label'] ),
    153                             $values
    154                         );
     164                        if ( in_array( $field_name, $sizes_fields, true ) ) {
     165                            printf( '<tr><td>%s</td><td class="%s">%s</td></tr>', esc_html( $field['label'] ), esc_attr( $field_name ), $values );
     166                        } else {
     167                            printf( '<tr><td>%s</td><td>%s</td></tr>', esc_html( $field['label'] ), $values );
     168                        }
    155169                    }
     170
    156171                    ?>
    157172                    </tbody>
Note: See TracChangeset for help on using the changeset viewer.