From f6ebc1a80cb2095a11c01b4b1a778d5bec6dc300 Mon Sep 17 00:00:00 2001 From: Felix Arntz Date: Fri, 18 Aug 2017 18:31:44 +0000 Subject: [PATCH] Role/Capability: Introduce capabilities dedicated to installing and updating language files. The new meta capabilities are called `install_languages` and `update_languages`. Prior to this change, there were no proper capability checks applied. Instead only the filesystem and related constants were checked, and for actual permissions a rather vague fallback was used where a user needed to have at least one of the other updating capabilities. In addition to being generally more verbose, the new capabilities make it possible for example to allow a user to update languages, but nothing else. By default they fall back to the original way of how they were handled. Props johnbillion, flixos90. Fixes #39677. Built from https://develop.svn.wordpress.org/trunk@41268 git-svn-id: http://core.svn.wordpress.org/trunk@41108 1a063a9b-81f0-0310-95a4-ce76da25c4cd --- wp-admin/menu.php | 9 ++++++--- wp-admin/network/settings.php | 4 ++-- wp-admin/network/site-new.php | 6 ++++-- wp-admin/options-general.php | 2 +- wp-admin/options.php | 10 ++++------ wp-admin/update-core.php | 18 +++++++++++------- wp-includes/capabilities.php | 33 +++++++++++++++++++++++++++++++++ wp-includes/default-filters.php | 3 +++ wp-includes/version.php | 2 +- 9 files changed, 65 insertions(+), 22 deletions(-) diff --git a/wp-admin/menu.php b/wp-admin/menu.php index 296f3c0ca6..990ddf7dbe 100644 --- a/wp-admin/menu.php +++ b/wp-admin/menu.php @@ -33,12 +33,15 @@ if ( ! is_multisite() || current_user_can( 'update_core' ) ) { } if ( ! is_multisite() ) { - if ( current_user_can( 'update_core' ) ) + if ( current_user_can( 'update_core' ) ) { $cap = 'update_core'; - elseif ( current_user_can( 'update_plugins' ) ) + } elseif ( current_user_can( 'update_plugins' ) ) { $cap = 'update_plugins'; - else + } elseif ( current_user_can( 'update_themes' ) ) { $cap = 'update_themes'; + } else { + $cap = 'update_languages'; + } $submenu[ 'index.php' ][10] = array( sprintf( __('Updates %s'), "" . number_format_i18n($update_data['counts']['total']) . "" ), $cap, 'update-core.php'); unset( $cap ); } diff --git a/wp-admin/network/settings.php b/wp-admin/network/settings.php index efeaebdcfd..3ca1daa6e1 100644 --- a/wp-admin/network/settings.php +++ b/wp-admin/network/settings.php @@ -63,7 +63,7 @@ if ( $_POST ) { ); // Handle translation install. - if ( ! empty( $_POST['WPLANG'] ) && wp_can_install_language_pack() ) { // @todo: Skip if already installed + if ( ! empty( $_POST['WPLANG'] ) && current_user_can( 'install_languages' ) ) { $language = wp_download_language_pack( $_POST['WPLANG'] ); if ( $language ) { $_POST['WPLANG'] = $language; @@ -342,7 +342,7 @@ if ( isset( $_GET['updated'] ) ) { 'selected' => $lang, 'languages' => $languages, 'translations' => $translations, - 'show_available_translations' => wp_can_install_language_pack(), + 'show_available_translations' => current_user_can( 'install_languages' ), ) ); ?> diff --git a/wp-admin/network/site-new.php b/wp-admin/network/site-new.php index 0810f8a87a..e0ccfc26fa 100644 --- a/wp-admin/network/site-new.php +++ b/wp-admin/network/site-new.php @@ -66,7 +66,9 @@ if ( isset($_REQUEST['action']) && 'add-site' == $_REQUEST['action'] ) { if ( isset( $_POST['WPLANG'] ) ) { if ( '' === $_POST['WPLANG'] ) { $meta['WPLANG'] = ''; // en_US - } elseif ( wp_can_install_language_pack() ) { + } elseif ( in_array( $_POST['WPLANG'], get_available_languages() ) ) { + $meta['WPLANG'] = $_POST['WPLANG']; + } elseif ( current_user_can( 'install_languages' ) ) { $language = wp_download_language_pack( wp_unslash( $_POST['WPLANG'] ) ); if ( $language ) { $meta['WPLANG'] = $language; @@ -234,7 +236,7 @@ if ( ! empty( $messages ) ) { 'selected' => $lang, 'languages' => $languages, 'translations' => $translations, - 'show_available_translations' => wp_can_install_language_pack(), + 'show_available_translations' => current_user_can( 'install_languages' ), ) ); ?> diff --git a/wp-admin/options-general.php b/wp-admin/options-general.php index 0fcdde3518..e85b5bb784 100644 --- a/wp-admin/options-general.php +++ b/wp-admin/options-general.php @@ -151,7 +151,7 @@ if ( ! empty( $languages ) || ! empty( $translations ) ) { 'selected' => $locale, 'languages' => $languages, 'translations' => $translations, - 'show_available_translations' => ( ! is_multisite() || is_super_admin() ) && wp_can_install_language_pack(), + 'show_available_translations' => current_user_can( 'install_languages' ), ) ); // Add note about deprecated WPLANG constant. diff --git a/wp-admin/options.php b/wp-admin/options.php index e11ffee9d5..9d9c35f58d 100644 --- a/wp-admin/options.php +++ b/wp-admin/options.php @@ -177,14 +177,12 @@ if ( 'update' == $action ) { } // Handle translation install. - if ( ! empty( $_POST['WPLANG'] ) && ( ! is_multisite() || is_super_admin() ) ) { // @todo: Skip if already installed + if ( ! empty( $_POST['WPLANG'] ) && current_user_can( 'install_languages' ) ) { require_once( ABSPATH . 'wp-admin/includes/translation-install.php' ); - if ( wp_can_install_language_pack() ) { - $language = wp_download_language_pack( $_POST['WPLANG'] ); - if ( $language ) { - $_POST['WPLANG'] = $language; - } + $language = wp_download_language_pack( $_POST['WPLANG'] ); + if ( $language ) { + $_POST['WPLANG'] = $language; } } } diff --git a/wp-admin/update-core.php b/wp-admin/update-core.php index a0801b9bad..efd86a0194 100644 --- a/wp-admin/update-core.php +++ b/wp-admin/update-core.php @@ -19,7 +19,7 @@ if ( is_multisite() && ! is_network_admin() ) { exit(); } -if ( ! current_user_can( 'update_core' ) && ! current_user_can( 'update_themes' ) && ! current_user_can( 'update_plugins' ) ) +if ( ! current_user_can( 'update_core' ) && ! current_user_can( 'update_themes' ) && ! current_user_can( 'update_plugins' ) && ! current_user_can( 'update_languages' ) ) wp_die( __( 'Sorry, you are not allowed to update this site.' ) ); /** @@ -608,15 +608,19 @@ if ( 'upgrade-core' == $action ) { echo '   ' . __( 'Check Again' ) . ''; echo '

