WordPress.org

Make WordPress Core

Ticket #22704: 22704.diff

File 22704.diff, 26.0 KB (added by dd32, 5 years ago)
  • src/wp-admin/includes/class-wp-upgrader.php

     
    166166        function install_package($args = array()) {
    167167                global $wp_filesystem, $wp_theme_directories;
    168168
    169                 $defaults = array( 'source' => '', 'destination' => '', //Please always pass these
    170                                                 'clear_destination' => false, 'clear_working' => false,
    171                                                 'abort_if_destination_exists' => true,
    172                                                 'hook_extra' => array());
     169                $defaults = array(
     170                        'source' => '', // Please always pass these
     171                        'destination' => '', // and this
     172                        'clear_destination' => false, 'clear_working' => false,
     173                        'abort_if_destination_exists' => true,
     174                        'hook_extra' => array()
     175                );
    173176
    174177                $args = wp_parse_args($args, $defaults);
    175178                extract($args);
     
    277280
    278281        function run($options) {
    279282
    280                 $defaults = array(      'package' => '', //Please always pass this.
    281                                                         'destination' => '', //And this
    282                                                         'clear_destination' => false,
    283                                                         'abort_if_destination_exists' => true, // Abort if the Destination directory exists, Pass clear_destination as false please
    284                                                         'clear_working' => true,
    285                                                         'is_multi' => false,
    286                                                         'hook_extra' => array() //Pass any extra $hook_extra args here, this will be passed to any hooked filters.
    287                                                 );
     283                $defaults = array(
     284                        'package' => '', // Please always pass this.
     285                        'destination' => '', // And this
     286                        'clear_destination' => false,
     287                        'abort_if_destination_exists' => true, // Abort if the Destination directory exists, Pass clear_destination as false please
     288                        'clear_working' => true,
     289                        'is_multi' => false,
     290                        'hook_extra' => array() // Pass any extra $hook_extra args here, this will be passed to any hooked filters.
     291                );
    288292
    289293                $options = wp_parse_args($options, $defaults);
    290294                extract($options);
     
    324328
    325329                //With the given options, this installs it to the destination directory.
    326330                $result = $this->install_package( array(
    327                                                                                         'source' => $working_dir,
    328                                                                                         'destination' => $destination,
    329                                                                                         'clear_destination' => $clear_destination,
    330                                                                                         'abort_if_destination_exists' => $abort_if_destination_exists,
    331                                                                                         'clear_working' => $clear_working,
    332                                                                                         'hook_extra' => $hook_extra
    333                                                                                 ) );
     331                        'source' => $working_dir,
     332                        'destination' => $destination,
     333                        'clear_destination' => $clear_destination,
     334                        'abort_if_destination_exists' => $abort_if_destination_exists,
     335                        'clear_working' => $clear_working,
     336                        'hook_extra' => $hook_extra
     337                ) );
     338
    334339                $this->skin->set_result($result);
    335340                if ( is_wp_error($result) ) {
    336341                        $this->skin->error($result);
     
    398403                $this->strings['process_success'] = __('Plugin installed successfully.');
    399404        }
    400405
    401         function install($package) {
     406        function install( $package, $args = array() ) {
    402407
     408                $defaults = array(
     409                        'clear_update_cache' => true,
     410                );
     411                $parsed_args = wp_parse_args( $defaults, $args );
     412
    403413                $this->init();
    404414                $this->install_strings();
    405415
    406416                add_filter('upgrader_source_selection', array(&$this, 'check_package') );
    407417
    408                 $this->run(array(
    409                                         'package' => $package,
    410                                         'destination' => WP_PLUGIN_DIR,
    411                                         'clear_destination' => false, //Do not overwrite files.
    412                                         'clear_working' => true,
    413                                         'hook_extra' => array()
    414                                         ));
     418                $this->run( array(
     419                        'package' => $package,
     420                        'destination' => WP_PLUGIN_DIR,
     421                        'clear_destination' => false, //Do not overwrite files.
     422                        'clear_working' => true,
     423                        'hook_extra' => array()
     424                ) );
    415425
    416426                remove_filter('upgrader_source_selection', array(&$this, 'check_package') );
    417427
    418428                if ( ! $this->result || is_wp_error($this->result) )
    419429                        return $this->result;
    420430
    421                 // Force refresh of plugin update information
    422                 delete_site_transient('update_plugins');
    423                 wp_cache_delete( 'plugins', 'plugins' );
     431                if ( $parsed_args['clear_update_cache'] ) {
     432                        // Force refresh of plugin update information
     433                        delete_site_transient('update_plugins');
     434                        wp_cache_delete( 'plugins', 'plugins' );
     435                }
     436
    424437                do_action( 'upgrader_process_complete', $this, array( 'action' => 'install', 'type' => 'plugin' ), $package );
    425438
    426439                return true;
    427440        }
    428441
    429         function upgrade($plugin) {
     442        function upgrade( $plugin, $args = array() ) {
    430443
     444                $defaults = array(
     445                        'clear_update_cache' => true,
     446                );
     447                $parsed_args = wp_parse_args( $defaults, $args );
     448
    431449                $this->init();
    432450                $this->upgrade_strings();
    433451
     
    447465                add_filter('upgrader_clear_destination', array(&$this, 'delete_old_plugin'), 10, 4);
    448466                //'source_selection' => array(&$this, 'source_selection'), //there's a trac ticket to move up the directory for zip's which are made a bit differently, useful for non-.org plugins.
    449467
    450                 $this->run(array(
    451                                         'package' => $r->package,
    452                                         'destination' => WP_PLUGIN_DIR,
    453                                         'clear_destination' => true,
    454                                         'clear_working' => true,
    455                                         'hook_extra' => array(
    456                                                                 'plugin' => $plugin
    457                                         )
    458                                 ));
     468                $this->run( array(
     469                        'package' => $r->package,
     470                        'destination' => WP_PLUGIN_DIR,
     471                        'clear_destination' => true,
     472                        'clear_working' => true,
     473                        'hook_extra' => array(
     474                                'plugin' => $plugin
     475                        ),
     476                ) );
    459477
    460478                // Cleanup our hooks, in case something else does a upgrade on this connection.
    461479                remove_filter('upgrader_pre_install', array(&$this, 'deactivate_plugin_before_upgrade'));
     
    464482                if ( ! $this->result || is_wp_error($this->result) )
    465483                        return $this->result;
    466484
    467                 // Force refresh of plugin update information
    468                 delete_site_transient('update_plugins');
    469                 wp_cache_delete( 'plugins', 'plugins' );
     485                if ( $parsed_args['clear_update_cache'] ) {
     486                        // Force refresh of plugin update information
     487                        delete_site_transient('update_plugins');
     488                        wp_cache_delete( 'plugins', 'plugins' );
     489                }
     490
    470491                do_action( 'upgrader_process_complete', $this, array( 'action' => 'update', 'type' => 'plugin' ), $plugin );
    471492
    472493                return true;
    473494        }
    474495
    475         function bulk_upgrade($plugins) {
     496        function bulk_upgrade( $plugins, $args = array() ) {
    476497
     498                $defaults = array(
     499                        'clear_update_cache' => true,
     500                );
     501                $parsed_args = wp_parse_args( $defaults, $args );
     502
    477503                $this->init();
    478504                $this->bulk = true;
    479505                $this->upgrade_strings();
     
    525551
    526552                        $this->skin->plugin_active = is_plugin_active($plugin);
    527553
    528                         $result = $this->run(array(
    529                                                 'package' => $r->package,
    530                                                 'destination' => WP_PLUGIN_DIR,
    531                                                 'clear_destination' => true,
    532                                                 'clear_working' => true,
    533                                                 'is_multi' => true,
    534                                                 'hook_extra' => array(
    535                                                                         'plugin' => $plugin
    536                                                 )
    537                                         ));
     554                        $result = $this->run( array(
     555                                'package' => $r->package,
     556                                'destination' => WP_PLUGIN_DIR,
     557                                'clear_destination' => true,
     558                                'clear_working' => true,
     559                                'is_multi' => true,
     560                                'hook_extra' => array(
     561                                        'plugin' => $plugin
     562                                )
     563                        ) );
    538564
    539565                        $results[$plugin] = $this->result;
    540566
     
    552578                // Cleanup our hooks, in case something else does a upgrade on this connection.
    553579                remove_filter('upgrader_clear_destination', array(&$this, 'delete_old_plugin'));
    554580
    555                 // Force refresh of plugin update information
    556                 delete_site_transient('update_plugins');
    557                 wp_cache_delete( 'plugins', 'plugins' );
     581                if ( $parsed_args['clear_update_cache'] ) {
     582                        // Force refresh of plugin update information
     583                        delete_site_transient('update_plugins');
     584                        wp_cache_delete( 'plugins', 'plugins' );
     585                }
     586
    558587                do_action( 'upgrader_process_complete', $this, array( 'action' => 'update', 'type' => 'plugin', 'bulk' => true ), $plugins );
    559588
    560589                return $results;
     
    755784                return $actions;
    756785        }
    757786
    758         function install($package) {
     787        function install( $package, $args = array() ) {
    759788
     789                $defaults = array(
     790                        'clear_update_cache' => true,
     791                );
     792                $parsed_args = wp_parse_args( $defaults, $args );
     793
    760794                $this->init();
    761795                $this->install_strings();
    762796
    763797                add_filter('upgrader_source_selection', array(&$this, 'check_package') );
    764798                add_filter('upgrader_post_install', array(&$this, 'check_parent_theme_filter'), 10, 3);
    765799
    766                 $options = array(
     800                $this->run( array(
    767801                        'package' => $package,
    768802                        'destination' => get_theme_root(),
    769803                        'clear_destination' => false, //Do not overwrite files.
    770804                        'clear_working' => true
    771                 );
     805                ) );
    772806
    773                 $this->run($options);
    774 
    775807                remove_filter('upgrader_source_selection', array(&$this, 'check_package') );
    776808                remove_filter('upgrader_post_install', array(&$this, 'check_parent_theme_filter'));
    777809
    778810                if ( ! $this->result || is_wp_error($this->result) )
    779811                        return $this->result;
    780812
    781                 // Force refresh of theme update information
    782                 wp_clean_themes_cache();
     813                if ( $parsed_args['clear_update_cache'] ) {
     814                        // Force refresh of theme update information
     815                        wp_clean_themes_cache();
     816                }
     817
    783818                do_action( 'upgrader_process_complete', $this, array( 'action' => 'install', 'type' => 'theme' ), $package );
    784819
    785820                return true;
    786821        }
    787822
    788         function upgrade($theme) {
     823        function upgrade( $theme, $args = array() ) {
    789824
     825                $defaults = array(
     826                        'clear_update_cache' => true,
     827                );
     828                $parsed_args = wp_parse_args( $defaults, $args );
     829
    790830                $this->init();
    791831                $this->upgrade_strings();
    792832
     
    806846                add_filter('upgrader_post_install', array(&$this, 'current_after'), 10, 2);
    807847                add_filter('upgrader_clear_destination', array(&$this, 'delete_old_theme'), 10, 4);
    808848
    809                 $options = array(
     849                $this->run( array(
    810850                        'package' => $r['package'],
    811851                        'destination' => get_theme_root( $theme ),
    812852                        'clear_destination' => true,
     
    814854                        'hook_extra' => array(
    815855                                'theme' => $theme
    816856                        ),
    817                 );
     857                ) );
    818858
    819                 $this->run($options);
    820 
    821859                remove_filter('upgrader_pre_install', array(&$this, 'current_before'));
    822860                remove_filter('upgrader_post_install', array(&$this, 'current_after'));
    823861                remove_filter('upgrader_clear_destination', array(&$this, 'delete_old_theme'));
     
    825863                if ( ! $this->result || is_wp_error($this->result) )
    826864                        return $this->result;
    827865
    828                 // Force refresh of theme update information
    829                 wp_clean_themes_cache();
     866                if ( $parsed_args['clear_update_cache'] ) {
     867                        // Force refresh of theme update information
     868                        wp_clean_themes_cache();
     869                }
    830870                do_action( 'upgrader_process_complete', $this, array( 'action' => 'update', 'type' => 'theme' ), $theme );
    831871
    832872                return true;
    833873        }
    834874
    835         function bulk_upgrade($themes) {
     875        function bulk_upgrade( $themes, $args = array() ) {
    836876
     877                $defaults = array(
     878                        'clear_update_cache' => true,
     879                );
     880                $parsed_args = wp_parse_args( $defaults, $args );
     881
    837882                $this->init();
    838883                $this->bulk = true;
    839884                $this->upgrade_strings();
     
    886931                        // Get the URL to the zip file
    887932                        $r = $current->response[ $theme ];
    888933
    889                         $options = array(
     934                        $result = $this->run( array(
    890935                                'package' => $r['package'],
    891936                                'destination' => get_theme_root( $theme ),
    892937                                'clear_destination' => true,
     
    894939                                'hook_extra' => array(
    895940                                        'theme' => $theme
    896941                                ),
    897                         );
     942                        ) );
    898943
    899                         $result = $this->run($options);
    900 
    901944                        $results[$theme] = $this->result;
    902945
    903946                        // Prevent credentials auth screen from displaying multiple times
     
    916959                remove_filter('upgrader_post_install', array(&$this, 'current_after'));
    917960                remove_filter('upgrader_clear_destination', array(&$this, 'delete_old_theme'));
    918961
    919                 // Force refresh of theme update information
    920                 wp_clean_themes_cache();
     962                if ( $parsed_args['clear_update_cache'] ) {
     963                        // Force refresh of theme update information
     964                        wp_clean_themes_cache();
     965                }
     966
    921967                do_action( 'upgrader_process_complete', $this, array( 'action' => 'update', 'type' => 'theme', 'bulk' => true ), $themes );
    922968
    923969                return $results;
     
    10381084                $this->strings['copy_failed_space'] = __('Could not copy files. You may have run out of disk space.' );
    10391085        }
    10401086
    1041         function upgrade($current) {
     1087        function upgrade( $current, $args = array() ) {
    10421088                global $wp_filesystem, $wp_version;
    10431089
     1090                $defaults = array(
     1091                );
     1092                $parsed_args = wp_parse_args( $defaults, $args );
     1093
    10441094                $this->init();
    10451095                $this->upgrade_strings();
    10461096
  • src/wp-content/mu-plugins/background-upgrader.php

     
     1<?php
     2
     3class WP_Background_Upgrader {
     4
     5        static $skin;
     6
     7        static function init() {
     8
     9                // Detect updates for Core, Plugins, and, Themes
     10                add_action( 'set_site_transient_' . 'update_core',    array( 'WP_Background_Upgrader', 'queue_updates_check_core' ) );
     11                add_action( 'set_site_transient_' . 'update_plugins', array( 'WP_Background_Upgrader', 'queue_updates_check_plugins_themes' ) );
     12                add_action( 'set_site_transient_' . 'update_themes',  array( 'WP_Background_Upgrader', 'queue_updates_check_plugins_themes' ) );
     13                // Uh.. Yeah, work around for #25213
     14                add_action( 'set_site_transient_' . '_site_transient_' . 'update_core',    array( 'WP_Background_Upgrader', 'queue_updates_check_core' ) );
     15                add_action( 'set_site_transient_' . '_site_transient_' . 'update_plugins', array( 'WP_Background_Upgrader', 'queue_updates_check_plugins_themes' ) );
     16                add_action( 'set_site_transient_' . '_site_transient_' . 'update_themes',  array( 'WP_Background_Upgrader', 'queue_updates_check_plugins_themes' ) );
     17
     18                // Cron Updates
     19                add_action( 'wp_background_upgrader_process', array( 'WP_Background_Upgrader', 'perform_queued_updates' ) );
     20
     21                // Temporary way of testing to see if the install is fataling
     22                // Used with WP_Background_Upgrader::test_if_site_is_ok()
     23                add_action( 'template_redirect', array( 'WP_Background_Upgrader','test_if_site_is_ok_callback' ) , 1 );
     24
     25        }
     26
     27        /**
     28         * Loads the WordPress Admin environment for performing the updates.
     29         * Cron runs as a front-end process
     30         */
     31        static function load_required_admin_includes() {
     32                error_reporting( E_ALL );
     33                // include ABSPATH . 'wp-admin/includes/admin.php'; // Load the whole lot of 'em
     34                include ABSPATH . 'wp-admin/includes/update.php';
     35                include ABSPATH . 'wp-admin/includes/plugin.php';
     36                include ABSPATH . 'wp-admin/includes/plugin-install.php';
     37                include ABSPATH . 'wp-admin/includes/theme.php';
     38                include ABSPATH . 'wp-admin/includes/theme-install.php';
     39                include ABSPATH . 'wp-admin/includes/file.php';
     40                include ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
     41        }
     42
     43        static function queue_updates_check_core( $updates ) {
     44
     45                if ( self::upgrader_disabled() )
     46                        return;
     47
     48                if ( ! self::find_core_auto_update() )
     49                        return;
     50
     51                if ( ! wp_next_scheduled( 'wp_background_upgrader_process' ) ) {
     52                        // If the transient update was triggered by a user pageview, update in an hours time, else, now.
     53                        // What if the user is active in an hours time and maintainence mode kicks in?
     54                        // Schedule it for $user_id_1_timezone midnight?
     55                        $when_to_update = get_current_user_id() ? time() + HOUR_IN_SECONDS : time();
     56                        $when_to_update = apply_filters( 'auto_upgrade_when_to_upgrade', $when_to_update );
     57
     58                        wp_schedule_single_event( $when_to_update, 'wp_background_upgrader_process' );
     59                }
     60        }
     61
     62        static function queue_updates_check_plugins_themes( $transient_value ) {
     63
     64                if ( self::upgrader_disabled() )
     65                        return;
     66
     67                if ( ! $transient_value || empty( $transient_value->response ) )
     68                        return;
     69
     70                if ( ! wp_next_scheduled( 'wp_auto_upgrader_upgrade_all_the_things' ) ) {
     71                        // If the transient update was triggered by a user pageview, update in an hours time, else, now.
     72                        $when_to_update = get_current_user_id() ? time() + HOUR_IN_SECONDS : time();
     73                        $when_to_update = apply_filters( 'auto_upgrade_when_to_upgrade', $when_to_update );
     74
     75                        wp_schedule_single_event( $when_to_update, 'wp_auto_upgrader_upgrade_all_the_things' );
     76                }
     77
     78        }
     79
     80        static function perform_queued_updates() {
     81
     82                $lock_name = 'auto_upgrader.lock';
     83                if ( get_site_transient( $lock_name ) ) {
     84                        // Test to see if it was set more than an hour ago, if so, cleanup.
     85                        if ( true || get_site_transient( $lock_name ) < ( time() - HOUR_IN_SECONDS ) )
     86                                delete_site_transient( $lock_name );
     87                        else // Recent lock
     88                                return;
     89                }
     90                // Lock upgrades for us for half an hour
     91                if ( ! set_site_transient( $lock_name, microtime( true ), HOUR_IN_SECONDS / 2 ) )
     92                        return;
     93       
     94                // Admin-ize ourselves
     95                self::load_required_admin_includes();
     96
     97                // Next, Plugins
     98                wp_update_plugins(); // Check for Plugin updates
     99                $plugin_updates = get_site_transient( 'update_plugins' );
     100                if ( $plugin_updates && !empty( $plugin_updates->response ) ) {
     101                        foreach ( array_keys( $plugin_updates->response ) as $plugin ) {
     102                                self::upgrade( 'plugin', $plugin );
     103                        }
     104                        // Force refresh of plugin update information
     105                        delete_site_transient('update_plugins');
     106                        wp_cache_delete( 'plugins', 'plugins' );
     107                }
     108
     109                // Next, those themes we all love
     110                wp_update_themes();  // Check for Theme updates
     111                $theme_updates = get_site_transient( 'update_themes' );
     112                if ( $theme_updates && !empty( $theme_updates->response ) ) {
     113                        foreach ( array_keys( $theme_updates->response ) as $theme ) {
     114                                self::upgrade( 'theme', $theme );
     115                        }
     116                        // Force refresh of theme update information
     117                        wp_clean_themes_cache();
     118                }
     119
     120                // Up first, Core.
     121                wp_version_check(); // Check for Core updates
     122                $core_update = self::find_core_auto_update();
     123                if ( $core_update )
     124                        self::upgrade( 'core', $core_update );
     125
     126                // Cleanup, These won't trigger any updates this time due to the locking transient
     127                wp_version_check();  // check for Core updates
     128                wp_update_themes();  // Check for Theme updates
     129                wp_update_plugins(); // Check for Plugin updates
     130
     131                delete_site_transient( $lock_name );
     132
     133        }
     134
     135        /**
     136         * Finds the best auto-update available for this site.
     137         * If there's 1.2.3 and 1.3 on offer, it'll choose 1.3 if the install allows it, else, 1.2.3
     138         */
     139        static function find_core_auto_update() {
     140                $updates = get_site_transient( 'update_core' );
     141                $auto_update = false;
     142                foreach ( $updates->updates as $update ) {
     143                        if ( 'autoupdate' != $update->response )
     144                                continue;
     145
     146                        if ( ! self::should_upgrade( 'core', $update, ABSPATH ) )
     147                                continue;
     148
     149                        if ( ! $auto_update || version_compare( $update->current, $auto_update->current, '>' ) )
     150                                $auto_update = $update;
     151                }
     152                return $auto_update;
     153        }
     154
     155        static function upgrader_disabled() {
     156                // That's a no if you don't want files changes
     157                if ( defined( 'DISABLE_FILE_MODS' ) && DISABLE_FILE_MODS )
     158                        return true;
     159
     160                if ( defined( 'AUTOMATIC_UPDATER_DISABLED' ) && AUTOMATIC_UPDATER_DISABLED )
     161                        return true;
     162
     163                return apply_filters( 'auto_upgrader_disabled', false );
     164        }
     165
     166        /**
     167         * Tests to see if we should upgrade a specific item, does not test to see if we CAN update the item.
     168         */
     169        static function should_upgrade( $type, $item, $context ) {
     170
     171                if ( self::upgrader_disabled() )
     172                        return false;
     173
     174                // ..and also check for GIT/SVN checkouts
     175                if ( ! apply_filters( 'auto_upgrade_ignore_checkout_status', false ) ) {
     176                        $stop_dirs = array(
     177                                ABSPATH,
     178                                untrailingslashit( $context ),
     179                        );
     180                        if ( ! file_exists( ABSPATH . '/wp-config.php' ) ) // wp-config.php up one folder in a deployment situation
     181                                $stop_dirs[] = dirname( ABSPATH );
     182                        foreach ( array_unique( $stop_dirs ) as $dir ) {
     183                                if ( file_exists( $dir . '/.svn' ) || file_exists( $dir . '/.git' ) )
     184                                        return false;
     185                        }
     186                }
     187
     188                // Next up, do we actually have it enabled for this type of update?
     189                switch ( $type ) {
     190                        default:       $upgrade = false; break;
     191                        case 'core':
     192                                $upgrade = self::should_upgrade_to_core_version( $item->current );
     193                                break;
     194                        case 'plugin': $upgrade = false; break;
     195                        case 'theme':  $upgrade = false; break;
     196                        case 'lang':   $upgrade = false; break;
     197                }
     198
     199                // And does the user / plugins want it?
     200                if ( ! apply_filters( 'auto_upgrade_' . $type, $upgrade, $item ) )
     201                        return false;
     202
     203                // If it's a core update, are we actually compatible with it?
     204                if ( 'core' == $type ) {
     205                        global $wpdb;
     206
     207                        $php_compat = version_compare( phpversion(), $item->php_version, '>=' );
     208                        if ( file_exists( WP_CONTENT_DIR . '/db.php' ) && empty( $wpdb->is_mysql ) )
     209                                $mysql_compat = true;
     210                        else
     211                                $mysql_compat = version_compare( $wpdb->db_version(), $item->mysql_version, '>=' );
     212
     213                        if ( ! $php_compat || ! $mysql_compat )
     214                                return false;
     215                }
     216
     217                // Make sure loop-back HTTP requests work, we need to be able to verify everything worked OK and to be able to upgrade the database
     218                // If this doesn't pass, chances are they don't want auto-updates anyway
     219                if ( ! self::test_if_site_is_ok() )
     220                        return false;
     221
     222                return true;
     223        }
     224
     225        // Checks to see if WP_Filesystem is setup to allow unattended upgrades
     226        static function can_upgrade( $context ) {
     227                if ( ! self::$skin )
     228                        self::$skin = new WP_Background_Upgrader_Skin();
     229                return (bool) self::$skin->request_filesystem_credentials();
     230        }
     231
     232        // Determines if this WordPress Core version should update to $offered_ver or not
     233        static function should_upgrade_to_core_version( $offered_ver /* x.y.z */ ) {
     234                include ABSPATH . WPINC . '/version.php'; // $wp_version; // x.y.z
     235
     236                $current_branch = implode( '.', array_slice( preg_split( '/[.-]/', $wp_version  ), 0, 2 ) ); // x.y
     237                $new_branch     = implode( '.', array_slice( preg_split( '/[.-]/', $offered_ver ), 0, 2 ) ); // x.y
     238                $current_is_development_version = (bool) strpos( $wp_version, '-' );
     239
     240                // Defaults:
     241                $upgrade_dev   = false;
     242                $upgrade_minor = true;
     243                $upgrade_major = false;
     244
     245                // WP_AUTO_UPDATE_CORE = true (all), 'minor', false.
     246                if ( defined( 'WP_AUTO_UPDATE_CORE' ) ) {
     247                        if ( false === WP_AUTO_UPDATE_CORE ) {
     248                                // Defaults to turned off, unless a filter allows it
     249                                $upgrade_dev = $upgrade_minor = $upgrade_major = false;
     250                        } elseif ( true === WP_AUTO_UPDATE_CORE ) {
     251                                // ALL updates for core
     252                                $upgrade_dev = $upgrade_minor = $upgrade_major = true;
     253                        } elseif ( 'minor' === WP_AUTO_UPDATE_CORE ) {
     254                                // Only minor updates for core
     255                                $upgrade_dev = $upgrade_major = false;
     256                                $upgrade_minor = true;
     257                        }
     258                }
     259
     260                // 1: If we're already on that version, not much point in updating?
     261                if ( $offered_ver == $wp_version )
     262                        return false;
     263
     264                // 2: If we're running a newer version, that's a nope
     265                if ( version_compare( $wp_version, $offered_ver, '>=' ) )
     266                        return false;
     267
     268                // 3: 3.7-alpha-25000 -> 3.7-alpha-25678 -> 3.7-beta1 -> 3.7-beta2
     269                if ( $current_is_development_version ) {
     270                        if ( ! apply_filters( 'allow_dev_background_core_updates', $upgrade_dev ) )
     271                                return false;
     272                        // else fall through to minor + major branches below
     273                }
     274
     275                // 4: Minor In-branch updates (3.7.0 -> 3.7.1 -> 3.7.2 -> 3.7.4)
     276                if ( $current_branch == $new_branch )
     277                        return apply_filters( 'allow_minor_background_core_updates', $upgrade_minor );
     278
     279                // 5: Major version updates (3.7.0 -> 3.8.0 -> 3.9.1)
     280                if ( version_compare( $new_branch, $current_branch, '>' ) )
     281                        return apply_filters( 'allow_major_background_core_updates', $upgrade_major );
     282
     283                // If we're not sure, we don't want it
     284                return false;
     285        }
     286
     287        static function upgrade( $type, $item ) {
     288
     289                wp_mail(
     290                        get_site_option( 'admin_email' ),
     291                        __METHOD__,
     292                        "Starting an upgrade for:\n\n" . var_export( compact( 'type', 'item' ), true ) . "\n\n" . wp_debug_backtrace_summary()
     293                );
     294
     295                self::$skin = new Background_Upgrader_Skin();
     296
     297                switch( $type ) {
     298                        case 'core':
     299                                // Okay, Why does the Core upgrader not use the Upgrader's skin during the actual main part of the upgrade???
     300                                add_filter( 'update_feedback', function( $message ) {
     301                                        WP_Background_Upgrader::$skin->feedback( $message );
     302                                } );
     303                                $upgrader = new Core_Upgrader( self::$skin );
     304                                $context  = ABSPATH;
     305                                break;
     306                        case 'plugin':
     307                                $upgrader = new Plugin_Upgrader( self::$skin );
     308                                $context  = WP_PLUGIN_DIR; // We don't support custom Plugin directories, or updates for WPMU_PLUGIN_DIR
     309                                break;
     310                        case 'theme':
     311                                $upgrader = new Theme_Upgrader( self::$skin );
     312                                $context  = get_theme_root( $item );
     313                                break;
     314                        case 'lang':
     315                                return false; // Not quite yet!
     316                        //      $upgrader = new Language_Upgrader( self::$skin );
     317                                $context  = WP_LANG_DIR;
     318                                break;
     319                }
     320
     321                // Determine if we can perform this upgrade or not
     322                if ( ! self::should_upgrade( $type, $item, $context )  || ! self::can_upgrade( $context ) )
     323                        return false;
     324
     325                // Boom, This sites about to get a whole new splash of paint!
     326                $upgrade_result = $upgrader->upgrade( $item, array(
     327                        'clear_update_cache' => false,
     328                ) );
     329
     330                // Core doesn't output this, so lets append it so we don't get confused
     331                if ( 'core' == $type ) {
     332                        if ( is_wp_error( $upgrade_result ) ) {
     333                                self::$skin->error( __( 'Installation Failed' ), $upgrade_result );
     334                        } else {
     335                                self::$skin->feedback( __( 'WordPress updated successfully' ) );
     336                        }
     337                }
     338
     339                var_dump( compact( 'type', 'item', 'upgrader', 'upgrade_result' ) );
     340
     341                wp_mail(
     342                        get_site_option( 'admin_email' ),
     343                        __METHOD__,
     344                        var_export( array(
     345                                $upgrade_result,
     346                                $upgrader,
     347                                self::$skin,
     348                        ), true )
     349                );
     350
     351                return $upgrade_result;
     352        }
     353
     354        static function test_if_site_is_ok() {
     355                // Is the Admin ajax handler returning what we expect of it?
     356                $http_result = wp_remote_get( admin_url( 'admin-ajax.php' ), array( 'timeout' => 10 ) );
     357                $admin_ok = ! is_wp_error( $http_result ) && ( '0' === wp_remote_retrieve_body( $http_result ) );
     358
     359                // Is the front-end returning what we'd expect of it? (Note, this is a filter on template_redirect + wp_footer outside of this class below)
     360                // This WILL break with caching plugins, Include a something that can be used to prevent the caching somehow? a GET parameter isn't enough for some caching plugins
     361                $http_result = wp_remote_get( site_url('?test-upgrade-OK=1'), array( 'timeout' => 10 ) );
     362                $front_ok = ! is_wp_error( $http_result ) && ( 'OK' === wp_remote_retrieve_body( $http_result ) );
     363
     364                return $admin_ok && $front_ok;
     365        }
     366
     367        static function test_if_site_is_ok_callback() {
     368                if ( ! isset( $_GET['test-upgrade-OK'] ) )
     369                        return;
     370
     371                ob_start();
     372                add_action( 'wp_footer', function() {
     373                        ob_end_clean();
     374                        die( 'OK' );
     375                }, 999 );
     376        }
     377
     378        // A static lifestyle is best. Go on, try it, I dare you.
     379        private function __construct() {}
     380}
     381WP_Background_Upgrader::init();