Прежде всего нужно понять один важный момент. Когда я только увидел в коде экшн pre_user_query
, я подумал: «А, наверное это что-то наподобие pre_get_posts, но только для пользователей».
Ничего подобного. На самом деле существуют два основных фильтра, связанных с полечением пользователей:
-
pre_get_users
(как раз он и является аналогомpre_get_posts
для постов) выполняется до того, как спарсится SQL запрос и позволяет поменять какие-то параметры WP_User_Query, например количество выводимых пользователей, их сортировка и т.д. -
pre_user_query
вступает в действие уже после того, как спарсится SQL запрос, непосредственно перед его выполнением. Ему и посвятим этот пост.
Если вы пришли сюда не за готовым примером, а для того, чтобы во всём разобраться, то предлагаю начать с того, чтобы вставить код ниже в functions.php
вашей текущей темы и перейти на любую страницу сайта, где присутствует вывод пользователей, например в список пользователей в админке.
add_action( 'pre_user_query', 'true_funkciya' ); function true_funkciya( $zapros ){ print_r( $zapros ); } |
Статья рассчитана на пользователей, которые уже кое-в-чём понимают, поэтому я не буду объяснять значение простых функций наподобие print_r()
.
И ещё кое-что, если ваша версия WordPress ниже, чем 3.1, то pre_user_query
у вас работать не будет (попробуйте использовать вместо неё pre_user_search
, а ещё лучше — обновитесь).
Окей, а теперь давайте на примерах посмотрим, что с этим можно сделать.
1. Скрытый пользователь.
Итак, как полностью скрыть какого-либо пользователя из сайта и админки, но при этом сам он себя будет видеть. Конечно при помощи pre_user_query
.
add_action('pre_user_query','true_skrivaem_polzovatelya'); function true_skrivaem_polzovatelya( $zapros ) { // так как сам себя пользователь видеть должен, поэтому нам понадобится следующее условия $tekuchij_polzovatel = wp_get_current_user(); if ($tekuchij_polzovatel->ID != 2) { // я взял пользователя с ID = 2, вы можете использовать любого другого global $wpdb; // используем обычную str_replace() для того, чтобы исключить пользователя из SQL запроса $zapros->query_where = str_replace('WHERE 1=1', "WHERE 1=1 AND {$wpdb->users}.ID<>2", $zapros->query_where); // если будете менять ID, то не забудьте поменять и тут } } |
Что можно понять из этого примера?
- То, что я извращаюсь с транслитом (надеюсь, это не слишком мешает, просто у меня есть ещё и англоязычный блог, на который я переношу многие из статей — не хочу получить дубликаты кода).
- Условие на проверку текущего пользователя вы кстати можете вынести за пределы функции и поставить под условие
add_action()
, в принципе получится вот так:$tekuchij_polzovatel = wp_get_current_user(); if ($tekuchij_polzovatel->ID != 2) add_action('pre_user_query','true_skrivaem_polzovatelya');
- Хоть пользователь и пропадёт из сайта, для того, чтобы полностью всех обмануть, вам также придётся поработать со счетчиками количества пользователей, для того, чтобы вам было понятно, о чём я говорю, вот скриншот:
Но не стоит беспокоиться, этот счетчик тоже можно спокойно поправить парой хуков, только это уже пожалуй тема отдельного поста.
- Как видите, мы просто заменили WHERE-часть запроса, те, кто хорошо знаком с базами данных, увидит здесь гораздо большую свободу действий.
2. Если пользователь не администратор, то скрываем всех администраторов
По сути всё основывается на том же принципе, что и в предыдущем примере, только SQL-запрос станет намного интереснее. Пример будет также основываться на ролях пользователей, про которые можно почитать здесь.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
add_action('pre_user_query','true_skrivaem_administratorov'); function true_skrivaem_administratorov( $zapros ) { // так же, как и в предыдущем примере получаем текущего пользователя и убеждаемся, что он не администратор // разумеется тут можно использовать любую свою проверку $tekuchij_polzovatel = wp_get_current_user(); if ( $tekuchij_polzovatel->roles[0] != 'administrator' ) { global $wpdb; $zapros->query_where = str_replace( 'WHERE 1=1', "WHERE 1=1 AND {$wpdb->users}.ID IN ( SELECT {$wpdb->usermeta}.user_id FROM $wpdb->usermeta WHERE {$wpdb->usermeta}.meta_key = '{$wpdb->prefix}capabilities' AND {$wpdb->usermeta}.meta_value NOT LIKE '%administrator%')", $zapros->query_where ); } } |
Если вам всё ещё многое непонятно, могу порекомендовать почитать статью про базы данных в WordPress, про $wpdb тут.
Теперь же краткое описание того, что сделали — как известно, название роли пользователя хранится в таблице базы данных wp_usermeta
(заменить wp_
на используемый у вас префикс) под ключом wp_capabilities
. И в примере мы получили только тех пользователей, у которых в значении wp_capabilities
в базе данных отсутствует administrator
.
3. Расширенный поиск пользователей
По умолчанию WordPress позволяет производить поиск пользователей по уже определенным полям, например по логину user_login
, емайлу user_email
, URL user_url
, отображаемому имени display_name
, айди ID
и по нику user_nicename
. Всё, что нам разрешается, это исключить какие-либо из колонок из поиска при помощи фильтра user_search_columns
.
Однако и тут pre_user_query
открывает перед нами новые возможности — мы можем можем включить в поиск как любые метаданные пользователя, так и заголовки постов!
add_action('pre_user_query','true_poisk_po_meta'); function true_poisk_po_meta( $zapros ){ // прежде всего делаем несколько проверок, для того, чтобы код применялся только при поиске пользователей if ( $zapros->query_vars['search'] ){ $poisk = trim( $zapros->query_vars['search'], '*' ); if ( $_REQUEST['s'] == $poisk ){ global $wpdb; // добавляем Имя first_name пользователя в поиск $zapros->query_from .= " JOIN {$wpdb->usermeta} fn ON fn.user_id = {$wpdb->users}.ID AND fn.meta_key = 'first_name'"; // добавляем любые метаданные пользователя // $zapros->query_from .= " JOIN {$wpdb->usermeta} cstm ON cstm.user_id = {$wpdb->users}.ID AND cstm.meta_key = 'ВАШ ПРОИЗВОЛЬНЫЙ meta_key'"; // ну и пример с заголовками постов (я включил все посты, любого статуса и типа, но вы можете это доработать) $zapros->query_from .= " JOIN {$wpdb->posts} psts ON psts.post_author = {$wpdb->users}.ID"; // решаем, по каким полям в итоге производить поиск $posik_po = array( 'user_login', 'user_email', 'fn.meta_value', 'psts.post_title' ); // применяем к запросу $zapros->query_where = 'WHERE 1=1' . $zapros->get_search_sql( $poisk, $posik_po, 'both' ); } } } |
Источник: misha.blog