В ReadyScript 3.0 были добавлены классы для работы с внутренними счетчиками. Счетчики должны показывать администратору кличество непросмотренных объектов. Например, кол-во непросмотренных заказов, покупок в 1 клик, предварительных заказов, комментариев и т.д.
Рассмотрим, как работает подсистема счетчиков и не происходит лишней нагрузки на время генерации страницы.
- При открытии страницы, в JS переменной global.meterNextRecalculation записывается время, через которое следует обновить счетчики.
- На стороне административной панели, в скрипте jquery.rs.admin.js инициализируется модуль jQuery.rsMeters, который через указанное в global.meterNextRecalculation время выолняет запрос на global.meterRecalculationUrl с ожиданием получить JSON с данными по счетчикам. Если в global.meterNextRecalculation будет 0, это будет означать, что запрос на получение счетчиков будет выполнен сразу после открытия страницы административной панели в отдельном потоке. Интервал между пересчетами задается в административной панели в разделе Управление → Настройка системы.
- В момент запроса на сервер к global.meterRecalculationUrl, на сервере происходит событие meter.recalculate. Любой модуль сожет его перехватить и предоставить сведения по своим счетчикам.
- Далее rsMeters скрипт парсит полученный JSON, получает идентификаторы и связанными с ними цифрами, затем пробегается по DOM дереву и обновляет заранее установленные метки, в которых должны быть вписаны счетчики.
- Последний результат получения счетчиков кэшируется на стороне сервера с помощью класса Main::Model::NoticeSystem::Meter, поэтому при обновлении страницы или переходе между страницами пересчета не происходит, счетчики отображаются из кэша. Фактически, пересчет может происходить только из AJAX-запроса.
- Заметки
- Счетчики могут рассчитываться в рамках, текущего сайта, пользователя, объекта. Соответственно у разных администраторов счетчики могут показывать независимую информацию.
Как добавить подсчет непросмотренных объектов в свой модуль?
Рассмотрим кейс. У вас есть модуль предоставляющий возможность писать комментарии к товару. Как сделать, чтобы число непросмотренных комментариев отображалось в административной панели в меню и на странице со списком комментариев? Очевидно, что пункт меню, как минимум должен добавляться вашим модулем в систему, чтобы возле него можно было отобразить счетчик. Напомним, что добавить пункт меню можно обработав событие getmenus.
Итак, начнем с отображения флажка "непрочитано" в списке комментариев.
Флаг просмотра объекта
Для начала нам нужно подготовить специальное API, которое сможет выполнять следующие действия:
- возвращение идентификатора счетчика,
- возвращает количество непросмотренных объектов
- установка отметки о просмотре одного объекта
- установка отметки о просмотре всех объектов
- удаление отметки о просмотре объекта
Все эти действия мы описали в интерфейсе Main::Model::NoticeSystem::MeterApiInterface в соответствующих методах:
Для самого распространенного случая, когда счетчик должен подсчитывать количество непросмотренных ORM-объектов одного типа, мы подготовили готовый класс Main::Model::NoticeSystem::MeterApi. Чтобы получить доступ к вышеперечисленным действиям, в конструктор данного класса достаточно передать следующие аргументы:
- $orm_object - объект класса RS::Orm::AbstractObject,
- $meter_id - Строковый идентификатор счетчика,
- $site_id - Идентификатор сайта или null, чтобы использовать текущий сайт
- $user_id - Идентификатор текущего пользователя или null, чтобы использовать текущего пользователя
Пример:
$meter_api = new \Main\Model\NoticeSystem\MeterApi(new \Comments\Model\Orm\Comment, 'rs-admin-menu-comments', null, null);
echo $meter_api->getUnviewedCounter();
Далее, если вы желаете, чтобы в CRUD контроллере была возможность просмотра красных флажков о непросмотренных объектах и установки флага просмотра того или иного объекта, нужно подсказать системе, что наша модель Comments::Model::Api умеет работать со счетчиками.
Для этого в классе Comments::Model::Api нужно имплементировать интерфейс Main::Model::NoticeSystem::HasMeterInterface. Интерфейс описывает следующие методы:
<?php
namespace Main\Model\NoticeSystem;
interface HasMeterInterface
{
}
Имплементируем указанный интерфейс в нашей модели:
<?php
namespace Comments\Model;
implements HasMeterInterface
{
const
{
return new \Main\Model\NoticeSystem\MeterApi(
$this->obj_instance,
self::METER_COMMENT,
$user_id);
}
}
Таким образом, мы сообщили CRUD контроллеру, что наша модель поддерживает работу со счетчиками, соответственно стали доступны действия actionMarkOneAsViewed (отметить один объект просмотренным), actionMarkAllAsViewed (отметить все объекты просмотренными), при выполнении действия actionEdit - объект также будет отмечен просмотренным.
Далее нужно добавить в таблицу специальную колонку, которая будет содержать нужный нам флажок, для этого корректируем административный CRUD контроллер:
<?php
namespace Comments\Controller\Admin;
use \RS\Html\Table\Type as TableType,
\RS\Html\Table;
{
protected
{
parent::__construct(new \Comments\Model\Api());
}
{
$helper = parent::helperIndex();
$helper->setTopHelp(t('Здесь отображаются комментарии ко всем объектам на сайте, для которых доступно комментирование. Воспользуйтесь фильтром, чтобы отобрать комментарии к нужному объекту. В настройках модуля можно установить, необходимо ли премодерировать комментарии, возможно ли написать более одного комментария к одному объекту с одного IP, а также другие настройки.'));
$helper->setTopTitle(t('Комментарии'));
$helper->setTable(new Table\Element(array(
'Columns' => array(
new TableType\Checkbox('id'),
new TableType\Viewed(null, $this->api->getMeterApi()),
))));
}
}
Далее привяжем пересчет счетчиков к общему событию meter.recalculate, чтобы находясь в административной панели на любой странице у вас периодически обновлялся ваш счетчик.
Класс с обработчиками событий может выглядеть так:
<?php
namespace Comments\Config;
{
{
$this
->bind('getmenus')
->bind('meter.recalculate');
}
{
$items[] = array(
'title' => t('Комментарии'),
'alias' => 'comments',
'link' => '%ADMINPATH%/comments-ctrl/',
'typelink' => 'link',
'parent' => 'modules'
);
return $items;
}
{
$comment_api = new CommentsApi();
$comment_meter_api = $comment_api->getMeterApi();
$meters[$comment_meter_api->getMeterId()] = $comment_meter_api->getUnviewedCounter();
return $meters;
}
}