Давайте представим, что у нас есть задача фиксировать Последний комментарий из Таймлайна смарт-процесса в отдельное поле. Но фиксировать не каждый комментарий, а только от пользователей не являющимися ответственными по элементу. Ниже будет приведен готовый код, который фиксирует последний комментарий не от ответственного и раскрашивает сам комментарий в фиолетовый цвет.
<?php
AddEventHandler('crm', 'OnAfterCrmTimelineCommentAdd', 'handleNewComment');
function handleNewComment($commentId) {
// 1. Настройки
$settings = [
'log_dir' => $_SERVER['DOCUMENT_ROOT'].'/upload/logs/', // Папка логов
'log_file' => 'comments_'.date('Y-m-d').'.log', // Название лог файла
'custom_field' => 'UF_CRM_3_1746033726221', // Код вашего поля
'error_color' => '[COLOR=#800080]' // Цвет комментария не от ответственного
];
// 2. Инициализация логов
try {
// Создаем директорию логов если нет
if (!file_exists($settings['log_dir'])) {
mkdir($settings['log_dir'], 0755, true);
}
$logPath = $settings['log_dir'].$settings['log_file'];
// Функция логирования
$log = function($message) use ($logPath) {
$logMessage = date('[Y-m-d H:i:s] ').$message.PHP_EOL;
file_put_contents($logPath, $logMessage, FILE_APPEND | LOCK_EX);
};
$log("=== Обработка нового комментария ===");
$log("ID комментария: ".$commentId);
// 3. Проверяем модуль CRM
if (!CModule::IncludeModule('crm')) {
$log("Ошибка: Модуль CRM не доступен");
return;
}
// 4. Получаем данные комментария через CommentEntry
$commentEntry = \Bitrix\Crm\Timeline\CommentEntry::getByID($commentId);
if (!$commentEntry) {
$log("Ошибка: Не найдена запись комментария");
return;
}
$log("Данные комментария: ".print_r($commentEntry, true));
// 5. Получаем привязку к сущности
$entityTypeId = (int)$commentEntry['ENTITY_TYPE_ID'];
$entityId = (int)$commentEntry['ENTITY_ID'];
if ($entityTypeId === 0 || $entityId === 0) {
// Альтернативный способ получить привязку через TimelineBinding
$binding = \Bitrix\Crm\Timeline\Entity\TimelineBindingTable::getList([
'filter' => ['OWNER_ID' => $commentId]
])->fetch();
if ($binding) {
$entityTypeId = (int)$binding['ENTITY_TYPE_ID'];
$entityId = (int)$binding['ENTITY_ID'];
$log("Найдена привязка через TimelineBinding: тип=$entityTypeId, ID=$entityId");
}
}
if ($entityTypeId === 0 || $entityId === 0) {
$log("Пропуск: Нет привязки к сущности");
return;
}
$log("Привязка: тип=$entityTypeId, ID=$entityId");
// 6. Получаем фабрику элемента
$factory = Bitrix\Crm\Service\Container::getInstance()
->getFactory($entityTypeId);
if (!$factory) {
$log("Ошибка: Не найдена фабрика для типа $entityTypeId");
return;
}
// 7. Получаем элемент
$item = $factory->getItem($entityId);
if (!$item) {
$log("Ошибка: Элемент $entityId не найден");
return;
}
// 8. Получаем текст комментария
$commentText = $commentEntry['COMMENT'] ?? '';
if (empty($commentText)) {
$log("Пропуск: Пустой комментарий");
return;
}
// 9. Получаем ID автора и ответственного
$commentAuthorId = (int)$commentEntry['AUTHOR_ID'];
$responsibleId = (int)$item->get('ASSIGNED_BY_ID');
$log("ID автора: $commentAuthorId, ID ответственного: $responsibleId");
// 10. Проверяем, что автор не является ответственным
if ($commentAuthorId != $responsibleId) {
$log("Автор не является ответственным - выполняем действия");
// 10.1. Обновляем кастомное поле
if ($factory->isFieldExists($settings['custom_field'])) {
$item->set($settings['custom_field'], $commentText);
$operation = $factory->getUpdateOperation($item);
$updateResult = $operation->launch();
if ($updateResult->isSuccess()) {
$log("Успех: Поле обновлено");
} else {
$errors = implode(', ', $updateResult->getErrorMessages());
$log("Ошибка обновления: $errors");
}
} else {
$log("Ошибка: Поле {$settings['custom_field']} не существует в сущности");
}
// 10.2. Изменяем цвет комментария
$newCommentText = $settings['error_color'].$commentText."[/COLOR]";
$settingsData = $commentEntry['SETTINGS'] ?? [];
$settingsData['COMMENT'] = $newCommentText;
$settingsData['COLOR'] = '#800080';
$settingsData['HAS_FILES'] = 'N';
// Обновляем через CommentEntry
$updateResult = \Bitrix\Crm\Timeline\CommentEntry::update($commentId, [
'COMMENT' => $newCommentText,
'SETTINGS' => $settingsData
]);
if ($updateResult->isSuccess()) {
$log("Успех: Цвет комментария изменен");
} else {
$errors = implode(', ', $updateResult->getErrorMessages());
$log("Ошибка изменения цвета: $errors");
}
} else {
$log("Пропуск: Автор комментария является ответственным - действия не требуются");
}
$log("=== Обработка завершена ===");
} catch (Exception $e) {
// Аварийное логирование
$errorMessage = "Критическая ошибка: ".$e->getMessage()."\n".$e->getTraceAsString();
file_put_contents(
$settings['log_dir'].'comments_errors.log',
date('[Y-m-d H:i:s] ').$errorMessage.PHP_EOL,
FILE_APPEND
);
}
}
// Тестовый вызов для проверки
if ($_GET['test_comment_handler'] == 'Y') {
handleNewComment(1); // Укажите реальный ID комментария
die('Тест завершен. Проверьте логи в /upload/logs/');
}Давайте посмотрим, как это выглядит….
