diff --git a/README.md b/README.md index a407ea1f..55b944a3 100644 --- a/README.md +++ b/README.md @@ -1378,6 +1378,12 @@ wp theme update [...] [--all] [--exclude=] [--format=] Comma separated list of theme names that should be excluded from updating. + [--minor] + Only perform updates for minor releases (e.g. from 1.3 to 1.4 instead of 2.0) + + [--patch] + Only perform updates for patch releases (e.g. from 1.3 to 1.3.3 instead of 1.4) + [--format=] Render output in a particular format. --- diff --git a/composer.json b/composer.json index 54b2863d..d68f3493 100644 --- a/composer.json +++ b/composer.json @@ -18,7 +18,7 @@ ], "require": { "composer/semver": "^1.4 || ^2 || ^3", - "wp-cli/wp-cli": "^2.5.1" + "wp-cli/wp-cli": "^2.10" }, "require-dev": { "wp-cli/cache-command": "^2.0", diff --git a/features/theme-update.feature b/features/theme-update.feature index 99330110..a9969804 100644 --- a/features/theme-update.feature +++ b/features/theme-update.feature @@ -113,3 +113,45 @@ Feature: Update WordPress themes """ Error: Can't find the requested theme's version 1.4.2 in the WordPress.org theme repository (HTTP code 404). """ + + Scenario: Error when both --minor and --patch are provided + Given a WP install + + When I try `wp theme update --patch --minor --all` + Then STDERR should be: + """ + Error: --minor and --patch cannot be used together. + """ + And the return code should be 1 + + Scenario: Update a theme to its latest minor release + Given a WP install + And I run `wp theme install --force twentytwelve --version=3.0` + + When I run `wp theme update twentytwelve --minor` + Then STDOUT should contain: + """ + Success: Updated 1 of 1 themes. + """ + + When I run `wp theme get twentytwelve --field=version` + Then STDOUT should be: + """ + 3.9 + """ + + Scenario: Update a theme to its latest patch release + Given a WP install + And I run `wp theme install --force twentytwelve --version=1.1` + + When I run `wp theme update twentytwelve --patch` + Then STDOUT should contain: + """ + Success: Updated 1 of 1 themes. + """ + + When I run `wp theme get twentytwelve --field=version` + Then STDOUT should be: + """ + 1.1.1 + """ diff --git a/src/Theme_Command.php b/src/Theme_Command.php index 9d55b50b..d65d97fa 100644 --- a/src/Theme_Command.php +++ b/src/Theme_Command.php @@ -439,7 +439,7 @@ protected function get_item_list() { protected function filter_item_list( $items, $args ) { $theme_files = array(); foreach ( $args as $arg ) { - $theme_files[] = $this->fetcher->get_check( $arg )->get_stylesheet_directory(); + $theme_files[] = $this->fetcher->get_check( $arg )->get_stylesheet(); } return Utils\pick_fields( $items, $theme_files ); @@ -589,6 +589,12 @@ public function get( $args, $assoc_args ) { * [--exclude=] * : Comma separated list of theme names that should be excluded from updating. * + * [--minor] + * : Only perform updates for minor releases (e.g. from 1.3 to 1.4 instead of 2.0) + * + * [--patch] + * : Only perform updates for patch releases (e.g. from 1.3 to 1.3.3 instead of 1.4) + * * [--format=] * : Render output in a particular format. * --- diff --git a/src/WP_CLI/CommandWithUpgrade.php b/src/WP_CLI/CommandWithUpgrade.php index 2e704544..566c25fc 100755 --- a/src/WP_CLI/CommandWithUpgrade.php +++ b/src/WP_CLI/CommandWithUpgrade.php @@ -348,12 +348,14 @@ protected function update_many( $args, $assoc_args ) { $minor = (bool) Utils\get_flag_value( $assoc_args, 'minor', false ); $patch = (bool) Utils\get_flag_value( $assoc_args, 'patch', false ); - if ( 'plugin' === $this->item_type - && ( $minor || $patch ) ) { + if ( + in_array( $this->item_type, [ 'plugin', 'theme' ], true ) && + ( $minor || $patch ) + ) { $type = $minor ? 'minor' : 'patch'; $insecure = (bool) Utils\get_flag_value( $assoc_args, 'insecure', false ); - $items_to_update = self::get_minor_or_patch_updates( $items_to_update, $type, $insecure, true ); + $items_to_update = self::get_minor_or_patch_updates( $items_to_update, $type, $insecure, true, $this->item_type ); } $exclude = Utils\get_flag_value( $assoc_args, 'exclude' ); @@ -368,11 +370,10 @@ protected function update_many( $args, $assoc_args ) { } unset( $items_to_update[ $plugin->file ] ); } elseif ( 'theme' === $this->item_type ) { - $theme_root = get_theme_root() . '/' . $item; - if ( ! is_dir( $theme_root ) ) { - continue; + $theme = wp_get_theme( $item ); + if ( $theme->exists() ) { + unset( $items_to_update[ $theme->get_stylesheet() ] ); } - unset( $items_to_update[ $theme_root ] ); } } } @@ -429,8 +430,13 @@ protected function update_many( $args, $assoc_args ) { $transient_filter = function ( $transient ) use ( $items_to_update ) { foreach ( $items_to_update as $name => $item_data ) { if ( isset( $transient->response[ $name ] ) ) { - $transient->response[ $name ]->new_version = $item_data['update_version']; - $transient->response[ $name ]->package = $item_data['update_package']; + if ( is_object( $transient->response[ $name ] ) ) { + $transient->response[ $name ]->new_version = $item_data['update_version']; + $transient->response[ $name ]->package = $item_data['update_package']; + } else { + $transient->response[ $name ]['new_version'] = $item_data['update_version']; + $transient->response[ $name ]['package'] = $item_data['update_package']; + } } } return $transient; @@ -611,19 +617,27 @@ private function get_color( $status ) { } /** - * Get the minor or patch version for plugins with available updates + * Get the minor or patch version for plugins and themes with available updates * - * @param array $items Plugins with updates. + * @param array $items Items with updates. * @param string $type Either 'minor' or 'patch'. * @param bool $insecure Whether to retry without certificate validation on TLS handshake failure. * @param bool $require_stable Whether to require stable version when comparing versions. + * @param string $item_type Item type, either 'plugin' or 'theme'. * @return array */ - private function get_minor_or_patch_updates( $items, $type, $insecure, $require_stable ) { + private function get_minor_or_patch_updates( $items, $type, $insecure, $require_stable, $item_type ) { $wp_org_api = new WpOrgApi( [ 'insecure' => $insecure ] ); foreach ( $items as $i => $item ) { try { - $data = $wp_org_api->get_plugin_info( $item['name'] ); + $data = call_user_func( + [ $wp_org_api, "get_{$item_type}_info" ], + $item['name'], + // The default. + 'en_US', + // We are only interested in the versions field. + [ 'versions' => true ] + ); } catch ( Exception $exception ) { unset( $items[ $i ] ); continue; diff --git a/src/WP_CLI/ParseThemeNameInput.php b/src/WP_CLI/ParseThemeNameInput.php index a5924ee2..34d75a82 100644 --- a/src/WP_CLI/ParseThemeNameInput.php +++ b/src/WP_CLI/ParseThemeNameInput.php @@ -76,38 +76,38 @@ private function get_all_themes() { } foreach ( wp_get_themes() as $key => $theme ) { - $file = $theme->get_stylesheet_directory(); + $stylesheet = $theme->get_stylesheet(); - $update_info = ( isset( $all_update_info->response[ $theme->get_stylesheet() ] ) && null !== $all_update_info->response[ $theme->get_stylesheet() ] ) ? (array) $all_update_info->response[ $theme->get_stylesheet() ] : null; + $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; - $items[ $file ] = [ + $items[ $stylesheet ] = [ 'name' => $key, 'status' => $this->get_status( $theme ), 'update' => (bool) $update_info, 'update_version' => isset( $update_info['new_version'] ) ? $update_info['new_version'] : null, 'update_package' => isset( $update_info['package'] ) ? $update_info['package'] : null, 'version' => $theme->get( 'Version' ), - 'update_id' => $theme->get_stylesheet(), + 'update_id' => $stylesheet, 'title' => $theme->get( 'Name' ), 'description' => wordwrap( $theme->get( 'Description' ) ), 'author' => $theme->get( 'Author' ), - 'auto_update' => in_array( $theme->get_stylesheet(), $auto_updates, true ), + 'auto_update' => in_array( $stylesheet, $auto_updates, true ), ]; // Compare version and update information in theme list. if ( isset( $theme_version_info[ $key ] ) && false === $theme_version_info[ $key ] ) { - $items[ $file ]['update'] = 'version higher than expected'; + $items[ $stylesheet ]['update'] = 'version higher than expected'; } if ( is_multisite() ) { if ( ! empty( $site_enabled[ $key ] ) && ! empty( $network_enabled[ $key ] ) ) { - $items[ $file ]['enabled'] = 'network,site'; + $items[ $stylesheet ]['enabled'] = 'network,site'; } elseif ( ! empty( $network_enabled[ $key ] ) ) { - $items[ $file ]['enabled'] = 'network'; + $items[ $stylesheet ]['enabled'] = 'network'; } elseif ( ! empty( $site_enabled[ $key ] ) ) { - $items[ $file ]['enabled'] = 'site'; + $items[ $stylesheet ]['enabled'] = 'site'; } else { - $items[ $file ]['enabled'] = 'no'; + $items[ $stylesheet ]['enabled'] = 'no'; } } }