pre_user_query. Фильтрация пользователей перед выводом на сайте (изменение SQL запроса).

Владислав Белецкий
Владислав Белецкий .
Категория:
Комментариев: 0

Прежде всего нужно понять один важный момент. Когда я только увидел в коде экшн pre_user_query, я подумал: «А, наверное это что-то наподобие pre_get_posts, но только для пользователей».

Ничего подобного. На самом деле существуют два основных фильтра, связанных с полечением пользователей:

Если вы пришли сюда не за готовым примером, а для того, чтобы во всём разобраться, то предлагаю начать с того, чтобы вставить код ниже в 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, то не забудьте поменять и тут
	}
 
}

Что можно понять из этого примера?

$tekuchij_polzovatel = wp_get_current_user();
if ($tekuchij_polzovatel->ID != 2)
	add_action('pre_user_query','true_skrivaem_polzovatelya');

Но не стоит беспокоиться, этот счетчик тоже можно спокойно поправить парой хуков, только это уже пожалуй тема отдельного поста.

2. Если пользователь не администратор, то скрываем всех администраторов

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

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' );
		}
	}
}

По теме

Подписаться
Уведомить о
guest
0 комментариев
Межтекстовые Отзывы
Посмотреть все комментарии