Мультивыбор ролей WordPress

Добавим мультивыбор ролей у пользователей в WordPress. Для этого отлично подойдёт популярный плагин User Role Editor

Мультивыбор ролей WordPress

В плагине можно назначить разные права для каждой роли, добавлять и удалять роли.

Кстати вот отличная статья о ролях в wordpress

Если Вы отредактировали роли и хотите оставить только функционал мультивыбора, то можно удалить плагин. При этом новые роли и их права не исчезнут, при удалении плагина только пропадёт мультивыбор. Поэтому добавим свой миниплагин для этого функционала.

Ведь чем меньше плагинов, тем быстрее будет ваш сайт, особенно критично, если на сайте уже +30 плагинов, да ещё и парочка тяжёлых.

Заодно кто-то в первый раз создаст свой первый плагин 😇 Обещаю это будет очень просто.

Если у вас мультисайт, то код нужно изменить!

Вот что у нас получится:

Multiselection of WordPress roles

Зайдите на ваш хостинг в файлы сайта ../ваш сайт/public_html/wp-content/plugins

В папке plugins создайте папку multi-role-selector. В этой папке создайте файл multi-role-selector.php и вставьте код:

<?php
/*
Plugin Name: Мультивыбор ролей
Description: Позволяет назначать несколько ролей одному пользователю.
Version: 1.5
Author: avsalexandra
Author URI: https://github.com/avs-alexandra
Text Domain: multiple-roles-per-user
Requires at least: 5.8
Requires PHP: 7.4
*/

if (!defined('ABSPATH')) {
	exit;
}

define('MRPU_VERSION', '1.5');

/**
 * Админ-уведомления (например, при попытке снять последнего администратора).
 */
add_action('admin_notices', function () {
	$msg = get_transient('mrpu_admin_notice');
	if (!$msg) {
		return;
	}
	echo '<div class="notice notice-error"><p>' . esc_html($msg) . '</p></div>';
	delete_transient('mrpu_admin_notice');
});

/**
 * Не даём ядру WordPress перезаписывать роли из скрытого <select name="role"> одной ролью.
 * Удаляем $_POST['role'] только если сохраняем через наш UI (есть наш nonce).
 */
function mrpu_prevent_core_single_role_override() {
	if (
		'POST' === $_SERVER['REQUEST_METHOD'] &&
		isset($_POST['_mrpu_roles_nonce']) &&
		wp_verify_nonce($_POST['_mrpu_roles_nonce'], 'mrpu_set_roles')
	) {
		unset($_POST['role']);
	}
}
add_action('load-user-edit.php', 'mrpu_prevent_core_single_role_override');
add_action('load-profile.php', 'mrpu_prevent_core_single_role_override');

/**
 * Возвращает человекочитаемые названия ролей пользователя.
 */
function mrpu_get_user_role_names( $user ) {
	$role_ids = (array) $user->roles;

	$wp_roles = wp_roles();
	$role_names_map = array();

	if (isset($wp_roles->role_names) && is_array($wp_roles->role_names)) {
		$role_names_map = $wp_roles->role_names; // переведённые названия
	} else {
		foreach ((array) $wp_roles->roles as $rid => $rdata) {
			$role_names_map[$rid] = isset($rdata['name']) ? translate_user_role($rdata['name']) : $rid;
		}
	}

	$names = array();
	foreach ($role_ids as $rid) {
		$names[] = isset($role_names_map[$rid]) ? $role_names_map[$rid] : $rid;
	}

	return $names;
}

/**
 * UI мультивыбора ролей на странице профиля/редактирования пользователя.
 * - Если есть право назначать роли — показываем чекбоксы.
 * - Иначе — показываем роли только для просмотра (через запятую).
 */
function mrpu_add_multiple_roles_ui($user) {
	// Можно ли менять роли?
	$can_edit_roles = ( current_user_can('promote_user', $user->ID) || current_user_can('promote_users') );

	// Названия текущих ролей пользователя (всегда показываем в нашем блоке)
	$current_role_names = mrpu_get_user_role_names($user);

	echo '<div class="mrpu-roles-container">';
	echo '<h3>Роли пользователя</h3>';
	echo '<table class="form-table" role="presentation">';

	if ( $can_edit_roles ) {
		$roles = get_editable_roles(); // роли, которые текущий пользователь может назначать
		$user_roles_allowed = array_intersect(array_values($user->roles), array_keys($roles));
		?>
		<tr>
			<th><label>Роли</label></th>
			<td>
				<?php foreach ($roles as $role_id => $role_data) : ?>
					<label for="user_role_<?php echo esc_attr($role_id); ?>">
						<input
							type="checkbox"
							id="user_role_<?php echo esc_attr($role_id); ?>"
							value="<?php echo esc_attr($role_id); ?>"
							name="mrpu_user_roles[]"
							<?php checked(in_array($role_id, $user_roles_allowed, true)); ?>
						/>
						<?php echo esc_html($role_data['name']); ?>
					</label>
					<br />
				<?php endforeach; ?>
				<br />
				<?php wp_nonce_field('mrpu_set_roles', '_mrpu_roles_nonce'); ?>
				<p class="description">Отметьте одну или несколько ролей для этого пользователя.</p>
			</td>
		</tr>
		<style>
			/* Скрываем стандартный селект "Роль" (чтобы виделись только чекбоксы) */
			label[for="role"], select#role { display: none !important; }
		</style>
		<?php
	} else {
		// Режим только просмотра: показываем роли через запятую
		?>
		<tr>
			<th><label>Роли</label></th>
			<td>
				<?php
				$list = implode(', ', array_map('esc_html', $current_role_names));
				echo $list ? $list : '—';
				?>
				<p class="description">Просмотр ролей. У вас нет прав на изменение ролей.</p>
			</td>
		</tr>
		<?php
	}

	echo '</table>';
	echo '</div>';
}
add_action('edit_user_profile', 'mrpu_add_multiple_roles_ui', 0);
add_action('show_user_profile', 'mrpu_add_multiple_roles_ui', 0);

