Статус онлайн в профиле (и не только) [реализация]




Спасибо ort и PSNet

Загорелся идеей вывести в профиль статус онлайн/оффлайн для пользователей. Понял, что по сути можно сделать напрямую в шаблоне примерно такой схемой
{если «текущее время в секундах» — «дата последнего визита в секундах» < 900 секунд} онлайн {иначе} оффлайн {/если}

Итак, поехали

1. Профиль пользователя

В любое месте в /actions/ActionProfile/whois.tpl или /actions/ActionProfile/sidebar.tpl
Вставляем следующее:

    {if (time() - strtotime($oSession->getDateLast()))<900}
        on
    {else}
        off
    {/if}

Сразу пояснение: «on» выводится если человек онлайн и «off» — соответственно, если оффлайн. Вместо этих условных обозначений можно выводить любой текст или картинки — все на ваше усмотрение.
Единственное, если вам нужно на русском языке выводить статус, тогда для этого добавьте записи в templates/language/russin.php, например:
'user_status_online' => 'онлайн',
'user_status_offline' => 'оффлайн',

А потом в шаблоне используете так:
{$aLang.user_status_online} или {$aLang.user_status_offline} соответственно

Для проверки можно вывести в шаблон также результат, который получается при вычитании дат:
{(time() - strtotime($oSession->getDateLast()))}

В профиле все работает, перебираемся к разделу «Люди»

2. Люди

Раздел люди включает в себя грубо говоря 3 вкладки:
— все люди
— новые люди
— люди онлайн
Начнем со всех людей:
Открываем файл actions/ActionPeople/index.tpl вашего шаблона и находим следующее:
{foreach from=$aUsersRating item=oUser}

После вставляем:
{assign var="oSession" value=$oUser->getSession()}

И рядом с логином:
<a href="{$oUser->getUserWebPath()}" class="username">{$oUser->getLogin()}</a>

Вставляем статус:
{if (time() - strtotime($oSession->getDateLast()))<900}on{else}off{/if}

Все, переходим к «новым людям», для этого открываем /actions/ActionPeople/new.tpl и находим:
{foreach from=$aUsersRegister item=oUser}

после чего вставляем
{assign var="oSession" value=$oUser->getSession()}

Находим опять логин:
<a href="{$oUser->getUserWebPath()}" class="username">{$oUser->getLogin()}</a>

и рядом ставим статус:
{if (time() - strtotime($oSession->getDateLast()))<900}on{else}off{/if}

Готово, теперь переходим к людям «онлайн».
Наша цель выводить только тех, кто действительно онлайн, ну и статус рядом, хотя и так понятно, что в разделе онлайн все онлайн.
Для этого небольшие пояснения — в разделе онлайн выводится таблица с людьми, а каждый человек занимает ровно одну строчку, поэтому мы сделаем условие не просто для статуса, а для целой строчки и если человек онлайн, то его строчку выводим, а если оффлайн — не выводим соответственно. Поехали.
Открываем файл /actions/ActionPeople/online.tpl и находим:
{foreach from=$aUsersLast item=oUser}

После вставляем:
{assign var="oSession" value=$oUser->getSession()}

Между этими {foreach...} и {/foreach} находится та самая строчка таблицы, выглядит она так:

    <tr>
        <td><a href="{$oUser->getUserWebPath()}"><img src="{$oUser->getProfileAvatarPath(24)}" alt="image" /></a>
<a href="{$oUser->getUserWebPath()}" class="username">{$oUser->getLogin()}</a></td>		
        <td align="center">{date_format date=$oSession->getDateLast()}</td>						
        <td align="center"><font style="color: #268D0F; font-size: 12px;">{$oUser->getSkill()}</font></td>
        <td align="center"><font style="color: #C30007; font-size: 12px;">{$oUser->getRating()}</font></td>	
    </tr>

Вот её мы и берем в условие и получается примерно так:

{if (time() - strtotime($oSession->getDateLast()))<900}

    <tr>
        <td><a href="{$oUser->getUserWebPath()}"><img src="{$oUser->getProfileAvatarPath(24)}" alt="image" /></a>
<a href="{$oUser->getUserWebPath()}" class="username">{$oUser->getLogin()}</a> - ONLINE!!!</td>		
        <td align="center">{date_format date=$oSession->getDateLast()}</td>						
        <td align="center"><font style="color: #268D0F; font-size: 12px;">{$oUser->getSkill()}</font></td>
        <td align="center"><font style="color: #C30007; font-size: 12px;">{$oUser->getRating()}</font></td>	
    </tr>

{else}

<!-- а если юзер оффлайн, то вообще его не выводим -->

{/if}


Таким образом закончили вывод в разделе «Люди»

3. Список читателей блога

