Перейти к содержимому

Notifly в Joomla

В Joomla всё расширяется плагинами. Небольшой системный плагин подписывается на события (onUserAfterSave, onContentAfterSave, onContactAfterSubmit) и шлёт push в Notifly. Никаких сторонних библиотек не нужно — используется встроенный HTTP-клиент фреймворка Joomla.

Функцию-helper notifly_send() берём общую — ту же, что и для остальных CMS. Внутри плагина её проще завернуть в приватный метод, а токен и URL хранить в параметрах плагина.

plugins/system/notifly/
├── notifly.xml
└── src/Extension/Notifly.php

notifly.xml — манифест с параметрами url и token:

<?xml version="1.0" encoding="utf-8"?>
<extension type="plugin" group="system" method="upgrade">
<name>System - Notifly</name>
<author>Notifly</author>
<version>1.0.0</version>
<namespace path="src">Notifly\Plugin\System\Notifly</namespace>
<files>
<folder plugin="notifly">src</folder>
</files>
<config>
<fields name="params">
<fieldset name="basic">
<field name="url" type="url" label="Notifly URL"
default="https://your-notifly.example.com" />
<field name="token" type="text" label="App token"
default="AGdjfk_L.dKe8q" />
</fieldset>
</fields>
</config>
</extension>

src/Extension/Notifly.php — здесь и живёт наш notifly_send() (как приватный метод) и все подписки на события:

<?php
namespace Notifly\Plugin\System\Notifly\Extension;
\defined('_JEXEC') or die;
use Joomla\CMS\Plugin\CMSPlugin;
use Joomla\CMS\Http\HttpFactory;
use Joomla\CMS\Uri\Uri;
final class Notifly extends CMSPlugin
{
/** Универсальный helper (та же логика, что в /cases/cms/). */
private function send(string $title, string $message, int $priority = 5): void
{
$url = $this->params->get('url');
$token = $this->params->get('token');
if (!$url || !$token) {
return;
}
try {
HttpFactory::getHttp()->post(
"$url/message?token=$token",
json_encode([
'title' => mb_substr($title, 0, 200),
'message' => mb_substr($message, 0, 1500),
'priority' => $priority,
], JSON_UNESCAPED_UNICODE),
['Content-Type' => 'application/json'],
5
);
} catch (\Throwable $e) {
// Никогда не роняем запрос сайта из-за нотификации.
}
}
/** Новая регистрация или изменение пользователя. */
public function onUserAfterSave($user, $isNew, $success, $msg): void
{
if (!$success || !$isNew) {
return;
}
$this->send(
"👤 Новый пользователь: {$user['username']}",
"Email: {$user['email']}\n" .
"ID: {$user['id']}\n" .
"Профиль: " . Uri::root() . "administrator/index.php?option=com_users&task=user.edit&id={$user['id']}",
4
);
}
/** Новая или изменённая статья / материал. */
public function onContentAfterSave($context, $article, $isNew): void
{
if ($context !== 'com_content.article') {
return;
}
$action = $isNew ? 'создан' : 'обновлён';
$this->send(
"📄 Материал $action: {$article->title}",
"ID: {$article->id}\n" .
"Категория: {$article->catid}\n" .
"Открыть: " . Uri::root() .
"administrator/index.php?option=com_content&task=article.edit&id={$article->id}",
$isNew ? 5 : 4
);
}
/** Отправка формы через com_contact. */
public function onContactAfterSubmit($contact, $data): void
{
$this->send(
"✉️ Обращение через контакт: {$contact->name}",
"Тема: " . ($data['contact_subject'] ?? '') . "\n" .
"Сообщение:\n" . mb_substr($data['contact_message'] ?? '', 0, 1000),
7
);
}
}

Системный плагин загружается очень рано, поэтому в нём же удобно перехватывать фатальные ошибки через register_shutdown_function — например, в onAfterInitialise:

public function onAfterInitialise(): void
{
register_shutdown_function(function () {
$err = error_get_last();
if ($err && \in_array($err['type'], [E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR])) {
$this->send(
"🔥 Fatal: {$err['message']}",
"Файл: {$err['file']}:{$err['line']}\n" .
"URL: " . ($_SERVER['REQUEST_URI'] ?? '-'),
10
);
}
});
}
  1. Заархивируйте папку notifly в ZIP и установите через Система → Установка → Расширения.
  2. Откройте Система → Плагины, найдите «System - Notifly», задайте URL и токен, включите плагин.

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

Чтобы форма контактов или бот-регистрации не завалили канал, кэшируйте отправку через встроенный \Joomla\CMS\Cache\Cache:

$cache = \Joomla\CMS\Factory::getCache('notifly', '');
$key = 'throttle_' . md5($title);
if ($cache->get($key)) {
return;
}
$cache->store(1, $key);
  • Мгновенная реакция на заявки. Обращение через com_contact — push раньше, чем письмо дойдёт до почты.
  • Контроль контента. Каждая правка материала видна редактору сразу.
  • Дешёвый мониторинг ошибок без Sentry для небольшого Joomla-сайта.
  • Разные каналы Notifly для контента, пользователей и ошибок.
  • Приоритеты по категориям материалов через параметры плагина.
  • Передача id статьи/пользователя в extras для deep-link.