map_meta_capхук-фильтрWP 2.8.0

Позволяет изменить требуемые примитивные права при проверке возможностей пользователя.

Хук срабатывает в конце функции map_meta_cap(), которая базово определяет возможность (право) текущего пользователя выполнять указанное действие, см. current_user_can(). Хук позволяет дополнительно проверить право пользователя и разрешить или запретить выполнять текущее действие.

Чтобы пройти проверку, хук должен вернуть массив прав, каждое из которых должно быть у пользователя, см. параметр $caps.

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

add_filter( 'map_meta_cap', 'wp_kama_map_meta_cap_filter', 10, 4 );

/**
 * Function for `map_meta_cap` filter-hook.
 * 
 * @param string[] $caps    Primitive capabilities required of the user.
 * @param string   $cap     Capability being checked.
 * @param int      $user_id The user ID.
 * @param array    $args    Adds context to the capability check, typically starting with an object ID.
 *
 * @return string[]
 */
function wp_kama_map_meta_cap_filter( $caps, $cap, $user_id, $args ){

	// filter...
	return $caps;
}
$caps(массив)

Содержит массив прав, которые должны быть у пользователя для прохождения проверки. У пользователя должны совпасть все права из этого массива.

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

Хук возвращает:
Array (
	[0] => edit_others_schools
	[1] => edit_published_schools
)

У пользовали есть примитивные права:
Array (
	[0] => edit_others_schools
	[1] => read
	[2] => edit_posts
)

В данном случае пользователь не сможет отредактировать проверяемый пост,
потому что у него нет права edit_published_schools.
  • Смотрите код WP_User::has_cap(), как проходит проверка.
  • Смотрите хук user_has_cap, который позволяет динамически добавлять права для роли.
$cap(строка)
Текущее название проверяемого права, например: edit_post (мета право) или edit_posts (примитивное право).
$user_id(число)
ID юзера для которого проверяется возможность.
$args(массив)

Дополнительные параметры указанные в функцию проверки права. Например тут будут содержаться все параметры, кроме первого параметра указанные в функции current_user_can().

Обычно этот массив содержит один элемент - ID объекта, для которого проверяется право. Например при current_user_can( 'edit_post', 123 ) этот параметр будет равен: array( [0] => 123 ).

Примеры

0

#1 Пример использования фильтра map_meta_cap

Этот пример показывает как можно дополнительно открыть доступ пользователя для выполнения каких-либо действий. В данном случае, открыть доступ к редактированию записи для подписчика с фронта.

Предполагается что запись можно редактировать с фронт-энда и проверка на эту возможность делается стандартно: current_user_can( 'edit_post', $post_id );

// разрешаем редактировать пост подписчику, если он автор поста и 
// со времени публикации поста не прошло больше X месяцев
! is_admin() && add_filter( 'map_meta_cap', 'allow_subscribers_edit_self_posts', 10, 4 );
function allow_subscribers_edit_self_posts( $caps, $cap, $user_id, $args ){
	// print_r( $caps );    // [0] => edit_published_posts
	// print_r( $cap );     // edit_post
	// print_r( $user_id ); // 80
	// print_r( $args );    // [0] => 913

	if( $cap === 'edit_post' && $caps[0] === 'edit_published_posts' ){
		$post = get_post( $args[0] );
		// разрешаем редактировать пост, если это автор поста и со времени 
		// публикации поста прошло не больше 2 месяца
		if( 
			$post->post_author && $user_id == $post->post_author && 
			get_userdata($user_id)->roles[0] === 'subscriber' && 
			( time() < ( MONTH_IN_SECONDS * 2 + strtotime( $post->post_date_gmt ) ) )
		){
			$caps[0] = 'read';
		}
	}

	return $caps;
}
0

#2 Разрешим определенным пользователям редактировать чужие Записи

Допустим, авторы публикуют проекты (Записи) и в метаполе указывают ID трекера (кастомная роль), который затем сможет редактировать их проекты.

add_filter( 'map_meta_cap', 'allow_tracker_edit_posts', 10, 4 );

/**
 * Разрешает Трекерам редактировать записи подопечных.
 *
 * @param array  $caps
 * @param string $cap
 * @param int    $user_id
 * @param array  $args
 *
 * @return array
 */
function allow_tracker_edit_posts( $caps, $cap, $user_id, $args ) {
	if (
		// Работаем только с нужной мета-возможностью
		$cap === 'edit_post'
		// ID текущего пользователя должен совпадать с тем, что в мете у записи
		&& (int) get_post( $args[0] )->project_tracker === $user_id
		// Роль текущего пользователя, для которого надо добавить возможность
		&& get_userdata( $user_id )->has_cap('project_tracker')
	) {
		$caps[0] = 'edit_posts'; // Добавляем фундаментальную возможность (право)
	}

	return $caps;
}
0

#3 Форсированно запретим что-либо абсолютно всем

Чтобы жестко запретить какое-либо право в хуке нужно вернуть массив с элементом 'do_not_allow'.

Потому что, если например вернуть массив вообще без прав - пустой массив, или массив содержащий несуществующие права, то например, супер-админ в сети мультисайт будет иметь право на любую возможность, даже если её не существует.

Поэтому, когда нужно чтобы никто не имел указанного права , в том числе и супер-админ, нужно добавить в массив возвращаемых прав строку 'do_not_allow'.

Например, удалим у всех (в том числе у супер-админа) право на работу с WP кастомайзером:

add_filter( 'map_meta_cap', 'remove_customize_capability', 10, 2 );
function remove_customize_capability( $caps, $cap ) {
	return ( $cap === 'customize' ) ? [ 'do_not_allow' ] : $caps;
}

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

С версии 2.8.0 Введена.

Где вызывается хук

map_meta_cap()
map_meta_cap
wp-includes/capabilities.php 842
return apply_filters( 'map_meta_cap', $caps, $cap, $user_id, $args );

Где используется хук в WordPress

wp-includes/class-wp-customize-manager.php 2963
add_filter( 'map_meta_cap', array( $this, 'grant_edit_post_capability_for_changeset' ), 10, 4 );
wp-includes/class-wp-customize-manager.php 2970
remove_filter( 'map_meta_cap', array( $this, 'grant_edit_post_capability_for_changeset' ), 10 );