current_user_can()WP 2.0.0

Проверяет права текущего пользователя, совершать указанное действие.

По умолчанию в WP текущий юзер устанавливается на событии init. Поэтмоу эту функцию рекомендуется использовать не раньше этого события. Однако, она почти всегда работает правильно с события plugins_loaded .

Супер-Админы в сети мультисайт всегда имеют все права (возвращает true), если првоеряемое право специально не запрещено. См. WP_User::has_cap().

Единственный способ явно запретить право для супер администраторов - использовать фильтр map_meta_cap где вернуть do_not_allow для возможности. Вариант запрета: $user->add_cap( 'capability', false ) работать не будет!

Когда нужно проверить право указанного, а не текущего пользователя, используйте user_can().

Работает на основе: WP_User::has_cap()
Основа для: get_edit_post_link()
1 раз — 0.0034041 сек (очень медленно) | 50000 раз — 3.84 сек (быстро) | PHP 7.4.8, WP 5.6

Хуков нет.

Возвращает

true|false. true — есть права, false — нет прав.

Использование

if( current_user_can( $capability, $args ) ){
	// есть право...
}
$capability(строка) (обязательный)
Название возможности или роли. Список возможностей и ролей смотрите здесь.
...$args(смешанный)

Дополнительные аргументы, которые будут использованы для проверки права. Например, ID поста.

Некоторые проверки нуждаются в таких аргументах. Например, edit_post нужно указать ID записи для которой выполняется проверка доступа.

Базовый список прав

По умолчанию в WordPress 6 ролей:

Super Admin Cупер-администратор. Имеет права для управления сетью сайтов. Эта роль появляется только при мультисайт установке.
administrator Aдминистратор сайта (отдельного сайта в сети мультисайт).
editor Редактор. Имеет доступ ко всем постам, страницам, комментариям, категориям, тегам и ссылкам.
author Автор. Может писать, загружать фотографии, редактировать и публиковать свои посты.
contributor Участник. Может писать посты, которые затем публикует редактор или админ.
subscriber Подписчик. Не может ничего, кроме редактирования профиля.

Какую роль получает новый пользователь указывается в Настройки > Общие. Данные сохраняются в опции: users_can_register и default_role:

Список прав по ролям

Список примитивных (фундаментальных) прав пользователя. Это возможности которые по умолчанию есть у указанных ролей (пользователей). Этот список прав задается единожды, при установке WordPress - он сохраняется в таблицу БД wp_options в опцию wp_user_roles.

Право Супер-Админ Админ Редактор Автор Участник Подписчик
read да да да да да да
delete_posts да да да да да
edit_posts да да да да да
delete_published_posts да да да да
edit_published_posts да да да да
publish_posts да да да да
upload_files да да да да
delete_others_pages да да да
delete_others_posts да да да
delete_pages да да да
delete_private_pages да да да
delete_private_posts да да да
delete_published_pages да да да
edit_others_pages да да да
edit_others_posts да да да
edit_pages да да да
edit_private_pages да да да
edit_private_posts да да да
edit_published_pages да да да
manage_categories да да да
manage_links да да да
moderate_comments да да да
publish_pages да да да
read_private_pages да да да
read_private_posts да да да
unfiltered_html да да ¹ да ¹
activate_plugins да да ²
create_users да да ¹
deactivate_plugins да да
delete_plugins да да ¹
delete_themes да да ¹
delete_users да да ¹
edit_dashboard да да
edit_files да да ¹
edit_plugins да да ¹
edit_theme_options да да
edit_themes да да ¹
edit_users да да ¹
export да да
import да да
install_languages да да ¹
install_plugins да да ¹
install_themes да да ¹
list_users да да
manage_options да да
promote_users да да
remove_users да да
switch_themes да да
update_core да да ¹
update_languages да да ¹
update_plugins да да ¹
update_themes да да ¹
unfiltered_upload да ³ да ³
manage_network_options да
manage_network_plugins да
manage_network_themes да
manage_network_users да
manage_network да
manage_sites да
setup_network да
upgrade_network да
  • ¹ — когда один сайт (не мультисайт).
  • ² — когда один сайт (не мультисайт). Или включается в настройках сети.
  • ³ — это право нужно включать отдельно, подробнее ниже.

