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

Свой канал доставки v200.1.0

Как реализовать ChannelInterface и зарегистрировать канал

Базовые каналы модуля: сайт, почта, личные сообщения. Свой канал — отдельный класс с ChannelInterface и регистрация в ChannelRegistry.

Когда слать — другой текст: Своё событие. Здесь — куда слать.

Контракт

ChannelInterface

namespace DevCraft\Modules\Notifications\Channels;

interface ChannelInterface {
	public function id(): string;
	public function deliver(ChannelDeliveryContext $ctx): bool;
}
МетодНазначение
id()Короткий ключ канала, например webhook. Им же передают флаг в $channels у notifySend.
deliver()Отправка одному получателю. true — успех, false — пропуск или ошибка (без исключения наружу).

ChannelDeliveryContext

Поля контекста (readonly, кроме entity):

ПолеТипСмысл
recipientIdintКому слать
senderIdintКто инициировал (0 — система)
bodystringГотовый текст (уже из сценария / $message)
varsarrayПлейсхолдеры {title}, {full-link}, …
cfgarrayКонфиг модуля Notifications
levelstringinfo / success / warning / …
contentType / contentTypeIdТип сущности в ленте
verb / targetType / targetId / dataслужебные поля события
entity?NotificationЗапись ленты (если уже создана каналом site)
newsRowarrayСтрока новости, если событие о материале

Права и «включён ли канал» соседний модуль проверяет сам в deliver(). Ядро только решает, вызывать ли канал.

Когда вызывается ваш канал

  1. notifySend / штатный сценарий собирает тело.
  2. Для site / email / pm — настройки модуля + права + личные настройки.
  3. Для любого другого id из реестра:
    • если $channels === [] → канал считается желаемым (true);
    • если передан массив → нужен 'ваш_id' => true;
    • затем UserPrefsService::wants($scenario, $channelId, …);
    • затем deliver($ctx).

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

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

Минимальный канал

Шаг 1: класс канала

Файл, например, в своём модуле DevCraft:

devcraft/src/modules/MyNotifyDiscord/Channels/DiscordChannel.php

<?php

declare(strict_types=1);

namespace DevCraft\Modules\MyNotifyDiscord\Channels;

use DevCraft\Modules\Notifications\Channels\ChannelDeliveryContext;
use DevCraft\Modules\Notifications\Channels\ChannelInterface;

final class DiscordChannel implements ChannelInterface {

	public function id(): string {
		return 'discord';
	}

	public function deliver(ChannelDeliveryContext $ctx): bool {
		$webhook = trim((string) ($ctx->cfg['discord_webhook'] ?? ''));
		// лучше брать из конфига своего модуля через DataManager::getConfig(...)

		if($webhook === '' || $ctx->body === '') {
			return false;
		}

		$text = strip_tags($ctx->body);
		$link = trim((string) ($ctx->vars['{full-link}'] ?? ''));

		if($link !== '') {
			$text .= "\n" . $link;
		}

		$payload = json_encode(['content' => $text], JSON_UNESCAPED_UNICODE);

		if($payload === false) {
			return false;
		}

		$ch = curl_init($webhook);
		curl_setopt_array($ch, [
			CURLOPT_POST           => true,
			CURLOPT_HTTPHEADER     => ['Content-Type: application/json'],
			CURLOPT_POSTFIELDS     => $payload,
			CURLOPT_RETURNTRANSFER => true,
			CURLOPT_TIMEOUT        => 10,
		]);
		curl_exec($ch);
		$code = (int) curl_getinfo($ch, CURLINFO_HTTP_CODE);
		curl_close($ch);

		return $code >= 200 && $code < 300;
	}

}

Шаг 2: регистрация при boot

Два рабочих варианта.

А. Соседний модуль уведомлений — каталог Notifications* рядом с модулем уведомлений, файл boot.php. SatelliteLoader подхватит его сам:

<?php

declare(strict_types=1);

use DevCraft\Modules\Notifications\Channels\ChannelRegistry;
use DevCraft\Modules\MyNotifyDiscord\Channels\DiscordChannel;

if(!defined('DATALIFEENGINE') || !defined('DEVCRAFT_BOOTSTRAPPED')) {
	return;
}

// Включайте канал только если настройка соседнего модуля активна
ChannelRegistry::instance()->register(new DiscordChannel());

Имя каталога: NotificationsDiscord (префикс Notifications обязателен для автозагрузки boot.php).

Б. Свой модуль DevCraft — зарегистрируйте канал из своего запуска / include после DEVCRAFT_BOOTSTRAPPED, тем же ChannelRegistry::instance()->register(...).

Шаг 3: права и настройки (рекомендуется)

ЧтоКуда
Включатель каналаsettings.schema.php вашего модуля
Право группыpermissions.defs.php → подхватывается страницей «Права групп» Notifications через SatelliteLoader::permissionFiles()
Проверка в deliver()PermissionService::allows($ctx->recipientId, 'notifications_receive_discord')

Файл permissions.defs.php в каталоге соседнего модуля:

<?php

declare(strict_types=1);

return [
	'notifications_receive_discord' => [
		'label'   => __('Получать уведомления в Discord'),
		'default' => false,
	],
];

Шаг 4: пункт в админке

Запись в dle_admin_sections (name = mod из манифеста) или положитесь на SatelliteLoader::ensureAdminSections() для известных каталогов / пропишите секцию в install.xml.

После этого: Админка → Уведомления — … → Настройки.

Чеклист

  1. Класс реализует ChannelInterface, id() уникален.
  2. deliver() не бросает наружу — ловит ошибки и возвращает false.
  3. Канал зарегистрирован до первой отправки (boot.php / запуск DevCraft).
  4. При $channels === [] канал будет вызываться всегда (если prefs не запретят) — держите выключатель внутри deliver().
  5. Для подписки пользователя на свой канал в кабинете нужна отдельная логика; базовый кабинет знает site / email / pm.

См. также

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