Make WordPress Core

Changeset 45176


Ignore:
Timestamp:
04/12/2019 07:23:13 PM (8 years 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.