Если к блогу присоединилось много читателей, то список этих читателей выводится на отдельную страницу, пример.
И здесь мы тоже выведем статус.
Для этого открываем файл /actions/ActionBlog/users.tpl и находим:
{foreach from=$aBlogUsers item=oBlogUser}
		{assign var="oUser" value=$oBlogUser->getUser()}

После вставляем:
{assign var="oSession" value=$oUser->getSession()}

Далее опять находим логин пользователя:
<a href="{$oUser->getUserWebPath()}" class="username">{$oUser->getLogin()}</a>

и после вставляем статус:
{if (time() - strtotime($oSession->getDateLast()))<900}<span style="color:green;">on</span>{else}<span style="color:gray;">off</span>{/if}

С этим закончили, переходим к комментариям.

4. Комментарии

Для начала идем в classes/modules/comment/Comment.class.php и находим:
public function GetCommentsAdditionalData($aCommentId,$aAllowData=array('vote','target','favourite','user'=>array())) {}

и удаляем из этого куска
=>array()

Теперь идем в папку с шаблоном и открываем файл comment.tpl, находим в нем:
{assign var="oUser" value=$oComment->getUser()}

после вставляем
{assign var="oSession" value=$oUser->getSession()}

Находим логин пользователя
<a href="{$oUser->getUserWebPath()}">{$oUser->getLogin()}</a>

и рядом вставляем статус
{if (time() - strtotime($oSession->getDateLast()))<900}on{else}off{/if}


Опять же — обозначения on и off условны и вместо них можно использовать любой текст или картинку с любым форматированием.

Это то, что есть на данный момент:
— профиль
— все пользователи
— новые пользователи
— пользователи онлайн (причем выводятся только те, кто действительно онлайн)
— список читателей блога
— комментарии
Сегодня постараюсь добавить для:
— топик
— лента активности
— прямой эфир

UPD:
Вот что мне нравится в ЛС — все сделано грамотно! Нарыл на сайте инфу интересну по поводу формирования дат в ЛС, поэтому вместо, допустим просто надписи оффлайн, можно выводить когда он было последний раз онлайн. Делается таким образом — вместо «off» ставим:
{date_format date=$oSession->getDateLast() hours_back="12" minutes_back="60" now="60" day="day H:i" format="d F Y, H:i"}

Код возможно кривоват) Выводит что типа:
«Только что»
«5 минут назад»
«6 часов назад»
«Вчера в 2.12»
«Сегодня в 1.15»
если очень давно — пишет просто дату ДД.ММ.ГГГГ, ЧЧ: ММ
Кое что еще — сессии для пользователя обновляются раз в 10 минут, поэтому не ждите, что при каждом обновлении страницы будет выводиться «Только что».

С ув. Frankenstein
Источник

40 комментариев

avatar
Сейчас статус онлайн/оффлайн уже есть в:
— профиль
— все пользователи
— новые пользователи
— пользователи онлайн (причем выводятся только те, кто действительно онлайн)
— список читателей блога
Осталось добавить в:
— топик
— комментарии
— лента активности
Вот там, где осталось добавить — туда не удается передать дату последнего визита — очень прошу помочь, т.к. на сайте везде переискал и нигде нету ответа на вопрос + реализации статуса онлайн/оффлайн так же нету (для версии 0.5.х)
avatar
все сработало, а комментариях в никакую… ХЗ почему
так почему же вы хотите получить oSession от комментария? он что, сам заходит на сайт?
у комментария берете автора (см. код — он уже взят там), у автора берете oSession, у oSession берете getDateLast() и сравниваете с текущим временем.
avatar
Почему-то не получается…
1)
у комментария берете автора
насколько я понимаю это вот это:
{assign var="oUser" value=$oComment->getUser()}
2)
у автора берете oSession
это я делаю так, наверное с ошибкой
{assign var="oSession" value=$oUser->getSession()}
3)
у oSession берете getDateLast()
вот тут при вызове getDateLast() и вылетает ошибка
{if (time() - strtotime($oSession->getDateLast()))<900} ...
Ошибка соответственно:
Fatal error: Call to a member function getDateLast() on a non-object in /home/.../123.file.comment.tpl.php
avatar
вот из-за этого github.com/livestreet/livestreet/blob/master/classes/modules/comment/Comment.class.php#L81
public function GetCommentsAdditionalData($aCommentId,$aAllowData=array('vote','target','favourite','user'=>array())) {}
если сделать
$aAllowData=array('vote','target','favourite','user')
то для юзер в комментариях всегда будут подтягиваться все данные
avatar
Действительно — все сработало, спасибо.
Мне осталось дописать статью для таких же как я)
avatar
Это было бы замечательно, если бы вы расписали по пунктам как все, что описано в комментарии №1!
avatar
поддерживаю. очень полезно читать такие инструкции для чайников. не все ведь гуру
avatar
Сделайте плагин по мотивам хака плизз…
avatar
не нужно тут плагина, все делается версткой
avatar
я когда вставляю код в любое место {if (time() — strtotime($oSession->getDateLast()) > 900}
on
{else}
off
{/if} у меня сразу ошибки. Может его не влюбое место нужно вставлять? или может какие теги нужно вставить?
avatar
В любом месте, главное после
{assign var="oSession" value=$oUserProfile->getSession()}
.
А в какой файл вставляете?
avatar
и в тот и в тот пробывал. да я ставил после этого кода — всё равно невыходит. у меня в профилях показывает последний визит когда и во сколько — только вот сейчас он онлайн не выходит
avatar
Дайте текст ошибки.
avatar
Так, прошу прощения, ошибка была моя) В самом первом примере же есть ошибка — пропущена одна закрывающая скобка ")". В посте поправил. Самое странное, что дальше без ошибки, а ведь когда писал пост скопировал первый код, но ошибок дальше нет.
avatar
Сейчас попробую и отпишусь)))
avatar
Да получилось!))) Сейчас на русский попробую перейти. А если за место слов — картинку онлайн поставить?
avatar
Ну и хорошо, что работает) Спасибо вам за неожиданный багрепорт. Странно, что вы первый, кто сказал, что не работает — пост в избранном у почти 40-ка людей.
Можно все что угодно ставить — картинку, текст:
{if (time() - strtotime($oSession->getDateLast()))<900}
        <img src="путь до картинки для онлайна" title="online">
    {else}
        <img src="путь до картинки для оффлайна" title="offline">
    {/if}
