static function flushNotificationBuffer($doGrouping = true)
{
self::initBuffer();
if (empty(self::$buffer))
{
return;
}
// get all users
$users = self::getUsersFromBuffer();
$sites = BitrixTasksUtilSite::getPair();
$byUser = [];
$mailed = [];
$type = null;
foreach(self::$buffer as $i => $message)
{
if(!is_array($message['TO_USER_IDS']))
{
continue;
}
// $skipImPush = false;
// if ($message['ENTITY_OPERATION'] == 'ADD' && $message['ENTITY_CODE'] == 'TASK')
// {
// $skipImPush = true;
// }
foreach($message['TO_USER_IDS'] as $userId)
{
if(!isset($users[$userId])) // no user found for that id
{
continue;
}
// determine notify event here, if it was not given
if((string) $message['NOTIFY_EVENT'] == '')
{
$notifyEvent = 'manage';
if (($message['ADDITIONAL_DATA']['TASK_ASSIGNED_TO'] ?? null) !== null)
{
if ($userId == $message['ADDITIONAL_DATA']['TASK_ASSIGNED_TO'])
{
$notifyEvent = 'task_assigned';
}
}
$message['NOTIFY_EVENT'] = $notifyEvent;
}
if(BitrixTasksIntegrationMailUser::isEmail($users[$userId])) // must send message to email users separately
{
if(!isset($mailed[$i]))
{
$mMessage = $message;
$mMessage['TO_USER_IDS'] = array();
$mailed[$i] = $mMessage;
}
$mailed[$i]['TO_USER_IDS'][] = $userId;
}
else
{
// if (!$skipImPush)
// {
$byUser[$userId][$message['TASK_ID']] = $message;
// }
}
}
}
// send regular messages
foreach($byUser as $userId => $messages)
{
$unGroupped = array();
if(
count($messages) > 1 && $doGrouping
) // new way
{
// send for each action type, notification type and author separately
$deepGrouping = array();
foreach($messages as $taskId => $message)
{
// we do not group entities that differ from 'TASK' and NOTIFY_EVENTS that differ from 'manage'
if($message['ENTITY_CODE'] != 'TASK' || $message['NOTIFY_EVENT'] != 'manage')
{
$unGroupped[$taskId] = $message;
continue;
}
// if type is unknown, let it be "update"
$possibleTypes = [
'TASK_ADD',
'TASK_UPDATE',
'TASK_DELETE',
'TASK_STATUS_CHANGED_MESSAGE',
'TASK_EXPIRED_SOON',
'TASK_EXPIRED',
'TASK_PINGED_STATUS',
];
$type = (string)($message['EVENT_DATA']['ACTION'] ?? null);
$type = ($type !== '' ? $type : 'TASK_UPDATE');
if (!in_array($type, $possibleTypes, true))
{
// unknown action type. nothing to report about
continue;
}
$fromUserId = $message['FROM_USER_ID'];
if((string) $fromUserId == '') // empty author is not allowed
{
continue;
}
$deepGrouping[$type][$fromUserId][$message['NOTIFY_EVENT']][] = $taskId;
}
if(!empty($deepGrouping))
{
foreach($deepGrouping as $type => $byAuthor)
{
foreach($byAuthor as $authorId => $byEvent)
{
foreach($byEvent as $event => $taskIds)
{
$path = CTaskNotifications::getNotificationPathMultiple($users[$userId], $taskIds, true);
$instantTemplate = self::getGenderMessage($authorId, 'TASKS_TASKS_'.$type.'_MESSAGE');
$emailTemplate = self::getGenderMessage($authorId, 'TASKS_TASKS_'.$type.'_MESSAGE_EMAIL');
$pushTemplate = self::getGenderMessage($authorId, 'TASKS_TASKS_'.$type.'_MESSAGE_PUSH');
$instant = self::placeLinkAnchor($instantTemplate, $path, 'BBCODE');
$email = self::placeLinkAnchor($emailTemplate, $path, 'EMAIL');
$push = self::placeLinkAnchor($pushTemplate, $path, 'NONE');
$push = self::placeUserName($push, $authorId);
$imNotificationTag = (new BitrixTasksIntegrationIMNotificationTag())
->setTasksIds($taskIds)
->setUserId($userId)
->setEntityCode('TASKS');
$arMessageFields = array(
"TO_USER_ID" => $userId,
"FROM_USER_ID" => $authorId,
"NOTIFY_TYPE" => IM_NOTIFY_FROM,
"NOTIFY_MODULE" => 'tasks',
"NOTIFY_EVENT" => $event,
"NOTIFY_MESSAGE" => $instant,
"NOTIFY_MESSAGE_OUT" => $email,
"NOTIFY_TAG" => $imNotificationTag->getNameWithSignature(),
// push
"PUSH_MESSAGE" => mb_substr($push, 0, self::PUSH_MESSAGE_MAX_LENGTH),
);
BitrixTasksIntegrationIm::notifyAdd($arMessageFields);
}
}
}
}
}
else // old way
{
$unGroupped = $messages;
}
// send each message separately
foreach($unGroupped as $taskId => $message)
{
$pathToTask = self::getNotificationPath($users[$userId], $taskId, true, $sites);
$pathToTask = self::addParameters($pathToTask, ($message['ADDITIONAL_DATA']['TASK_URL'] ?? null));
$message['ENTITY_CODE'] = ToUpper($message['ENTITY_CODE']);
// replace #TASK_URL_BEGIN# placeholder
$message['MESSAGE']['INSTANT'] = self::placeLinkAnchor($message['MESSAGE']['INSTANT'], $pathToTask, 'BBCODE');
$message['MESSAGE']['EMAIL'] = self::placeLinkAnchor($message['MESSAGE']['EMAIL'], $pathToTask, 'EMAIL');
if((string) $message['MESSAGE']['PUSH'] != '')
{
$message['MESSAGE']['PUSH'] = self::placeLinkAnchor($message['MESSAGE']['PUSH'], $pathToTask, 'NONE');
}
// replace #TASK_TITLE# placeholder, if any
if(is_array($message['ADDITIONAL_DATA']['TASK_DATA'] ?? null))
{
$taskData = $message['ADDITIONAL_DATA']['TASK_DATA'];
$taskTitle = CTaskNotifications::formatTaskName($taskData["ID"], $taskData["TITLE"], $taskData["GROUP_ID"]);
$message['MESSAGE']['INSTANT'] = str_replace('#TASK_TITLE#', $taskTitle, $message['MESSAGE']['INSTANT']);
$message['MESSAGE']['EMAIL'] = str_replace('#TASK_TITLE#', strip_tags($taskTitle), $message['MESSAGE']['INSTANT']);
if((string) $message['MESSAGE']['PUSH'] != '')
{
$message['MESSAGE']['PUSH'] = str_replace('#TASK_TITLE#', $taskTitle, $message['MESSAGE']['PUSH']);
}
}
$message['TO_USER_IDS'] = array($userId);
// message callbacks here
if(is_callable($message['CALLBACK']['BEFORE_SEND'] ?? null))
{
$message = call_user_func_array($message['CALLBACK']['BEFORE_SEND'], array($message));
}
// event process here
if(!static::fireMessageEvent($message))
{
continue;
}
$userId = $message['TO_USER_IDS'][0]; // it may have changed on event
// make IM parameters
$actionName = ((string)($message['EVENT_DATA']['ACTION'] ?? null) !== '' ? $message['EVENT_DATA']['ACTION'] : 'TASK_UPDATE');
$imNotificationTag = (new BitrixTasksIntegrationIMNotificationTag())
->setTasksIds(array($taskId))
->setUserId($userId)
->setEntityCode($message['ENTITY_CODE'])
->setActionName($actionName);
if('COMMENT' == $message['ENTITY_CODE'])
{
$imNotificationTag->setEntityId(intval($message['EVENT_DATA']['MESSAGE_ID']));
}
$arMessageFields = array(
"TO_USER_ID" => $userId,
"FROM_USER_ID" => $message['FROM_USER_ID'],
"NOTIFY_TYPE" => isset($message['NOTIFY_TYPE']) ? $message['NOTIFY_TYPE'] : IM_NOTIFY_FROM,
"NOTIFY_MODULE" => "tasks",
"NOTIFY_EVENT" => $message['NOTIFY_EVENT'],
"NOTIFY_TAG" => $imNotificationTag->getName(),
"NOTIFY_SUB_TAG" => $imNotificationTag->getSubName(),
"NOTIFY_MESSAGE" => $message['MESSAGE']['INSTANT'],
"NOTIFY_MESSAGE_OUT" => $message['MESSAGE']['EMAIL'],
"PARAMS" => array(
"taskId" => $message['TASK_ID'],
"operation" => $message['ENTITY_OPERATION']
),
// "NOTIFY_ONLY_FLASH" => "Y",
// "NOTIFY_LINK" => $pathToTask
);
if((string)($message['ADDITIONAL_DATA']['NOTIFY_ANSWER'] ?? null))
{
// enabling notify answer for desktop
$arMessageFields['NOTIFY_ANSWER'] = 'Y';
}
if ((string)$message['MESSAGE']['PUSH'] !== '')
{
// add push message
$arMessageFields['PUSH_MESSAGE'] = self::placeLinkAnchor($message['MESSAGE']['PUSH'], $pathToTask);
// user should be able to open the task window to see the changes ...
// see /mobile/install/components/bitrix/mobile.rtc/templates/.default/script.js for handling details
$arMessageFields['PUSH_PARAMS'] = [
'ACTION' => 'tasks',
'TAG' => $imNotificationTag->getName(),
'ADVANCED_PARAMS' => [],
];
if ((string)($message['ADDITIONAL_DATA']['NOTIFY_ANSWER'] ?? null))
{
// ... and open an answer dialog in mobile
$arMessageFields['PUSH_PARAMS'] = array_merge(
$arMessageFields['PUSH_PARAMS'],
[
'CATEGORY' => 'ANSWER',
'URL' => SITE_DIR . 'mobile/ajax.php?mobile_action=task_answer',
'PARAMS' => [
'TASK_ID' => $taskId,
],
]
);
}
if (
array_key_exists('PUSH_PARAMS', $message)
&& is_string($message['PUSH_PARAMS']['SENDER_NAME'])
)
{
$arMessageFields['PUSH_PARAMS']['ADVANCED_PARAMS'] = [
'senderName' => $message['PUSH_PARAMS']['SENDER_NAME'],
'senderMessage' => $arMessageFields['PUSH_MESSAGE'],
];
}
$pushData = [];
if ($type !== 'TASK_DELETE')
{
$oldData = ($message['ADDITIONAL_DATA']['TASK_DATA'] ?? []);
$newData = ($message['EVENT_DATA']['arFields'] ?? []);
$pushData = static::preparePushData($taskId, $userId, array_merge($oldData, $newData));
}
$arMessageFields['PUSH_PARAMS']['ADVANCED_PARAMS'] = array_merge(
$arMessageFields['PUSH_PARAMS']['ADVANCED_PARAMS'],
[
'group' => 'tasks_task',
'data' => $pushData,
]
);
}
BitrixTasksIntegrationIM::notifyAdd($arMessageFields);
}
}
// send email messages
foreach($mailed as $message)
{
if (!is_array($sites["INTRANET"]))
{
continue;
}
self::notifyByMail($message, $sites["INTRANET"]);
}
self::$buffer = array();
}