Make WordPress Core

Ticket #34878: 34878.diff

File 34878.diff, 15.4 KB (added by dd32, 9 years ago)
  • src/wp-admin/includes/class-wp-upgrader.php

    class Language_Pack_Upgrader extends WP_ 
    21562156 *
    21572157 * @since 2.8.0
    21582158 *
    21592159 * @see WP_Upgrader
    21602160 */
    21612161class Core_Upgrader extends WP_Upgrader {
    21622162
    21632163        /**
    21642164         * Initialize the upgrade strings.
    21652165         *
    21662166         * @since 2.8.0
    21672167         * @access public
    21682168         */
    21692169        public function upgrade_strings() {
    21702170                $this->strings['up_to_date'] = __('WordPress is at the latest version.');
     2171                $this->strings['locked'] = __('Another update is currently in progress.');
    21712172                $this->strings['no_package'] = __('Update package not available.');
    21722173                $this->strings['downloading_package'] = __('Downloading update from <span class="code">%s</span>&#8230;');
    21732174                $this->strings['unpack_package'] = __('Unpacking the update&#8230;');
    21742175                $this->strings['copy_failed'] = __('Could not copy files.');
    21752176                $this->strings['copy_failed_space'] = __('Could not copy files. You may have run out of disk space.' );
    21762177                $this->strings['start_rollback'] = __( 'Attempting to roll back to previous version.' );
    21772178                $this->strings['rollback_was_required'] = __( 'Due to an error during updating, WordPress has rolled back to your previous version.' );
    21782179        }
    21792180
    21802181        /**
    21812182         * Upgrade WordPress core.
    21822183         *
    21832184         * @since 2.8.0
    21842185         * @access public
    21852186         *
    class Core_Upgrader extends WP_Upgrader  
    22402241                 * the new_bundled zip. Don't though if the constant is set to skip bundled items.
    22412242                 * If the API returns a no_content zip, go with it. Finally, default to the full zip.
    22422243                 */
    22432244                if ( $parsed_args['do_rollback'] && $current->packages->rollback )
    22442245                        $to_download = 'rollback';
    22452246                elseif ( $current->packages->partial && 'reinstall' != $current->response && $wp_version == $current->partial_version && $partial )
    22462247                        $to_download = 'partial';
    22472248                elseif ( $current->packages->new_bundled && version_compare( $wp_version, $current->new_bundled, '<' )
    22482249                        && ( ! defined( 'CORE_UPGRADE_SKIP_NEW_BUNDLED' ) || ! CORE_UPGRADE_SKIP_NEW_BUNDLED ) )
    22492250                        $to_download = 'new_bundled';
    22502251                elseif ( $current->packages->no_content )
    22512252                        $to_download = 'no_content';
    22522253                else
    22532254                        $to_download = 'full';
    22542255
     2256                // Lock to prevent multiple Core Updates occuring
     2257                $lock = wp_create_lock( 'core_updater', 15 * MINUTE_IN_SECONDS );
     2258                if ( ! $lock ) {
     2259                        return new WP_Error( 'locked', $this->strings['locked'] );
     2260                }
     2261
    22552262                $download = $this->download_package( $current->packages->$to_download );
    2256                 if ( is_wp_error($download) )
     2263                if ( is_wp_error( $download ) ) {
     2264                        wp_release_lock( 'core_updater' );
    22572265                        return $download;
     2266                }
    22582267
    22592268                $working_dir = $this->unpack_package( $download );
    2260                 if ( is_wp_error($working_dir) )
     2269                if ( is_wp_error( $working_dir ) ) {
     2270                        wp_release_lock( 'core_updater' );
    22612271                        return $working_dir;
     2272                }
    22622273
    22632274                // Copy update-core.php from the new version into place.
    22642275                if ( !$wp_filesystem->copy($working_dir . '/wordpress/wp-admin/includes/update-core.php', $wp_dir . 'wp-admin/includes/update-core.php', true) ) {
    22652276                        $wp_filesystem->delete($working_dir, true);
     2277                        wp_release_lock( 'core_updater' );
    22662278                        return new WP_Error( 'copy_failed_for_update_core_file', __( 'The update cannot be installed because we will be unable to copy some files. This is usually due to inconsistent file permissions.' ), 'wp-admin/includes/update-core.php' );
    22672279                }
    22682280                $wp_filesystem->chmod($wp_dir . 'wp-admin/includes/update-core.php', FS_CHMOD_FILE);
    22692281
    22702282                require_once( ABSPATH . 'wp-admin/includes/update-core.php' );
    22712283
    2272                 if ( ! function_exists( 'update_core' ) )
     2284                if ( ! function_exists( 'update_core' ) ) {
     2285                        wp_release_lock( 'core_updater' );
    22732286                        return new WP_Error( 'copy_failed_space', $this->strings['copy_failed_space'] );
     2287                }
    22742288
    22752289                $result = update_core( $working_dir, $wp_dir );
    22762290
    22772291                // In the event of an issue, we may be able to roll back.
    22782292                if ( $parsed_args['attempt_rollback'] && $current->packages->rollback && ! $parsed_args['do_rollback'] ) {
    22792293                        $try_rollback = false;
    22802294                        if ( is_wp_error( $result ) ) {
    22812295                                $error_code = $result->get_error_code();
    22822296                                /*
    22832297                                 * Not all errors are equal. These codes are critical: copy_failed__copy_dir,
    22842298                                 * mkdir_failed__copy_dir, copy_failed__copy_dir_retry, and disk_full.
    22852299                                 * do_rollback allows for update_core() to trigger a rollback if needed.
    22862300                                 */
    22872301                                if ( false !== strpos( $error_code, 'do_rollback' ) )
    22882302                                        $try_rollback = true;
    class Core_Upgrader extends WP_Upgrader  
    23332347                                        // Was the rollback successful? If not, collect its error too.
    23342348                                        $stats['rollback'] = ! is_wp_error( $rollback_result );
    23352349                                        if ( is_wp_error( $rollback_result ) ) {
    23362350                                                $stats['rollback_code'] = $rollback_result->get_error_code();
    23372351                                                $stats['rollback_data'] = $rollback_result->get_error_data();
    23382352                                        }
    23392353                                } else {
    23402354                                        $stats['error_code'] = $result->get_error_code();
    23412355                                        $stats['error_data'] = $result->get_error_data();
    23422356                                }
    23432357                        }
    23442358
    23452359                        wp_version_check( $stats );
    23462360                }
    23472361
     2362                wp_release_lock( 'core_updater' );
     2363
    23482364                return $result;
    23492365        }
    23502366
    23512367        /**
    23522368         * Determines if this WordPress Core version should update to an offered version or not.
    23532369         *
    23542370         * @since 3.7.0
    23552371         * @access public
    23562372         *
    23572373         * @static
    23582374         *
    23592375         * @param string $offered_ver The offered version, of the format x.y.z.
    23602376         * @return bool True if we should update to the offered version, otherwise false.
    23612377         */
    23622378        public static function should_update_to_version( $offered_ver ) {
    class WP_Automatic_Updater { 
    29262942                $upgrade_result = $upgrader->upgrade( $upgrader_item, array(
    29272943                        'clear_update_cache' => false,
    29282944                        // Always use partial builds if possible for core updates.
    29292945                        'pre_check_md5'      => false,
    29302946                        // Only available for core updates.
    29312947                        'attempt_rollback'   => true,
    29322948                        // Allow relaxed file ownership in some scenarios
    29332949                        'allow_relaxed_file_ownership' => $allow_relaxed_file_ownership,
    29342950                ) );
    29352951
    29362952                // If the filesystem is unavailable, false is returned.
    29372953                if ( false === $upgrade_result ) {
    29382954                        $upgrade_result = new WP_Error( 'fs_unavailable', __( 'Could not access filesystem.' ) );
    29392955                }
    29402956
    2941                 // Core doesn't output this, so let's append it so we don't get confused.
    29422957                if ( 'core' == $type ) {
     2958                        if ( is_wp_error( $upgrade_result ) && ( 'up_to_date' == $upgrade_result->get_error_code() || 'locked' == $upgrade_result->get_error_code() ) ) {
     2959                                // These aren't actual errors, treat it as a skipped-update instead to avoid triggering the post-core update failure routines.
     2960                                return false;
     2961                        }
     2962
     2963                        // Core doesn't output this, so let's append it so we don't get confused.
    29432964                        if ( is_wp_error( $upgrade_result ) ) {
    29442965                                $skin->error( __( 'Installation Failed' ), $upgrade_result );
    29452966                        } else {
    29462967                                $skin->feedback( __( 'WordPress updated successfully' ) );
    29472968                        }
    29482969                }
    29492970
    29502971                $this->update_results[ $type ][] = (object) array(
    29512972                        'item'     => $item,
    29522973                        'result'   => $upgrade_result,
    29532974                        'name'     => $item_name,
    29542975                        'messages' => $skin->get_upgrade_messages()
    29552976                );
    29562977
    29572978                return $upgrade_result;
    class WP_Automatic_Updater { 
    29632984         * @since 3.7.0
    29642985         * @access public
    29652986         *
    29662987         * @global wpdb   $wpdb
    29672988         * @global string $wp_version
    29682989         */
    29692990        public function run() {
    29702991                global $wpdb, $wp_version;
    29712992
    29722993                if ( $this->is_disabled() )
    29732994                        return;
    29742995
    29752996                if ( ! is_main_network() || ! is_main_site() )
    29762997                        return;
    29772998
    2978                 $lock_name = 'auto_updater.lock';
    2979 
    2980                 // Try to lock
    2981                 $lock_result = $wpdb->query( $wpdb->prepare( "INSERT IGNORE INTO `$wpdb->options` ( `option_name`, `option_value`, `autoload` ) VALUES (%s, %s, 'no') /* LOCK */", $lock_name, time() ) );
    2982 
    2983                 if ( ! $lock_result ) {
    2984                         $lock_result = get_option( $lock_name );
    2985 
    2986                         // If we couldn't create a lock, and there isn't a lock, bail
    2987                         if ( ! $lock_result )
    2988                                 return;
    2989 
    2990                         // Check to see if the lock is still valid
    2991                         if ( $lock_result > ( time() - HOUR_IN_SECONDS ) )
    2992                                 return;
    2993                 }
    2994 
    2995                 // Update the lock, as by this point we've definitely got a lock, just need to fire the actions
    2996                 update_option( $lock_name, time() );
     2999                if ( ! wp_create_lock( 'auto_updater' ) )
     3000                        return;
    29973001
    29983002                // Don't automatically run these thins, as we'll handle it ourselves
    29993003                remove_action( 'upgrader_process_complete', array( 'Language_Pack_Upgrader', 'async_upgrade' ), 20 );
    30003004                remove_action( 'upgrader_process_complete', 'wp_version_check' );
    30013005                remove_action( 'upgrader_process_complete', 'wp_update_plugins' );
    30023006                remove_action( 'upgrader_process_complete', 'wp_update_themes' );
    30033007
    30043008                // Next, Plugins
    30053009                wp_update_plugins(); // Check for Plugin updates
    30063010                $plugin_updates = get_site_transient( 'update_plugins' );
    30073011                if ( $plugin_updates && !empty( $plugin_updates->response ) ) {
    30083012                        foreach ( $plugin_updates->response as $plugin ) {
    30093013                                $this->update( 'plugin', $plugin );
    30103014                        }
    30113015                        // Force refresh of plugin update information
    class WP_Automatic_Updater { 
    30803084                                $this->send_debug_email();
    30813085
    30823086                        if ( ! empty( $this->update_results['core'] ) )
    30833087                                $this->after_core_update( $this->update_results['core'][0] );
    30843088
    30853089                        /**
    30863090                         * Fires after all automatic updates have run.
    30873091                         *
    30883092                         * @since 3.8.0
    30893093                         *
    30903094                         * @param array $update_results The results of all attempted updates.
    30913095                         */
    30923096                        do_action( 'automatic_updates_complete', $this->update_results );
    30933097                }
    30943098
    3095                 // Clear the lock
    3096                 delete_option( $lock_name );
     3099                wp_release_lock( 'core_updater' );
    30973100        }
    30983101
    30993102        /**
    31003103         * If we tried to perform a core update, check if we should send an email,
    31013104         * and if we need to avoid processing future updates.
    31023105         *
    31033106         * @since Unknown
    31043107         * @access protected
    31053108         *
    31063109         * @global string $wp_version
    31073110         *
    31083111         * @param object|WP_Error $update_result The result of the core update. Includes the update offer and result.
    31093112         */
    31103113        protected function after_core_update( $update_result ) {
    31113114                global $wp_version;
    class WP_Automatic_Updater { 
    31513154                        return;
    31523155                }
    31533156
    31543157                /*
    31553158                 * Any other WP_Error code (like download_failed or files_not_writable) occurs before
    31563159                 * we tried to copy over core files. Thus, the failures are early and graceful.
    31573160                 *
    31583161                 * We should avoid trying to perform a background update again for the same version.
    31593162                 * But we can try again if another version is released.
    31603163                 *
    31613164                 * For certain 'transient' failures, like download_failed, we should allow retries.
    31623165                 * In fact, let's schedule a special update for an hour from now. (It's possible
    31633166                 * the issue could actually be on WordPress.org's side.) If that one fails, then email.
    31643167                 */
    31653168                $send = true;
    3166                 $transient_failures = array( 'incompatible_archive', 'download_failed', 'insane_distro' );
     3169                $transient_failures = array( 'incompatible_archive', 'download_failed', 'insane_distro', 'locked' );
    31673170                if ( in_array( $error_code, $transient_failures ) && ! get_site_option( 'auto_core_update_failed' ) ) {
    31683171                        wp_schedule_single_event( time() + HOUR_IN_SECONDS, 'wp_maybe_auto_update' );
    31693172                        $send = false;
    31703173                }
    31713174
    31723175                $n = get_site_option( 'auto_core_update_notified' );
    31733176                // Don't notify if we've already notified the same email address of the same version of the same notification type.
    31743177                if ( $n && 'fail' == $n['type'] && $n['email'] == get_site_option( 'admin_email' ) && $n['version'] == $core_update->current )
    31753178                        $send = false;
    31763179
    31773180                update_site_option( 'auto_core_update_failed', array(
    31783181                        'attempted'  => $core_update->current,
    31793182                        'current'    => $wp_version,
    31803183                        'error_code' => $error_code,
    31813184                        'error_data' => $result->get_error_data(),
  • src/wp-admin/update-core.php

    function do_core_upgrade( $reinstall = f 
    472472                return;
    473473        }
    474474
    475475        if ( $reinstall )
    476476                $update->response = 'reinstall';
    477477
    478478        add_filter( 'update_feedback', 'show_message' );
    479479
    480480        $upgrader = new Core_Upgrader();
    481481        $result = $upgrader->upgrade( $update, array(
    482482                'allow_relaxed_file_ownership' => $allow_relaxed_file_ownership
    483483        ) );
    484484
    485485        if ( is_wp_error($result) ) {
    486486                show_message($result);
    487                 if ('up_to_date' != $result->get_error_code() )
     487                if ( 'up_to_date' != $result->get_error_code() && 'locked' != $result->get_error_code() )
    488488                        show_message( __('Installation Failed') );
    489489                echo '</div>';
    490490                return;
    491491        }
    492492
    493493        show_message( __('WordPress updated successfully') );
    494494        show_message( '<span class="hide-if-no-js">' . sprintf( __( 'Welcome to WordPress %1$s. You will be redirected to the About WordPress screen. If not, click <a href="%2$s">here</a>.' ), $result, esc_url( self_admin_url( 'about.php?updated' ) ) ) . '</span>' );
    495495        show_message( '<span class="hide-if-js">' . sprintf( __( 'Welcome to WordPress %1$s. <a href="%2$s">Learn more</a>.' ), $result, esc_url( self_admin_url( 'about.php?updated' ) ) ) . '</span>' );
    496496        ?>
    497497        </div>
    498498        <script type="text/javascript">
    499499        window.location = '<?php echo self_admin_url( 'about.php?updated' ); ?>';
    500500        </script>
    501501        <?php
    502502}
  • src/wp-includes/option.php

    function set_site_transient( $transient, 
    16671667                do_action( 'set_site_transient_' . $transient, $value, $expiration, $transient );
    16681668
    16691669                /**
    16701670                 * Fires after the value for a site transient has been set.
    16711671                 *
    16721672                 * @since 3.0.0
    16731673                 *
    16741674                 * @param string $transient  The name of the site transient.
    16751675                 * @param mixed  $value      Site transient value.
    16761676                 * @param int    $expiration Time until expiration in seconds.
    16771677                 */
    16781678                do_action( 'setted_site_transient', $transient, $value, $expiration );
    16791679        }
    16801680        return $result;
    16811681}
     1682
     1683/**
     1684 * Create a Lock using WordPress options.
     1685 *
     1686 * @since 4.5.0
     1687 * @param $lock_name       string The name of this unique lock.
     1688 * @param $release_timeout int    The duration in seconds to respect an existing lock. Default: 1 hour.
     1689 * @return bool
     1690 */
     1691function wp_create_lock( $lock_name, $release_timeout = null ) {
     1692        global $wpdb;
     1693        if ( ! $release_timeout ) {
     1694                $release_timeout = HOUR_IN_SECONDS;
     1695        }
     1696        /**
     1697         * Filter doc TODO
     1698         */
     1699        if ( null !== ( $result = apply_filters( 'create_lock', null, $lock_name, $release_timeout ) ) ) {
     1700                return $reslt;
     1701        }
     1702
     1703        $lock_option = $lock_name . '.lock';
     1704
     1705        // Try to lock
     1706        $lock_result = $wpdb->query( $wpdb->prepare( "INSERT IGNORE INTO `$wpdb->options` ( `option_name`, `option_value`, `autoload` ) VALUES (%s, %s, 'no') /* LOCK */", $lock_option, time() ) );
     1707
     1708        if ( ! $lock_result ) {
     1709                $lock_result = get_option( $lock_option );
     1710       
     1711                // If we couldn't create a lock, and there isn't a lock, bail
     1712                if ( ! $lock_result ) {
     1713                        return false;
     1714                }
     1715       
     1716                // Check to see if the lock is still valid
     1717                if ( $lock_result > ( time() - $release_timeout ) ) {
     1718                        return false;
     1719                }
     1720
     1721                // There must exist an expired lock, clear it and re-gain it.
     1722                wp_release_lock( $lock_name );
     1723
     1724                return wp_create_lock( $lock_name, $release_timeout );
     1725        }
     1726
     1727        // Update the lock, as by this point we've definitely got a lock, just need to fire the actions
     1728        update_option( $lock_option, time() );
     1729
     1730        return true;
     1731}
     1732
     1733/**
     1734 * Release a lock created by `wp_create_lock()`
     1735 *
     1736 * @since 4.5.0
     1737 * @param $lock_name string The name of this unique lock.
     1738 * @return bool
     1739 */
     1740function wp_release_lock( $lock_name ) {
     1741        /**
     1742         * Filter doc TODO
     1743         */
     1744        if ( null !== ( $result = apply_filters( 'release_lock', null, $lock_name ) ) ) {
     1745                return $reslt;
     1746        }
     1747        $lock_option = $lock_name . '.lock';
     1748        return delete_option( $lock_option );
     1749}
     1750 No newline at end of file