diff --git a/features/language-core.feature b/features/language-core.feature index 4fe8e115..86944a2a 100644 --- a/features/language-core.feature +++ b/features/language-core.feature @@ -476,3 +476,26 @@ Feature: Manage core translation files for a WordPress install | en_US | active | | nl_NL | installed | And STDERR should be empty + + @require-wp-4.0 + Scenario: Core translation update with format flag + Given a WP install + And an empty cache + + When I run `wp language core update --format=json` + Then STDOUT should be: + """ + [] + """ + And STDERR should be empty + + When I run `wp language core update --format=csv` + Then STDOUT should be empty + And STDERR should be empty + + When I run `wp language core update --format=summary` + Then STDOUT should contain: + """ + Success: Translations are up to date. + """ + And STDERR should be empty diff --git a/features/language-plugin.feature b/features/language-plugin.feature index a94e9636..31b0e6f7 100644 --- a/features/language-plugin.feature +++ b/features/language-plugin.feature @@ -444,3 +444,78 @@ Feature: Manage plugin translation files for a WordPress install | akismet | en_US | active | | akismet | nl_NL | installed | And STDERR should be empty + + @require-wp-4.0 + Scenario: Plugin translation update with format flag + Given a WP install + + When I run `wp plugin install hello-dolly --force` + Then STDERR should be empty + + When I run `wp language plugin update hello-dolly --format=json` + Then STDOUT should be: + """ + [] + """ + And STDERR should be empty + + When I run `wp language plugin update --all --format=csv` + Then STDOUT should be empty + And STDERR should be empty + + When I run `wp language plugin update --all --format=summary` + Then STDOUT should contain: + """ + Success: Translations are up to date. + """ + And STDERR should be empty + + @require-wp-4.0 + Scenario: Plugin translation update with format flag and actual updates + Given a WP install + And an empty cache + + When I run `wp plugin install akismet --version=3.2 --force` + Then STDERR should be empty + + When I run `wp language plugin install akismet de_DE` + Then STDERR should be empty + + When I run `wp plugin install akismet --version=4.0 --force` + And I run `wp language plugin list akismet --fields=plugin,language,update,status` + Then STDOUT should be a table containing rows: + | plugin | language | update | status | + | akismet | de_DE | available | installed | + + When I run `wp language plugin update akismet --format=json` + Then STDOUT should be JSON containing: + """ + [{"slug":"akismet","language":"de_DE","status":"updated"}] + """ + And STDERR should be empty + + When I run `wp language plugin uninstall akismet de_DE` + And I run `wp plugin install akismet --version=3.2 --force` + And I run `wp language plugin install akismet de_DE` + And I run `wp plugin install akismet --version=4.0 --force` + And I run `wp language plugin update akismet --format=csv` + Then STDOUT should contain: + """ + slug,language,status + """ + And STDOUT should contain: + """ + akismet,de_DE,updated + """ + And STDERR should be empty + + When I run `wp language plugin uninstall akismet de_DE` + And I run `wp plugin install akismet --version=3.2 --force` + And I run `wp language plugin install akismet de_DE` + And I run `wp plugin install akismet --version=4.0 --force` + And I run `wp language plugin update akismet --format=summary` + Then STDOUT should contain: + """ + Success: Updated 1/1 translation. + """ + And STDERR should be empty diff --git a/features/language-theme.feature b/features/language-theme.feature index 6bbfc725..285864f1 100644 --- a/features/language-theme.feature +++ b/features/language-theme.feature @@ -328,3 +328,78 @@ Feature: Manage theme translation files for a WordPress install | en_US | active | | nl_NL | installed | And STDERR should be empty + + @require-wp-4.0 + Scenario: Theme translation update with format flag + Given a WP install + + When I try `wp theme install twentyten` + Then STDOUT should not be empty + + When I run `wp language theme update twentyten --format=json` + Then STDOUT should be: + """ + [] + """ + And STDERR should be empty + + When I run `wp language theme update --all --format=csv` + Then STDOUT should be empty + And STDERR should be empty + + When I run `wp language theme update --all --format=summary` + Then STDOUT should contain: + """ + Success: Translations are up to date. + """ + And STDERR should be empty + + @require-wp-4.0 + Scenario: Theme translation update with format flag and actual updates + Given a WP install + And an empty cache + + When I run `wp theme install twentyfifteen --version=2.0 --force` + Then STDERR should be empty + + When I run `wp language theme install twentyfifteen de_DE` + Then STDERR should be empty + + When I run `wp theme install twentyfifteen --version=2.5 --force` + And I run `wp language theme list twentyfifteen --fields=theme,language,update,status` + Then STDOUT should be a table containing rows: + | theme | language | update | status | + | twentyfifteen | de_DE | available | installed | + + When I run `wp language theme update twentyfifteen --format=json` + Then STDOUT should be JSON containing: + """ + [{"slug":"twentyfifteen","language":"de_DE","status":"updated"}] + """ + And STDERR should be empty + + When I run `wp language theme uninstall twentyfifteen de_DE` + And I run `wp theme install twentyfifteen --version=2.0 --force` + And I run `wp language theme install twentyfifteen de_DE` + And I run `wp theme install twentyfifteen --version=2.5 --force` + And I run `wp language theme update twentyfifteen --format=csv` + Then STDOUT should contain: + """ + slug,language,status + """ + And STDOUT should contain: + """ + twentyfifteen,de_DE,updated + """ + And STDERR should be empty + + When I run `wp language theme uninstall twentyfifteen de_DE` + And I run `wp theme install twentyfifteen --version=2.0 --force` + And I run `wp language theme install twentyfifteen de_DE` + And I run `wp theme install twentyfifteen --version=2.5 --force` + And I run `wp language theme update twentyfifteen --format=summary` + Then STDOUT should contain: + """ + Success: Updated 1/1 translation. + """ + And STDERR should be empty diff --git a/src/Core_Language_Command.php b/src/Core_Language_Command.php index c1b01af1..573b9bac 100644 --- a/src/Core_Language_Command.php +++ b/src/Core_Language_Command.php @@ -339,6 +339,17 @@ public function uninstall( $args ) { * [--dry-run] * : Preview which translations would be updated. * + * [--format=] + * : Render output in a particular format. + * --- + * default: table + * options: + * - table + * - csv + * - json + * - summary + * --- + * * ## EXAMPLES * * # Update installed core languages packs. @@ -351,7 +362,7 @@ public function uninstall( $args ) { * @subcommand update * * @param string[] $args Positional arguments. - * @param array{'dry-run'?: bool} $assoc_args Associative arguments. + * @param array{'dry-run'?: bool, format?: string} $assoc_args Associative arguments. */ public function update( $args, $assoc_args ) { // phpcs:ignore Generic.CodeAnalysis.UselessOverridingMethod.Found -- Overruling the documentation, so not useless ;-). parent::update( $args, $assoc_args ); diff --git a/src/Plugin_Language_Command.php b/src/Plugin_Language_Command.php index 532e5110..1d3cf2a3 100644 --- a/src/Plugin_Language_Command.php +++ b/src/Plugin_Language_Command.php @@ -588,6 +588,17 @@ public function uninstall( $args, $assoc_args ) { * [--dry-run] * : Preview which translations would be updated. * + * [--format=] + * : Render output in a particular format. + * --- + * default: table + * options: + * - table + * - csv + * - json + * - summary + * --- + * * ## EXAMPLES * * # Update all installed language packs for all plugins. @@ -600,7 +611,7 @@ public function uninstall( $args, $assoc_args ) { * @subcommand update * * @param string[] $args Positional arguments. - * @param array{'dry-run'?: bool, all?: bool} $assoc_args Associative arguments. + * @param array{'dry-run'?: bool, all?: bool, format?: string} $assoc_args Associative arguments. */ public function update( $args, $assoc_args ) { $all = \WP_CLI\Utils\get_flag_value( $assoc_args, 'all', false ); diff --git a/src/Theme_Language_Command.php b/src/Theme_Language_Command.php index a9589627..d17246bc 100644 --- a/src/Theme_Language_Command.php +++ b/src/Theme_Language_Command.php @@ -607,6 +607,17 @@ public function uninstall( $args, $assoc_args ) { * [--dry-run] * : Preview which translations would be updated. * + * [--format=] + * : Render output in a particular format. + * --- + * default: table + * options: + * - table + * - csv + * - json + * - summary + * --- + * * ## EXAMPLES * * # Update all installed language packs for all themes. @@ -619,7 +630,7 @@ public function uninstall( $args, $assoc_args ) { * @subcommand update * * @param string[] $args Positional arguments. - * @param array{'dry-run'?: bool, all?: bool} $assoc_args Associative arguments. + * @param array{'dry-run'?: bool, all?: bool, format?: string} $assoc_args Associative arguments. */ public function update( $args, $assoc_args ) { $all = \WP_CLI\Utils\get_flag_value( $assoc_args, 'all', false ); diff --git a/src/WP_CLI/CommandWithTranslation.php b/src/WP_CLI/CommandWithTranslation.php index c273dc8e..f4638543 100644 --- a/src/WP_CLI/CommandWithTranslation.php +++ b/src/WP_CLI/CommandWithTranslation.php @@ -26,13 +26,20 @@ protected function sort_translations_callback( $a, $b ) { * Updates installed languages for the current object type. * * @param string[] $args Positional arguments. - * @param array{'dry-run'?: bool, all?: bool} $assoc_args Associative arguments. + * @param array{'dry-run'?: bool, all?: bool, format?: string} $assoc_args Associative arguments. */ public function update( $args, $assoc_args ) { $updates = $this->get_translation_updates(); + $format = Utils\get_flag_value( $assoc_args, 'format' ); if ( empty( $updates ) ) { - WP_CLI::success( 'Translations are up to date.' ); + if ( $format && in_array( $format, array( 'json', 'csv' ), true ) ) { + Utils\format_items( $format, array(), array() ); + } + + if ( ! $format || in_array( $format, array( 'table', 'summary' ), true ) ) { + WP_CLI::success( 'Translations are up to date.' ); + } return; } @@ -41,9 +48,17 @@ public function update( $args, $assoc_args ) { $args = array( null ); // Used for core. } + if ( $format && in_array( $format, array( 'json', 'csv' ), true ) ) { + $logger = new \WP_CLI\Loggers\Quiet(); + WP_CLI::set_logger( $logger ); + } + $upgrader = 'WP_CLI\\LanguagePackUpgrader'; $results = array(); + $results_data = array(); $num_to_update = 0; + $obj_type = rtrim( $this->obj_type, 's' ); + $slug_key = 'core' === $obj_type ? 'version' : 'slug'; foreach ( $args as $slug ) { // Gets a list of all languages. @@ -96,7 +111,6 @@ public function update( $args, $assoc_args ) { $updates_per_type[ $update->type ][] = $update; } - $obj_type = rtrim( $this->obj_type, 's' ); $available_updates = isset( $updates_per_type[ $obj_type ] ) ? $updates_per_type[ $obj_type ] : null; if ( ! is_array( $available_updates ) ) { @@ -108,7 +122,7 @@ public function update( $args, $assoc_args ) { if ( ! Utils\get_flag_value( $assoc_args, 'dry-run' ) ) { // Update translations. foreach ( $available_updates as $update ) { - WP_CLI::line( "Updating '{$update->Language}' translation for {$update->Name} {$update->Version}..." ); + WP_CLI::log( "Updating '{$update->Language}' translation for {$update->Name} {$update->Version}..." ); /** * @var \WP_CLI\LanguagePackUpgrader $upgrader_instance @@ -118,6 +132,16 @@ public function update( $args, $assoc_args ) { $result = $upgrader_instance->upgrade( $update ); $results[] = $result; + + // Capture data for formatted output (skip for summary format). + if ( $format && 'summary' !== $format ) { + $slug_value = 'version' === $slug_key ? $update->Version : $update->slug; + $results_data[] = array( + $slug_key => $slug_value, + 'language' => $update->language, + 'status' => $result ? 'updated' : 'failed', + ); + } } } } @@ -126,29 +150,42 @@ public function update( $args, $assoc_args ) { if ( Utils\get_flag_value( $assoc_args, 'dry-run' ) ) { $update_count = count( $updates ); - WP_CLI::line( - sprintf( - 'Found %d translation %s that would be processed:', - $update_count, - WP_CLI\Utils\pluralize( 'update', $update_count ) - ) - ); - - Utils\format_items( 'table', $updates, array( 'Type', 'Name', 'Version', 'Language' ) ); + if ( $format && ! in_array( $format, array( 'table', 'summary' ), true ) ) { + // For json/csv formats, just output the formatted data without the message + Utils\format_items( $format, $updates, array( 'Type', 'Name', 'Version', 'Language' ) ); + } else { + // For table/summary/no format, show the message and table + WP_CLI::line( + sprintf( + 'Found %d translation %s that would be processed:', + $update_count, + WP_CLI\Utils\pluralize( 'update', $update_count ) + ) + ); + + Utils\format_items( 'table', $updates, array( 'Type', 'Name', 'Version', 'Language' ) ); + } return; } $num_updated = count( array_filter( $results ) ); - $line = sprintf( "Updated $num_updated/$num_to_update %s.", WP_CLI\Utils\pluralize( 'translation', $num_updated ) ); + // Format output if --format is specified. + if ( $format && 'summary' !== $format ) { + Utils\format_items( $format, $results_data, array( $slug_key, 'language', 'status' ) ); + } - if ( $num_to_update === $num_updated ) { - WP_CLI::success( $line ); - } elseif ( $num_updated > 0 ) { - WP_CLI::warning( $line ); - } else { - WP_CLI::error( $line ); + if ( ! $format || in_array( $format, array( 'table', 'summary' ), true ) ) { + $line = sprintf( "Updated $num_updated/$num_to_update %s.", WP_CLI\Utils\pluralize( 'translation', $num_updated ) ); + + if ( $num_to_update === $num_updated ) { + WP_CLI::success( $line ); + } elseif ( $num_updated > 0 ) { + WP_CLI::warning( $line ); + } else { + WP_CLI::error( $line ); + } } }