Мета права

Выше перечислен список примитивных (фундаментальных) прав. Но есть еще так называемые мета-права. Они нигде не сохраняются, а вычисляются «налету» и в итоге превращаются в примитивное право.

Список мета-прав:

activate_plugin
activate_plugins
add_comment_meta
add_post_meta
add_term_meta
add_user_meta
add_users
assign_categories
assign_post_tags
assign_term
create_app_password
create_sites
create_users
customize
deactivate_plugin
deactivate_plugins
delete_app_password
delete_app_passwords
delete_categories
delete_comment_meta
delete_page
delete_page
delete_plugins
delete_post
delete_post
delete_post_meta
delete_post_tags
delete_site
delete_sites
delete_term
delete_term_meta
delete_themes
delete_user
delete_user
delete_user_meta
delete_users
edit_app_password
edit_categories
edit_comment
edit_comment
edit_comment_meta
edit_css
edit_files
edit_page
edit_page
edit_plugins
edit_post
edit_post
edit_post_meta
edit_post_tags
edit_term
edit_term_meta
edit_themes
edit_user
edit_user
edit_user_meta
edit_users
erase_others_personal_data
export_others_personal_data
install_languages
install_plugins
install_themes
list_app_passwords
manage_links
manage_network
manage_network_options
manage_network_plugins
manage_network_themes
manage_network_users
manage_post_tags
manage_privacy_options
manage_sites
promote_user
promote_user
publish_post
read_app_password
read_page
read_page
read_post
read_post
remove_user
remove_user
resume_plugin
resume_theme
setup_network
unfiltered_html
unfiltered_upload
update_core
update_https
update_languages
update_php
update_plugins
update_themes
upgrade_network
upload_plugins
upload_themes

edit_term                   — WP 4.7 — Не проверят кто создал термин - только проверяет наличие указанного термина и таксономии.
delete_term                 — WP 4.7 —
assign_term                 — WP 4.7 —
activate_plugin             — WP 4.9 — current_user_can( 'activate_plugin', 'my-plugin/my-plugin.php' )
deactivate_plugin           — WP 4.9 — current_user_can( 'deactivate_plugin', 'my-plugin/my-plugin.php' )

export_others_personal_data — WP 4.9.6 — is_multisite() ? 'manage_network' : 'manage_options'
erase_others_personal_data  — WP 4.9.6 — is_multisite() ? 'manage_network' : 'manage_options'
manage_privacy_options      — WP 4.9.6 — is_multisite() ? 'manage_network' : 'manage_options'

update_php                  — WP 5.0 — is_multisite() ? is_super_admin() : update_core
update_https                — WP 5.7 — is_multisite() ? is_super_admin() : manage_options | update_core

create_app_password         — WP 5.7 — map_meta_cap( 'edit_user', $user_id )
list_app_passwords          — WP 5.7 — map_meta_cap( 'edit_user', $user_id )
read_app_password           — WP 5.7 — map_meta_cap( 'edit_user', $user_id )
edit_app_password           — WP 5.7 — map_meta_cap( 'edit_user', $user_id )
delete_app_passwords        — WP 5.7 — map_meta_cap( 'edit_user', $user_id )
delete_app_password         — WP 5.7 — map_meta_cap( 'edit_user', $user_id )

Для проверки таких прав нужно передавать дополнительные параметры, например ID записи для которой нужно проверить может ли пользователь её редактировать. Например:

if( current_user_can( 'edit_post', 123 ) ){
	 echo 'Текущий пользователь может редактировать пост 123';
}

В этом, случае WP налету проверяет является ли пользователь автором этого поста, или у него есть примитивное право редактировать все посты. В результате, если проверка пройдена, это мета право превращается в аналогичное примитивное право, которое разрешает выполнять действие.

