diff --git a/composer.json b/composer.json index 62a605a1..e3261860 100644 --- a/composer.json +++ b/composer.json @@ -56,6 +56,7 @@ "plugin path", "plugin search", "plugin status", + "plugin check-update", "plugin toggle", "plugin uninstall", "plugin update", @@ -76,6 +77,7 @@ "theme path", "theme search", "theme status", + "theme check-update", "theme update", "theme mod list" ] diff --git a/features/plugin-check-update.feature b/features/plugin-check-update.feature new file mode 100644 index 00000000..f8190ae6 --- /dev/null +++ b/features/plugin-check-update.feature @@ -0,0 +1,102 @@ +Feature: Check for plugin updates + + @require-wp-5.2 + Scenario: Check for plugin updates with no updates available + Given a WP install + + When I run `wp plugin install wordpress-importer --activate` + Then STDOUT should not be empty + + When I run `wp plugin check-update --all` + Then STDOUT should contain: + """ + Success: All plugins are up to date. + """ + + When I run `wp plugin check-update wordpress-importer` + Then STDOUT should contain: + """ + Success: All plugins are up to date. + """ + + Scenario: Check for plugin updates should throw an error unless --all given + Given a WP install + + When I try `wp plugin check-update` + Then the return code should be 1 + And STDERR should be: + """ + Error: Please specify one or more plugins, or use --all. + """ + And STDOUT should be empty + + @require-wp-5.2 + Scenario: Check for specific plugin updates + Given a WP install + + When I run `wp plugin install wordpress-importer --version=0.5` + Then STDOUT should not be empty + + When I run `wp plugin check-update wordpress-importer --format=csv` + Then STDOUT should contain: + """ + wordpress-importer,inactive,0.5, + """ + + @require-wp-5.2 + Scenario: Check for all plugin updates with --all flag + Given a WP install + + When I run `wp plugin install wordpress-importer --version=0.5 --activate` + Then STDOUT should not be empty + + When I run `wp plugin check-update --all --format=csv` + Then STDOUT should contain: + """ + wordpress-importer,active,0.5, + """ + + @require-wp-5.2 + Scenario: Check for plugin updates in different output formats + Given a WP install + + When I run `wp plugin install wordpress-importer --version=0.5` + Then STDOUT should not be empty + + When I run `wp plugin check-update wordpress-importer --format=json` + Then STDOUT should be JSON containing: + """ + [{"name":"wordpress-importer","status":"inactive","version":"0.5"}] + """ + + When I run `wp plugin check-update wordpress-importer --format=csv` + Then STDOUT should contain: + """ + name,status,version,update_version + """ + And STDOUT should contain: + """ + wordpress-importer,inactive,0.5 + """ + + @require-wp-5.2 + Scenario: Check for plugin updates with custom fields + Given a WP install + + When I run `wp plugin install wordpress-importer --version=0.5` + Then STDOUT should not be empty + + When I run `wp plugin check-update wordpress-importer --fields=name,version` + Then STDOUT should be a table containing rows: + | name | version | + | wordpress-importer | 0.5 | + + Scenario: Check for invalid plugin should error + Given a WP install + + When I try `wp plugin check-update invalid-plugin-name` + Then the return code should be 1 + And STDERR should contain: + """ + Error: + """ diff --git a/features/theme-check-update.feature b/features/theme-check-update.feature new file mode 100644 index 00000000..e85269b9 --- /dev/null +++ b/features/theme-check-update.feature @@ -0,0 +1,100 @@ +Feature: Check for theme updates + + Scenario: Check for theme updates with no updates available + Given a WP install + + When I run `wp theme install twentytwelve --force` + Then STDOUT should not be empty + + When I run `wp theme check-update --all` + Then STDOUT should contain: + """ + Success: All themes are up to date. + """ + + When I run `wp theme check-update twentytwelve` + Then STDOUT should contain: + """ + Success: All themes are up to date. + """ + + Scenario: Check for theme updates should throw an error unless --all given + Given a WP install + + When I try `wp theme check-update` + Then the return code should be 1 + And STDERR should be: + """ + Error: Please specify one or more themes, or use --all. + """ + And STDOUT should be empty + + Scenario: Check for specific theme updates + Given a WP install + + When I run `wp theme install twentyfourteen --version=1.0 --force` + Then STDOUT should not be empty + + When I run `wp theme install twentytwelve --force` + Then STDOUT should not be empty + + When I run `wp theme check-update twentyfourteen --format=csv` + Then STDOUT should contain: + """ + twentyfourteen,inactive,1.0, + """ + + Scenario: Check for all theme updates with --all flag + Given a WP install + + When I run `wp theme install twentyfourteen --version=1.0 --force` + Then STDOUT should not be empty + + When I run `wp theme check-update --all --format=csv` + Then STDOUT should contain: + """ + twentyfourteen,inactive,1.0, + """ + + Scenario: Check for theme updates in different output formats + Given a WP install + + When I run `wp theme install twentyfourteen --version=1.0 --force` + Then STDOUT should not be empty + + When I run `wp theme check-update twentyfourteen --format=json` + Then STDOUT should be JSON containing: + """ + [{"name":"twentyfourteen","status":"inactive","version":"1.0"}] + """ + + When I run `wp theme check-update twentyfourteen --format=csv` + Then STDOUT should contain: + """ + name,status,version,update_version + """ + And STDOUT should contain: + """ + twentyfourteen,inactive,1.0 + """ + + Scenario: Check for theme updates with custom fields + Given a WP install + + When I run `wp theme install twentyfourteen --version=1.0 --force` + Then STDOUT should not be empty + + When I run `wp theme check-update twentyfourteen --fields=name,version` + Then STDOUT should be a table containing rows: + | name | version | + | twentyfourteen | 1.0 | + + Scenario: Check for invalid theme should error + Given a WP install + + When I try `wp theme check-update invalid-theme-name` + Then the return code should be 1 + And STDERR should contain: + """ + Error: + """ diff --git a/src/Plugin_Command.php b/src/Plugin_Command.php index c257debb..b239d479 100644 --- a/src/Plugin_Command.php +++ b/src/Plugin_Command.php @@ -115,6 +115,100 @@ public function status( $args ) { parent::status( $args ); } + /** + * Checks for plugin updates without performing them. + * + * Lists the available plugin updates. Similar to `wp core check-update`. + * + * ## OPTIONS + * + * [...] + * : One or more plugins to check for updates. + * + * [--all] + * : If set, all plugins will be checked for updates. + * + * [--field=] + * : Prints the value of a single field for each update. + * + * [--fields=] + * : Limit the output to specific object fields. Defaults to name,status,version,update_version. + * + * [--format=] + * : Render output in a particular format. + * --- + * default: table + * options: + * - table + * - csv + * - json + * - yaml + * --- + * + * ## EXAMPLES + * + * # Check for plugin updates + * $ wp plugin check-update + * +-----------+--------+---------+----------------+ + * | name | status | version | update_version | + * +-----------+--------+---------+----------------+ + * | akismet | active | 4.1.0 | 4.1.1 | + * +-----------+--------+---------+----------------+ + * + * # List plugins with available updates in JSON format + * $ wp plugin check-update --format=json + * [{"name":"akismet","status":"active","version":"4.1.0","update_version":"4.1.1"}] + * + * @subcommand check-update + */ + public function check_update( $args, $assoc_args ) { + $all = Utils\get_flag_value( $assoc_args, 'all', false ); + + $args = $this->check_optional_args_and_all( $args, $all ); + if ( ! $args ) { + return; + } + + // Force WordPress to check for updates. + call_user_func( $this->upgrade_refresh ); + + if ( $all ) { + // Get all plugins + $items = $this->get_item_list(); + } else { + // Get specific plugins and their update info + $plugins = $this->fetcher->get_many( $args ); + $all_items = $this->get_item_list(); + $items = []; + foreach ( $plugins as $plugin ) { + if ( isset( $all_items[ $plugin->file ] ) ) { + $items[ $plugin->file ] = $all_items[ $plugin->file ]; + } + } + } + + // Filter to only plugins with available updates + $items_with_updates = array_filter( + $items, + function ( $item ) { + return 'available' === $item['update']; + } + ); + + if ( empty( $items_with_updates ) ) { + WP_CLI::success( 'All plugins are up to date.' ); + return; + } + + // Set default fields for check-update output + if ( ! isset( $assoc_args['fields'] ) ) { + $assoc_args['fields'] = 'name,status,version,update_version'; + } + + $formatter = $this->get_formatter( $assoc_args ); + $formatter->display_items( array_values( $items_with_updates ) ); + } + /** * Searches the WordPress.org plugin directory. * diff --git a/src/Theme_Command.php b/src/Theme_Command.php index e18b17e8..489acce9 100644 --- a/src/Theme_Command.php +++ b/src/Theme_Command.php @@ -109,6 +109,101 @@ public function status( $args ) { parent::status( $args ); } + /** + * Checks for theme updates without performing them. + * + * Lists the available theme updates. Similar to `wp core check-update`. + * + * ## OPTIONS + * + * [...] + * : One or more themes to check for updates. + * + * [--all] + * : If set, all themes will be checked for updates. + * + * [--field=] + * : Prints the value of a single field for each update. + * + * [--fields=] + * : Limit the output to specific object fields. Defaults to name,status,version,update_version. + * + * [--format=] + * : Render output in a particular format. + * --- + * default: table + * options: + * - table + * - csv + * - json + * - yaml + * --- + * + * ## EXAMPLES + * + * # Check for theme updates + * $ wp theme check-update + * +------------+----------+---------+----------------+ + * | name | status | version | update_version | + * +------------+----------+---------+----------------+ + * | twentytwelve | inactive | 2.0 | 2.1 | + * +------------+----------+---------+----------------+ + * + * # List themes with available updates in JSON format + * $ wp theme check-update --format=json + * [{"name":"twentytwelve","status":"inactive","version":"2.0","update_version":"2.1"}] + * + * @subcommand check-update + */ + public function check_update( $args, $assoc_args ) { + $all = Utils\get_flag_value( $assoc_args, 'all', false ); + + $args = $this->check_optional_args_and_all( $args, $all ); + if ( ! $args ) { + return; + } + + // Force WordPress to check for updates. + call_user_func( $this->upgrade_refresh ); + + if ( $all ) { + // Get all themes + $items = $this->get_item_list(); + } else { + // Get specific themes and their update info + $themes = $this->fetcher->get_many( $args ); + $all_items = $this->get_item_list(); + $items = []; + foreach ( $themes as $theme ) { + $stylesheet = $theme->get_stylesheet(); + if ( isset( $all_items[ $stylesheet ] ) ) { + $items[ $stylesheet ] = $all_items[ $stylesheet ]; + } + } + } + + // Filter to only themes with available updates + $items_with_updates = array_filter( + $items, + function ( $item ) { + return 'available' === $item['update']; + } + ); + + if ( empty( $items_with_updates ) ) { + WP_CLI::success( 'All themes are up to date.' ); + return; + } + + // Set default fields for check-update output + if ( ! isset( $assoc_args['fields'] ) ) { + $assoc_args['fields'] = 'name,status,version,update_version'; + } + + $formatter = $this->get_formatter( $assoc_args ); + $formatter->display_items( array_values( $items_with_updates ) ); + } + /** * Searches the WordPress.org theme directory. *