Версия: 3.x
Подсистема уведомлений на Email, SMS, ПК

ReadyScript предоставляет готовую подсистему уведомлений, которые могут быть доставлены через Email, SMS, Desktop приложение "Уведомления ReadyScript". Разработчики в момент происхождения того или иного события могут создавать уведомления и не задумываться о транспорте доставки этих уведомлений.

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

alerts.png
Настройка уведомлений

Класс уведомления

За работу подсистемы уведомлений отвечает модуль Alerts, входящий во все редакции ReadyScript. Каждое уведомление прдставляет собой класс, потомок Alerts::Model::Types::AbstractNotice. Чтобы модуль Alerts автоматически подхватил уведомление, класс должен располагаться в следующем пространстве имен:

\ModuleName\Model\Notice

Например, создадим уведомление CustomNotice в простейшем модуле ModuleName, для этого поместим в файл /modules/modulename/model/notice./customnotice.inc.php следующее содержимое:

namespace \ModuleName\Model\Notice;
/**
* Скелет класса, будущего уведомления о покупке в 1 клик для администратора
*/
class CustomNotice extends \Alerts\Model\Types\AbstractNotice
{
public
$oneclick;
/**
* Возвращает краткое описание уведомления
* @return string
*/
public function getDescription()
{
return t('Покупка в 1 клик(администратору)');
}
/**
* Инициализирует уведомление
* @return void
*/
public function init(\Catalog\Model\Orm\OneClickItem $oneclick)
{
$this->oneclick = $oneclick;
}
}

Чтобы наделить класс уведомления тем или иным поведением (отправка на Email, SMS, ПК), необходимо имплементировать соответствующий интерфейс или сразу несколько интерфейсов.

Разработчик должен реализовать в каждом классе метод init(), который будет инициализировать переменные, которые необходимы для формирования тела письма или получателя уведомления. Таким образом в момент созникновения события, например, покупки в 1 клик есть возможность инициализировать уведомление.

$oneclick = new \Catalog\Model\Orm\OneClickItem(1); //Загрузим покупку в 1 клик с ID = 1
//Инициализируем уведомление
$notice = new \ModuleName\Model\Notice\CustomNotice();
$notice->init($oneclick);
//Такое уведомление уже можно отправить с помощью менеджера уведомлений, об этом далее.

Уведомления на Email

Интерфейс Alerts::Model::Types::InterfaceEmail добавляет уведомлению возможность быть отправленным на Email. Рассмотрим его подробнее.

/**
* Интерфейс уведомления, которое может быть отправлено на Email
*/
interface InterfaceEmail
{
/**
* Возвращает путь к шаблону письма
* Данный шаблон может быть перегружен пользователем в административной панели
*
* @return string
*/
public function getTemplateEmail();
/**
* Возвращает объект NoticeData
*
* @return \Alerts\Model\Types\NoticeDataEmail
*/
public function getNoticeDataEmail();
}

Метод getTemplateEmail() должен вернуть путь к Smarty шаблону, редеринг которого сформирует тело письма. Метод getNoticeDataEmail() должен вернуть объект Alerts::Model::Types::NoticeDataEmail со всеми сведениями, необходимыми для отправки письма.

/**
* Объект с обязательными параметрами для уведомления
*/
class NoticeDataEmail
{
/**
* Тема письма
*
* @var string
*/
public $subject;
/**
* Адрес получателя
*
* @var string
*/
public $email;
/**
* Данные, передаваемы в шаблон
*
* @var mixed
*/
public $vars;
}

Класс NoticeDataEmail не содержит никаких методов, он представляет из себя некоторый набор публичных свойств, которые необходимо заполнить.

Пример реализации уведомления с интерфейсом Alerts::Model::Types::InterfaceEmail.

