Plugins: Introduce singular capabilities for activating and deactivating individual plugins.
This introduces the following meta capabilities: * `activate_plugin` * `deactivate_plugin` * `deactivate_plugins` The singular `activate_plugin` and `deactivate_plugin` capabilities are used along with the corresponding plugin name when determining whether or not a user can activate or deactivate an individual plugin. The plural `deactivate_plugins` capability is used in place of the existing `activate_plugins` capability when determining whether a user can deactivate plugins. Each of these new meta capabilities map to the existing `activate_plugins` primitive capability, which means there is no change in existing behaviour, but plugins can now filter the capabilities required to activate and deactivate individual plugins. Fixes #38652 Built from https://develop.svn.wordpress.org/trunk@41290 git-svn-id: http://core.svn.wordpress.org/trunk@41130 1a063a9b-81f0-0310-95a4-ce76da25c4cd
This commit is contained in:
parent
28eda6f4bc
commit
c7a79b0e6a
|
@ -3704,7 +3704,7 @@ function wp_ajax_install_plugin() {
|
||||||
// If installation request is coming from import page, do not return network activation link.
|
// If installation request is coming from import page, do not return network activation link.
|
||||||
$plugins_url = ( 'import' === $pagenow ) ? admin_url( 'plugins.php' ) : network_admin_url( 'plugins.php' );
|
$plugins_url = ( 'import' === $pagenow ) ? admin_url( 'plugins.php' ) : network_admin_url( 'plugins.php' );
|
||||||
|
|
||||||
if ( current_user_can( 'activate_plugins' ) && is_plugin_inactive( $install_status['file'] ) ) {
|
if ( current_user_can( 'activate_plugin', $install_status['file'] ) && is_plugin_inactive( $install_status['file'] ) ) {
|
||||||
$status['activateUrl'] = add_query_arg( array(
|
$status['activateUrl'] = add_query_arg( array(
|
||||||
'_wpnonce' => wp_create_nonce( 'activate-plugin_' . $install_status['file'] ),
|
'_wpnonce' => wp_create_nonce( 'activate-plugin_' . $install_status['file'] ),
|
||||||
'action' => 'activate',
|
'action' => 'activate',
|
||||||
|
|
|
@ -71,7 +71,7 @@ class Plugin_Installer_Skin extends WP_Upgrader_Skin {
|
||||||
|
|
||||||
if ( ! $this->result || is_wp_error($this->result) ) {
|
if ( ! $this->result || is_wp_error($this->result) ) {
|
||||||
unset( $install_actions['activate_plugin'], $install_actions['network_activate'] );
|
unset( $install_actions['activate_plugin'], $install_actions['network_activate'] );
|
||||||
} elseif ( ! current_user_can( 'activate_plugins' ) ) {
|
} elseif ( ! current_user_can( 'activate_plugin', $plugin_file ) ) {
|
||||||
unset( $install_actions['activate_plugin'] );
|
unset( $install_actions['activate_plugin'] );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -51,7 +51,7 @@ class Plugin_Upgrader_Skin extends WP_Upgrader_Skin {
|
||||||
'activate_plugin' => '<a href="' . wp_nonce_url( 'plugins.php?action=activate&plugin=' . urlencode( $this->plugin ), 'activate-plugin_' . $this->plugin) . '" target="_parent">' . __( 'Activate Plugin' ) . '</a>',
|
'activate_plugin' => '<a href="' . wp_nonce_url( 'plugins.php?action=activate&plugin=' . urlencode( $this->plugin ), 'activate-plugin_' . $this->plugin) . '" target="_parent">' . __( 'Activate Plugin' ) . '</a>',
|
||||||
'plugins_page' => '<a href="' . self_admin_url( 'plugins.php' ) . '" target="_parent">' . __( 'Return to Plugins page' ) . '</a>'
|
'plugins_page' => '<a href="' . self_admin_url( 'plugins.php' ) . '" target="_parent">' . __( 'Return to Plugins page' ) . '</a>'
|
||||||
);
|
);
|
||||||
if ( $this->plugin_active || ! $this->result || is_wp_error( $this->result ) || ! current_user_can( 'activate_plugins' ) )
|
if ( $this->plugin_active || ! $this->result || is_wp_error( $this->result ) || ! current_user_can( 'activate_plugin', $this->plugin ) )
|
||||||
unset( $update_actions['activate_plugin'] );
|
unset( $update_actions['activate_plugin'] );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -468,7 +468,7 @@ class WP_Plugin_Install_List_Table extends WP_List_Table {
|
||||||
case 'newer_installed':
|
case 'newer_installed':
|
||||||
if ( is_plugin_active( $status['file'] ) ) {
|
if ( is_plugin_active( $status['file'] ) ) {
|
||||||
$action_links[] = '<button type="button" class="button button-disabled" disabled="disabled">' . _x( 'Active', 'plugin' ) . '</button>';
|
$action_links[] = '<button type="button" class="button button-disabled" disabled="disabled">' . _x( 'Active', 'plugin' ) . '</button>';
|
||||||
} elseif ( current_user_can( 'activate_plugins' ) ) {
|
} elseif ( current_user_can( 'activate_plugin', $status['file'] ) ) {
|
||||||
$button_text = __( 'Activate' );
|
$button_text = __( 'Activate' );
|
||||||
/* translators: %s: Plugin name */
|
/* translators: %s: Plugin name */
|
||||||
$button_label = _x( 'Activate %s', 'plugin' );
|
$button_label = _x( 'Activate %s', 'plugin' );
|
||||||
|
|
|
@ -620,11 +620,15 @@ class WP_Plugins_List_Table extends WP_List_Table {
|
||||||
'network_only' => __( 'Network Only' ),
|
'network_only' => __( 'Network Only' ),
|
||||||
);
|
);
|
||||||
} elseif ( $is_active ) {
|
} elseif ( $is_active ) {
|
||||||
/* translators: %s: plugin name */
|
if ( current_user_can( 'deactivate_plugin', $plugin_file ) ) {
|
||||||
$actions['deactivate'] = '<a href="' . wp_nonce_url( 'plugins.php?action=deactivate&plugin=' . $plugin_file . '&plugin_status=' . $context . '&paged=' . $page . '&s=' . $s, 'deactivate-plugin_' . $plugin_file ) . '" aria-label="' . esc_attr( sprintf( _x( 'Deactivate %s', 'plugin' ), $plugin_data['Name'] ) ) . '">' . __( 'Deactivate' ) . '</a>';
|
/* translators: %s: plugin name */
|
||||||
|
$actions['deactivate'] = '<a href="' . wp_nonce_url( 'plugins.php?action=deactivate&plugin=' . $plugin_file . '&plugin_status=' . $context . '&paged=' . $page . '&s=' . $s, 'deactivate-plugin_' . $plugin_file ) . '" aria-label="' . esc_attr( sprintf( _x( 'Deactivate %s', 'plugin' ), $plugin_data['Name'] ) ) . '">' . __( 'Deactivate' ) . '</a>';
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
/* translators: %s: plugin name */
|
if ( current_user_can( 'activate_plugin', $plugin_file ) ) {
|
||||||
$actions['activate'] = '<a href="' . wp_nonce_url( 'plugins.php?action=activate&plugin=' . $plugin_file . '&plugin_status=' . $context . '&paged=' . $page . '&s=' . $s, 'activate-plugin_' . $plugin_file ) . '" class="edit" aria-label="' . esc_attr( sprintf( _x( 'Activate %s', 'plugin' ), $plugin_data['Name'] ) ) . '">' . __( 'Activate' ) . '</a>';
|
/* translators: %s: plugin name */
|
||||||
|
$actions['activate'] = '<a href="' . wp_nonce_url( 'plugins.php?action=activate&plugin=' . $plugin_file . '&plugin_status=' . $context . '&paged=' . $page . '&s=' . $s, 'activate-plugin_' . $plugin_file ) . '" class="edit" aria-label="' . esc_attr( sprintf( _x( 'Activate %s', 'plugin' ), $plugin_data['Name'] ) ) . '">' . __( 'Activate' ) . '</a>';
|
||||||
|
}
|
||||||
|
|
||||||
if ( ! is_multisite() && current_user_can( 'delete_plugins' ) ) {
|
if ( ! is_multisite() && current_user_can( 'delete_plugins' ) ) {
|
||||||
/* translators: %s: plugin name */
|
/* translators: %s: plugin name */
|
||||||
|
|
|
@ -29,8 +29,9 @@ if ( $action ) {
|
||||||
|
|
||||||
switch ( $action ) {
|
switch ( $action ) {
|
||||||
case 'activate':
|
case 'activate':
|
||||||
if ( ! current_user_can('activate_plugins') )
|
if ( ! current_user_can( 'activate_plugin', $plugin ) ) {
|
||||||
wp_die(__('Sorry, you are not allowed to activate plugins for this site.'));
|
wp_die( __( 'Sorry, you are not allowed to activate this plugin.' ) );
|
||||||
|
}
|
||||||
|
|
||||||
if ( is_multisite() && ! is_network_admin() && is_network_only_plugin( $plugin ) ) {
|
if ( is_multisite() && ! is_network_admin() && is_network_only_plugin( $plugin ) ) {
|
||||||
wp_redirect( self_admin_url("plugins.php?plugin_status=$status&paged=$page&s=$s") );
|
wp_redirect( self_admin_url("plugins.php?plugin_status=$status&paged=$page&s=$s") );
|
||||||
|
@ -88,6 +89,10 @@ if ( $action ) {
|
||||||
if ( is_plugin_active( $plugin ) || ( is_multisite() && is_network_only_plugin( $plugin ) ) ) {
|
if ( is_plugin_active( $plugin ) || ( is_multisite() && is_network_only_plugin( $plugin ) ) ) {
|
||||||
unset( $plugins[ $i ] );
|
unset( $plugins[ $i ] );
|
||||||
}
|
}
|
||||||
|
// Only activate plugins which the user can activate.
|
||||||
|
if ( ! current_user_can( 'activate_plugin', $plugin ) ) {
|
||||||
|
unset( $plugins[ $i ] );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -146,8 +151,9 @@ if ( $action ) {
|
||||||
exit;
|
exit;
|
||||||
|
|
||||||
case 'error_scrape':
|
case 'error_scrape':
|
||||||
if ( ! current_user_can('activate_plugins') )
|
if ( ! current_user_can( 'activate_plugin', $plugin ) ) {
|
||||||
wp_die(__('Sorry, you are not allowed to activate plugins for this site.'));
|
wp_die( __( 'Sorry, you are not allowed to activate this plugin.' ) );
|
||||||
|
}
|
||||||
|
|
||||||
check_admin_referer('plugin-activation-error_' . $plugin);
|
check_admin_referer('plugin-activation-error_' . $plugin);
|
||||||
|
|
||||||
|
@ -167,8 +173,9 @@ if ( $action ) {
|
||||||
exit;
|
exit;
|
||||||
|
|
||||||
case 'deactivate':
|
case 'deactivate':
|
||||||
if ( ! current_user_can('activate_plugins') )
|
if ( ! current_user_can( 'deactivate_plugin', $plugin ) ) {
|
||||||
wp_die(__('Sorry, you are not allowed to deactivate plugins for this site.'));
|
wp_die( __( 'Sorry, you are not allowed to deactivate this plugin.' ) );
|
||||||
|
}
|
||||||
|
|
||||||
check_admin_referer('deactivate-plugin_' . $plugin);
|
check_admin_referer('deactivate-plugin_' . $plugin);
|
||||||
|
|
||||||
|
@ -192,8 +199,9 @@ if ( $action ) {
|
||||||
exit;
|
exit;
|
||||||
|
|
||||||
case 'deactivate-selected':
|
case 'deactivate-selected':
|
||||||
if ( ! current_user_can('activate_plugins') )
|
if ( ! current_user_can( 'deactivate_plugins' ) ) {
|
||||||
wp_die(__('Sorry, you are not allowed to deactivate plugins for this site.'));
|
wp_die(__('Sorry, you are not allowed to deactivate plugins for this site.'));
|
||||||
|
}
|
||||||
|
|
||||||
check_admin_referer('bulk-plugins');
|
check_admin_referer('bulk-plugins');
|
||||||
|
|
||||||
|
@ -204,6 +212,14 @@ if ( $action ) {
|
||||||
} else {
|
} else {
|
||||||
$plugins = array_filter( $plugins, 'is_plugin_active' );
|
$plugins = array_filter( $plugins, 'is_plugin_active' );
|
||||||
$plugins = array_diff( $plugins, array_filter( $plugins, 'is_plugin_active_for_network' ) );
|
$plugins = array_diff( $plugins, array_filter( $plugins, 'is_plugin_active_for_network' ) );
|
||||||
|
|
||||||
|
foreach ( $plugins as $i => $plugin ) {
|
||||||
|
// Only deactivate plugins which the user can deactivate.
|
||||||
|
if ( ! current_user_can( 'deactivate_plugin', $plugin ) ) {
|
||||||
|
unset( $plugins[ $i ] );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
if ( empty($plugins) ) {
|
if ( empty($plugins) ) {
|
||||||
wp_redirect( self_admin_url("plugins.php?plugin_status=$status&paged=$page&s=$s") );
|
wp_redirect( self_admin_url("plugins.php?plugin_status=$status&paged=$page&s=$s") );
|
||||||
|
|
|
@ -407,7 +407,10 @@ function map_meta_cap( $cap, $user_id ) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'activate_plugins':
|
case 'activate_plugins':
|
||||||
$caps[] = $cap;
|
case 'deactivate_plugins':
|
||||||
|
case 'activate_plugin':
|
||||||
|
case 'deactivate_plugin':
|
||||||
|
$caps[] = 'activate_plugins';
|
||||||
if ( is_multisite() ) {
|
if ( is_multisite() ) {
|
||||||
// update_, install_, and delete_ are handled above with is_super_admin().
|
// update_, install_, and delete_ are handled above with is_super_admin().
|
||||||
$menu_perms = get_site_option( 'menu_items', array() );
|
$menu_perms = get_site_option( 'menu_items', array() );
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
*
|
*
|
||||||
* @global string $wp_version
|
* @global string $wp_version
|
||||||
*/
|
*/
|
||||||
$wp_version = '4.9-alpha-41289';
|
$wp_version = '4.9-alpha-41290';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.
|
* Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.
|
||||||
|
|
Loading…
Reference in New Issue