Make WordPress Core


Ignore:
Timestamp:
09/13/2013 06:18:16 AM (13 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

File:
1 edited

Legend:

Unmodified
Added
Removed
  • 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}
Note: See TracChangeset for help on using the changeset viewer.