namespace \ModuleName\Model\Notice;
{
public
$oneclick;
//...
function getTemplateEmail()
{
return '%modulename%/notice/toadmin_oneclick.tpl';
}
function getNoticeDataEmail()
{
//Загружаем настройки сайта
$notice_data = new \Alerts\Model\Types\NoticeDataEmail();
//Указываем Email администратора в качестве получателя.
//Сюда можно передать несколько адресов через запятую, при необходимости.
$notice_data->email = $site_config['admin_email'];
//Указываем тему письма
$notice_data->subject = t('Купить в один клик на сайте %0 №-%1', array(\RS\Http\Request::commonInstance()->getDomainStr(), $this->oneclick['id']));
//Передаем весь текущий объект в шаблон.
//В шаблоне Smarty текущий объект будет доступен в переменной $data
//Для обращения в шаблоне к объекту покупки в 1 клик воспользуйтесь $data->oneclick
$notice_data->vars = $this;
return $notice_data;
}
}

Пример шаблона /modules/modulename/view/notice/toadmin_oneclick.tpl:

1 <p>{t d=$url->getDomainStr()}Уважаемый, администратор! На сайте %d хотят купить в 1 клик товары.{/t}</p>
2 
3 <h3>{t}Контакты заказчика{/t}</h3>
4 <p>{t}Имя заказчика{/t}: {$data->oneclick.user_fio}</p>
5 <p>{t}Телефон{/t}: {$data->oneclick.user_phone}</p>
6 <p>{t}Автоматическая рассылка{/t} {$url->getDomainStr()}.</p>

Уведомления на SMS

Интерфейс Alerts::Model::Types::InterfaceSms добавляет уведомлению возможность быть отправленным по SMS, через транспортный модуль, установленный в разделе Веб-сайт → Настройка модулей → Уведомления.

/**
* Интерфейс уведомления, которое может быть отправлено по SMS
*/
interface InterfaceSms
{
/**
* Возвращает путь к шаблону SMS-сообщения
* @return string
*/
public function getTemplateSms();
/**
* Возвращает объект NoticeData
* @return \Alerts\Model\Types\NoticeDataSms
*/
public function getNoticeDataSms();
}

Метод getTemplateSMS() должен вернуть путь к Smarty шаблону, редеринг которого сформирует тело SMS. Метод getNoticeDataSmS() должен вернуть объект Alerts::Model::Types::NoticeDataSms со всеми сведениями, необходимыми для отправки SMS.

/**
* Объект с обязательными параметрами для уведомления
*/
class NoticeDataSms
{
/**
* Телефон получателя
*
* @var string
*/
public $phone;
/**
* Данные, передаваемы в шаблон
*
* @var mixed
*/
public $vars;
}

Пример реализации уведомления с интерфейсом Alerts::Model::Types::InterfaceSms.

namespace \ModuleName\Model\Notice;
{
public
$oneclick;
//...
function getTemplateSms()
{
return '%modulename%/notice/toadmin_oneclick_sms.tpl';
}
function getNoticeDataSms()
{
//Загружаем настройки сайта
$notice_data = new \Alerts\Model\Types\NoticeDataSms();
if(!$site_config['admin_phone']) return; //Если метод вернет null, то отправка по SMS не произойдет
//Устанавливаем телефон администратора
//При необходимости можно указать несколько телефонов через запятую
$notice_data->phone = $site_config['admin_phone'];
//Передаем весь текущий объект в шаблон.
//В шаблоне Smarty текущий объект будет доступен в переменной $data
//Для обращения в шаблоне к объекту покупки в 1 клик воспользуйтесь $data->oneclick
$notice_data->vars = $this;
return $notice_data;
}
}

Пример шаблона /modules/modulename/view/notice/toadmin_oneclick_sms.tpl:

1 {t d=$url->getDomainStr()}На сайте %d заказаны товары.{/t} {if $data->oneclick.user_fio}Заказчик {$data->oneclick.user_fio}.{/if} {t}Телефон:{/t} {$data->oneclick.user_phone}

