Как разрешить роли пользователя создавать нового пользователя под ролью, которая ниже его уровня?

14

У меня есть три дополнительные роли на моем сайте.

  1. Доктор
  2. портье
  3. гость

эти роли добавляются с помощью следующего кода:

* adding Doctor role */
$doctor_role = add_role('Doctor', __('Doctor'), array('read'=>'true'));

/* adding Receptionist role */
$receptionist_role = add_role('Receptionist', __('Receptionist'), array('read'=>'true'));

/* adding Guest role */
$guest_role = add_role('Guest', __('Guest'), array('read'=>'true'));

По умолчанию Administratorроли создают все остальные роли. Но я хочу ограничить эту роль назначением на уровне пользователя. Я имею в виду:

  1. Администратор - должен иметь возможность создавать всех пользователей ролей - возможно по умолчанию.
  2. Доктор - должен быть в состоянии создавать Receptionistи Guestроль пользователей ТОЛЬКО
  3. Регистратор - должен быть в состоянии создать Guestроль пользователей ТОЛЬКО
  4. Гость - запрещено создавать пользователей.

Как это сделать? Лучше, если я смогу добиться этого без использования каких-либо плагинов.

Риффаз Старр
источник

Ответы:

23

Во - первых, вам необходимо добавить следующие возможности к Doctorи Receptionistроли:

  • list_users
  • edit_users
  • create_users
  • delete_users

Теперь мы можем приступить к контролю, каких пользователей они могут создавать / редактировать / удалять. Давайте начнем с «вспомогательной» функции, которая будет возвращать, какие роли пользователь может редактировать:

/**
 * Helper function get getting roles that the user is allowed to create/edit/delete.
 *
 * @param   WP_User $user
 * @return  array
 */
function wpse_188863_get_allowed_roles( $user ) {
    $allowed = array();

    if ( in_array( 'administrator', $user->roles ) ) { // Admin can edit all roles
        $allowed = array_keys( $GLOBALS['wp_roles']->roles );
    } elseif ( in_array( 'Doctor', $user->roles ) ) {
        $allowed[] = 'Receptionist';
        $allowed[] = 'Guest';
    } elseif ( in_array( 'Receptionist', $user->roles ) ) {
        $allowed[] = 'Guest';
    }

    return $allowed;
}

И установить, какие роли они могут назначить пользователю:

/**
 * Remove roles that are not allowed for the current user role.
 */
function wpse_188863_editable_roles( $roles ) {
    if ( $user = wp_get_current_user() ) {
        $allowed = wpse_188863_get_allowed_roles( $user );

        foreach ( $roles as $role => $caps ) {
            if ( ! in_array( $role, $allowed ) )
                unset( $roles[ $role ] );
        }
    }

    return $roles;
}

add_filter( 'editable_roles', 'wpse_188863_editable_roles' );

И, наконец, ограничьте пользователей, которых они могут редактировать / удалять, исходя из их роли:

/**
 * Prevent users deleting/editing users with a role outside their allowance.
 */
function wpse_188863_map_meta_cap( $caps, $cap, $user_ID, $args ) {
    if ( ( $cap === 'edit_user' || $cap === 'delete_user' ) && $args ) {
        $the_user = get_userdata( $user_ID ); // The user performing the task
        $user     = get_userdata( $args[0] ); // The user being edited/deleted

        if ( $the_user && $user && $the_user->ID != $user->ID /* User can always edit self */ ) {
            $allowed = wpse_188863_get_allowed_roles( $the_user );

            if ( array_diff( $user->roles, $allowed ) ) {
                // Target user has roles outside of our limits
                $caps[] = 'not_allowed';
            }
        }
    }

    return $caps;
}

add_filter( 'map_meta_cap', 'wpse_188863_map_meta_cap', 10, 4 );
TheDeadMedic
источник
Отлично, большое спасибо. После того, как я добавил возможности и ваш код, он работает, как мы и ожидали. Но Doctors, Receptionistи Guestне в состоянии изменить свой собственный профиль тоже. Я хочу, чтобы они редактировали свой профиль. Как я могу это сделать?
Риффаз Старр
Привет TheDeadMedic .. Ты здесь? Я проголосовал за твой ответ. Можете ли вы посмотреть мой комментарий выше?
Riffaz Starr
Проверь мою ревизию.
TheDeadMedic
@TheDeadMedic Ваш код мне очень помог. У меня только одна проблема. Я использую это на мультисайте. И хотя этот код решил мою проблему, он создал еще один. Когда вы вошли в систему как Супер Администратор, я вообще не могу выбирать какие-либо роли со страниц Сети Супер Администратора. Как мне это решить?
Jockebq
1
Это блестящий ответ на вопрос. Я обнаружил, что собственная документация Wordpress полностью отсутствует в этой области, даже полная грамматических ошибок. Это действительно эффективное решение проблемы.
Бенджи
0

Приведенный выше ответ работал отлично. Тем не менее, роли должны быть строчными

function wpse_188863_get_allowed_roles( $user ) { }

Например:

if ( in_array( 'administrator', $user->roles ) ) { // Admin can edit all roles
    $allowed = array_keys( $GLOBALS['wp_roles']->roles );
} elseif ( in_array( 'doctor', $user->roles ) ) {
    $allowed[] = 'receptionist';
    $allowed[] = 'guest';
} elseif ( in_array( 'receptionist', $user->roles ) ) {
    $allowed[] = 'guest';
}
Что-нибудь графическое
источник
В большинстве случаев регистр ролей должен быть строчным. В приведенном выше примере и слаг, и имя даны с использованием регистра case, так что это технически правильно, хотя и не рекомендуется.
Бенджи