Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
"commands": [
"core",
"core check-update",
"core check-update-db",
"core download",
"core install",
"core is-installed",
Expand Down
99 changes: 99 additions & 0 deletions features/core-check-update-db.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
Feature: Check if WordPress database update is needed

# This test downgrades to an older WordPress version, but the SQLite plugin requires 6.0+
@require-mysql
Scenario: Check if database update is needed on a single site
Given a WP install
And a disable_sidebar_check.php file:
"""
<?php
WP_CLI::add_wp_hook( 'init', static function () {
remove_action( 'after_switch_theme', '_wp_sidebars_changed' );
} );
"""
And I try `wp theme install twentytwenty --activate`
And I run `wp core download --version=5.4 --force`
And I run `wp option update db_version 45805 --require=disable_sidebar_check.php`

When I try `wp core check-update-db`
Then the return code should be 1
And STDOUT should contain:
"""
WordPress database update required from db version 45805 to 47018.
"""

When I run `wp core update-db`
Then STDOUT should contain:
"""
Success: WordPress database upgraded successfully from db version 45805 to 47018.
"""

When I run `wp core check-update-db`
Then STDOUT should contain:
"""
Success: WordPress database is up to date.
"""

Scenario: Check if database update is needed when database is already up to date
Given a WP install

When I run `wp core check-update-db`
Then STDOUT should contain:
"""
Success: WordPress database is up to date.
"""

Scenario: Check if database update is needed across network
Given a WP multisite install
And a disable_sidebar_check.php file:
"""
<?php
WP_CLI::add_wp_hook( 'init', static function () {
remove_action( 'after_switch_theme', '_wp_sidebars_changed' );
} );
"""
And I try `wp theme install twentytwenty --activate`
And I run `wp core download --version=6.6 --force`
And I run `wp option update db_version 57155 --require=disable_sidebar_check.php`
And I run `wp site option update wpmu_upgrade_site 57155`
And I run `wp site create --slug=foo`
And I run `wp site create --slug=bar`
And I run `wp site create --slug=burrito --porcelain`
And save STDOUT as {BURRITO_ID}
And I run `wp site create --slug=taco --porcelain`
And save STDOUT as {TACO_ID}
And I run `wp site create --slug=pizza --porcelain`
And save STDOUT as {PIZZA_ID}
And I run `wp site archive {BURRITO_ID}`
And I run `wp site spam {TACO_ID}`
And I run `wp site delete {PIZZA_ID} --yes`
And I run `wp core update`

When I try `wp core check-update-db --network`
Then the return code should be 1
And STDOUT should contain:
"""
WordPress database update needed on 3/3 sites:
"""

When I run `wp core update-db --network`
Then STDOUT should contain:
"""
Success: WordPress database upgraded on 3/3 sites.
"""

When I run `wp core check-update-db --network`
Then STDOUT should contain:
"""
Success: WordPress databases are up to date on 3/3 sites.
"""

Scenario: Check database update on network installation errors on single site
Given a WP install

When I try `wp core check-update-db --network`
Then STDERR should contain:
"""
Error: This is not a multisite installation.
"""
And the return code should be 1
102 changes: 102 additions & 0 deletions src/Core_Command.php
Original file line number Diff line number Diff line change
Expand Up @@ -1244,6 +1244,108 @@ public function update( $args, $assoc_args ) {
}
}

/**
* Checks for the need for WordPress database updates.
*
* Compares the current database version with the version required by WordPress core
* to determine if database updates are needed.
*
* ## OPTIONS
*
* [--network]
* : Check databases for all sites on a network.
*
* ## EXAMPLES
*
* # Check if database update is needed
* $ wp core check-update-db
* Success: WordPress database is up to date.
*
* # Check database update status for all sites on a network
* $ wp core check-update-db --network
* Success: WordPress databases are up to date on 5/5 sites.
*
* @subcommand check-update-db
*
* @param string[] $args Positional arguments. Unused.
* @param array{network?: bool} $assoc_args Associative arguments.
*/
public function check_update_db( $args, $assoc_args ) {
global $wpdb, $wp_db_version, $wp_current_db_version;

$network = Utils\get_flag_value( $assoc_args, 'network' );
if ( $network && ! is_multisite() ) {
WP_CLI::error( 'This is not a multisite installation.' );
}

if ( $network ) {
$iterator_args = [
'table' => $wpdb->blogs,
'where' => [
'spam' => 0,
'deleted' => 0,
'archived' => 0,
],
];
$it = new TableIterator( $iterator_args );
$total = 0;
$needs_update = 0;
$sites_needing_update = [];

/**
* @var object{site_id: int, domain: string, path: string} $blog
*/
foreach ( $it as $blog ) {
++$total;
$url = $blog->domain . $blog->path;
$cmd = "--url={$url} core check-update-db";

/**
* @var object{stdout: string, stderr: string, return_code: int} $process
*/
$process = WP_CLI::runcommand(
$cmd,
[
'return' => 'all',
'exit_error' => false,
]
);
// If return code is 1, it means update is needed
if ( 1 === (int) $process->return_code ) {
++$needs_update;
$sites_needing_update[] = $url;
}
}

if ( $needs_update > 0 ) {
WP_CLI::log( "WordPress database update needed on {$needs_update}/{$total} sites:" );
foreach ( $sites_needing_update as $site_url ) {
WP_CLI::log( " - {$site_url}" );
}
WP_CLI::halt( 1 );
} else {
WP_CLI::success( "WordPress databases are up to date on {$total}/{$total} sites." );
}
} else {
require_once ABSPATH . 'wp-admin/includes/upgrade.php';

/**
* @var string $wp_current_db_version
*/
// phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited -- Replacing WP Core behavior is the goal here.
$wp_current_db_version = __get_option( 'db_version' );
// phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited -- Replacing WP Core behavior is the goal here.
$wp_current_db_version = (int) $wp_current_db_version;

if ( $wp_db_version !== $wp_current_db_version ) {
WP_CLI::log( "WordPress database update required from db version {$wp_current_db_version} to {$wp_db_version}." );
WP_CLI::halt( 1 );
} else {
WP_CLI::success( 'WordPress database is up to date.' );
}
}
}

/**
* Runs the WordPress database update procedure.
*
Expand Down