DevCraft Документации
Руководства

Кастомное событие v200.1.0

Свой notifySend: шаблон, права групп, настройки модуля и доп. поле

Штатные сценарии (новость, комментарий, упоминание) закрывают типовые кейсы. Свой триггер — через публичный API notifySend / Notify::send.

Предварительно: шаблоны и теги, справочник Notify.

Два способа

  1. Готовый текст — без файла в scenarios/.
  2. Свой сценарий.tpl в теме + имя в параметре $scenario.

Вариант 1: текст без сценария

if (function_exists('notifySend')) {
	notifySend(
		$recipientId,
		'Вам назначена новая задача №' . $taskId,
		'task',           // contentType — тип сущности в ленте
		$taskId,          // contentTypeId
		$senderId,        // кто инициировал
		'info',           // level: info|success|warning|…
		[],               // channels: [] = настройки модуля
		null,             // scenario не нужен
	);
}

Тело берётся из $message. Каналы «сайт» / почта / ЛС — по настройкам модуля и настройкам получателя.

Вариант 2: свой .tpl сценарий

Шаг 1: файл сценария

В скине (или Default):

templates/ВАША_ТЕМА/devcraft/notifications/scenarios/order_paid.tpl

Заказ #{order_id} оплачен
Сумма: {amount}
{full-link}

Имя файла без .tpl = значение $scenario.

Шаг 2: вызов из кода

Хак DLE, cron-обработчик или другой модуль DevCraft — после bootstrap:

if (function_exists('notifySend')) {
	notifySend(
		$buyerId,
		null,                    // текст из сценария
		'order',
		$orderId,
		0,                       // системное событие без отправителя
		'success',
		[],
		'order_paid',            // → scenarios/order_paid.tpl
		[
			'{order_id}'  => (string) $orderId,
			'{amount}'    => $amountFormatted,
			'{full-link}' => $orderUrl,
			'{title}'     => 'Заказ #' . $orderId,
			'{sender}'    => 'Система',
		],
		[],                      // newsRow: опционально строка новости для тегов DLE
	);
}

$message = null — тело только из .tpl. Если шаблон пуст или не найден, а $message тоже пуст — уведомление не уйдёт.

Шаг 3: каналы (по желанию)

Пустой $channels — берутся флаги модуля send_email / send_pm и site по умолчанию.

Принудительно только сайт:

notifySend($uid, 'Текст', 'custom', 0, 0, 'info', ['site' => true, 'email' => false, 'pm' => false]);

Параметры, которые важны для кастома

ПараметрЗачем
$recipientIdкому
$messageготовый текст или null, если есть сценарий
$scenarioимя файла в scenarios/ без расширения
$extraVarsплейсхолдеры {'{…}'} для .tpl
$contentType / $contentTypeIdсвязь в ленте (фильтры, клик)
$newsRowесли нужны штатные теги новости DLE в шаблоне
$channelsсузить сайт / почту / ЛС

Через класс: DevCraft\Modules\Notifications\Services\Notify::send(…).

Куда вешать вызов

Типичные точки:

  • PHP-хак после сохранения сущности (addnews, свой AJAX, оплата);
  • сервис другого модуля DevCraft после бизнес-действия;
  • cron / очередь — тот же notifySend, если DevCraft уже загружен.

Проверка: function_exists('notifySend') (функции подключает плагин через devcraft/src/modules/Notifications/Site/include.php).

Настройки и права (базово)

Без доработок модуля:

  • Получатель должен иметь notifications_allow_view_notifications.
  • Email / ЛС — notifications_receive_mail / notifications_receive_message + каналы в настройках.
  • Кастомный $scenario не привязан к штатным доп. полям (news_update, mention, …).
  • $recipientId === $senderId — отправка молча пропускается.

Чтобы событие можно было выключать в админке, ограничивать по группам и давать пользователю свой выключатель — см. ниже.

Продвинутое подключение

Пример: событие order_paid. Цель — как у штатных сценариев: глобальный флаг, право группы, опциональное доп. поле профиля.

Цепочка при отправке:

выключатель в настройках модуля
  → право группы (получатель / отправитель)
    → доп. поле пользователя (если привязан)
      → notifySend / Notify::send

Файлы модуля: devcraft/src/modules/Notifications/.

1. Настройка модуля (глобальный выключатель)

В settings.schema.php добавьте checkbox рядом с остальными notify_*:

->checkbox('notify_order_paid', __('Уведомлять об оплате заказа'))
	->description(__('Сценарий order_paid из хака / модуля заказов.'))
	->default(true)

Конфиг читается так же, как у штатных событий:

use DevCraft\Core\Support\DataManager;
use DevCraft\Modules\Notifications\NotificationsIdentity;

$cfg = DataManager::getConfig(NotificationsIdentity::code());

if (empty($cfg['notify_order_paid'])) {
	return; // событие выключено в админке
}

После изменения схемы откройте DLE Уведомления → Настройки и сохраните форму (значение попадёт в devcraft/config/…).

