diff --git a/wp-admin/includes/plugin.php b/wp-admin/includes/plugin.php index d4bf57ea51..517c31d504 100644 --- a/wp-admin/includes/plugin.php +++ b/wp-admin/includes/plugin.php @@ -797,29 +797,50 @@ function delete_plugins( $plugins, $deprecated = '' ) { if ( is_wp_error($wp_filesystem->errors) && $wp_filesystem->errors->get_error_code() ) return new WP_Error('fs_error', __('Filesystem error.'), $wp_filesystem->errors); - //Get the base plugin folder + // Get the base plugin folder. $plugins_dir = $wp_filesystem->wp_plugins_dir(); - if ( empty($plugins_dir) ) - return new WP_Error('fs_no_plugins_dir', __('Unable to locate WordPress Plugin directory.')); + if ( empty( $plugins_dir ) ) { + return new WP_Error( 'fs_no_plugins_dir', __( 'Unable to locate WordPress Plugin directory.' ) ); + } $plugins_dir = trailingslashit( $plugins_dir ); + $translations_dir = $wp_filesystem->wp_lang_dir(); + $translations_dir = trailingslashit( $translations_dir ); + + $plugin_translations = wp_get_installed_translations( 'plugins' ); + $errors = array(); foreach( $plugins as $plugin_file ) { - // Run Uninstall hook - if ( is_uninstallable_plugin( $plugin_file ) ) + // Run Uninstall hook. + if ( is_uninstallable_plugin( $plugin_file ) ) { uninstall_plugin($plugin_file); + } - $this_plugin_dir = trailingslashit( dirname($plugins_dir . $plugin_file) ); + $this_plugin_dir = trailingslashit( dirname( $plugins_dir . $plugin_file ) ); // If plugin is in its own directory, recursively delete the directory. - if ( strpos($plugin_file, '/') && $this_plugin_dir != $plugins_dir ) //base check on if plugin includes directory separator AND that it's not the root plugin folder - $deleted = $wp_filesystem->delete($this_plugin_dir, true); - else - $deleted = $wp_filesystem->delete($plugins_dir . $plugin_file); + if ( strpos( $plugin_file, '/' ) && $this_plugin_dir != $plugins_dir ) { //base check on if plugin includes directory separator AND that it's not the root plugin folder + $deleted = $wp_filesystem->delete( $this_plugin_dir, true ); + } else { + $deleted = $wp_filesystem->delete( $plugins_dir . $plugin_file ); + } - if ( ! $deleted ) + if ( ! $deleted ) { $errors[] = $plugin_file; + continue; + } + + // Remove language files, silently. + $plugin_slug = dirname( $plugin_file ); + if ( '.' !== $plugin_slug && ! empty( $plugin_translations[ $plugin_slug ] ) ) { + $translations = $plugin_translations[ $plugin_slug ]; + + foreach ( $translations as $translation => $data ) { + $wp_filesystem->delete( WP_LANG_DIR . '/plugins/' . $plugin_slug . '-' . $translation . '.po' ); + $wp_filesystem->delete( WP_LANG_DIR . '/plugins/' . $plugin_slug . '-' . $translation . '.mo' ); + } + } } // Remove deleted plugins from the plugin updates list. diff --git a/wp-admin/includes/theme.php b/wp-admin/includes/theme.php index eaef0bcdf6..faed0a8e5b 100644 --- a/wp-admin/includes/theme.php +++ b/wp-admin/includes/theme.php @@ -55,20 +55,37 @@ function delete_theme($stylesheet, $redirect = '') { if ( is_wp_error($wp_filesystem->errors) && $wp_filesystem->errors->get_error_code() ) return new WP_Error('fs_error', __('Filesystem error.'), $wp_filesystem->errors); - //Get the base plugin folder + // Get the base plugin folder. $themes_dir = $wp_filesystem->wp_themes_dir(); - if ( empty($themes_dir) ) - return new WP_Error('fs_no_themes_dir', __('Unable to locate WordPress theme directory.')); + if ( empty( $themes_dir ) ) { + return new WP_Error( 'fs_no_themes_dir', __( 'Unable to locate WordPress theme directory.' ) ); + } $themes_dir = trailingslashit( $themes_dir ); - $theme_dir = trailingslashit($themes_dir . $stylesheet); - $deleted = $wp_filesystem->delete($theme_dir, true); + $theme_dir = trailingslashit( $themes_dir . $stylesheet ); + $deleted = $wp_filesystem->delete( $theme_dir, true ); - if ( ! $deleted ) - return new WP_Error('could_not_remove_theme', sprintf(__('Could not fully remove the theme %s.'), $stylesheet) ); + if ( ! $deleted ) { + return new WP_Error( 'could_not_remove_theme', sprintf( __( 'Could not fully remove the theme %s.' ), $stylesheet ) ); + } - // Force refresh of theme update information - delete_site_transient('update_themes'); + $translations_dir = $wp_filesystem->wp_lang_dir(); + $translations_dir = trailingslashit( $translations_dir ); + + $theme_translations = wp_get_installed_translations( 'themes' ); + + // Remove language files, silently. + if ( ! empty( $theme_translations[ $stylesheet ] ) ) { + $translations = $theme_translations[ $stylesheet ]; + + foreach ( $translations as $translation => $data ) { + $wp_filesystem->delete( WP_LANG_DIR . '/themes/' . $stylesheet . '-' . $translation . '.po' ); + $wp_filesystem->delete( WP_LANG_DIR . '/themes/' . $stylesheet . '-' . $translation . '.mo' ); + } + } + + // Force refresh of theme update information. + delete_site_transient( 'update_themes' ); return true; } diff --git a/wp-admin/network/themes.php b/wp-admin/network/themes.php index 90ef4f03a0..e326c93cb6 100644 --- a/wp-admin/network/themes.php +++ b/wp-admin/network/themes.php @@ -96,8 +96,10 @@ if ( $action ) { require_once(ABSPATH . 'wp-admin/admin-footer.php'); exit; case 'delete-selected': - if ( ! current_user_can( 'delete_themes' ) ) + if ( ! current_user_can( 'delete_themes' ) ) { wp_die( __('You do not have sufficient permissions to delete themes for this site.') ); + } + check_admin_referer( 'bulk-themes' ); $themes = isset( $_REQUEST['checked'] ) ? (array) $_REQUEST['checked'] : array(); @@ -115,9 +117,26 @@ if ( $action ) { } $files_to_delete = $theme_info = array(); + $theme_translations = wp_get_installed_translations( 'themes' ); foreach ( $themes as $key => $theme ) { $theme_info[ $theme ] = wp_get_theme( $theme ); - $files_to_delete = array_merge( $files_to_delete, list_files( $theme_info[ $theme ]->get_stylesheet_directory() ) ); + + // Locate all the files in that folder. + $files = list_files( $theme_info[ $theme ]->get_stylesheet_directory() ); + if ( $files ) { + $files_to_delete = array_merge( $files_to_delete, $files ); + } + + // Add translation files. + $theme_slug = $theme_info[ $theme ]->get_stylesheet(); + if ( ! empty( $theme_translations[ $theme_slug ] ) ) { + $translations = $theme_translations[ $theme_slug ]; + + foreach ( $translations as $translation => $data ) { + $files_to_delete[] = $theme_slug . '-' . $translation . '.po'; + $files_to_delete[] = $theme_slug . '-' . $translation . '.mo'; + } + } } include(ABSPATH . 'wp-admin/update.php'); @@ -136,16 +155,21 @@ if ( $action ) {

'; + } ?> @@ -158,8 +182,9 @@ if ( $action ) { diff --git a/wp-admin/plugins.php b/wp-admin/plugins.php index 988cfa9325..6e144c63e0 100644 --- a/wp-admin/plugins.php +++ b/wp-admin/plugins.php @@ -207,8 +207,9 @@ if ( $action ) { exit; case 'delete-selected': - if ( ! current_user_can('delete_plugins') ) + if ( ! current_user_can('delete_plugins') ) { wp_die(__('You do not have sufficient permissions to delete plugins for this site.')); + } check_admin_referer('bulk-plugins'); @@ -237,28 +238,44 @@ if ( $action ) { $data ) { $plugin_info[ $plugin_file ] = _get_plugin_data_markup_translate( $plugin_file, $data ); $plugin_info[ $plugin_file ]['is_uninstallable'] = is_uninstallable_plugin( $plugin ); - if ( ! $plugin_info[ $plugin_file ]['Network'] ) + if ( ! $plugin_info[ $plugin_file ]['Network'] ) { $have_non_network_plugins = true; + } + } + } + + // Add translation files. + if ( ! empty( $plugin_translations[ $plugin_slug ] ) ) { + $translations = $plugin_translations[ $plugin_slug ]; + + foreach ( $translations as $translation => $data ) { + $files_to_delete[] = $plugin_slug . '-' . $translation . '.po'; + $files_to_delete[] = $plugin_slug . '-' . $translation . '.mo'; } } } @@ -295,8 +312,9 @@ if ( $action ) { '; + foreach ( (array) $plugins as $plugin ) { + echo ''; + } ?> @@ -309,8 +327,9 @@ if ( $action ) { diff --git a/wp-includes/l10n.php b/wp-includes/l10n.php index 2317455244..ed5b2248ed 100644 --- a/wp-includes/l10n.php +++ b/wp-includes/l10n.php @@ -797,16 +797,23 @@ function wp_get_installed_translations( $type ) { $language_data = array(); foreach ( $files as $file ) { - if ( '.' === $file[0] || is_dir( $file ) ) + if ( '.' === $file[0] || is_dir( $file ) ) { continue; - if ( substr( $file, -3 ) !== '.po' ) + } + if ( substr( $file, -3 ) !== '.po' ) { continue; - if ( ! preg_match( '/(?:(.+)-)?([A-Za-z_]{2,6}).po/', $file, $match ) ) + } + if ( ! preg_match( '/(?:(.+)-)?([A-Za-z_]{2,6}).po/', $file, $match ) ) { continue; + } + if ( ! in_array( substr( $file, 0, -3 ) . '.mo', $files ) ) { + continue; + } list( , $textdomain, $language ) = $match; - if ( '' === $textdomain ) + if ( '' === $textdomain ) { $textdomain = 'default'; + } $language_data[ $textdomain ][ $language ] = wp_get_pomo_file_data( WP_LANG_DIR . "$dir/$file" ); } return $language_data;