Уведомления на ПК

Интерфейс Alerts::Model::Types::InterfaceDesktopApp добавляет уведомлению возможность быть отправленным на Desktop приложение. При возникновении события модуль запишет уведомление в базу данных, затем модуль Внешнее API по запросу Desktop приложения выдаст необходимые уведомлений.

Система не будет хранить уведомления в базе, возраст которых старше указанного в разделе Веб-сайт → Настройка модулей → Уведомления → Вкладка "Desktop уведомления" → опция "Количество часов, которое следует хранить уведомления".

Рассмотрим подробнее интерфейс:

/**
* Интерфейс уведомления, которое может быть отправлено на Desktop приложение
*/
interface InterfaceDesktopApp
{
/**
* Возвращает путь к шаблону уведомления для Desktop приложения
*
* @return string
*/
public function getTemplateDesktopApp();
/**
* Возвращает данные, которые необходимо передать при инициализации уведомления
*
* @return NoticeDataDesktopApp
*/
public function getNoticeDataDesktopApp();
}

Метод getTemplateDesktopApp() должен вернуть путь к Smarty шаблону, редеринг которого сформирует тело уведомления. Если метод вернет null, то Desktop приложение просто покажет уведомление и не сохранит его в своей истории. Это удобно использовать для не очень важных уведомлений.

Метод getNoticeDataDesktopApp() должен вернуть объект Alerts::Model::Types::NoticeDataDesktopApp со всеми сведениями, необходимыми для отправки уведомления. Расмотрим подробнее класс NoticeDataDesktopApp.

<?php
/**
* Объект с обязательными параметрами для уведомления
*/
class NoticeDataDesktopApp
{
public
/**
* Заголовок уведомления
*
* @var string
*/
/**
* Краткий текст уведомления без тегов
*
* @var string
*/
/**
* Абсолютная ссылка для перехода на сайт
*
* @var string
*/
/**
* Подпись к ссылке
*
* @var string
*/
/**
* Переменные, которые будут переданы в шаблон уведомления
*
* @var array
*/
/**
* ID пользователя, для которого предназначено сообщение.
* Если не заполнено или 0, то предназначается всем пользователям.
*
* @var integer
*/
}

Пример реализации уведомления с интерфейсом Alerts::Model::Types::InterfaceDesktopApp.

namespace \ModuleName\Model\Notice;
{
public
$oneclick;
//...
function getTemplateDesktopApp()
{
return '%modulename%/notice/desktop_oneclick.tpl';
}
function getNoticeDataDesktopApp()
{
$notice_data = new \Alerts\Model\Types\NoticeDataDesktopApp();
$notice_data->title = t('Покупка в один клик №%0', array($this->oneclick->id));
$products = $this->oneclick->tableDataUnserialized();
if (count($products) == 1) {
$product_title = t('Товар: %product(%barcode)', array(
'product' => \RS\Helper\Tools::teaser($products[0]['title'], 120),
'barcode' => $products[0]['barcode']
));
} else {
$product_title = t('Заказано: %count [plural:%count:товар|товара|товаров]', array('count' => count($products)));
}
$notice_data->short_message = $this->oneclick->user_fio
.($this->oneclick->user_phone ? " ({$this->oneclick->user_phone})" : '')
."\n".$product_title;
$notice_data->link = \RS\Router\Manager::obj()->getAdminUrl('edit', array('id' => $this->oneclick->id), 'catalog-oneclickctrl', true);
$notice_data->link_title = t('Перейти к покупке');
$notice_data->vars = $this;
return $notice_data;
}
}

Пример шаблона /modules/modulename/view/notice/desktop_oneclick.tpl:

1 <h1>{t}Покупка в 1 клик{/t}</h1>
2 <p>{t}Имя заказчика{/t}: {$data->oneclick.user_fio}</p>
3 <p>{t}Телефон{/t}: {$data->oneclick.user_phone}</p>