Подробнее о мета правах читайте в описании map_meta_cap().

unfiltered_upload

По умолчанию возможность unfiltered_upload есть у администратора. Однако это право по умолчанию заблокировано, т.е. роли не пройдут проверку if( current_user_can('unfiltered_upload') ), несмотря на наличие у них такого права.

Чтобы право unfiltered_upload начало работать как ожидается, нужно в файле wp-config.php «включить» константу:

define( 'ALLOW_UNFILTERED_UPLOADS', true );

С определением этой константы роли имеющие право unfiltered_upload смогут загружать файлы с любым расширением (без проверки типа файла).

Для мультисайт сборки право unfiltered_upload есть только у Супер Администратора. Если у другой роли есть право unfiltered_upload, оно просто будет игнорироваться. Подробнее смотрите проверку мета-права в map_meta_cap():

case 'unfiltered_upload':
	if ( defined( 'ALLOW_UNFILTERED_UPLOADS' ) && ALLOW_UNFILTERED_UPLOADS && ( ! is_multisite() || is_super_admin( $user_id ) ) ) {
		$caps[] = $cap;
	} else {
		$caps[] = 'do_not_allow';
	}
	break;

Примеры

0

#1 Проверим администратор пользователь или нет:

// проверим возможность
if( current_user_can('manage_options') ){
	echo "У пользователя есть права изменять настройки";
}
0

#2 Используем user_can(), чтобы проверить права текущего пользователя:

// определяем пользователя глобально
global $user;
if( user_can($user->ID, 'manage_options') ){
	// делаем что-то что может пользователь с этими правами
};

manage_options - права администратора

0

#3 Пример использования второго аргумента $args:

if( current_user_can('edit_post', 123) ) {
	 echo 'Текущий пользователь может редактировать пост 123'.
}
0

#4 Проверка прав для отдельного элемента таксономии

C версии 4.7. Стало возможным проверять права для отдельного термина. Для этого нужно использовать права: edit_term, delete_term, assign_term.

Например, давайте выведем ссылку на редактирование элемента таксономии, только если текущий текущий пользователь имеет такое право.

if( current_user_can('edit_term', $term_id) ){
	echo '<a href="'. get_edit_term_link( $term_id ) .'">Редакт.</a>';
}
0

#5 Проверка более двух ролей

Если вы хотите проверить более двух ролей, вы можете проверить, находится ли роль текущего пользователя внутри массива ролей, например:

$user = wp_get_current_user();
$allowed_roles = array( 'editor', 'administrator', 'author' );

if ( array_intersect( $allowed_roles, $user->roles ) ) {
   // Stuff here for allowed roles
}
0

#6 Проверка роли текущего пользователя

Не рекомендуется использовать название роли в current_user_can(), Потому что код может работать неправильно.

Пример, как делать не следует:

// если текущий пользователь редактор (editor), то функция вернет:
current_user_can('administrator') // false
current_user_can('editor')        // true
current_user_can('contributor')   // false
current_user_can('subscriber')    // false

Почему так писать не стоит? Например, мы используем проверку current_user_can('editor'), которая позволяет редактору делать что-либо, вроде бы все хорошо и пользователь с ролью 'editor' проходит проверку, но вот пользователь с ролью 'administrator', который также должен проходить проверку, её не пройдет!

Хак для возможности использовать имена ролей в проверке права пользователя

Если вставить этот хук в файле темы functions.php, то в список прав проверяемого пользователя будут добавляться все роли которые считаются ниже по уровню доступа, например для юзера с ролью автор будут добавлены также роли contributor и subscriber. Таким образом, проверка current_user_can( 'contributor' ) будет также пройдена для любой роли выше указанной - это author > editor > administrator.

add_filter( 'user_has_cap', 'user_lower_roles_to_allcaps', 10, 4 );