2. Право группы

Права хранятся JSON-картой (dc_notification_permissions.settings) — миграция БД не нужна. Достаточно описания в permissions.defs.php:

[
	'id'          => 'notifications_receive_order_paid',
	'title'       => __('Получать уведомления об оплате заказа?'),
	'description' => __('Сценарий order_paid.'),
	'level'       => 'user', // user | mod | admin
],

Страница Права групп подхватит флаг сама (PermissionService::defs()).

В коде отправки:

use DevCraft\Modules\Notifications\Services\PermissionService;

$perms = new PermissionService();

if (!$perms->allows($recipientId, 'notifications_receive_order_paid')) {
	return;
}

// опционально: кто может инициировать
if ($senderId > 0 && !$perms->allows($senderId, 'notifications_allow_view_notifications')) {
	return;
}

Пока у группы нет сохранённой строки прав, базовые user-флаги считаются включёнными, admin / mod — выключенными. После первого сохранения матрицы в админке действуют явные галочки — включите новый флаг нужным группам.

См. также Права групп.

3. Доп. поле пользователя (отписка от сценария)

Штатные сценарии мапятся в UserPrefsService. Для кастома — три правки.

a) select в settings.schema.php (секция «Настройки пользователя»):

->select('xf_notify_order_paid', __('Доп. поле: оплата заказа'))
	->description(__('Пусто = не ограничивать. 0/off/no у пользователя — отказ.'))
	->options([])
	->default('')

b) список опций в Pages/SettingsPage.phpsupplementFormData():

return [
	// …существующие ключи…
	'xf_notify_order_paid' => $options,
];

c) ветка в UserPrefsService::wants():

$scenarioXf = match ($scenario) {
	'news_update', 'news_published' => 'xf_notify_news_update',
	'moderation_approve', 'moderation_reject' => 'xf_notify_moderation',
	'mention'     => 'xf_notify_mention',
	'order_paid'  => 'xf_notify_order_paid',
	default       => null,
};

Имя сценария в match должно совпадать с $scenario в notifySend. В настройках модуля выберите доп. поле профиля; логика значений — как в Настройки пользователя.

notifySend уже вызывает UserPrefsService::wants($scenarioKey, …) для каналов — отдельная проверка настроек в хаке не нужен, если сценарий заведён в match.

4. Сборка вызова

Файл сценария: templates/…/devcraft/notifications/scenarios/order_paid.tpl.

use DevCraft\Core\Support\DataManager;
use DevCraft\Modules\Notifications\NotificationsIdentity;
use DevCraft\Modules\Notifications\Services\PermissionService;

function notifyOrderPaid(int $buyerId, int $orderId, string $amount, string $url, int $senderId = 0): void
{
	if (!function_exists('notifySend') || $buyerId <= 0) {
		return;
	}

	$cfg = DataManager::getConfig(NotificationsIdentity::code());
	if (empty($cfg['notify_order_paid'])) {
		return;
	}

	$perms = new PermissionService();
	if (!$perms->allows($buyerId, 'notifications_receive_order_paid')) {
		return;
	}

	notifySend(
		$buyerId,
		null,
		'order',
		$orderId,
		$senderId,
		'success',
		[],
		'order_paid',
		[
			'{order_id}'  => (string) $orderId,
			'{amount}'    => $amount,
			'{full-link}' => $url,
			'{title}'     => 'Заказ #' . $orderId,
			'{sender}'    => 'Система',
		],
	);
}

Права ленты / почты / ЛС (notifications_allow_view_notifications, notifications_receive_mail, …) и каналы модуля по-прежнему проверяет NotificationService::send.

5. Свой модуль DevCraft (без патча Notifications)

Если событие живёт в вашем модуле:

ЧтоГде
Выключательsettings.schema.php вашего модуля + DataManager::getConfig(YourIdentity::code())
Правасвои defs или проверка существующих флагов Notifications через PermissionService
Текст / tplnotifySend + сценарий в скине Notifications (шаблоны общие)
Доп. поле пользователялибо патч UserPrefsService как выше, либо своя проверка доп. поля до notifySend

Патч Notifications нужен только если хотите единый UX: флаг в «Правах групп» уведомлений и выбор доп. поля на их странице настроек.

Чеклист продвинутого подключения

  1. scenarios/{имя}.tpl
  2. Checkbox notify_* в settings.schema.php + проверка empty($cfg[…])
  3. Флаг в permissions.defs.php + PermissionService::allows
  4. (Опционально) xf_notify_* + SettingsPage::supplementFormData + ветка в UserPrefsService
  5. Включить флаг группам в админке; выбрать доп. поле; сохранить настройки
  6. Вызов notifySend с тем же $scenario

Минимальный чеклист

  1. Файл scenarios/{имя}.tpl (или готовый $message).
  2. notifySend(...) с $scenario = '{имя}' и нужными extraVars.
  3. Проверка на сайте: колокольчик / стена; при необходимости email и ЛС в настройках модуля.

См. также

На этой странице