WordPress.org

Make WordPress Core

Changeset 41290


Ignore:
Timestamp:
08/22/2017 02:01:36 PM (4 years ago)
Author:
johnbillion
Message:

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

Location:
trunk
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-admin/includes/ajax-actions.php

    r41289 r41290  
    37053705    $plugins_url = ( 'import' === $pagenow ) ? admin_url( 'plugins.php' ) : network_admin_url( 'plugins.php' );
    37063706
    3707     if ( current_user_can( 'activate_plugins' ) && is_plugin_inactive( $install_status['file'] ) ) {
     3707    if ( current_user_can( 'activate_plugin', $install_status['file'] ) && is_plugin_inactive( $install_status['file'] ) ) {
    37083708        $status['activateUrl'] = add_query_arg( array(
    37093709            '_wpnonce' => wp_create_nonce( 'activate-plugin_' . $install_status['file'] ),
  • trunk/src/wp-admin/includes/class-plugin-installer-skin.php

    r41161 r41290  
    7272        if ( ! $this->result || is_wp_error($this->result) ) {
    7373            unset( $install_actions['activate_plugin'], $install_actions['network_activate'] );
    74         } elseif ( ! current_user_can( 'activate_plugins' ) ) {
     74        } elseif ( ! current_user_can( 'activate_plugin', $plugin_file ) ) {
    7575            unset( $install_actions['activate_plugin'] );
    7676        }
  • trunk/src/wp-admin/includes/class-plugin-upgrader-skin.php

    r41161 r41290  
    5252            'plugins_page' => '<a href="' . self_admin_url( 'plugins.php' ) . '" target="_parent">' . __( 'Return to Plugins page' ) . '</a>'
    5353        );
    54         if ( $this->plugin_active || ! $this->result || is_wp_error( $this->result ) || ! current_user_can( 'activate_plugins' ) )
     54        if ( $this->plugin_active || ! $this->result || is_wp_error( $this->result ) || ! current_user_can( 'activate_plugin', $this->plugin ) )
    5555            unset( $update_actions['activate_plugin'] );
    5656
  • trunk/src/wp-admin/includes/class-wp-plugin-install-list-table.php

    r41289 r41290  
    469469                        if ( is_plugin_active( $status['file'] ) ) {
    470470                            $action_links[] = '<button type="button" class="button button-disabled" disabled="disabled">' . _x( 'Active', 'plugin' ) . '</button>';
    471                         } elseif ( current_user_can( 'activate_plugins' ) ) {
     471                        } elseif ( current_user_can( 'activate_plugin', $status['file'] ) ) {
    472472                            $button_text  = __( 'Activate' );
    473473                            /* translators: %s: Plugin name */
  • trunk/src/wp-admin/includes/class-wp-plugins-list-table.php

    r41231 r41290  
    621621                    );
    622622                } elseif ( $is_active ) {
    623                     /* translators: %s: plugin name */
    624                     $actions['deactivate'] = '<a href="' . wp_nonce_url( 'plugins.php?action=deactivate&amp;plugin=' . $plugin_file . '&amp;plugin_status=' . $context . '&amp;paged=' . $page . '&amp;s=' . $s, 'deactivate-plugin_' . $plugin_file ) . '" aria-label="' . esc_attr( sprintf( _x( 'Deactivate %s', 'plugin' ), $plugin_data['Name'] ) ) . '">' . __( 'Deactivate' ) . '</a>';
     623                    if ( current_user_can( 'deactivate_plugin', $plugin_file ) ) {
     624                        /* translators: %s: plugin name */
     625                        $actions['deactivate'] = '<a href="' . wp_nonce_url( 'plugins.php?action=deactivate&amp;plugin=' . $plugin_file . '&amp;plugin_status=' . $context . '&amp;paged=' . $page . '&amp;s=' . $s, 'deactivate-plugin_' . $plugin_file ) . '" aria-label="' . esc_attr( sprintf( _x( 'Deactivate %s', 'plugin' ), $plugin_data['Name'] ) ) . '">' . __( 'Deactivate' ) . '</a>';
     626                    }
    625627                } else {
    626                     /* translators: %s: plugin name */
    627                     $actions['activate'] = '<a href="' . wp_nonce_url( 'plugins.php?action=activate&amp;plugin=' . $plugin_file . '&amp;plugin_status=' . $context . '&amp;paged=' . $page . '&amp;s=' . $s, 'activate-plugin_' . $plugin_file ) . '" class="edit" aria-label="' . esc_attr( sprintf( _x( 'Activate %s', 'plugin' ), $plugin_data['Name'] ) ) . '">' . __( 'Activate' ) . '</a>';
     628                    if ( current_user_can( 'activate_plugin', $plugin_file ) ) {
     629                        /* translators: %s: plugin name */
     630                        $actions['activate'] = '<a href="' . wp_nonce_url( 'plugins.php?action=activate&amp;plugin=' . $plugin_file . '&amp;plugin_status=' . $context . '&amp;paged=' . $page . '&amp;s=' . $s, 'activate-plugin_' . $plugin_file ) . '" class="edit" aria-label="' . esc_attr( sprintf( _x( 'Activate %s', 'plugin' ), $plugin_data['Name'] ) ) . '">' . __( 'Activate' ) . '</a>';
     631                    }
    628632
    629633                    if ( ! is_multisite() && current_user_can( 'delete_plugins' ) ) {
  • trunk/src/wp-admin/plugins.php

    r40169 r41290  
    3030    switch ( $action ) {
    3131        case 'activate':
    32             if ( ! current_user_can('activate_plugins') )
    33                 wp_die(__('Sorry, you are not allowed to activate plugins for this site.'));
     32            if ( ! current_user_can( 'activate_plugin', $plugin ) ) {
     33                wp_die( __( 'Sorry, you are not allowed to activate this plugin.' ) );
     34            }
    3435
    3536            if ( is_multisite() && ! is_network_admin() && is_network_only_plugin( $plugin ) ) {
     
    8990                        unset( $plugins[ $i ] );
    9091                    }
     92                    // Only activate plugins which the user can activate.
     93                    if ( ! current_user_can( 'activate_plugin', $plugin ) ) {
     94                        unset( $plugins[ $i ] );
     95                    }
    9196                }
    9297            }
     
    147152
    148153        case 'error_scrape':
    149             if ( ! current_user_can('activate_plugins') )
    150                 wp_die(__('Sorry, you are not allowed to activate plugins for this site.'));
     154            if ( ! current_user_can( 'activate_plugin', $plugin ) ) {
     155                wp_die( __( 'Sorry, you are not allowed to activate this plugin.' ) );
     156            }
    151157
    152158            check_admin_referer('plugin-activation-error_' . $plugin);
     
    168174
    169175        case 'deactivate':
    170             if ( ! current_user_can('activate_plugins') )
    171                 wp_die(__('Sorry, you are not allowed to deactivate plugins for this site.'));
     176            if ( ! current_user_can( 'deactivate_plugin', $plugin ) ) {
     177                wp_die( __( 'Sorry, you are not allowed to deactivate this plugin.' ) );
     178            }
    172179
    173180            check_admin_referer('deactivate-plugin_' . $plugin);
     
    193200
    194201        case 'deactivate-selected':
    195             if ( ! current_user_can('activate_plugins') )
     202            if ( ! current_user_can( 'deactivate_plugins' ) ) {
    196203                wp_die(__('Sorry, you are not allowed to deactivate plugins for this site.'));
     204            }
    197205
    198206            check_admin_referer('bulk-plugins');
     
    205213                $plugins = array_filter( $plugins, 'is_plugin_active' );
    206214                $plugins = array_diff( $plugins, array_filter( $plugins, 'is_plugin_active_for_network' ) );
     215
     216                foreach ( $plugins as $i => $plugin ) {
     217                    // Only deactivate plugins which the user can deactivate.
     218                    if ( ! current_user_can( 'deactivate_plugin', $plugin ) ) {
     219                        unset( $plugins[ $i ] );
     220                    }
     221                }
     222
    207223            }
    208224            if ( empty($plugins) ) {
  • trunk/src/wp-includes/capabilities.php

    r41268 r41290  
    408408        break;
    409409    case 'activate_plugins':
    410         $caps[] = $cap;
     410    case 'deactivate_plugins':
     411    case 'activate_plugin':
     412    case 'deactivate_plugin':
     413        $caps[] = 'activate_plugins';
    411414        if ( is_multisite() ) {
    412415            // update_, install_, and delete_ are handled above with is_super_admin().
  • trunk/tests/phpunit/tests/user/capabilities.php

    r41268 r41290  
    236236            'install_languages'      => array( 'administrator' ),
    237237            'update_languages'       => array( 'administrator' ),
     238            'deactivate_plugins'     => array( 'administrator' ),
    238239
    239240            'edit_categories'        => array( 'administrator', 'editor' ),
     
    266267            'install_languages'      => array(),
    267268            'update_languages'       => array(),
     269            'deactivate_plugins'     => array(),
    268270
    269271            'customize'              => array( 'administrator' ),
     
    426428            $expected['manage_links'],
    427429            // Singular object meta capabilities (where an object ID is passed) are not tested:
     430            $expected['activate_plugin'],
     431            $expected['deactivate_plugin'],
    428432            $expected['remove_user'],
    429433            $expected['promote_user'],
Note: See TracChangeset for help on using the changeset viewer.