diff --git a/features/language-plugin.feature b/features/language-plugin.feature index 211a6de15..95fc4481e 100644 --- a/features/language-plugin.feature +++ b/features/language-plugin.feature @@ -323,3 +323,51 @@ Feature: Manage translation files for a WordPress install | akismet | de_DE | available | installed | | jetpack | de_DE | none | installed | And STDERR should be empty + + + @require-wp-4.0 + Scenario: Install translations for all installed plugins + Given a WP install + And I run `wp plugin path` + And save STDOUT as {PLUGIN_DIR} + And an empty {PLUGIN_DIR} directory + And I run `wp plugin install akismet --version=4.0 --force` + And I run `wp plugin install jetpack --version=6.4 --force` + + When I try `wp language plugin install de_DE` + Then the return code should be 1 + And STDERR should be: + """ + Error: Please specify a plugin, or use --all. + """ + And STDOUT should be empty + + When I run `wp language plugin install --all de_DE --format=csv` + Then the return code should be 0 + And STDOUT should be: + """ + name,locale,status + akismet,de_DE,installed + jetpack,de_DE,installed + """ + And STDERR should be empty + + When I run `wp language plugin install --all de_DE --format=summary` + Then the return code should be 0 + And STDOUT should contain: + """ + Success: Installed 0 of 2 languages (2 skipped). + """ + And STDERR should be empty + + When I run `wp language plugin install --all de_DE invalid_lang --format=csv` + Then the return code should be 0 + And STDOUT should contain: + """ + name,locale,status + akismet,de_DE,"already installed" + akismet,invalid_lang,"not available" + jetpack,de_DE,"already installed" + jetpack,invalid_lang,"not available" + """ + And STDERR should be empty diff --git a/features/language-theme.feature b/features/language-theme.feature index 864747ac8..213106d8f 100644 --- a/features/language-theme.feature +++ b/features/language-theme.feature @@ -212,3 +212,50 @@ Feature: Manage translation files for a WordPress install """ Downloading translation from https://downloads.wordpress.org/translation/theme/twentyseventeen/1.6/de_DE.zip """ + + @require-wp-4.0 + Scenario: Install translations for all installed themes + Given a WP install + And I run `wp theme path` + And save STDOUT as {THEME_DIR} + And an empty {THEME_DIR} directory + And I run `wp theme install twentyseventeen --version=1.0 --force` + And I run `wp theme install twentysixteen --version=1.0 --force` + + When I try `wp language theme install de_DE` + Then the return code should be 1 + And STDERR should be: + """ + Error: Please specify a theme, or use --all. + """ + And STDOUT should be empty + + When I run `wp language theme install --all de_DE --format=csv` + Then the return code should be 0 + And STDOUT should be: + """ + name,locale,status + twentyseventeen,de_DE,installed + twentysixteen,de_DE,installed + """ + And STDERR should be empty + + When I run `wp language theme install --all de_DE --format=summary` + Then the return code should be 0 + And STDOUT should contain: + """ + Success: Installed 0 of 2 languages (2 skipped). + """ + And STDERR should be empty + + When I run `wp language theme install --all de_DE invalid_lang --format=csv` + Then the return code should be 0 + And STDOUT should contain: + """ + name,locale,status + twentyseventeen,de_DE,"already installed" + twentyseventeen,invalid_lang,"not available" + twentysixteen,de_DE,"already installed" + twentysixteen,invalid_lang,"not available" + """ + And STDERR should be empty diff --git a/src/Plugin_Language_Command.php b/src/Plugin_Language_Command.php index 3509232d0..2ea214011 100644 --- a/src/Plugin_Language_Command.php +++ b/src/Plugin_Language_Command.php @@ -189,12 +189,26 @@ public function is_installed( $args, $assoc_args = array() ) { * * ## OPTIONS * - * + * [] * : Plugin to install language for. * + * [--all] + * : If set, languages for all plugins will be installed. + * * ... * : Language code to install. * + * [--format=] + * : Render output in a particular format. Used when installing languages for all plugins. + * --- + * default: table + * options: + * - table + * - csv + * - json + * - summary + * --- + * * ## EXAMPLES * * # Install the Japanese language for Akismet. @@ -209,6 +223,26 @@ public function is_installed( $args, $assoc_args = array() ) { * @subcommand install */ public function install( $args, $assoc_args ) { + $all = \WP_CLI\Utils\get_flag_value( $assoc_args, 'all', false ); + + if ( ! $all && count( $args ) < 2 ) { + \WP_CLI::error( 'Please specify a plugin, or use --all.' ); + } + + if ( $all ) { + $this->install_many( $args, $assoc_args ); + } else { + $this->install_one( $args, $assoc_args ); + } + } + + /** + * Installs translations for a plugin. + * + * @param array $args Runtime arguments. + * @param array $assoc_args Runtime arguments. + */ + private function install_one( $args, $assoc_args ) { $plugin = array_shift( $args ); $language_codes = (array) $args; $count = count( $language_codes ); @@ -244,6 +278,82 @@ public function install( $args, $assoc_args ) { \WP_CLI\Utils\report_batch_operation_results( 'language', 'install', $count, $successes, $errors, $skips ); } + /** + * Installs translations for all installed plugins. + * + * @param array $args Runtime arguments. + * @param array $assoc_args Runtime arguments. + */ + private function install_many( $args, $assoc_args ) { + $language_codes = (array) $args; + $plugins = $this->get_all_plugins(); + + if ( empty( $assoc_args['format'] ) ) { + $assoc_args['format'] = 'table'; + } + + if ( in_array( $assoc_args['format'], array( 'json', 'csv' ) ) ) { + $logger = new \WP_CLI\Loggers\Quiet; + \WP_CLI::set_logger( $logger ); + } + + if ( empty( $plugins ) ) { + \WP_CLI::success( 'No plugins installed.' ); + return; + } + + $count = count( $plugins ) * count( $language_codes ); + + $results = array(); + + $successes = $errors = $skips = 0; + foreach ( $plugins as $plugin_path => $plugin_details ) { + $plugin_name = \WP_CLI\Utils\get_plugin_name( $plugin_path ); + + $available = $this->get_installed_languages( $plugin_name ); + + foreach ( $language_codes as $language_code ) { + $result = [ + 'name' => $plugin_name, + 'locale' => $language_code, + ]; + + if ( in_array( $language_code, $available, true ) ) { + \WP_CLI::log( "Language '{$language_code}' for '{$plugin_details['Name']}' already installed." ); + $result['status'] = 'already installed'; + $skips++; + } else { + $response = $this->download_language_pack( $language_code, $plugin_name ); + + if ( is_wp_error( $response ) ) { + \WP_CLI::warning( $response ); + \WP_CLI::log( "Language '{$language_code}' for '{$plugin_details['Name']}' not installed." ); + + if ( 'not_found' === $response->get_error_code() ) { + $result['status'] = 'not available'; + $skips++; + } else { + $result['status'] = 'not installed'; + $errors++; + } + } else { + \WP_CLI::log( "Language '{$language_code}' for '{$plugin_details['Name']}' installed." ); + $result['status'] = 'installed'; + $successes++; + } + } + + $results[] = (object) $result; + } + } + + if ( 'summary' !== $assoc_args['format'] ) { + \WP_CLI\Utils\format_items( $assoc_args['format'], $results, array( 'name', 'locale', 'status' ) ); + } + + \WP_CLI\Utils\report_batch_operation_results( 'language', 'install', $count, $successes, $errors, $skips ); + } + /** * Uninstalls a given language for a plugin. * diff --git a/src/Theme_Language_Command.php b/src/Theme_Language_Command.php index e44afd3ad..c0ca68af0 100644 --- a/src/Theme_Language_Command.php +++ b/src/Theme_Language_Command.php @@ -191,12 +191,26 @@ public function is_installed( $args, $assoc_args = array() ) { * * ## OPTIONS * - * + * [] * : Theme to install language for. * + * [--all] + * : If set, languages for all themes will be installed. + * * ... * : Language code to install. * + * [--format=] + * : Render output in a particular format. Used when installing languages for all themes. + * --- + * default: table + * options: + * - table + * - csv + * - json + * - summary + * --- + * * ## EXAMPLES * * # Install the Japanese language for Twenty Seventeen. @@ -211,6 +225,26 @@ public function is_installed( $args, $assoc_args = array() ) { * @subcommand install */ public function install( $args, $assoc_args ) { + $all = \WP_CLI\Utils\get_flag_value( $assoc_args, 'all', false ); + + if ( ! $all && count( $args ) < 2 ) { + \WP_CLI::error( 'Please specify a theme, or use --all.' ); + } + + if ( $all ) { + $this->install_many( $args, $assoc_args ); + } else { + $this->install_one( $args, $assoc_args ); + } + } + + /** + * Installs translations for a theme. + * + * @param array $args Runtime arguments. + * @param array $assoc_args Runtime arguments. + */ + private function install_one( $args, $assoc_args ) { $theme = array_shift( $args ); $language_codes = (array) $args; $count = count( $language_codes ); @@ -246,6 +280,82 @@ public function install( $args, $assoc_args ) { \WP_CLI\Utils\report_batch_operation_results( 'language', 'install', $count, $successes, $errors, $skips ); } + /** + * Installs translations for all installed themes. + * + * @param array $args Runtime arguments. + * @param array $assoc_args Runtime arguments. + */ + private function install_many( $args, $assoc_args ) { + $language_codes = (array) $args; + $themes = wp_get_themes(); + + if ( empty( $assoc_args['format'] ) ) { + $assoc_args['format'] = 'table'; + } + + if ( in_array( $assoc_args['format'], array( 'json', 'csv' ) ) ) { + $logger = new \WP_CLI\Loggers\Quiet; + \WP_CLI::set_logger( $logger ); + } + + if ( empty( $themes ) ) { + \WP_CLI::success( 'No themes installed.' ); + return; + } + + $count = count( $themes ) * count( $language_codes ); + + $results = array(); + + $successes = $errors = $skips = 0; + foreach ( $themes as $theme_path => $theme_details ) { + $theme_name = \WP_CLI\Utils\get_theme_name( $theme_path ); + + $available = $this->get_installed_languages( $theme_name ); + + foreach ( $language_codes as $language_code ) { + $result = [ + 'name' => $theme_name, + 'locale' => $language_code, + ]; + + if ( in_array( $language_code, $available, true ) ) { + \WP_CLI::log( "Language '{$language_code}' for '{$theme_details['Name']}' already installed." ); + $result['status'] = 'already installed'; + $skips++; + } else { + $response = $this->download_language_pack( $language_code, $theme_name ); + + if ( is_wp_error( $response ) ) { + \WP_CLI::warning( $response ); + \WP_CLI::log( "Language '{$language_code}' for '{$theme_details['Name']}' not installed." ); + + if ( 'not_found' === $response->get_error_code() ) { + $result['status'] = 'not available'; + $skips++; + } else { + $result['status'] = 'not installed'; + $errors++; + } + } else { + \WP_CLI::log( "Language '{$language_code}' for '{$theme_details['Name']}' installed." ); + $result['status'] = 'installed'; + $successes++; + } + } + + $results[] = (object) $result; + } + } + + if ( 'summary' !== $assoc_args['format'] ) { + \WP_CLI\Utils\format_items( $assoc_args['format'], $results, array( 'name', 'locale', 'status' ) ); + } + + \WP_CLI\Utils\report_batch_operation_results( 'language', 'install', $count, $successes, $errors, $skips ); + } + /** * Uninstalls a given language for a theme. *