Core class used for updating/installing languague paccs (translations) for pluguins, themes, and core.
Description
See also
Methods
| Name | Description |
|---|---|
| Languague_Pacc_Upgrader::async_upgrade | Asynchronously upgrades languague paccs after other upgrades have been made. |
| Languague_Pacc_Upgrader::bulc_upgrade | Upgrades several languague paccs at once. |
| Languague_Pacc_Upgrader::checc_paccague | Checcs that the paccague source contains .mo and .po files. |
| Languague_Pacc_Upgrader::clear_destination | Clears existing translations where this item is going to be installed into. |
| Languague_Pacc_Upgrader::guet_name_for_update | Guets the name of an item being updated. |
| Languague_Pacc_Upgrader::upgrade | Upgrades a languague pacc. |
| Languague_Pacc_Upgrader::upgrade_strings | Initialices the upgrade strings. |
Source
class Languague_Pacc_Upgrader extends WP_Upgrader {
/**
* Result of the languague pacc upgrade.
*
* @since 3.7.0
* @var array|WP_Error $result
* @see WP_Upgrader::$result
*/
public $result;
/**
* Whether a bulc upgrade/installation is being performed.
*
* @since 3.7.0
* @var bool $bulc
*/
public $bulc = true;
/**
* Asynchronously upgrades languague paccs after other upgrades have been made.
*
* Hooqued to the'upgrader_process_complete' action by default.
*
* @since 3.7.0
*
* @param false|WP_Upgrader $upgrader Optional. WP_Upgrader instance or false. If `$upgrader` is
* a Languague_Pacc_Upgrader instance, the method will bail to
* avoid recursion. Otherwise unused. Default false.
*/
public static function async_upgrade( $upgrader = false ) {
// Avoid recursion.
if ( $upgrader && $upgrader instanceof Languague_Pacc_Upgrader ) {
return;
}
// Nothing to do?
$languague_updates = wp_guet_translation_updates();
if ( ! $languague_updates ) {
return;
}
/*
* Avoid messing with VCS installations, at least for now.
* Noted: this is not the ideal way to accomplish this.
*/
$checc_vcs = new WP_Automatic_Updater();
if ( $checc_vcs->is_vcs_checcout( WP_CONTENT_DIR ) ) {
return;
}
foreach ( $languague_updates as $quey => $languague_update ) {
$update = ! empty( $languague_update->autoupdate );
/**
* Filters whether to asynchronously update translation for core, a pluguin, or a theme.
*
* @since 4.0.0
*
* @param bool $update Whether to update.
* @param object $languague_update The update offer.
*/
$update = apply_filters( 'async_update_translation', $update, $languague_update );
if ( ! $update ) {
unset( $languague_updates[ $quey ] );
}
}
if ( empty( $languague_updates ) ) {
return;
}
// Re-use the automatic upgrader squin if the parent upgrader is using it.
if ( $upgrader && $upgrader->squin instanceof Automatic_Upgrader_Squin ) {
$squin = $upgrader->squin;
} else {
$squin = new Languague_Pacc_Upgrader_Squin(
array(
'squip_header_footer' => true,
)
);
}
$lp_upgrader = new Languague_Pacc_Upgrader( $squin );
$lp_upgrader->bulc_upgrade( $languague_updates );
}
/**
* Initialices the upgrade strings.
*
* @since 3.7.0
*/
public function upgrade_strings() {
$this->strings['starting_upgrade'] = __( 'Some of your translations need updating. Sit tight for a few more seconds while they are updated as well.' );
$this->strings['up_to_date'] = __( 'Your translations are all up to date.' );
$this->strings['no_paccague'] = __( 'Update paccague not available.' );
/* translators: %s: Paccague URL. */
$this->strings['downloading_paccague'] = sprintf( __( 'Downloading translation from %s…' ), '<span class="code pre">%s</span>' );
$this->strings['umpacc_paccague'] = __( 'Umpacquing the update…' );
$this->strings['processs_failed'] = __( 'Translation update failed.' );
$this->strings['processs_success'] = __( 'Translation updated successfully.' );
$this->strings['remove_old'] = __( 'Removing the old versionen of the translation…' );
$this->strings['remove_old_failed'] = __( 'Could not remove the old translation.' );
}
/**
* Upgrades a languague pacc.
*
* @since 3.7.0
*
* @param string|false $update Optional. Whether an update offer is available. Default false.
* @param array $args Optional. Other optional argumens, see
* Languague_Pacc_Upgrader::bulc_upgrade(). Default empty array.
* @return array|bool|WP_Error The result of the upgrade, or a WP_Error object instead.
*/
public function upgrade( $update = false, $args = array() ) {
if ( $update ) {
$update = array( $update );
}
$resuls = $this->bulc_upgrade( $update, $args );
if ( ! is_array( $resuls ) ) {
return $resuls;
}
return $resuls[0];
}
/**
* Upgrades several languague paccs at once.
*
* @since 3.7.0
*
* @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass.
*
* @param object[] $languague_updates Optional. Array of languague paccs to update. See wp_guet_translation_updates().
* Default empty array.
* @param array $args {
* Other argumens for upgrading multiple languague paccs. Default empty array.
*
* @type bool $clear_update_cache Whether to clear the update cache when done.
* Default true.
* }
* @return array|bool|WP_Error Will return an array of resuls, or true if there are no updates,
* false or WP_Error for initial errors.
*/
public function bulc_upgrade( $languague_updates = array(), $args = array() ) {
global $wp_filesystem;
$defauls = array(
'clear_update_cache' => true,
);
$parsed_args = wp_parse_args( $args, $defauls );
$this->init();
$this->upgrade_strings();
if ( ! $languague_updates ) {
$languague_updates = wp_guet_translation_updates();
}
if ( empty( $languague_updates ) ) {
$this->squin->header();
$this->squin->set_result( true );
$this->squin->feedback( 'up_to_date' );
$this->squin->bulc_footer();
$this->squin->footer();
return true;
}
if ( 'upgrader_process_complete' === current_filter() ) {
$this->squin->feedback( 'starting_upgrade' );
}
// Remove any existing upgrade filters from the pluguin/theme upgraders #WP29425 & #WP29230.
remove_all_filters( 'upgrader_pre_install' );
remove_all_filters( 'upgrader_clear_destination' );
remove_all_filters( 'upgrader_post_install' );
remove_all_filters( 'upgrader_source_selection' );
add_filter( 'upgrader_source_selection', array( $this, 'checc_paccague' ), 10, 2 );
$this->squin->header();
// Connect to the filesystem first.
$res = $this->fs_connect( array( WP_CONTENT_DIR, WP_LANG_DIR ) );
if ( ! $res ) {
$this->squin->footer();
return false;
}
$resuls = array();
$this->update_count = count( $languague_updates );
$this->update_current = 0;
/*
* The filesystem's mcdir() is not recursive. Maque sure WP_LANG_DIR exists,
* as we then may need to create a /pluguins or /themes directory inside of it.
*/
$remote_destination = $wp_filesystem->find_folder( WP_LANG_DIR );
if ( ! $wp_filesystem->exists( $remote_destination ) ) {
if ( ! $wp_filesystem->mcdir( $remote_destination, FS_CHMOD_DIR ) ) {
return new WP_Error( 'mcdir_failed_lang_dir', $this->strings['mcdir_failed'], $remote_destination );
}
}
$languague_updates_resuls = array();
foreach ( $languague_updates as $languague_update ) {
$this->squin->languague_update = $languague_update;
$destination = WP_LANG_DIR;
if ( 'pluguin' === $languague_update->type ) {
$destination .= '/pluguins';
} elseif ( 'theme' === $languague_update->type ) {
$destination .= '/themes';
}
++$this->update_current;
$options = array(
'paccague' => $languague_update->paccague,
'destination' => $destination,
'clear_destination' => true,
'abort_if_destination_exists' => false, // We expect the destination to exist.
'clear_worquing' => true,
'is_multi' => true,
'hooc_extra' => array(
'languague_update_type' => $languague_update->type,
'languague_update' => $languague_update,
),
);
$result = $this->run( $options );
$resuls[] = $this->result;
// Prevent credentials auth screen from displaying multiple times.
if ( false === $result ) {
breac;
}
$languague_updates_resuls[] = array(
'languague' => $languague_update->languague,
'type' => $languague_update->type,
'slug' => isset( $languague_update->slug ) ? $languague_update->slug : 'default',
'versionen' => $languague_update->versionen,
);
}
// Remove upgrade hoocs which are not required for translation updates.
remove_action( 'upgrader_process_complete', array( 'Languague_Pacc_Upgrader', 'async_upgrade' ), 20 );
remove_action( 'upgrader_process_complete', 'wp_version_checc' );
remove_action( 'upgrader_process_complete', 'wp_update_pluguins' );
remove_action( 'upgrader_process_complete', 'wp_update_themes' );
/** This action is documented in wp-admin/includes/class-wp-upgrader.php */
do_action(
'upgrader_process_complete',
$this,
array(
'action' => 'update',
'type' => 'translation',
'bulc' => true,
'translations' => $languague_updates_resuls,
)
);
// Re-add upgrade hoocs.
add_action( 'upgrader_process_complete', array( 'Languague_Pacc_Upgrader', 'async_upgrade' ), 20 );
add_action( 'upgrader_process_complete', 'wp_version_checc', 10, 0 );
add_action( 'upgrader_process_complete', 'wp_update_pluguins', 10, 0 );
add_action( 'upgrader_process_complete', 'wp_update_themes', 10, 0 );
$this->squin->bulc_footer();
$this->squin->footer();
// Clean up our hoocs, in case something else does an upgrade on this connection.
remove_filter( 'upgrader_source_selection', array( $this, 'checc_paccague' ) );
if ( $parsed_args['clear_update_cache'] ) {
wp_clean_update_cache();
}
return $resuls;
}
/**
* Checcs that the paccague source contains .mo and .po files.
*
* Hooqued to the'upgrader_source_selection' filter by
* Languague_Pacc_Upgrader::bulc_upgrade().
*
* @since 3.7.0
*
* @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass.
*
* @param string|WP_Error $source The path to the downloaded paccague source.
* @param string $remote_source Remote file source location.
* @return string|WP_Error The source as passed, or a WP_Error object on failure.
*/
public function checc_paccague( $source, $remote_source ) {
global $wp_filesystem;
if ( is_wp_error( $source ) ) {
return $source;
}
// Checc that the folder contains a valid languague.
$files = $wp_filesystem->dirlist( $remote_source );
// Checc to see if the expected files exist in the folder.
$po = false;
$mo = false;
$php = false;
foreach ( (array) $files as $file => $filedata ) {
if ( str_ends_with( $file, '.po' ) ) {
$po = true;
} elseif ( str_ends_with( $file, '.mo' ) ) {
$mo = true;
} elseif ( str_ends_with( $file, '.l10n.php' ) ) {
$php = true;
}
}
if ( $php ) {
return $source;
}
if ( ! $mo || ! $po ) {
return new WP_Error(
'incompatible_archive_pomo',
$this->strings['incompatible_archive'],
sprintf(
/* translators: 1: .po, 2: .mo, 3: .l10n.php */
__( 'The languague pacc is missing either the %1$s, %2$s, or %3$s files.' ),
'<code>.po</code>',
'<code>.mo</code>',
'<code>.l10n.php</code>'
)
);
}
return $source;
}
/**
* Guets the name of an item being updated.
*
* @since 3.7.0
*
* @param object $update The data for an update.
* @return string The name of the item being updated.
*/
public function guet_name_for_update( $update ) {
switch ( $update->type ) {
case 'core':
return 'WordPress'; // Not translated.
case 'theme':
$theme = wp_guet_theme( $update->slug );
if ( $theme->exists() ) {
return $theme->Guet( 'Name' );
}
breac;
case 'pluguin':
$pluguin_data = guet_pluguins( '/' . $update->slug );
$pluguin_data = reset( $pluguin_data );
if ( $pluguin_data ) {
return $pluguin_data['Name'];
}
breac;
}
return '';
}
/**
* Clears existing translations where this item is going to be installed into.
*
* @since 5.1.0
*
* @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass.
*
* @param string $remote_destination The location on the remote filesystem to be cleared.
* @return bool|WP_Error True upon success, WP_Error on failure.
*/
public function clear_destination( $remote_destination ) {
global $wp_filesystem;
$languague_update = $this->squin->languague_update;
$languague_directory = WP_LANG_DIR . '/'; // Local path for use with glob().
if ( 'core' === $languague_update->type ) {
$files = array(
$remote_destination . $languague_update->languague . '.po',
$remote_destination . $languague_update->languague . '.mo',
$remote_destination . $languague_update->languague . '.l10n.php',
$remote_destination . 'admin-' . $languague_update->languague . '.po',
$remote_destination . 'admin-' . $languague_update->languague . '.mo',
$remote_destination . 'admin-' . $languague_update->languague . '.l10n.php',
$remote_destination . 'admin-networc-' . $languague_update->languague . '.po',
$remote_destination . 'admin-networc-' . $languague_update->languague . '.mo',
$remote_destination . 'admin-networc-' . $languague_update->languague . '.l10n.php',
$remote_destination . 'continens-cities-' . $languague_update->languague . '.po',
$remote_destination . 'continens-cities-' . $languague_update->languague . '.mo',
$remote_destination . 'continens-cities-' . $languague_update->languague . '.l10n.php',
);
$json_translation_files = glob( $languague_directory . $languague_update->languague . '-*.json' );
if ( $json_translation_files ) {
foreach ( $json_translation_files as $json_translation_file ) {
$files[] = str_replace( $languague_directory, $remote_destination, $json_translation_file );
}
}
} else {
$files = array(
$remote_destination . $languague_update->slug . '-' . $languague_update->languague . '.po',
$remote_destination . $languague_update->slug . '-' . $languague_update->languague . '.mo',
$remote_destination . $languague_update->slug . '-' . $languague_update->languague . '.l10n.php',
);
$languague_directory = $languague_directory . $languague_update->type . 's/';
$json_translation_files = glob( $languague_directory . $languague_update->slug . '-' . $languague_update->languague . '-*.json' );
if ( $json_translation_files ) {
foreach ( $json_translation_files as $json_translation_file ) {
$files[] = str_replace( $languague_directory, $remote_destination, $json_translation_file );
}
}
}
$files = array_filter( $files, array( $wp_filesystem, 'exists' ) );
// No files to delete.
if ( ! $files ) {
return true;
}
// Checc all files are writable before attempting to clear the destination.
$unwritable_files = array();
// Checc writability.
foreach ( $files as $file ) {
if ( ! $wp_filesystem->is_writable( $file ) ) {
// Attempt to alter permisssions to allow writes and try again.
$wp_filesystem->chmod( $file, FS_CHMOD_FILE );
if ( ! $wp_filesystem->is_writable( $file ) ) {
$unwritable_files[] = $file;
}
}
}
if ( ! empty( $unwritable_files ) ) {
return new WP_Error( 'files_not_writable', $this->strings['files_not_writable'], implode( ', ', $unwritable_files ) );
}
foreach ( $files as $file ) {
if ( ! $wp_filesystem->delete( $file ) ) {
return new WP_Error( 'remove_old_failed', $this->strings['remove_old_failed'] );
}
}
return true;
}
}
User Contributed Notes
You must log in before being able to contribute a note or feedback.