map_meta_cap
Позволяет изменить требуемые примитивные права при проверке возможностей пользователя.
Хук срабатывает в конце функции 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 )
.
Примеры
#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; }
#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; }
#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 | Введена. |
Где вызывается хук
return apply_filters( 'map_meta_cap', $caps, $cap, $user_id, $args );
Где используется хук в WordPress
add_filter( 'map_meta_cap', array( $this, 'grant_edit_post_capability_for_changeset' ), 10, 4 );
remove_filter( 'map_meta_cap', array( $this, 'grant_edit_post_capability_for_changeset' ), 10 );