7.5 KiB
Взаимодействия
Модуль interactions хранит унифицированные действия посетителей: оценки,
голоса, реакции и выбор вариантов. Он не выводит самостоятельный виджет и не
имеет вставочного тега. Пользовательский интерфейс предоставляют зависимые
модули, например Рейтинги, Комментарии и Опросы.
Модель данных
Каждое действие определяется четырьмя частями:
| Часть | Пример | Назначение |
|---|---|---|
| Тип объекта | document, comment, poll |
К какому классу сущностей относится действие. |
| Ключ объекта | 145 |
ID или другой стабильный строковый ключ сущности. |
| Канал | rating, comment_vote, poll_vote |
Набор правил и разрешённых действий. |
| Действие | rating, up, option:8 |
Конкретный выбор пользователя внутри канала. |
Перед любой записью модуль проверяет существование прикладного объекта. Тип
document поддерживается самим runtime: удалённый или отсутствующий документ
получит 404. Типы comment, poll и gallery регистрируют соответствующие
модули. Для собственного типа нужен resolver interactions.target.resolve;
одной проверки формата ключа или policy канала недостаточно.
Режимы каналов
| Режим | Поведение |
|---|---|
selection |
У пользователя остаётся один вариант. Повторный toggle может снять выбор. |
multiple |
Одновременно хранится несколько вариантов с ограничением max_selections. |
rating |
Хранится одна числовая оценка в диапазоне min_value–max_value. |
Операция set создаёт или обновляет действие, toggle переключает его, а
remove удаляет. После изменения агрегаты канала перестраиваются в той же
транзакции: публичному коду не нужно считать голоса по сырым записям.
Публичный API
Сводка объекта:
GET /api/v1/interactions/document/145
Ответ содержит публичные определения каналов, агрегаты по действиям и выбор
текущего посетителя. Новый CSRF-токен возвращается в поле csrf.
Запись действия:
POST /api/v1/interactions/document/145/rating
Content-Type: application/json
X-CSRF-Token: <token>
{"operation":"set","action":"rating","value":5}
Для реакции запрос может выглядеть так:
{"operation":"toggle","action":"up"}
Успешный ответ возвращает changed, выполненную операцию, actor и полную новую
сводку snapshot. Ошибки используют HTTP-коды 401, 403, 409, 419,
422 и 429.
Регистрация своего канала
Модуль добавляет канал фильтром interactions.channels:
Hooks::add('interactions.channels', function ($channels) {
$channels['reaction'] = array(
'code' => 'reaction',
'label' => 'Реакция',
'mode' => 'selection',
'actions' => array('like', 'useful'),
'target_types' => array('document'),
'public_read' => true,
'public_write' => true,
'anonymous' => true,
'toggle' => true,
'rate_limit' => 20,
'rate_window' => 60,
);
return $channels;
});
Код канала и действия допускают латиницу, цифры и служебные разделители. Для
динамических действий вместо actions можно объявить action_pattern.
Регистрация своего типа объекта
Resolver должен явно сообщить, обработал ли он тип, существует ли объект и разрешена ли запись в его текущем состоянии:
Hooks::add('interactions.target.resolve', function ($target) {
if (!is_array($target) || $target['type'] !== 'article') {
return $target;
}
$article = ArticleRepository::find($target['key']);
$target['handled'] = true;
$target['exists'] = $article !== null;
$target['writable'] = $article && $article['status'] === 'published';
$target['message'] = $article ? 'Материал закрыт для действий' : 'Материал не найден';
return $target;
});
Неизвестный тип без resolver-а отклоняется с 422, отсутствующий объект — с
404, существующий, но недоступный для записи — с 409. Resolver не должен
создавать объект или изменять его состояние.
Хуки
| Hook | Когда вызывается | Основные данные |
|---|---|---|
interactions.channels |
При сборке реестра каналов | Ассоциативный массив definitions. |
interactions.target.resolve |
Перед policy записи и созданием внутренней цели | type, key, operation, handled, exists, writable, message. |
interactions.recording |
До rate limit и записи | target, channel, action, value, operation, metadata, actor. |
interactions.recorded |
После commit и пересчёта агрегатов | changed, operation, actor и snapshot. |
В interactions.recording можно изменить данные либо выбросить исключение с
подходящим HTTP-кодом. Не выполняйте повторную запись в тот же канал из
interactions.recorded: это создаст рекурсивный цикл.
Настройки и удаление
- Анонимные действия разрешают выдавать посетителю устойчивый анонимный actor.
- Действий в минуту задаёт общий лимит, если канал не объявил свой.
- Каждая запись ограничивается по actor. Для гостя дополнительно действует
лимит по HMAC-префиксу сети и конкретной цели: IPv4
/24, IPv6/64. - Хеш IP управляет только сохранением диагностического хеша в записи. Сетевой limiter работает независимо и не хранит исходный IP.
Uninstall удаляет цели, действия и агрегаты. Зависимые активные модули сначала нужно отключить или деинсталлировать.