Пример уведомления, отправляемого на все устройства

Уведомление может имплементировать одновременно несколько интерфейсов, в этом случае класс будет выглядеть так:

namespace ModuleName\Model\Notice;
class CustomNotice extends \Alerts\Model\Types\AbstractNotice
{
public
$oneclick;
public function getDescription()
{
return t('Купить в один клик (администратору)');
}
/**
* Инициализация уведомления
*
* @param \Catalog\Model\Orm\OneClickItem $oneclick - массив с параметрами для передачи
* @return void
*/
function init(\Catalog\Model\Orm\OneClickItem $oneclick)
{
$this->oneclick = $oneclick;
}
function getNoticeDataEmail()
{
$notice_data = new \Alerts\Model\Types\NoticeDataEmail();
$notice_data->email = $site_config['admin_email'];
$notice_data->subject = t('Купить в один клик на сайте %0 №-%1', array(\RS\Http\Request::commonInstance()->getDomainStr(), $this->oneclick['id']));
$notice_data->vars = $this;
return $notice_data;
}
function getTemplateEmail()
{
return '%modulename%/notice/toadmin_oneclick.tpl';
}
function getNoticeDataSms()
{
$notice_data = new \Alerts\Model\Types\NoticeDataSms();
if(!$site_config['admin_phone']) return;
$notice_data->phone = $site_config['admin_phone'];
$notice_data->vars = $this;
return $notice_data;
}
function getTemplateSms()
{
return '%modulename%/notice/toadmin_oneclick_sms.tpl';
}
function getTemplateDesktopApp()
{
return '%modulename%/notice/desktop_oneclick.tpl';
}
function getNoticeDataDesktopApp()
{
$notice_data = new \Alerts\Model\Types\NoticeDataDesktopApp();
$notice_data->title = t('Покупка в один клик №%0', array($this->oneclick->id));
$products = $this->oneclick->tableDataUnserialized();
if (count($products) == 1) {
$product_title = t('Товар: %product(%barcode)', array(
'product' => \RS\Helper\Tools::teaser($products[0]['title'], 120),
'barcode' => $products[0]['barcode']
));
} else {
$product_title = t('Заказано: %count [plural:%count:товар|товара|товаров]', array('count' => count($products)));
}
$notice_data->short_message = $this->oneclick->user_fio
.($this->oneclick->user_phone ? " ({$this->oneclick->user_phone})" : '')
."\n".$product_title;
$notice_data->link = \RS\Router\Manager::obj()->getAdminUrl('edit', array('id' => $this->oneclick->id), 'catalog-oneclickctrl', true);
$notice_data->link_title = t('Перейти к покупке');
$notice_data->vars = $this;
return $notice_data;
}
}

Менеджер отправки уведомлений

Для отправки уведомлений модуль Alerts предлагает специальный класс Alerts::Model::Manager - менеджер отправки, который содержит один публичный статичный метод send. Данный метод отправляет уведомление по нужному каналу в зависимости от того, какие интерфейсы были в нем имплементированы.

Пример отправки уведомления:

$notice = new \ModuleName\Model\Notice\CustomNotice();
$notice->init($oneclick);
\Alerts\Model\Manager::send($notice); //Отправляет уведомление

Места формирования уведомлений

Часто, уведомление следует отправить в момент записи в базу того или иного объекта из "чужого" модуля, для таких случаев рекомендуем с помощью подсистемы событий добавять обработчик на событие orm.afterwrite.ОБЪЕКТ и внутри обработчика формировать и отправлять уведомление.

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

При отправке уведомлений из обработчика собития cron, следует помнить, что скрипт был запущен из коммандной строки, соответственно переменной $_SERVER не существует, как и не существует выбранного текущего сайта (в случае мультисайтовости). Учитывайте это, если вы используете абсолютные ссылки на ваш сайт в шаблонах писем.