• Модуль: tasks
  • Путь к файлу: ~/bitrix/modules/tasks/classes/general/tasknotifications.php
  • Класс: CTaskNotifications
  • Вызов: CTaskNotifications::flushNotificationBuffer
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();
}