Skip to content
Merged
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
88 changes: 88 additions & 0 deletions features/plugin-update.feature
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,94 @@ Feature: Update WordPress plugins
Success: Updated 1 of 1 plugins (1 skipped).
"""

# Tests for --auto-update-indicated feature
# Note: These tests verify the flag handling and error cases.
# The actual update behavior when autoupdate is true from the server
# cannot be easily tested as it requires mocking WordPress.org API responses.
# The update functionality itself is handled by the existing update_many method.

@require-wp-5.2
Scenario: Show auto_update_indicated field in plugin list
Given a WP install

When I run `wp plugin install wordpress-importer --version=0.5 --force`
Then STDOUT should not be empty

When I run `wp plugin list --fields=name,version,update,auto_update_indicated`
Then STDOUT should be a table containing rows:
| name | version | update | auto_update_indicated |
| wordpress-importer | 0.5 | available | no |

@require-wp-5.2
Scenario: Using --auto-update-indicated flag when no plugins have auto-update indicated
Given a WP install

When I run `wp plugin install wordpress-importer --version=0.5 --force`
Then STDOUT should not be empty

When I run `wp plugin update --auto-update-indicated`
Then STDOUT should be:
"""
Success: No plugins with server-indicated automatic updates available.
"""

@require-wp-5.2
Scenario: Error when using --version with --auto-update-indicated
Given a WP install

When I try `wp plugin update --auto-update-indicated --version=1.0.0`
Then STDERR should be:
"""
Error: Cannot use --version with --auto-update-indicated. The version is determined by the server.
"""
And the return code should be 1

@require-wp-5.2
Scenario: Error when using --minor with --auto-update-indicated
Given a WP install

When I try `wp plugin update --auto-update-indicated --minor`
Then STDERR should be:
"""
Error: Cannot use --minor or --patch with --auto-update-indicated. The version is determined by the server.
"""
And the return code should be 1

@require-wp-5.2
Scenario: Error when using --patch with --auto-update-indicated
Given a WP install

When I try `wp plugin update --auto-update-indicated --patch`
Then STDERR should be:
"""
Error: Cannot use --minor or --patch with --auto-update-indicated. The version is determined by the server.
"""
And the return code should be 1

@require-wp-5.2
Scenario: Error when specifying plugin names with --auto-update-indicated
Given a WP install

When I try `wp plugin update akismet --auto-update-indicated`
Then STDERR should be:
"""
Error: Cannot specify plugin names with --auto-update-indicated. This flag updates all plugins with server-indicated automatic updates.
"""
And the return code should be 1

@require-wp-5.2
Scenario: Preview updates with --auto-update-indicated and --dry-run
Given a WP install

When I run `wp plugin install wordpress-importer --version=0.5 --force`
Then STDOUT should not be empty

When I run `wp plugin update --auto-update-indicated --dry-run`
Then STDOUT should be:
"""
Success: No plugins with server-indicated automatic updates available.
"""

@require-wp-5.2
Scenario: Updating all plugins should show the name of each plugin as it is updated
Given a WP install
Expand Down
81 changes: 81 additions & 0 deletions features/theme-update.feature
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,87 @@ Feature: Update WordPress themes
1.1.1
"""

# Tests for --auto-update-indicated feature
# Note: These tests verify the flag handling and error cases.
# The actual update behavior when autoupdate is true from the server
# cannot be easily tested as it requires mocking WordPress.org API responses.
# The update functionality itself is handled by the existing update_many method.

Scenario: Show auto_update_indicated field in theme list
Given a WP install

When I run `wp theme install twentytwelve --version=3.0 --force`
Then STDOUT should not be empty

When I run `wp theme list --fields=name,version,update,auto_update_indicated`
Then STDOUT should be a table containing rows:
| name | version | update | auto_update_indicated |
| twentytwelve | 3.0 | available | no |

Scenario: Using --auto-update-indicated flag when no themes have auto-update indicated
Given a WP install

When I run `wp theme install twentytwelve --version=3.0 --force`
Then STDOUT should not be empty

When I run `wp theme update --auto-update-indicated`
Then STDOUT should be:
"""
Success: No themes with server-indicated automatic updates available.
"""

Scenario: Error when using --version with --auto-update-indicated
Given a WP install

When I try `wp theme update --auto-update-indicated --version=1.0.0`
Then STDERR should be:
"""
Error: Cannot use --version with --auto-update-indicated. The version is determined by the server.
"""
And the return code should be 1

Scenario: Error when using --minor with --auto-update-indicated
Given a WP install

When I try `wp theme update --auto-update-indicated --minor`
Then STDERR should be:
"""
Error: Cannot use --minor or --patch with --auto-update-indicated. The version is determined by the server.
"""
And the return code should be 1