avatar
Вам спасибо огромное)))) А В ШАБЛОНЕ Где именно {$aLang.user_status_online} или {$aLang.user_status_offline} соответственно / там же где of и on?
avatar
Да, конечно, {$aLang.user_status_online} вместо on и {$aLang.user_status_offline} вместо off
avatar
да да да я понял))) просто поторопился написать)))

Спасибо огромное!!!)))
avatar
Кстати здесь тоже скобки нехватает {(time() — strtotime($oSession->getDateLast())}

Только я вот не понял вот это значение: онлайн 2122 это цыфра сколько минут нет человека?
avatar
а понял это сколько секунд его небыло и сколько секунд он находиться да?)) а можно там как нибудь подписать что это секунды?
avatar
Сейчас появилась странная ошибка. Везде выводится онлайн, а при оффлайн пишется ошибка.
avatar
А какая ошибка?
avatar
Вот к примеру:
Fatal error: Call to a member function getDateLast() on a non-object in /templates/compiled/simple/31656b51259c0090ae8e6e8e3f1d9ef078e98724.file.index.tpl.php on line 63

Причём такое везде. Онлайн отображается нормально.
avatar
Надеюсь, вы понимаете, что дело не в выводе статуса) У всех пользователей такое? Если он в оффлайне, то такая ошибка? И на всех страницах?
avatar
Ошибка на всех страницах, где использован хак.
Ну это очевидно, что не в выводе
avatar
А после чего начала появляться ошибка? Плагины не ставили?
avatar
Переустановил ls. База слетела, бэкапы не делал
avatar
Такая ошибка вылетала у меня, когда получалось, что при регистрации у человека не происходил первый вход (по каким-то причинам, у меня, допустим, первый раз была ошибка сервера просто), поэтому нет даты последнего логина и, соответственно, эта ошибка.
У вас (админский аккаунт, с которого вы заходите на сайт) тоже такая ошибка, когда вы в оффлайне?
avatar
В профиле в смысле.
avatar
Люди по-любому первый раз заходили. С этим не связано. Как ни странно всё работало раньше. Сейчас не знаю в чём ошибка.
avatar
Видимо данные по онлайн подгружаются, а данные по оффлайн нет.
avatar
Если выводит онлайн, значит все-таки сессии есть, значит и оффлайн должен выводить нормально. Вы по поводу своего профиля так и не ответили.
avatar
Я понял в чём проблема. Плагин autoopenid (который платный) по какой-то причине не пишет сессию, те не пишет время последней активности, время последнего визита, последний ip.
avatar
{if $oSession and (time() - strtotime($oSession->getDateLast()))<900}
avatar
Не помогло.
avatar
У меня установлен плагин EditComment, когда делаю удаление 'user'=>array() плагин отваливается… Есть ли еще варианты получать этот самый getDateLast? Оставив array() на месте.
avatar
Плагин от netlanc'a? Если да, то у меня он тоже стоит и все работает нормально.
avatar
Понял. Задумался.
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.