/**
 * Сохранение выбранных ролей.
 */
function mrpu_save_multiple_user_roles($user_id) {
	// Базовые проверки: права + nonce
	if (
		!current_user_can('edit_user', $user_id) ||
		!(current_user_can('promote_user', $user_id) || current_user_can('promote_users')) ||
		!isset($_POST['_mrpu_roles_nonce']) ||
		!wp_verify_nonce($_POST['_mrpu_roles_nonce'], 'mrpu_set_roles')
	) {
		return;
	}

	$user         = new WP_User($user_id);
	$roles        = get_editable_roles();
	$editable_ids = array_keys($roles);

	// Новые роли из POST с санитизацией
	$new_roles = array();
	if (isset($_POST['mrpu_user_roles'])) {
		$new_roles = (array) wp_unslash($_POST['mrpu_user_roles']);
		$new_roles = array_map('sanitize_key', $new_roles);
		$new_roles = array_intersect($new_roles, $editable_ids); // отсечь чужие значения
	}

	// Текущие роли пользователя из допустимых
	$current_roles = array_intersect(array_values($user->roles), $editable_ids);

	// Нельзя снять роль administrator у себя
	$removing_admin_from_self = (
		get_current_user_id() === (int) $user_id
		&& in_array('administrator', $current_roles, true)
		&& !in_array('administrator', $new_roles, true)
	);
	if ($removing_admin_from_self) {
		set_transient('mrpu_admin_notice', 'Вы не можете снять роль Администратора со своего аккаунта.', 60);
		return;
	}

	// Нельзя оставить сайт без единственного администратора
	$admin_count = count(get_users(array('role' => 'administrator', 'fields' => 'ID')));
	$would_leave_zero_admins = (
		in_array('administrator', $current_roles, true)
		&& !in_array('administrator', $new_roles, true)
		&& $admin_count <= 1
	);
	if ($would_leave_zero_admins) {
		set_transient('mrpu_admin_notice', 'Нельзя удалять последнего администратора с сайта.', 60);
		return;
	}

	// Удаляем роли, которых больше нет в выборе
	$roles_to_remove = $new_roles ? array_diff($current_roles, $new_roles) : $current_roles;
	foreach ($roles_to_remove as $_role) {
		$user->remove_role($_role);
	}

	// Добавляем недостающие роли
	if (!empty($new_roles)) {
		$to_add = array_diff($new_roles, array_intersect(array_values($user->roles), $editable_ids));
		foreach ($to_add as $_role) {
			$user->add_role($_role);
		}
	}
}
add_action('edit_user_profile_update', 'mrpu_save_multiple_user_roles');
add_action('personal_options_update', 'mrpu_save_multiple_user_roles');

/**
 * Колонка «Роли» в списке пользователей (всегда показываем все роли пользователя).
 */
function mrpu_add_roles_column($columns) {
	$old_posts = isset($columns['posts']) ? $columns['posts'] : false;
	unset($columns['role'], $columns['posts']);
	$columns['mrpu_roles'] = 'Роли';
	if ($old_posts) {
		$columns['posts'] = $old_posts;
	}
	return $columns;
}
add_filter('manage_users_columns', 'mrpu_add_roles_column');

function mrpu_display_user_roles($value, $column_name, $user_id) {
	if ('mrpu_roles' !== $column_name) {
		return $value;
	}
	$user = get_userdata($user_id);
	if (!$user) {
		return $value;
	}
	$names = mrpu_get_user_role_names($user);
	return esc_html(implode(', ', $names));
}
add_filter('manage_users_custom_column', 'mrpu_display_user_roles', 10, 3);

И потом как обычный плагин активируйте! Либо Вы можете вставить это как сниппет код.

Picture of Автор: Александра

Автор: Александра

@avsalexandra
Занимаюсь натуральным питанием собак и кошек BARF. Wordpress для души ☺️

Crocoblock
Elementor
Gutenberg
Jetengine
Jetformbuilder
profile builder
Woocommerce
Wordpress
WYSIWYG
Лейка
#автосохранение
#доменная почта
#рассылка
#бейдж
#благотворительность
#заказ ожидает
#подарок
#подчёркивание
#публикация постов
#видео
#пожертвования
#мультивыбор
#роли
#drag and drop
#изображения товаров
#подписки
#распродажа
#личный кабинет
#пагинация
#alt text
#галерея товара
#аватар
#возврат
#видео товара
#купон
#отменить заказ
Комментарии:

Добавить комментарий