From 330a8daccd255a36d26b51fc70d3159182ac2ad8 Mon Sep 17 00:00:00 2001 From: Andrew Nacin Date: Mon, 23 Sep 2013 02:07:51 +0000 Subject: [PATCH] Add a language pack upgrader class. At the conclusion of any upgrade, after the transients are refreshed from the API, pending translations are downloaded and installed to wp-content/languages. props dd32. see #18200. git-svn-id: https://develop.svn.wordpress.org/trunk@25566 602fd350-edb4-49c9-b593-d223f7449a82 --- .../includes/class-wp-upgrader-skins.php | 16 ++- src/wp-admin/includes/class-wp-upgrader.php | 121 ++++++++++++++++++ src/wp-admin/includes/update.php | 22 ++++ src/wp-includes/update.php | 9 ++ 4 files changed, 167 insertions(+), 1 deletion(-) diff --git a/src/wp-admin/includes/class-wp-upgrader-skins.php b/src/wp-admin/includes/class-wp-upgrader-skins.php index d51456566c..d196be883f 100644 --- a/src/wp-admin/includes/class-wp-upgrader-skins.php +++ b/src/wp-admin/includes/class-wp-upgrader-skins.php @@ -608,4 +608,18 @@ class Automatic_Upgrader_Skin extends WP_Upgrader_Skin { function bulk_footer() {} function before() {} function after() {} -} \ No newline at end of file +} + +/** + * A basic Upgrader skin which doesn't have any headers or footers. + * + * @package WordPress + * @subpackage Upgrader + * @since 3.7.0 + */ +class Headerless_Upgrader_Skin extends WP_Upgrader_Skin { + function before() {} + function after() {} + function header() {} + function footer() {} +} diff --git a/src/wp-admin/includes/class-wp-upgrader.php b/src/wp-admin/includes/class-wp-upgrader.php index 2d3fa87504..adce5788ff 100644 --- a/src/wp-admin/includes/class-wp-upgrader.php +++ b/src/wp-admin/includes/class-wp-upgrader.php @@ -1073,6 +1073,127 @@ class Theme_Upgrader extends WP_Upgrader { } +add_action( 'upgrader_process_complete', array( 'Language_Pack_Upgrader', 'async_upgrade' ), 20, 3 ); +class Language_Pack_Upgrader extends WP_Upgrader { + + var $result; + var $bulk = true; + + static function async_upgrade( $upgrader, $context, $package ) { + // Avoid recursion. + if ( $upgrader instanceof Language_Pack_Upgrader ) + return; + + $lp_upgrader = new Language_Pack_Upgrader( new Headerless_Upgrader_Skin() ); + $lp_upgrader->upgrade(); + } + + function upgrade_strings() { + $this->strings['starting_upgrade'] = __( 'Some of your language files need updating. Sit tight for a few more seconds while we update them as well.' ); + $this->strings['up_to_date'] = __( 'The language is up to date.' ); // We need to silently skip this case + $this->strings['no_package'] = __( 'Update package not available.' ); + $this->strings['downloading_package'] = __( 'Downloading language update from %s…' ); + $this->strings['unpack_package'] = __( 'Unpacking the update…' ); + $this->strings['process_failed'] = __( 'Language update failed.' ); + $this->strings['process_success'] = __( 'Language updated successfully.' ); + } + + function upgrade() { + return $this->bulk_upgrade(); + } + + function bulk_upgrade() { + + $this->init(); + $this->upgrade_strings(); + + $language_updates = wp_get_translation_updates(); + + if ( empty( $language_updates ) ) + return true; + + $this->skin->feedback( 'starting_upgrade' ); + + add_filter( 'upgrader_source_selection', array( &$this, 'check_package' ), 10, 3 ); + + $this->skin->header(); + + // Connect to the Filesystem first. + $res = $this->fs_connect( array( WP_CONTENT_DIR, WP_LANG_DIR ) ); + if ( ! $res ) { + $this->skin->footer(); + return false; + } + + $results = array(); + + $this->update_count = count( $language_updates ); + $this->update_current = 0; + foreach ( $language_updates as $language_update ) { + + $destination = WP_LANG_DIR; + if ( 'plugin' == $language_update->type ) + $destination .= '/plugins'; + elseif ( 'theme' == $language_update->type ) + $destination .= '/themes'; + + $this->update_current++; + + $options = array( + 'package' => $language_update->package, + 'destination' => $destination, + 'clear_destination' => false, + 'abort_if_destination_exists' => false, // We expect the destination to exist. + 'clear_working' => true, + 'is_multi' => true, + 'hook_extra' => array( + 'language_update_type' => $language_update->type, + 'language_update' => $language_update, + ) + ); + + $result = $this->run( $options ); + + $results[] = $this->result; + + // Prevent credentials auth screen from displaying multiple times. + if ( false === $result ) + break; + } + + // Clean up our hooks, in case something else does an upgrade on this connection. + remove_filter( 'upgrader_source_selection', array( &$this, 'check_package' ), 10, 2 ); + + return $results; + } + + function check_package( $source, $remote_source ) { + global $wp_filesystem; + + if ( is_wp_error( $source ) ) + return $source; + + // Check that the folder contains a valid language. + $files = $wp_filesystem->dirlist( $remote_source ); + + // Check to see if a .po and .mo exist in the folder. + $po = $mo = false; + foreach ( (array) $files as $file => $filedata ) { + if ( '.po' == substr( $file, -3 ) ) + $po = true; + elseif ( '.mo' == substr( $file, -3 ) ) + $mo = true; + } + + if ( ! $mo || ! $po ) + return new WP_Error( 'incompatible_archive', $this->strings['incompatible_archive'], + __( 'The language pack is missing either the .po or .mo files.' ) ); + + return $source; + } + +} + /** * Core Upgrader class for WordPress. It allows for WordPress to upgrade itself in combination with the wp-admin/includes/update-core.php file * diff --git a/src/wp-admin/includes/update.php b/src/wp-admin/includes/update.php index 9417c79e00..26c2fb6448 100644 --- a/src/wp-admin/includes/update.php +++ b/src/wp-admin/includes/update.php @@ -379,3 +379,25 @@ function maintenance_nag() { echo "
$msg
"; } add_action( 'admin_notices', 'maintenance_nag' ); + +/** + * Retrieves a list of all language updates available. + * + * @since 3.7.0 + */ +function wp_get_translation_updates() { + $updates = array(); + $transients = array( 'update_core' => 'core', 'update_plugins' => 'plugin', 'update_themes' => 'theme' ); + foreach ( $transients as $transient => $type ) { + + $transient = get_site_transient( $transient ); + if ( empty( $transient->translations ) ) + continue; + + foreach ( $transient->translations as $translation ) { + $updates[] = (object) $translation; + } + } + + return $updates; +} diff --git a/src/wp-includes/update.php b/src/wp-includes/update.php index c3904ccae3..d98ed37a2b 100644 --- a/src/wp-includes/update.php +++ b/src/wp-includes/update.php @@ -158,6 +158,9 @@ function wp_update_plugins() { // Check for update on a different schedule, depending on the page. switch ( current_filter() ) { + case 'upgrader_process_complete' : + $timeout = 0; + break; case 'load-update-core.php' : $timeout = MINUTE_IN_SECONDS; break; @@ -283,6 +286,9 @@ function wp_update_themes() { // Check for update on a different schedule, depending on the page. switch ( current_filter() ) { + case 'upgrader_process_complete' : + $timeout = 0; + break; case 'load-update-core.php' : $timeout = MINUTE_IN_SECONDS; break; @@ -485,18 +491,21 @@ if ( ( ! is_main_site() && ! is_network_admin() ) || ( defined( 'DOING_AJAX' ) & add_action( 'admin_init', '_maybe_update_core' ); add_action( 'wp_version_check', 'wp_version_check' ); +add_action( 'upgrader_process_complete', 'wp_version_check' ); add_action( 'load-plugins.php', 'wp_update_plugins' ); add_action( 'load-update.php', 'wp_update_plugins' ); add_action( 'load-update-core.php', 'wp_update_plugins' ); add_action( 'admin_init', '_maybe_update_plugins' ); add_action( 'wp_update_plugins', 'wp_update_plugins' ); +add_action( 'upgrader_process_complete', 'wp_update_plugins' ); add_action( 'load-themes.php', 'wp_update_themes' ); add_action( 'load-update.php', 'wp_update_themes' ); add_action( 'load-update-core.php', 'wp_update_themes' ); add_action( 'admin_init', '_maybe_update_themes' ); add_action( 'wp_update_themes', 'wp_update_themes' ); +add_action( 'upgrader_process_complete', 'wp_update_themes' ); // Automatic Updates - Cron callback add_action( 'wp_auto_updates_maybe_update', 'wp_auto_updates_maybe_update' );