WordPress.org

Make WordPress Core

Changeset 25421


Ignore:
Timestamp:
09/13/13 06:18:16 (4 years ago)
Author:
dd32
Message:

WordPress Core Automatic Updates: Add the first slice of Automatic Upgrades, This is presently disabled, and requires a filter to enable ( 'auto_upgrade_core' ). See #22704

Location:
trunk/src
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-admin/includes/class-wp-upgrader-skins.php

    r25228 r25421  
    530530 
    531531/** 
    532  * Upgrader Skin for Background WordPress Upgrades 
     532 * Upgrader Skin for Automatic WordPress Upgrades 
    533533 * 
    534534 * This skin is designed to be used when no output is intended, all output  
     
    539539 * @since 3.7.0 
    540540 */ 
    541 class Background_Upgrader_Skin extends WP_Upgrader_Skin { 
     541class Automatic_Upgrader_Skin extends WP_Upgrader_Skin { 
    542542    var $messages = array(); 
    543543 
  • trunk/src/wp-admin/includes/class-wp-upgrader.php

    r25370 r25421  
    11381138    } 
    11391139 
     1140    // Determines if this WordPress Core version should update to $offered_ver or not 
     1141    static function should_upgrade_to_version( $offered_ver /* x.y.z */ ) { 
     1142        include ABSPATH . WPINC . '/version.php'; // $wp_version; // x.y.z 
     1143 
     1144        $current_branch = implode( '.', array_slice( preg_split( '/[.-]/', $wp_version  ), 0, 2 ) ); // x.y 
     1145        $new_branch     = implode( '.', array_slice( preg_split( '/[.-]/', $offered_ver ), 0, 2 ) ); // x.y 
     1146        $current_is_development_version = (bool) strpos( $wp_version, '-' ); 
     1147 
     1148        // Defaults: 
     1149        $upgrade_dev   = false; 
     1150        $upgrade_minor = false; // @TODO: Update for release by toggling to true. 
     1151        $upgrade_major = false; 
     1152 
     1153        // WP_AUTO_UPDATE_CORE = true (all), 'minor', false. 
     1154        if ( defined( 'WP_AUTO_UPDATE_CORE' ) ) { 
     1155            if ( false === WP_AUTO_UPDATE_CORE ) { 
     1156                // Defaults to turned off, unless a filter allows it 
     1157                $upgrade_dev = $upgrade_minor = $upgrade_major = false; 
     1158            } elseif ( true === WP_AUTO_UPDATE_CORE ) { 
     1159                // ALL updates for core 
     1160                $upgrade_dev = $upgrade_minor = $upgrade_major = true; 
     1161            } elseif ( 'minor' === WP_AUTO_UPDATE_CORE ) { 
     1162                // Only minor updates for core 
     1163                $upgrade_dev = $upgrade_major = false; 
     1164                $upgrade_minor = true; 
     1165            } 
     1166        } 
     1167 
     1168        // 1: If we're already on that version, not much point in updating? 
     1169        if ( $offered_ver == $wp_version ) 
     1170            return false; 
     1171 
     1172        // 2: If we're running a newer version, that's a nope 
     1173        if ( version_compare( $wp_version, $offered_ver, '>=' ) ) 
     1174            return false; 
     1175 
     1176        // 3: 3.7-alpha-25000 -> 3.7-alpha-25678 -> 3.7-beta1 -> 3.7-beta2 
     1177        if ( $current_is_development_version ) { 
     1178            if ( ! apply_filters( 'allow_dev_auto_core_updates', $upgrade_dev ) ) 
     1179                return false; 
     1180            // else fall through to minor + major branches below 
     1181        } 
     1182 
     1183        // 4: Minor In-branch updates (3.7.0 -> 3.7.1 -> 3.7.2 -> 3.7.4) 
     1184        if ( $current_branch == $new_branch ) 
     1185            return apply_filters( 'allow_minor_auto_core_updates', $upgrade_minor ); 
     1186 
     1187        // 5: Major version updates (3.7.0 -> 3.8.0 -> 3.9.1) 
     1188        if ( version_compare( $new_branch, $current_branch, '>' ) ) 
     1189            return apply_filters( 'allow_major_auto_core_updates', $upgrade_major ); 
     1190 
     1191        // If we're not sure, we don't want it 
     1192        return false; 
     1193    } 
     1194 
    11401195} 
    11411196 
     
    12131268    } 
    12141269} 
     1270 
     1271/** 
     1272 * WordPress Automatic Upgrader helper class 
     1273 * 
     1274 * @since 3.7.0 
     1275 */ 
     1276class WP_Automatic_Upgrader { 
     1277 
     1278    static $skin; 
     1279 
     1280    static function upgrader_disabled() { 
     1281        // That's a no if you don't want files changes 
     1282        if ( defined( 'DISABLE_FILE_MODS' ) && DISABLE_FILE_MODS ) 
     1283            return true; 
     1284 
     1285        // More fine grained control can be done through the WP_AUTO_UPDATE_CORE constant and filters 
     1286        if ( defined( 'AUTOMATIC_UPDATER_DISABLED' ) && AUTOMATIC_UPDATER_DISABLED ) 
     1287            return true; 
     1288 
     1289        if ( defined( 'WP_INSTALLING' ) ) 
     1290            return true; 
     1291 
     1292        return apply_filters( 'auto_upgrader_disabled', false ); 
     1293    } 
     1294 
     1295    /** 
     1296     * Tests to see if we should upgrade a specific item, does not test to see if we CAN update the item. 
     1297     */ 
     1298    static function should_auto_update( $type, $item, $context ) { 
     1299 
     1300        if ( self::upgrader_disabled() ) 
     1301            return false; 
     1302 
     1303        // ..and also check for GIT/SVN checkouts 
     1304        if ( ! apply_filters( 'auto_upgrade_ignore_checkout_status', false ) ) { 
     1305            $stop_dirs = array( 
     1306                ABSPATH, 
     1307                untrailingslashit( $context ), 
     1308            ); 
     1309            if ( ! file_exists( ABSPATH . '/wp-config.php' ) ) // wp-config.php up one folder in a deployment situation 
     1310                $stop_dirs[] = dirname( ABSPATH ); 
     1311            foreach ( array_unique( $stop_dirs ) as $dir ) { 
     1312                if ( file_exists( $dir . '/.svn' ) || file_exists( $dir . '/.git' ) ) 
     1313                    return false; 
     1314            } 
     1315        } 
     1316 
     1317        // Next up, do we actually have it enabled for this type of update? 
     1318        switch ( $type ) { 
     1319            case 'core': 
     1320                $upgrade = Core_Upgrader::should_upgrade_to_version( $item->current ); 
     1321                break; 
     1322            default: 
     1323            case 'plugin': 
     1324            case 'theme': 
     1325                $upgrade = false; 
     1326                break; 
     1327        } 
     1328 
     1329        // And does the user / plugins want it? 
     1330        // Plugins may filter on 'auto_upgrade_plugin', and check the 2nd param, $item, to only enable it for certain Plugins/Themes 
     1331        if ( ! apply_filters( 'auto_upgrade_' . $type, $upgrade, $item ) ) 
     1332            return false; 
     1333 
     1334        // If it's a core update, are we actually compatible with it's requirements? 
     1335        if ( 'core' == $type ) { 
     1336            global $wpdb; 
     1337 
     1338            $php_compat = version_compare( phpversion(), $item->php_version, '>=' ); 
     1339            if ( file_exists( WP_CONTENT_DIR . '/db.php' ) && empty( $wpdb->is_mysql ) ) 
     1340                $mysql_compat = true; 
     1341            else 
     1342                $mysql_compat = version_compare( $wpdb->db_version(), $item->mysql_version, '>=' ); 
     1343 
     1344            if ( ! $php_compat || ! $mysql_compat ) 
     1345                return false; 
     1346        } 
     1347 
     1348        return true; 
     1349    } 
     1350 
     1351    // Checks to see if WP_Filesystem is setup to allow unattended upgrades 
     1352    static function can_auto_update( $context ) { 
     1353        if ( ! self::$skin ) 
     1354            self::$skin = new Automatic_Upgrader_Skin(); 
     1355        return (bool) self::$skin->request_filesystem_credentials(); 
     1356    } 
     1357 
     1358    static function upgrade( $type, $item ) { 
     1359 
     1360        self::$skin = new Automatic_Upgrader_Skin(); 
     1361 
     1362        switch ( $type ) { 
     1363            case 'core': 
     1364                // The Core upgrader doesn't use the Upgrader's skin during the actual main part of the upgrade, instead, firing a filter 
     1365                add_filter( 'update_feedback', function( $message ) { 
     1366                    WP_Background_Upgrader::$skin->feedback( $message ); 
     1367                    return $message; 
     1368                } ); 
     1369                $upgrader = new Core_Upgrader( self::$skin ); 
     1370                $context  = ABSPATH; 
     1371                break; 
     1372            case 'plugin': 
     1373                $upgrader = new Plugin_Upgrader( self::$skin ); 
     1374                $context  = WP_PLUGIN_DIR; // We don't support custom Plugin directories, or updates for WPMU_PLUGIN_DIR 
     1375                break; 
     1376            case 'theme': 
     1377                $upgrader = new Theme_Upgrader( self::$skin ); 
     1378                $context  = get_theme_root( $item ); 
     1379                break; 
     1380        } 
     1381 
     1382        // Determine if we can perform this upgrade or not 
     1383        if ( ! self::should_auto_update( $type, $item, $context )  || ! self::can_auto_update( $context ) ) 
     1384            return false; 
     1385 
     1386        /*wp_mail( 
     1387            get_site_option( 'admin_email' ), 
     1388            __METHOD__, 
     1389            "Starting an upgrade for:\n\n" . var_export( compact( 'type', 'item' ), true ) . "\n\n" . wp_debug_backtrace_summary() 
     1390        );*/ 
     1391 
     1392        // Boom, This sites about to get a whole new splash of paint! 
     1393        $upgrade_result = $upgrader->upgrade( $item, array( 
     1394            'clear_update_cache' => false, 
     1395        ) ); 
     1396 
     1397        // Core doesn't output this, so lets append it so we don't get confused 
     1398        if ( 'core' == $type ) { 
     1399            if ( is_wp_error( $upgrade_result ) ) { 
     1400                self::$skin->error( __( 'Installation Failed' ), $upgrade_result ); 
     1401            } else { 
     1402                self::$skin->feedback( __( 'WordPress updated successfully' ) ); 
     1403            } 
     1404        } 
     1405 
     1406        // Clear cache's and transients 
     1407        switch ( $type ) { 
     1408            case 'core': 
     1409                delete_site_transient( 'update_core' ); 
     1410                break; 
     1411            case 'theme': 
     1412                wp_clean_themes_cache(); 
     1413                break; 
     1414            case 'plugin': 
     1415                wp_clean_plugins_cache(); 
     1416                break; 
     1417        } 
     1418 
     1419        //var_dump( compact( 'type', 'item', 'upgrader', 'upgrade_result' ) ); 
     1420 
     1421        wp_mail( 
     1422            get_site_option( 'admin_email' ), 
     1423            __METHOD__, 
     1424            var_export( array( 
     1425                $upgrade_result, 
     1426                $upgrader, 
     1427                self::$skin, 
     1428            ), true ) 
     1429        ); 
     1430 
     1431        return $upgrade_result; 
     1432    } 
     1433 
     1434    /** 
     1435     * Kicks off a upgrade request for each item in the upgrade "queue" 
     1436     */ 
     1437    static function perform_auto_updates() { 
     1438 
     1439        $lock_name = 'auto_upgrader.lock'; 
     1440        if ( get_site_transient( $lock_name ) ) { 
     1441            // Test to see if it was set more than an hour ago, if so, cleanup. 
     1442            if ( true || get_site_transient( $lock_name ) < ( time() - HOUR_IN_SECONDS ) ) 
     1443                delete_site_transient( $lock_name ); 
     1444            else // Recent lock 
     1445                return; 
     1446        } 
     1447        // Lock upgrades for us for half an hour 
     1448        if ( ! set_site_transient( $lock_name, microtime( true ), HOUR_IN_SECONDS / 2 ) ) 
     1449            return; 
     1450 
     1451        // Next, Plugins 
     1452        wp_update_plugins(); // Check for Plugin updates 
     1453        $plugin_updates = get_site_transient( 'update_plugins' ); 
     1454        if ( $plugin_updates && !empty( $plugin_updates->response ) ) { 
     1455            foreach ( array_keys( $plugin_updates->response ) as $plugin ) { 
     1456                self::upgrade( 'plugin', $plugin ); 
     1457            } 
     1458            // Force refresh of plugin update information 
     1459            wp_clean_plugins_cache(); 
     1460        } 
     1461 
     1462        // Next, those themes we all love 
     1463        wp_update_themes();  // Check for Theme updates 
     1464        $theme_updates = get_site_transient( 'update_themes' ); 
     1465        if ( $theme_updates && !empty( $theme_updates->response ) ) { 
     1466            foreach ( array_keys( $theme_updates->response ) as $theme ) { 
     1467                self::upgrade( 'theme', $theme ); 
     1468            } 
     1469            // Force refresh of theme update information 
     1470            wp_clean_themes_cache(); 
     1471        } 
     1472 
     1473        // Finally, Process any core upgrade 
     1474        wp_version_check(); // Check for Core updates 
     1475        $core_update = find_core_auto_update(); 
     1476        if ( $core_update ) 
     1477            self::upgrade( 'core', $core_update ); 
     1478 
     1479        // Cleanup, These won't trigger any updates this time due to the locking transient 
     1480        wp_version_check();  // check for Core updates 
     1481        wp_update_themes();  // Check for Theme updates 
     1482        wp_update_plugins(); // Check for Plugin updates 
     1483 
     1484        // TODO The core database upgrade has already cleared this transient.. 
     1485        delete_site_transient( $lock_name ); 
     1486 
     1487    } 
     1488 
     1489} 
  • trunk/src/wp-admin/includes/update.php

    r25307 r25421  
    5858} 
    5959 
     60/** 
     61 * Gets the best available (and enabled) Auto-Update for WordPress Core. 
     62 * 
     63 * 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 
     64 * 
     65 * @since 3.7.0 
     66 * 
     67 * @return bool|array False on failure, otherwise the core update offering. 
     68 */ 
     69function find_core_auto_update() { 
     70    $updates = get_site_transient( 'update_core' ); 
     71    if ( ! $updates || empty( $updates->updates ) ) 
     72        return false; 
     73 
     74    include_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php'; 
     75 
     76    $auto_update = false; 
     77    foreach ( $updates->updates as $update ) { 
     78        if ( 'autoupdate' != $update->response ) 
     79            continue; 
     80 
     81        if ( ! WP_Automatic_Upgrader::should_auto_update( 'core', $update, ABSPATH ) ) 
     82            continue; 
     83 
     84        if ( ! $auto_update || version_compare( $update->current, $auto_update->current, '>' ) ) 
     85            $auto_update = $update; 
     86    } 
     87    return $auto_update; 
     88} 
     89 
    6090function dismiss_core_update( $update ) { 
    6191    $dismissed = get_site_option( 'dismissed_update_core' ); 
  • trunk/src/wp-includes/update.php

    r25308 r25421  
    121121    $updates->version_checked = $wp_version; 
    122122    set_site_transient( 'update_core',  $updates); 
     123 
     124    wp_auto_updates_maybe_queue( 'core' ); 
    123125} 
    124126 
     
    222224 
    223225    set_site_transient( 'update_plugins', $new_option ); 
     226 
     227    wp_auto_updates_maybe_queue( 'plugins' ); 
    224228} 
    225229 
     
    332336 
    333337    set_site_transient( 'update_themes', $new_update ); 
     338 
     339    wp_auto_updates_maybe_queue( 'themes' ); 
     340} 
     341 
     342/** 
     343 * Queues a cron entry if a potentially upgrade is detected. 
     344 * 
     345 * @since 3.7.0 
     346 * 
     347 * @param string $type The type of update to check for, may be 'core', 'plugins', or, 'themes'. 
     348 */ 
     349function wp_auto_updates_maybe_queue( $type = 'core' ) { 
     350    include_once ABSPATH . '/wp-admin/includes/class-wp-upgrader.php'; 
     351    include_once ABSPATH . '/wp-admin/includes/update.php'; 
     352 
     353    if ( WP_Automatic_Upgrader::upgrader_disabled() ) 
     354        return; 
     355 
     356    $updates_available = false; 
     357    if ( 'core' == $type ) { 
     358        $updates_available = (bool) find_core_auto_update(); 
     359    } elseif ( 'plugins' == $type ) { 
     360        $plugin_updates = get_site_transient( 'update_plugins' ); 
     361        $updates_available = !empty( $plugin_updates->response ); 
     362    } elseif ( 'themes' == $type ) { 
     363        $theme_updates = get_site_transient( 'update_themes' ); 
     364        $updates_available = empty( $theme_updates->response ); 
     365    } 
     366 
     367    if ( $updates_available && ! wp_next_scheduled( 'wp_auto_updates_execute' ) ) { 
     368        // If the transient update was triggered by a user pageview, update in an hours time, else, now. 
     369        $when_to_update = get_current_user_id() ? time() + HOUR_IN_SECONDS : time(); 
     370        $when_to_update = apply_filters( 'auto_upgrade_when_to_upgrade', $when_to_update ); 
     371 
     372        wp_schedule_single_event( $when_to_update, 'wp_auto_updates_execute' ); 
     373    } 
     374 
     375} 
     376 
     377function wp_auto_updates_execute() { 
     378    include_once ABSPATH . '/wp-admin/includes/admin.php'; 
     379    include_once ABSPATH . '/wp-admin/includes/class-wp-upgrader.php'; 
     380 
     381    if ( WP_Automatic_Upgrader::upgrader_disabled() ) 
     382        return; 
     383 
     384    WP_Automatic_Upgrader::perform_auto_updates(); 
    334385} 
    335386 
     
    457508add_action( 'wp_update_themes', 'wp_update_themes' ); 
    458509 
     510// Automatic Updates - Cron callback 
     511add_action( 'wp_auto_updates_execute', 'wp_auto_updates_execute' ); 
     512 
    459513add_action('init', 'wp_schedule_update_checks'); 
Note: See TracChangeset for help on using the changeset viewer.