Scenario: Error when using --patch with --auto-update-indicated
Given a WP install

When I try `wp theme update --auto-update-indicated --patch`
Then STDERR should be:
"""
Error: Cannot use --minor or --patch with --auto-update-indicated. The version is determined by the server.
"""
And the return code should be 1

Scenario: Error when specifying theme names with --auto-update-indicated
Given a WP install

When I try `wp theme update twentytwelve --auto-update-indicated`
Then STDERR should be:
"""
Error: Cannot specify theme names with --auto-update-indicated. This flag updates all themes with server-indicated automatic updates.
"""
And the return code should be 1

Scenario: Preview updates with --auto-update-indicated and --dry-run
Given a WP install

When I run `wp theme install twentytwelve --version=3.0 --force`
Then STDOUT should not be empty

When I run `wp theme update --auto-update-indicated --dry-run`
Then STDOUT should be:
"""
Success: No themes with server-indicated automatic updates available.
"""

@require-wp-4.5
Scenario: Updating all themes should show the name of each theme as it is updated
Given a WP install
Expand Down
15 changes: 13 additions & 2 deletions src/Plugin_Command.php
Original file line number Diff line number Diff line change
Expand Up @@ -726,6 +726,9 @@ protected function install_from_repo( $slug, $assoc_args ) {
* [--insecure]
* : Retry downloads without certificate validation if TLS handshake fails. Note: This makes the request vulnerable to a MITM attack.
*
* [--auto-update-indicated]
* : Only update plugins where the server response indicates an automatic update. Updates to the version indicated by the server, not necessarily the latest version. Cannot be used with `--version`, `--minor`, or `--patch`.
*
* ## EXAMPLES
*
* $ wp plugin update bbpress --version=dev
Expand Down Expand Up @@ -777,6 +780,11 @@ protected function install_from_repo( $slug, $assoc_args ) {
public function update( $args, $assoc_args ) {
$all = Utils\get_flag_value( $assoc_args, 'all', false );

// Handle --auto-update-indicated flag if present.
if ( $this->handle_auto_update_indicated( $args, $assoc_args ) ) {
return;
}

$args = $this->check_optional_args_and_all( $args, $all );
if ( ! $args ) {
return;
Expand Down Expand Up @@ -825,8 +833,9 @@ protected function get_item_list() {
$duplicate_names[ $name ] = array();
}

$requires = isset( $update_info ) && isset( $update_info['requires'] ) ? $update_info['requires'] : null;
$requires_php = isset( $update_info ) && isset( $update_info['requires_php'] ) ? $update_info['requires_php'] : null;
$requires = isset( $update_info ) && isset( $update_info['requires'] ) ? $update_info['requires'] : null;
$requires_php = isset( $update_info ) && isset( $update_info['requires_php'] ) ? $update_info['requires_php'] : null;
$auto_update_indicated = isset( $update_info ) && isset( $update_info['autoupdate'] ) ? (bool) $update_info['autoupdate'] : false;

// If an update has requires_php set, check to see if the local version of PHP meets that requirement
// The plugins update API already filters out plugins that don't meet WordPress requirements, but does not
Expand Down Expand Up @@ -868,6 +877,7 @@ protected function get_item_list() {
'description' => wordwrap( $details['Description'] ),
'file' => $file,
'auto_update' => in_array( $file, $auto_updates, true ),
'auto_update_indicated' => $auto_update_indicated,
'author' => $details['Author'],
'tested_up_to' => '',
'requires' => $requires,
Expand Down Expand Up @@ -1794,6 +1804,7 @@ public function delete( $args, $assoc_args ) {
* * requires_php
* * wporg_status
* * wporg_last_updated
* * auto_update_indicated
*
* ## EXAMPLES
*
Expand Down
9 changes: 9 additions & 0 deletions src/Theme_Command.php
Original file line number Diff line number Diff line change
Expand Up @@ -691,6 +691,9 @@ public function get( $args, $assoc_args ) {
* [--insecure]
* : Retry downloads without certificate validation if TLS handshake fails. Note: This makes the request vulnerable to a MITM attack.
*
* [--auto-update-indicated]
* : Only update themes where the server response indicates an automatic update. Updates to the version indicated by the server, not necessarily the latest version. Cannot be used with `--version`, `--minor`, or `--patch`.
*
* ## EXAMPLES
*
* # Update multiple themes
Expand Down Expand Up @@ -741,6 +744,11 @@ public function get( $args, $assoc_args ) {
public function update( $args, $assoc_args ) {
$all = Utils\get_flag_value( $assoc_args, 'all', false );

// Handle --auto-update-indicated flag if present.
if ( $this->handle_auto_update_indicated( $args, $assoc_args ) ) {
return;
}

$args = $this->check_optional_args_and_all( $args, $all );
if ( ! $args ) {
return;
Expand Down Expand Up @@ -945,6 +953,7 @@ public function delete( $args, $assoc_args ) {
* * update_id
* * title
* * description
* * auto_update_indicated
*
* ## EXAMPLES
*
Expand Down
62 changes: 62 additions & 0 deletions src/WP_CLI/CommandWithUpgrade.php
Original file line number Diff line number Diff line change
Expand Up @@ -562,6 +562,62 @@ protected function get_upgrader( $assoc_args ) {
return Utils\get_upgrader( $upgrader_class, $insecure, new ExtensionUpgraderSkin() );
}

/**
* Handles the --auto-update-indicated flag logic for both plugins and themes.
*
* This method validates flag combinations, filters items by auto_update_indicated,
* and processes updates if any items are found.
*
* @param array $args Positional arguments (item names).
* @param array $assoc_args Associative arguments (flags).
* @return bool Returns true if auto-update-indicated was handled, false otherwise.
*/
protected function handle_auto_update_indicated( $args, $assoc_args ) {
$auto_update_indicated = Utils\get_flag_value( $assoc_args, 'auto-update-indicated', false );

if ( ! $auto_update_indicated ) {
return false;
}

// Don't allow --version to be set with --auto-update-indicated, as the version comes from the server.
if ( isset( $assoc_args['version'] ) ) {
WP_CLI::error( 'Cannot use --version with --auto-update-indicated. The version is determined by the server.' );
}

// Don't allow --minor or --patch to be set with --auto-update-indicated, as the version comes from the server.
if ( isset( $assoc_args['minor'] ) || isset( $assoc_args['patch'] ) ) {
WP_CLI::error( 'Cannot use --minor or --patch with --auto-update-indicated. The version is determined by the server.' );
}

// Don't allow item names to be specified with --auto-update-indicated.
if ( ! empty( $args ) ) {
WP_CLI::error( "Cannot specify {$this->item_type} names with --auto-update-indicated. This flag updates all {$this->item_type}s with server-indicated automatic updates." );
}

// Get all items with their update info.
$items = $this->get_item_list();

// Filter to only include items where auto_update_indicated is true.
$auto_update_items = array_filter(
$items,
function ( $item ) {
return ! empty( $item['auto_update_indicated'] );
}
);

// Get the item names to update.
$args = array_values( wp_list_pluck( $auto_update_items, 'name' ) );

if ( empty( $args ) ) {
WP_CLI::success( "No {$this->item_type}s with server-indicated automatic updates available." );
return true;
}

// Process the updates.
$this->update_many( $args, $assoc_args );
return true;
}

protected function update_many( $args, $assoc_args ) {
call_user_func( $this->upgrade_refresh );

Expand Down Expand Up @@ -812,6 +868,12 @@ function ( $value ) {
} elseif ( false === $value ) {
$value = 'off';
}
} elseif ( 'auto_update_indicated' === $field ) {
if ( true === $value ) {
$value = 'yes';
} elseif ( false === $value ) {
$value = 'no';
}
}
}

Expand Down
6 changes: 4 additions & 2 deletions src/WP_CLI/ParseThemeNameInput.php
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,9 @@ private function get_all_themes() {
}

foreach ( wp_get_themes( [ 'errors' => null ] ) as $key => $theme ) {
$stylesheet = $theme->get_stylesheet();
$update_info = ( isset( $all_update_info->response[ $stylesheet ] ) && null !== $all_update_info->response[ $theme->get_stylesheet() ] ) ? (array) $all_update_info->response[ $theme->get_stylesheet() ] : null;
$stylesheet = $theme->get_stylesheet();
$update_info = ( isset( $all_update_info->response[ $stylesheet ] ) && null !== $all_update_info->response[ $theme->get_stylesheet() ] ) ? (array) $all_update_info->response[ $theme->get_stylesheet() ] : null;
$auto_update_indicated = isset( $update_info ) && isset( $update_info['autoupdate'] ) ? (bool) $update_info['autoupdate'] : false;

// Unlike plugin update responses, the wordpress.org API does not seem to check and filter themes that don't meet
// WordPress version requirements into a separate no_updates array
Expand Down Expand Up @@ -149,6 +150,7 @@ private function get_all_themes() {
'description' => wordwrap( $theme->get( 'Description' ) ),
'author' => $theme->get( 'Author' ),
'auto_update' => in_array( $stylesheet, $auto_updates, true ),
'auto_update_indicated' => $auto_update_indicated,
'requires' => $requires,
'requires_php' => $requires_php,
'update_unavailable_reason' => isset( $update_unavailable_reason ) ? $update_unavailable_reason : '',
Expand Down
Loading