'; - if ( $core = current_user_can( 'update_core' ) ) + if ( current_user_can( 'update_core' ) ) { core_upgrade_preamble(); - if ( $plugins = current_user_can( 'update_plugins' ) ) + } + if ( current_user_can( 'update_plugins' ) ) { list_plugin_updates(); - if ( $themes = current_user_can( 'update_themes' ) ) + } + if ( current_user_can( 'update_themes' ) ) { list_theme_updates(); - if ( $core || $plugins || $themes ) + } + if ( current_user_can( 'update_languages' ) ) { list_translation_updates(); - unset( $core, $plugins, $themes ); + } + /** * Fires after the core, plugin, and theme update tables. * @@ -729,7 +733,7 @@ if ( 'upgrade-core' == $action ) { } elseif ( 'do-translation-upgrade' == $action ) { - if ( ! current_user_can( 'update_core' ) && ! current_user_can( 'update_plugins' ) && ! current_user_can( 'update_themes' ) ) + if ( ! current_user_can( 'update_languages' ) ) wp_die( __( 'Sorry, you are not allowed to update this site.' ) ); check_admin_referer( 'upgrade-translations' ); diff --git a/wp-includes/capabilities.php b/wp-includes/capabilities.php index 13851cc2e1..5993a77caf 100644 --- a/wp-includes/capabilities.php +++ b/wp-includes/capabilities.php @@ -392,6 +392,20 @@ function map_meta_cap( $cap, $user_id ) { $caps[] = $cap; } break; + case 'install_languages': + case 'update_languages': + if ( ! function_exists( 'wp_can_install_language_pack' ) ) { + require_once( ABSPATH . 'wp-admin/includes/translation-install.php' ); + } + + if ( ! wp_can_install_language_pack() ) { + $caps[] = 'do_not_allow'; + } elseif ( is_multisite() && ! is_super_admin( $user_id ) ) { + $caps[] = 'do_not_allow'; + } else { + $caps[] = 'install_languages'; + } + break; case 'activate_plugins': $caps[] = $cap; if ( is_multisite() ) { @@ -826,3 +840,22 @@ function revoke_super_admin( $user_id ) { } return false; } + +/** + * Filters the user capabilities to grant the 'install_languages' capability as necessary. + * + * A user must have at least one out of the 'update_core', 'install_plugins', and + * 'install_themes' capabilities to qualify for 'install_languages'. + * + * @since 4.9.0 + * + * @param array $allcaps An array of all the user's capabilities. + * @return array Filtered array of the user's capabilities. + */ +function wp_maybe_grant_install_languages_cap( $allcaps ) { + if ( ! empty( $allcaps['update_core'] ) || ! empty( $allcaps['install_plugins'] ) || ! empty( $allcaps['install_themes'] ) ) { + $allcaps['install_languages'] = true; + } + + return $allcaps; +} diff --git a/wp-includes/default-filters.php b/wp-includes/default-filters.php index 39254ca7f9..a196f4ff19 100644 --- a/wp-includes/default-filters.php +++ b/wp-includes/default-filters.php @@ -512,4 +512,7 @@ add_filter( 'oembed_dataparse', 'wp_filter_oembed_result', 10, 3 ); add_filter( 'oembed_response_data', 'get_oembed_response_data_rich', 10, 4 ); add_filter( 'pre_oembed_result', 'wp_filter_pre_oembed_result', 10, 3 ); +// Capabilities +add_filter( 'user_has_cap', 'wp_maybe_grant_install_languages_cap', 1 ); + unset( $filter, $action ); diff --git a/wp-includes/version.php b/wp-includes/version.php index 077cfe8dee..66a53b50fc 100644 --- a/wp-includes/version.php +++ b/wp-includes/version.php @@ -4,7 +4,7 @@ * * @global string $wp_version */ -$wp_version = '4.9-alpha-41267'; +$wp_version = '4.9-alpha-41268'; /** * Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.