Make WordPress Core


Ignore:
Timestamp:
09/15/2021 06:39:09 PM (3 years ago)
Author:
SergeyBiryukov
Message:

Upgrade/Install: Create a temporary backup of plugins and themes before updating.

This aims to make the update process more reliable and ensures that if a plugin or theme update fails, the previous version can be safely restored.

  • When updating a plugin or theme, the old version is moved to a temporary backup directory:
    • wp-content/upgrade/temp-backup/plugins/[plugin-slug] for plugins
    • wp-content/upgrade/temp-backup/themes/[theme-slug] for themes.
  • If the update fails, then the temporary backup kept in the upgrade/temp-backup directory is restored to its original location.
  • If the update succeeds, the temporary backup is deleted.

To further help troubleshoot plugin and theme updates, two new checks were added to the Site Health screen:

  • A check to make sure that the temp-backup directory is writable.
  • A check that there is enough disk space available to safely perform updates.

To avoid confusion: The temp-backup directory will NOT be used to "roll back" a plugin to a previous version after a completed update. This directory will simply contain a transient backup of the previous version of a plugin or theme being updated, and as soon as the update process finishes, the directory will be empty.

Props aristath, afragen, pbiron, dd32, poena, TimothyBlynJacobs, audrasjb, mikeschroder, a2hosting, hellofromTonya, KZeni, galbaras, richards1052, Boniu91, mai21, francina, SergeyBiryukov.
See #51857.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-admin/includes/class-wp-site-health.php

    r51805 r51815  
    18841884
    18851885    /**
     1886     * Test available disk space for updates.
     1887     *
     1888     * @since 5.9.0
     1889     *
     1890     * @return array The test results.
     1891     */
     1892    public function get_test_available_updates_disk_space() {
     1893        $available_space       = function_exists( 'disk_free_space' ) ? (int) @disk_free_space( WP_CONTENT_DIR . '/upgrade/' ) : false;
     1894        $available_space_in_mb = $available_space / MB_IN_BYTES;
     1895
     1896        $result = array(
     1897            'label'       => __( 'Disk space available to safely perform updates' ),
     1898            'status'      => 'good',
     1899            'badge'       => array(
     1900                'label' => __( 'Security' ),
     1901                'color' => 'blue',
     1902            ),
     1903            'description' => sprintf(
     1904                /* translators: %s: Available disk space in MB or GB. */
     1905                '<p>' . __( '%s available disk space was detected, update routines can be performed safely.' ),
     1906                size_format( $available_space )
     1907            ),
     1908            'actions'     => '',
     1909            'test'        => 'available_updates_disk_space',
     1910        );
     1911
     1912        if ( $available_space_in_mb < 100 ) {
     1913            $result['description'] = __( 'Available disk space is low, less than 100 MB available.' );
     1914            $result['status']      = 'recommended';
     1915        }
     1916
     1917        if ( $available_space_in_mb < 20 ) {
     1918            $result['description'] = __( 'Available disk space is critically low, less than 20 MB available. Proceed with caution, updates may fail.' );
     1919            $result['status']      = 'critical';
     1920        }
     1921
     1922        if ( ! $available_space ) {
     1923            $result['description'] = __( 'Could not determine available disk space for updates.' );
     1924            $result['status']      = 'recommended';
     1925        }
     1926
     1927        return $result;
     1928    }
     1929
     1930    /**
     1931     * Test if plugin and theme updates temp-backup directories are writable or can be created.
     1932     *
     1933     * @since 5.9.0
     1934     *
     1935     * @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass.
     1936     *
     1937     * @return array The test results.
     1938     */
     1939    public function get_test_update_temp_backup_writable() {
     1940        global $wp_filesystem;
     1941
     1942        $result = array(
     1943            'label'       => sprintf(
     1944                /* translators: %s: temp-backup */
     1945                __( 'Plugin and theme update %s directory is writable' ),
     1946                'temp-backup'
     1947            ),
     1948            'status'      => 'good',
     1949            'badge'       => array(
     1950                'label' => __( 'Security' ),
     1951                'color' => 'blue',
     1952            ),
     1953            'description' => sprintf(
     1954                /* translators: %s: wp-content/upgrade/temp-backup */
     1955                '<p>' . __( 'The %s directory used to improve the stability of plugin and theme updates is writable.' ),
     1956                '<code>wp-content/upgrade/temp-backup</code>'
     1957            ),
     1958            'actions'     => '',
     1959            'test'        => 'update_temp_backup_writable',
     1960        );
     1961
     1962        if ( ! $wp_filesystem ) {
     1963            if ( ! function_exists( 'WP_Filesystem' ) ) {
     1964                require_once wp_normalize_path( ABSPATH . '/wp-admin/includes/file.php' );
     1965            }
     1966            WP_Filesystem();
     1967        }
     1968        $wp_content = $wp_filesystem->wp_content_dir();
     1969
     1970        $upgrade_dir_exists      = $wp_filesystem->is_dir( "$wp_content/upgrade" );
     1971        $upgrade_dir_is_writable = $wp_filesystem->is_writable( "$wp_content/upgrade" );
     1972        $backup_dir_exists       = $wp_filesystem->is_dir( "$wp_content/upgrade/temp-backup" );
     1973        $backup_dir_is_writable  = $wp_filesystem->is_writable( "$wp_content/upgrade/temp-backup" );
     1974
     1975        $plugins_dir_exists      = $wp_filesystem->is_dir( "$wp_content/upgrade/temp-backup/plugins" );
     1976        $plugins_dir_is_writable = $wp_filesystem->is_writable( "$wp_content/upgrade/temp-backup/plugins" );
     1977        $themes_dir_exists       = $wp_filesystem->is_dir( "$wp_content/upgrade/temp-backup/themes" );
     1978        $themes_dir_is_writable  = $wp_filesystem->is_writable( "$wp_content/upgrade/temp-backup/themes" );
     1979
     1980        if ( $plugins_dir_exists && ! $plugins_dir_is_writable && $themes_dir_exists && ! $themes_dir_is_writable ) {
     1981            $result['status']      = 'critical';
     1982            $result['label']       = sprintf(
     1983                /* translators: %s: temp-backup */
     1984                __( 'Plugins and themes %s directories exist but are not writable' ),
     1985                'temp-backup'
     1986            );
     1987            $result['description'] = sprintf(
     1988                /* translators: 1: wp-content/upgrade/temp-backup/plugins, 2: wp-content/upgrade/temp-backup/themes. */
     1989                '<p>' . __( 'The %1$s and %2$s directories exist but are not writable. These directories are used to improve the stability of plugin updates. Please make sure the server has write permissions to these directories.' ) . '</p>',
     1990                '<code>wp-content/upgrade/temp-backup/plugins</code>',
     1991                '<code>wp-content/upgrade/temp-backup/themes</code>'
     1992            );
     1993            return $result;
     1994        }
     1995
     1996        if ( $plugins_dir_exists && ! $plugins_dir_is_writable ) {
     1997            $result['status']      = 'critical';
     1998            $result['label']       = sprintf(
     1999                /* translators: %s: temp-backup */
     2000                __( 'Plugins %s directory exists but is not writable' ),
     2001                'temp-backup'
     2002            );
     2003            $result['description'] = sprintf(
     2004                /* translators: %s: wp-content/upgrade/temp-backup/plugins */
     2005                '<p>' . __( 'The %s directory exists but is not writable. This directory is used to improve the stability of plugin updates. Please make sure the server has write permissions to this directory.' ) . '</p>',
     2006                '<code>wp-content/upgrade/temp-backup/plugins</code>'
     2007            );
     2008            return $result;
     2009        }
     2010
     2011        if ( $themes_dir_exists && ! $themes_dir_is_writable ) {
     2012            $result['status']      = 'critical';
     2013            $result['label']       = sprintf(
     2014                /* translators: %s: temp-backup */
     2015                __( 'Themes %s directory exists but is not writable' ),
     2016                'temp-backup'
     2017            );
     2018            $result['description'] = sprintf(
     2019                /* translators: %s: wp-content/upgrade/temp-backup/themes */
     2020                '<p>' . __( 'The %s directory exists but is not writable. This directory is used to improve the stability of theme updates. Please make sure the server has write permissions to this directory.' ) . '</p>',
     2021                '<code>wp-content/upgrade/temp-backup/themes</code>'
     2022            );
     2023            return $result;
     2024        }
     2025
     2026        if ( ( ! $plugins_dir_exists || ! $themes_dir_exists ) && $backup_dir_exists && ! $backup_dir_is_writable ) {
     2027            $result['status']      = 'critical';
     2028            $result['label']       = sprintf(
     2029                /* translators: %s: temp-backup */
     2030                __( 'The %s directory exists but is not writable' ),
     2031                'temp-backup'
     2032            );
     2033            $result['description'] = sprintf(
     2034                /* translators: %s: wp-content/upgrade/temp-backup */
     2035                '<p>' . __( 'The %s directory exists but is not writable. This directory is used to improve the stability of plugin and theme updates. Please make sure the server has write permissions to this directory.' ) . '</p>',
     2036                '<code>wp-content/upgrade/temp-backup</code>'
     2037            );
     2038            return $result;
     2039        }
     2040
     2041        if ( ! $backup_dir_exists && $upgrade_dir_exists && ! $upgrade_dir_is_writable ) {
     2042            $result['status']      = 'critical';
     2043            $result['label']       = sprintf(
     2044                /* translators: %s: upgrade */
     2045                __( 'The %s directory exists but is not writable' ),
     2046                'upgrade'
     2047            );
     2048            $result['description'] = sprintf(
     2049                /* translators: %s: wp-content/upgrade */
     2050                '<p>' . __( 'The %s directory exists but is not writable. This directory is used for plugin and theme updates. Please make sure the server has write permissions to this directory.' ) . '</p>',
     2051                '<code>wp-content/upgrade</code>'
     2052            );
     2053            return $result;
     2054        }
     2055
     2056        if ( ! $upgrade_dir_exists && ! $wp_filesystem->is_writable( $wp_content ) ) {
     2057            $result['status']      = 'critical';
     2058            $result['label']       = sprintf(
     2059                /* translators: %s: upgrade */
     2060                __( 'The %s directory cannot be created' ),
     2061                'upgrade'
     2062            );
     2063            $result['description'] = sprintf(
     2064                /* translators: 1: wp-content/upgrade, 2: wp-content. */
     2065                '<p>' . __( 'The %1$s directory does not exist, and the server does not have write permissions in %2$s to create it. This directory is used for plugin and theme updates. Please make sure the server has write permissions in %2$s.' ) . '</p>',
     2066                '<code>wp-content/upgrade</code>',
     2067                '<code>wp-content</code>'
     2068            );
     2069            return $result;
     2070        }
     2071
     2072        return $result;
     2073    }
     2074
     2075    /**
    18862076     * Test if loopbacks work as expected.
    18872077     *
     
    22672457        $tests = array(
    22682458            'direct' => array(
    2269                 'wordpress_version'         => array(
     2459                'wordpress_version'            => array(
    22702460                    'label' => __( 'WordPress Version' ),
    22712461                    'test'  => 'wordpress_version',
    22722462                ),
    2273                 'plugin_version'            => array(
     2463                'plugin_version'               => array(
    22742464                    'label' => __( 'Plugin Versions' ),
    22752465                    'test'  => 'plugin_version',
    22762466                ),
    2277                 'theme_version'             => array(
     2467                'theme_version'                => array(
    22782468                    'label' => __( 'Theme Versions' ),
    22792469                    'test'  => 'theme_version',
    22802470                ),
    2281                 'php_version'               => array(
     2471                'php_version'                  => array(
    22822472                    'label' => __( 'PHP Version' ),
    22832473                    'test'  => 'php_version',
    22842474                ),
    2285                 'php_extensions'            => array(
     2475                'php_extensions'               => array(
    22862476                    'label' => __( 'PHP Extensions' ),
    22872477                    'test'  => 'php_extensions',
    22882478                ),
    2289                 'php_default_timezone'      => array(
     2479                'php_default_timezone'         => array(
    22902480                    'label' => __( 'PHP Default Timezone' ),
    22912481                    'test'  => 'php_default_timezone',
    22922482                ),
    2293                 'php_sessions'              => array(
     2483                'php_sessions'                 => array(
    22942484                    'label' => __( 'PHP Sessions' ),
    22952485                    'test'  => 'php_sessions',
    22962486                ),
    2297                 'sql_server'                => array(
     2487                'sql_server'                   => array(
    22982488                    'label' => __( 'Database Server version' ),
    22992489                    'test'  => 'sql_server',
    23002490                ),
    2301                 'utf8mb4_support'           => array(
     2491                'utf8mb4_support'              => array(
    23022492                    'label' => __( 'MySQL utf8mb4 support' ),
    23032493                    'test'  => 'utf8mb4_support',
    23042494                ),
    2305                 'ssl_support'               => array(
     2495                'ssl_support'                  => array(
    23062496                    'label' => __( 'Secure communication' ),
    23072497                    'test'  => 'ssl_support',
    23082498                ),
    2309                 'scheduled_events'          => array(
     2499                'scheduled_events'             => array(
    23102500                    'label' => __( 'Scheduled events' ),
    23112501                    'test'  => 'scheduled_events',
    23122502                ),
    2313                 'http_requests'             => array(
     2503                'http_requests'                => array(
    23142504                    'label' => __( 'HTTP Requests' ),
    23152505                    'test'  => 'http_requests',
    23162506                ),
    2317                 'rest_availability'         => array(
     2507                'rest_availability'            => array(
    23182508                    'label'     => __( 'REST API availability' ),
    23192509                    'test'      => 'rest_availability',
    23202510                    'skip_cron' => true,
    23212511                ),
    2322                 'debug_enabled'             => array(
     2512                'debug_enabled'                => array(
    23232513                    'label' => __( 'Debugging enabled' ),
    23242514                    'test'  => 'is_in_debug_mode',
    23252515                ),
    2326                 'file_uploads'              => array(
     2516                'file_uploads'                 => array(
    23272517                    'label' => __( 'File uploads' ),
    23282518                    'test'  => 'file_uploads',
    23292519                ),
    2330                 'plugin_theme_auto_updates' => array(
     2520                'plugin_theme_auto_updates'    => array(
    23312521                    'label' => __( 'Plugin and theme auto-updates' ),
    23322522                    'test'  => 'plugin_theme_auto_updates',
     2523                ),
     2524                'update_temp_backup_writable'  => array(
     2525                    /* translators: %s: temp-backup */
     2526                    'label' => sprintf( __( 'Updates %s directory access' ), 'temp-backup' ),
     2527                    'test'  => 'update_temp_backup_writable',
     2528                ),
     2529                'available_updates_disk_space' => array(
     2530                    'label' => __( 'Available disk space' ),
     2531                    'test'  => 'available_updates_disk_space',
    23332532                ),
    23342533            ),
Note: See TracChangeset for help on using the changeset viewer.