/**
 * Add lower roles to the list of all caps of current checking user.
 *
 * @param bool[]   $allcaps Array of key/value pairs where keys represent a capability name and
 *                          boolean values represent whether the user has that capability.
 * @param string[] $caps    Required primitive capabilities for the requested capability.
 * @param array    $args    Arguments that accompany the requested capability check.
 * @param WP_User  $user    The user object.
 *
 * @return bool[]
 */
function user_lower_roles_to_allcaps( $allcaps, $caps, $args, $user ){

	$roles_chain = ' > administrator > editor > author > contributor > subscriber > ';

	// do nothing if no need
	if( false === strpos( $roles_chain, $args[0] ) ){
		return $allcaps;
	}

	$low_roles = '';
	foreach( $user->roles as $role ){

		$pos = strpos( $roles_chain, " > $role > " );

		if( false === $pos ){
			continue;
		}

		$_low_roles = substr( $roles_chain, $pos );

		if( strlen( $_low_roles ) > strlen( $low_roles ) ){
			$low_roles = $_low_roles;
		}
	}

	// add top roles to all caps
	$low_roles = explode( ' > ', trim( $low_roles, '> ' ) );
	foreach( $low_roles as $lowrole ){
		$allcaps[ $lowrole ] = 1;
	}

	return $allcaps;
}

Проверим как работает хак:

$user = get_userdata( 141 );  // editor
var_dump( user_can( $user, 'administrator' ) ); // bool(false)
var_dump( user_can( $user, 'contributor' ) );   // bool(true)
echo "---\n";

$user = get_userdata( 3 );    // author
var_dump( user_can( $user, 'administrator' ) ); // bool(false)
var_dump( user_can( $user, 'contributor' ) );   // bool(true)
echo "---\n";

$user = get_userdata( 1220 ); // contributor
var_dump( user_can( $user, 'administrator' ) ); // bool(false)
var_dump( user_can( $user, 'contributor' ) );   // bool(true)
var_dump( user_can( $user, 'subscriber' ) );    // bool(true)
echo "---\n";

$user = get_userdata( 2486 ); // subscriber
var_dump( user_can( $user, 'administrator' ) ); // bool(false)
var_dump( user_can( $user, 'contributor' ) );   // bool(false)
var_dump( user_can( $user, 'subscriber' ) );    // bool(true)
0

#7 Функция проверки нескольких ролей пользователя

Чтобы иметь возможность надежно проверять права точно по ролям, было бы удобно перечислять их в массиве, но мы не можем написать так - это вызовет нотисы:

current_user_can( [ 'administrator', 'author' ] );

Для такой проверки я иногда использую такую функцию:

/**
 * Checks if the specified role is in the roles of the current/specified user.
 *
 * @param string|array      $roles The name of the role you want to check with the current user.
 * @param empty|int|WP_User $user  Default: current user
 *
 * @return bool
 */
function is_user_role_in( $roles, $user = false ) {

	$user || $user = wp_get_current_user();

	if( is_numeric( $user ) ){
		$user = get_userdata( $user );
	}

	if( empty( $user->ID ) ){
		return false;
	}

	foreach( (array) $roles as $role ){
		if( isset( $user->caps[ $role ] ) || in_array( $role, $user->roles, true ) ){
			return true;
		}
	}

	return false;
}

Пример использования:

if( is_user_role_in( [ 'new_role','new_role2' ] ) ){
	echo 'Роль текущего пользователя new_role или new_role2';
}

if( is_user_role_in( [ 'new_role','new_role2' ], 5 ) ){
	echo 'Роль пользователя 5 new_role или new_role2';
}

Заметки

Список изменений

С версии 2.0.0 Введена.
С версии 5.3.0 Formalized the existing and already documented ...$args parameter by adding it to the function signature.
С версии 5.8.0 Converted to wrapper for the user_can() function.

Код current_user_can() WP 6.1.1

function current_user_can( $capability, ...$args ) {
	return user_can( wp_get_current_user(), $capability, ...$args );
}