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
git-svn-id: https://develop.svn.wordpress.org/trunk@25421 602fd350-edb4-49c9-b593-d223f7449a82
This commit is contained in:
parent
96d12ddd9d
commit
63956aa479
@ -529,7 +529,7 @@ class Theme_Upgrader_Skin extends WP_Upgrader_Skin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Upgrader Skin for Background WordPress Upgrades
|
* Upgrader Skin for Automatic WordPress Upgrades
|
||||||
*
|
*
|
||||||
* This skin is designed to be used when no output is intended, all output
|
* This skin is designed to be used when no output is intended, all output
|
||||||
* is captured and stored for the caller to process and log/email/discard.
|
* is captured and stored for the caller to process and log/email/discard.
|
||||||
@ -538,7 +538,7 @@ class Theme_Upgrader_Skin extends WP_Upgrader_Skin {
|
|||||||
* @subpackage Upgrader
|
* @subpackage Upgrader
|
||||||
* @since 3.7.0
|
* @since 3.7.0
|
||||||
*/
|
*/
|
||||||
class Background_Upgrader_Skin extends WP_Upgrader_Skin {
|
class Automatic_Upgrader_Skin extends WP_Upgrader_Skin {
|
||||||
var $messages = array();
|
var $messages = array();
|
||||||
|
|
||||||
function request_filesystem_credentials( $error = false ) {
|
function request_filesystem_credentials( $error = false ) {
|
||||||
|
@ -1137,6 +1137,61 @@ class Core_Upgrader extends WP_Upgrader {
|
|||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Determines if this WordPress Core version should update to $offered_ver or not
|
||||||
|
static function should_upgrade_to_version( $offered_ver /* x.y.z */ ) {
|
||||||
|
include ABSPATH . WPINC . '/version.php'; // $wp_version; // x.y.z
|
||||||
|
|
||||||
|
$current_branch = implode( '.', array_slice( preg_split( '/[.-]/', $wp_version ), 0, 2 ) ); // x.y
|
||||||
|
$new_branch = implode( '.', array_slice( preg_split( '/[.-]/', $offered_ver ), 0, 2 ) ); // x.y
|
||||||
|
$current_is_development_version = (bool) strpos( $wp_version, '-' );
|
||||||
|
|
||||||
|
// Defaults:
|
||||||
|
$upgrade_dev = false;
|
||||||
|
$upgrade_minor = false; // @TODO: Update for release by toggling to true.
|
||||||
|
$upgrade_major = false;
|
||||||
|
|
||||||
|
// WP_AUTO_UPDATE_CORE = true (all), 'minor', false.
|
||||||
|
if ( defined( 'WP_AUTO_UPDATE_CORE' ) ) {
|
||||||
|
if ( false === WP_AUTO_UPDATE_CORE ) {
|
||||||
|
// Defaults to turned off, unless a filter allows it
|
||||||
|
$upgrade_dev = $upgrade_minor = $upgrade_major = false;
|
||||||
|
} elseif ( true === WP_AUTO_UPDATE_CORE ) {
|
||||||
|
// ALL updates for core
|
||||||
|
$upgrade_dev = $upgrade_minor = $upgrade_major = true;
|
||||||
|
} elseif ( 'minor' === WP_AUTO_UPDATE_CORE ) {
|
||||||
|
// Only minor updates for core
|
||||||
|
$upgrade_dev = $upgrade_major = false;
|
||||||
|
$upgrade_minor = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1: If we're already on that version, not much point in updating?
|
||||||
|
if ( $offered_ver == $wp_version )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// 2: If we're running a newer version, that's a nope
|
||||||
|
if ( version_compare( $wp_version, $offered_ver, '>=' ) )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// 3: 3.7-alpha-25000 -> 3.7-alpha-25678 -> 3.7-beta1 -> 3.7-beta2
|
||||||
|
if ( $current_is_development_version ) {
|
||||||
|
if ( ! apply_filters( 'allow_dev_auto_core_updates', $upgrade_dev ) )
|
||||||
|
return false;
|
||||||
|
// else fall through to minor + major branches below
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4: Minor In-branch updates (3.7.0 -> 3.7.1 -> 3.7.2 -> 3.7.4)
|
||||||
|
if ( $current_branch == $new_branch )
|
||||||
|
return apply_filters( 'allow_minor_auto_core_updates', $upgrade_minor );
|
||||||
|
|
||||||
|
// 5: Major version updates (3.7.0 -> 3.8.0 -> 3.9.1)
|
||||||
|
if ( version_compare( $new_branch, $current_branch, '>' ) )
|
||||||
|
return apply_filters( 'allow_major_auto_core_updates', $upgrade_major );
|
||||||
|
|
||||||
|
// If we're not sure, we don't want it
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1212,3 +1267,223 @@ class File_Upload_Upgrader {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* WordPress Automatic Upgrader helper class
|
||||||
|
*
|
||||||
|
* @since 3.7.0
|
||||||
|
*/
|
||||||
|
class WP_Automatic_Upgrader {
|
||||||
|
|
||||||
|
static $skin;
|
||||||
|
|
||||||
|
static function upgrader_disabled() {
|
||||||
|
// That's a no if you don't want files changes
|
||||||
|
if ( defined( 'DISABLE_FILE_MODS' ) && DISABLE_FILE_MODS )
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// More fine grained control can be done through the WP_AUTO_UPDATE_CORE constant and filters
|
||||||
|
if ( defined( 'AUTOMATIC_UPDATER_DISABLED' ) && AUTOMATIC_UPDATER_DISABLED )
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if ( defined( 'WP_INSTALLING' ) )
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return apply_filters( 'auto_upgrader_disabled', false );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests to see if we should upgrade a specific item, does not test to see if we CAN update the item.
|
||||||
|
*/
|
||||||
|
static function should_auto_update( $type, $item, $context ) {
|
||||||
|
|
||||||
|
if ( self::upgrader_disabled() )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// ..and also check for GIT/SVN checkouts
|
||||||
|
if ( ! apply_filters( 'auto_upgrade_ignore_checkout_status', false ) ) {
|
||||||
|
$stop_dirs = array(
|
||||||
|
ABSPATH,
|
||||||
|
untrailingslashit( $context ),
|
||||||
|
);
|
||||||
|
if ( ! file_exists( ABSPATH . '/wp-config.php' ) ) // wp-config.php up one folder in a deployment situation
|
||||||
|
$stop_dirs[] = dirname( ABSPATH );
|
||||||
|
foreach ( array_unique( $stop_dirs ) as $dir ) {
|
||||||
|
if ( file_exists( $dir . '/.svn' ) || file_exists( $dir . '/.git' ) )
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Next up, do we actually have it enabled for this type of update?
|
||||||
|
switch ( $type ) {
|
||||||
|
case 'core':
|
||||||
|
$upgrade = Core_Upgrader::should_upgrade_to_version( $item->current );
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
case 'plugin':
|
||||||
|
case 'theme':
|
||||||
|
$upgrade = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// And does the user / plugins want it?
|
||||||
|
// Plugins may filter on 'auto_upgrade_plugin', and check the 2nd param, $item, to only enable it for certain Plugins/Themes
|
||||||
|
if ( ! apply_filters( 'auto_upgrade_' . $type, $upgrade, $item ) )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// If it's a core update, are we actually compatible with it's requirements?
|
||||||
|
if ( 'core' == $type ) {
|
||||||
|
global $wpdb;
|
||||||
|
|
||||||
|
$php_compat = version_compare( phpversion(), $item->php_version, '>=' );
|
||||||
|
if ( file_exists( WP_CONTENT_DIR . '/db.php' ) && empty( $wpdb->is_mysql ) )
|
||||||
|
$mysql_compat = true;
|
||||||
|
else
|
||||||
|
$mysql_compat = version_compare( $wpdb->db_version(), $item->mysql_version, '>=' );
|
||||||
|
|
||||||
|
if ( ! $php_compat || ! $mysql_compat )
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Checks to see if WP_Filesystem is setup to allow unattended upgrades
|
||||||
|
static function can_auto_update( $context ) {
|
||||||
|
if ( ! self::$skin )
|
||||||
|
self::$skin = new Automatic_Upgrader_Skin();
|
||||||
|
return (bool) self::$skin->request_filesystem_credentials();
|
||||||
|
}
|
||||||
|
|
||||||
|
static function upgrade( $type, $item ) {
|
||||||
|
|
||||||
|
self::$skin = new Automatic_Upgrader_Skin();
|
||||||
|
|
||||||
|
switch ( $type ) {
|
||||||
|
case 'core':
|
||||||
|
// The Core upgrader doesn't use the Upgrader's skin during the actual main part of the upgrade, instead, firing a filter
|
||||||
|
add_filter( 'update_feedback', function( $message ) {
|
||||||
|
WP_Background_Upgrader::$skin->feedback( $message );
|
||||||
|
return $message;
|
||||||
|
} );
|
||||||
|
$upgrader = new Core_Upgrader( self::$skin );
|
||||||
|
$context = ABSPATH;
|
||||||
|
break;
|
||||||
|
case 'plugin':
|
||||||
|
$upgrader = new Plugin_Upgrader( self::$skin );
|
||||||
|
$context = WP_PLUGIN_DIR; // We don't support custom Plugin directories, or updates for WPMU_PLUGIN_DIR
|
||||||
|
break;
|
||||||
|
case 'theme':
|
||||||
|
$upgrader = new Theme_Upgrader( self::$skin );
|
||||||
|
$context = get_theme_root( $item );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determine if we can perform this upgrade or not
|
||||||
|
if ( ! self::should_auto_update( $type, $item, $context ) || ! self::can_auto_update( $context ) )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
/*wp_mail(
|
||||||
|
get_site_option( 'admin_email' ),
|
||||||
|
__METHOD__,
|
||||||
|
"Starting an upgrade for:\n\n" . var_export( compact( 'type', 'item' ), true ) . "\n\n" . wp_debug_backtrace_summary()
|
||||||
|
);*/
|
||||||
|
|
||||||
|
// Boom, This sites about to get a whole new splash of paint!
|
||||||
|
$upgrade_result = $upgrader->upgrade( $item, array(
|
||||||
|
'clear_update_cache' => false,
|
||||||
|
) );
|
||||||
|
|
||||||
|
// Core doesn't output this, so lets append it so we don't get confused
|
||||||
|
if ( 'core' == $type ) {
|
||||||
|
if ( is_wp_error( $upgrade_result ) ) {
|
||||||
|
self::$skin->error( __( 'Installation Failed' ), $upgrade_result );
|
||||||
|
} else {
|
||||||
|
self::$skin->feedback( __( 'WordPress updated successfully' ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear cache's and transients
|
||||||
|
switch ( $type ) {
|
||||||
|
case 'core':
|
||||||
|
delete_site_transient( 'update_core' );
|
||||||
|
break;
|
||||||
|
case 'theme':
|
||||||
|
wp_clean_themes_cache();
|
||||||
|
break;
|
||||||
|
case 'plugin':
|
||||||
|
wp_clean_plugins_cache();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
//var_dump( compact( 'type', 'item', 'upgrader', 'upgrade_result' ) );
|
||||||
|
|
||||||
|
wp_mail(
|
||||||
|
get_site_option( 'admin_email' ),
|
||||||
|
__METHOD__,
|
||||||
|
var_export( array(
|
||||||
|
$upgrade_result,
|
||||||
|
$upgrader,
|
||||||
|
self::$skin,
|
||||||
|
), true )
|
||||||
|
);
|
||||||
|
|
||||||
|
return $upgrade_result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Kicks off a upgrade request for each item in the upgrade "queue"
|
||||||
|
*/
|
||||||
|
static function perform_auto_updates() {
|
||||||
|
|
||||||
|
$lock_name = 'auto_upgrader.lock';
|
||||||
|
if ( get_site_transient( $lock_name ) ) {
|
||||||
|
// Test to see if it was set more than an hour ago, if so, cleanup.
|
||||||
|
if ( true || get_site_transient( $lock_name ) < ( time() - HOUR_IN_SECONDS ) )
|
||||||
|
delete_site_transient( $lock_name );
|
||||||
|
else // Recent lock
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Lock upgrades for us for half an hour
|
||||||
|
if ( ! set_site_transient( $lock_name, microtime( true ), HOUR_IN_SECONDS / 2 ) )
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Next, Plugins
|
||||||
|
wp_update_plugins(); // Check for Plugin updates
|
||||||
|
$plugin_updates = get_site_transient( 'update_plugins' );
|
||||||
|
if ( $plugin_updates && !empty( $plugin_updates->response ) ) {
|
||||||
|
foreach ( array_keys( $plugin_updates->response ) as $plugin ) {
|
||||||
|
self::upgrade( 'plugin', $plugin );
|
||||||
|
}
|
||||||
|
// Force refresh of plugin update information
|
||||||
|
wp_clean_plugins_cache();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Next, those themes we all love
|
||||||
|
wp_update_themes(); // Check for Theme updates
|
||||||
|
$theme_updates = get_site_transient( 'update_themes' );
|
||||||
|
if ( $theme_updates && !empty( $theme_updates->response ) ) {
|
||||||
|
foreach ( array_keys( $theme_updates->response ) as $theme ) {
|
||||||
|
self::upgrade( 'theme', $theme );
|
||||||
|
}
|
||||||
|
// Force refresh of theme update information
|
||||||
|
wp_clean_themes_cache();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finally, Process any core upgrade
|
||||||
|
wp_version_check(); // Check for Core updates
|
||||||
|
$core_update = find_core_auto_update();
|
||||||
|
if ( $core_update )
|
||||||
|
self::upgrade( 'core', $core_update );
|
||||||
|
|
||||||
|
// Cleanup, These won't trigger any updates this time due to the locking transient
|
||||||
|
wp_version_check(); // check for Core updates
|
||||||
|
wp_update_themes(); // Check for Theme updates
|
||||||
|
wp_update_plugins(); // Check for Plugin updates
|
||||||
|
|
||||||
|
// TODO The core database upgrade has already cleared this transient..
|
||||||
|
delete_site_transient( $lock_name );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -57,6 +57,36 @@ function get_core_updates( $options = array() ) {
|
|||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the best available (and enabled) Auto-Update for WordPress Core.
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
*
|
||||||
|
* @since 3.7.0
|
||||||
|
*
|
||||||
|
* @return bool|array False on failure, otherwise the core update offering.
|
||||||
|
*/
|
||||||
|
function find_core_auto_update() {
|
||||||
|
$updates = get_site_transient( 'update_core' );
|
||||||
|
if ( ! $updates || empty( $updates->updates ) )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
include_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
|
||||||
|
|
||||||
|
$auto_update = false;
|
||||||
|
foreach ( $updates->updates as $update ) {
|
||||||
|
if ( 'autoupdate' != $update->response )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if ( ! WP_Automatic_Upgrader::should_auto_update( 'core', $update, ABSPATH ) )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if ( ! $auto_update || version_compare( $update->current, $auto_update->current, '>' ) )
|
||||||
|
$auto_update = $update;
|
||||||
|
}
|
||||||
|
return $auto_update;
|
||||||
|
}
|
||||||
|
|
||||||
function dismiss_core_update( $update ) {
|
function dismiss_core_update( $update ) {
|
||||||
$dismissed = get_site_option( 'dismissed_update_core' );
|
$dismissed = get_site_option( 'dismissed_update_core' );
|
||||||
$dismissed[ $update->current . '|' . $update->locale ] = true;
|
$dismissed[ $update->current . '|' . $update->locale ] = true;
|
||||||
|
@ -120,6 +120,8 @@ function wp_version_check() {
|
|||||||
$updates->last_checked = time();
|
$updates->last_checked = time();
|
||||||
$updates->version_checked = $wp_version;
|
$updates->version_checked = $wp_version;
|
||||||
set_site_transient( 'update_core', $updates);
|
set_site_transient( 'update_core', $updates);
|
||||||
|
|
||||||
|
wp_auto_updates_maybe_queue( 'core' );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -221,6 +223,8 @@ function wp_update_plugins() {
|
|||||||
$new_option->response = array();
|
$new_option->response = array();
|
||||||
|
|
||||||
set_site_transient( 'update_plugins', $new_option );
|
set_site_transient( 'update_plugins', $new_option );
|
||||||
|
|
||||||
|
wp_auto_updates_maybe_queue( 'plugins' );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -331,6 +335,53 @@ function wp_update_themes() {
|
|||||||
$new_update->response = $response;
|
$new_update->response = $response;
|
||||||
|
|
||||||
set_site_transient( 'update_themes', $new_update );
|
set_site_transient( 'update_themes', $new_update );
|
||||||
|
|
||||||
|
wp_auto_updates_maybe_queue( 'themes' );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Queues a cron entry if a potentially upgrade is detected.
|
||||||
|
*
|
||||||
|
* @since 3.7.0
|
||||||
|
*
|
||||||
|
* @param string $type The type of update to check for, may be 'core', 'plugins', or, 'themes'.
|
||||||
|
*/
|
||||||
|
function wp_auto_updates_maybe_queue( $type = 'core' ) {
|
||||||
|
include_once ABSPATH . '/wp-admin/includes/class-wp-upgrader.php';
|
||||||
|
include_once ABSPATH . '/wp-admin/includes/update.php';
|
||||||
|
|
||||||
|
if ( WP_Automatic_Upgrader::upgrader_disabled() )
|
||||||
|
return;
|
||||||
|
|
||||||
|
$updates_available = false;
|
||||||
|
if ( 'core' == $type ) {
|
||||||
|
$updates_available = (bool) find_core_auto_update();
|
||||||
|
} elseif ( 'plugins' == $type ) {
|
||||||
|
$plugin_updates = get_site_transient( 'update_plugins' );
|
||||||
|
$updates_available = !empty( $plugin_updates->response );
|
||||||
|
} elseif ( 'themes' == $type ) {
|
||||||
|
$theme_updates = get_site_transient( 'update_themes' );
|
||||||
|
$updates_available = empty( $theme_updates->response );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( $updates_available && ! wp_next_scheduled( 'wp_auto_updates_execute' ) ) {
|
||||||
|
// If the transient update was triggered by a user pageview, update in an hours time, else, now.
|
||||||
|
$when_to_update = get_current_user_id() ? time() + HOUR_IN_SECONDS : time();
|
||||||
|
$when_to_update = apply_filters( 'auto_upgrade_when_to_upgrade', $when_to_update );
|
||||||
|
|
||||||
|
wp_schedule_single_event( $when_to_update, 'wp_auto_updates_execute' );
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function wp_auto_updates_execute() {
|
||||||
|
include_once ABSPATH . '/wp-admin/includes/admin.php';
|
||||||
|
include_once ABSPATH . '/wp-admin/includes/class-wp-upgrader.php';
|
||||||
|
|
||||||
|
if ( WP_Automatic_Upgrader::upgrader_disabled() )
|
||||||
|
return;
|
||||||
|
|
||||||
|
WP_Automatic_Upgrader::perform_auto_updates();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -456,4 +507,7 @@ add_action( 'load-update-core.php', 'wp_update_themes' );
|
|||||||
add_action( 'admin_init', '_maybe_update_themes' );
|
add_action( 'admin_init', '_maybe_update_themes' );
|
||||||
add_action( 'wp_update_themes', 'wp_update_themes' );
|
add_action( 'wp_update_themes', 'wp_update_themes' );
|
||||||
|
|
||||||
|
// Automatic Updates - Cron callback
|
||||||
|
add_action( 'wp_auto_updates_execute', 'wp_auto_updates_execute' );
|
||||||
|
|
||||||
add_action('init', 'wp_schedule_update_checks');
|
add_action('init', 'wp_schedule_update_checks');
|
||||||
|
Loading…
Reference in New Issue
Block a user