Создание индикатора присутствия пользователя на сайте

3008

Сегодня хотел поделиться реализацией одной интересной штуковины на сайт: отображения индикатора присутствия пользователя на сайте. Хотя он пока не очень популярен, все же можно придумать массу областей, где его можно с пользой применить. Например, показать посетителям, что администратор в сети, и может быстро ответить на вопрос. Соцсети, чаты, формы для комментирования и обратной связи. Это неполный список применения индикатора.

Программирование в первую очередь — размышление, а потом уже написание кода. Поэтому, в начале давайте определимся с алгоритмом реализации поставленной задачи, а потом перейдем к коду.

В WordPress нет встроенной функции для получения данных об авторизации какого-либо другого пользователя (если это не так, поправьте меня). Однако, мы можем узнать вошел ли пользователь под своим логином. Что ж, уже не мало.  Ведь эти данные мы можем затем сохранить, и передать эти сведения другим посетителям сайта.

Для этого, давайте создадим метаполе каждому юзеру. Назовем его logged. При входе на сайт, запишем в него значение true, то есть, пользователь на сайте, а при выходе false. Для отображения индикатора будем получать значения этого поля. Попробуем это сделать?

Создаем метаполе logged

Чтобы проверить смену значения поля, отобразим его на странице пользователя. Следующий код нужно разместить в файл function.php:

add_filter('user_contactmethods', 'my_user_contactmethods');
function my_user_contactmethods($user_contactmethods){
	$user_contactmethods['logged'] = 'Залогинен ли пользователь';
	return $user_contactmethods;
}

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

Выводим индикатор во фронтэнде

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

<span class="photo">
	<?php if ( get_user_meta( 1, 'logged', true) == 'true' ) { 
		echo '<span class="mgo-widget-call_pulse" title="Я онлайн. Вы можете написать мне."></span>';
	} else { 
		echo '<span class="mgo-widget-call" title="Я не в сети. Но вы можете написать мне. Отвечу в ближайшее время."></span>'; }
	; ?>
	<img src="путь к аватарке" alt="Описание каринки" />
</span>

Программируем смену значения метаполя

Создадим проверку авторизован ли текущий пользователь с помощью функции is_user_logged_in. Если пользователь залогинен, определим его id и впишем в созданное метаполе значение true. Кроме того, необходимо заложить основание для замены значения поля на false при выходе. Для этого запустим сессию, в которой сохраним id пользователя. Данные сессии мы удалим, если пользователь выходит. Разместите в файле function.php следующее:

// Добавление мета поля пользователя при регистрации
if ( is_user_logged_in() ) {
	$user_ids = get_current_user_id();
	update_user_meta( $user_ids, 'logged', 'true' );
	
	session_start();
	$_SESSION['user_id'] = get_current_user_id();
}

Теперь установим значение мета поля false при выходе с сайта.

$detected_user_id = $_SESSION['user_id'];
function user_loginout_detect() {
	
	$id = $GLOBALS['detected_user_id'];
	
	// проверка, вышел ли пользователь
	if ( isset($_GET['loggedout']) && TRUE == $_GET['loggedout'] ) {
		update_user_meta( $id, 'logged', 'false' );
	}
	// уничтожаем переменную сессии и саму сессию
	unset($_SESSION['user_id']);
	session_destroy();
	
}
add_filter( 'login_message', 'user_loginout_detect' );

Хочется отметить, что данный способ изменения значения метаполя logged я проверял только на стандартной форме входа и выхода с сайта. Кроме того, он не учитывает ситуацию, когда пользователь забыл произвести выход с сайта и просто закрыл вкладку браузера. Учитывая это, предложенный в этой статье способ хорошо подходит скорее отображения присутствия администратора.

Если вы хотите менять состояние индикатора при отсутствии активности пользователя в течении установленного времени, придется обратиться к планировщику, основанному на wp_schedule_event(). Возможно, я разовью эту мысль в другой раз.

Оформление индикатора

Теперь осталось красиво оформить. Давайте сделаем так, чтобы при активном состоянии индикатор был зеленого цвета и пульсировал, а при неактивном состоянии, становился серого цвета. Прописываем стили:

/* Пульсация блока */
.mgo-widget-call {
	cursor: pointer;
	height: 10px;
	width: 10px;
	background-color: #909090;
	border-radius: 100%;
	position: absolute;
	margin: 5px;
	opacity: 1;
}
.mgo-widget-call_pulse {
	cursor: pointer;
	height: 10px;
	width: 10px;
	background-color: #8bc34a;
	border-radius: 100%;
	position: absolute;
	margin: 5px;
	opacity: 1;
	-webkit-animation: shake 2s infinite ease-in-out;
	animation: shake 2s infinite ease-in-out;
	-webkit-animation-delay: .6s;
	animation-delay: .6s;
}
.mgo-widget-call_pulse:after,
.mgo-widget-call_pulse:before {
	content: '';
	position: absolute;
	left: 50%;
	bottom: 0;
	top: 0;
	background-color: #8bc34a;
	border-radius: 100%;
	-webkit-animation: pulse 2s infinite ease-in-out;
	animation: pulse 2s infinite ease-in-out;
}
.mgo-widget-call_pulse:before {
	margin: auto 0 auto -10px;
	height: 20px;
	width: 20px;
	opacity: .75;
	-webkit-animation-delay: .6s;
	animation-delay: .6s;
}
.mgo-widget-call_pulse:after {
	margin: auto 0 auto -15px;
	height: 30px;
	width: 30px;
	-webkit-animation-delay: .2s;
	animation-delay: .2s;
	opacity: .5;
}
@-webkit-keyframes pulse {
	0% {
		transform: scale(0);
	}
	50% {
		transform: scale(1);
	}
	100% {
		transform: scale(1);
		opacity: 0;
	}
}
@keyframes pulse {
	0% {
		transform: scale(0);
	}
	50% {
		transform: scale(1);
	}
	100% {
		transform: scale(1);
		opacity: 0;
	}
}

Пример работы индикаторы вы можете увидеть у меня на сайте под меню. На этом, пожалуй все. Если у вас есть предложения, как можно улучшить реализацию данной идеи, пожалуйста, напишите в комментариях.

8 comments to post “"Создание индикатора присутствия пользователя на сайте"
  • Yan Alexandrov
    Kowalski13 Авг 2017 06:33

    Все оказалось гораздо проще, чем я думал. Спасибо.
    P.S. Это же из плагина?

    Ответить
    • Yan Alexandrov
      Yan AlexandrovАвтор13 Авг 2017 10:25

      Всегда пожалуйста. Реализация не из плагина. Если есть похожее решение плагином, было бы интересно взглянуть 🙂

      Ответить
  • Yan Alexandrov
    Kowalski22 Авг 2017 18:27

    Здравствуйте! Решил реализовать это на тестово-учебном сайте. В итоге получилось, что сессия не хочет «уничтожаться». Ну, и вот такое сообщение в форме входа/выхода: Warning: session_destroy(): Trying to destroy uninitialized session in /home/u760442852/public_html/wp-content/themes/n.tech/functions.php on line 127

    Ответить
  • Yan Alexandrov
    FreeMan12 Фев 2018 20:56

    А почему сессия не уничтожается?

    Ответить
    • Yan Alexandrov
      anton21 Авг 2018 11:23

      uninitialized session <— почему сессия не уничтожается?… непонятно…

      Ответить
  • Yan Alexandrov
    TrueUser6 Окт 2019 17:46

    Отсутствии активности говорите? Так можно ведь это реализовать.

    Вот код:

    function user_last_seen() {
    	if ( is_user_logged_in() ) {
    		update_user_meta( get_current_user_id(), 'last_seen', time() );
    	} else {
    		return;
    	}
    }
    add_action( 'wp_footer', 'user_last_seen', 10 );
    add_action( 'admin_print_footer_scripts', 'user_last_seen' );

    Дальше начинаем «танцевать с бубном».

    Извлекаем 🙂

    $last_seen = get_the_author_meta( 'last_seen' );

    «Заковываем» непонятные цифры в human_time_diff (формате удобном для чтения)

    $last_seen_date = human_time_diff( $last_seen );

    Теперь создаем условия.

    $ago    = __( 'назад', 'text_domain' );
    $online = __( 'в сети', 'text_domain' );
    
    // Выводим "в сети", если пользователь сохраняет активность в течении 15 минут
    if( $last_seen > strtotime( '-15 minutes' ) ){
    	$html = ''. $online .'';
    // Иначе показываем дату последней активности
    } else {
    	$html = ''. $last_seen_date.''. $ago .'';
    }

    P.S У вас комментарии прыгают в начало при вводе каждого символа, что крайне неудобно и не дает мне опубликовать мысли в полном масштабе.

    Ответить
    • Yan Alexandrov
      Yan AlexandrovАвтор6 Окт 2019 18:11

      Спасибо за комментарии. Хорошее решение с определением времени последней активности.

      Ответить
  • Yan Alexandrov
    TrueUser6 Окт 2019 17:52

    Кстати! Если пользователь никогда не входил, то human_time_diff вызывает ошибку.

    Решение проблемы:

    if( ! empty( $last_seen ) ){
    	$last_seen_date = human_time_diff( $last_seen );
    }
    Ответить
Добавить комментарий

B I PHP JS

Made with by CodyShop