• Модуль: tasks
  • Путь к файлу: ~/bitrix/modules/tasks/classes/general/tasknotifications.php
  • Класс: CTaskNotifications
  • Вызов: CTaskNotifications::SendMessageToSocNet
static function SendMessageToSocNet($arFields, $bSpawnedByAgent, $arChanges = null, $arTask = null, array $parameters = array())
{
	global $DB;

	$effectiveUserId = self::getEffectiveUserId($arFields, array(), $bSpawnedByAgent, $parameters);

	if ( ! CModule::IncludeModule('socialnetwork') )
		return (null);

	$arLogFilter = array();
	$bCrmTask = false;

	if (!empty($arTask))
	{
		$bCrmTask = self::isCrmTask($arTask);
		$arLogFilter = self::getSonetLogFilter($arTask["ID"], $bCrmTask);
		if (empty($arLogFilter))
		{
			return (null);
		}
	}
	static $arCheckedUsers = array();		// users that checked for their existing
	static $cachedSiteTimeFormat = -1;

	// select "real" author

	$occurAsUserId = CTasksTools::getOccurAsUserId();
	if ( ! $occurAsUserId )
		$occurAsUserId = $effectiveUserId;

	if ($cachedSiteTimeFormat === -1)
		$cachedSiteTimeFormat = CSite::GetDateFormat('FULL', SITE_ID);

	static $cachedAllSitesIds = -1;

	if ($cachedAllSitesIds === -1)
	{
		$cachedAllSitesIds = array();

		$dbSite = CSite::GetList(
			'sort',
			'desc',
			array('ACTIVE' => 'Y')
		);

		while ($arSite = $dbSite->Fetch())
			$cachedAllSitesIds[] = $arSite['ID'];
	}

	// Check that user exists
	if ( ! in_array( (int) $arFields["CREATED_BY"], $arCheckedUsers, true) )
	{
		$rsUser = CUser::GetList(
			'ID',
			'ASC',
			array('ID' => $arFields["CREATED_BY"]),
			array('FIELDS' => array('ID'))
		);

		if ( ! ($arUser = $rsUser->Fetch()) )
			return (false);

		$arCheckedUsers[] = (int) $arFields["CREATED_BY"];
	}

	if (is_array($arChanges))
	{
		if (!empty($arLogFilter) && empty($arChanges))
		{
			$rsSocNetLogItems = CSocNetLog::GetList(
				["ID" => "DESC"],
				$arLogFilter,
				false,
				false,
				["ID", "ENTITY_TYPE", "ENTITY_ID"]
			);
			while ($log = $rsSocNetLogItems->Fetch())
			{
				$logId = (int)$log['ID'];
				$authorId = (
					isset($arFields['CREATED_BY']) ? (int)$arFields['CREATED_BY'] : (int)$arTask['CREATED_BY']
				);

				$oldForumTopicId = $arTask['FORUM_TOPIC_ID'];
				$newForumTopicId = ($arFields['FORUM_TOPIC_ID'] ?? null);
				$forumTopicAdded = $oldForumTopicId == 0 && isset($newForumTopicId) && $newForumTopicId > 0;

				// Add author to list of users that view log about task in livefeed
				// But only when some other person change task
				// or if added FORUM_TOPIC_ID
				if (($authorId !== $effectiveUserId) || $forumTopicAdded)
				{
					$authorGroupCode = 'U'.$authorId;

					$rightsResult = CSocNetLogRights::GetList([], [
						'LOG_ID' => $logId,
						'GROUP_CODE' => $authorGroupCode,
					]);

					// If task's author hasn't rights yet, give them
					if (!$rightsResult->fetch())
					{
						$follow = !UserOption::isOptionSet($arTask['ID'], $authorId, (UserOptionOption::MUTED));
						CSocNetLogRights::Add($logId, [$authorGroupCode], false, $follow);
					}
				}
			}

			return null;
		}

		if (count($arChanges) === 1 && isset($arChanges['STATUS']))
		{
			return null;	// if only status changes - don't send message, because it will be sent by SendStatusMessage()
		}
	}

	if ($bSpawnedByAgent === 'Y')
		$bSpawnedByAgent = true;
	elseif ($bSpawnedByAgent === 'N')
		$bSpawnedByAgent = false;

	if ( ! is_bool($bSpawnedByAgent) )
		return (false);

	$taskId = false;
	if (is_array($arFields) && isset($arFields['ID']) && ($arFields['ID'] > 0))
		$taskId = $arFields['ID'];
	elseif (is_array($arTask) && isset($arTask['ID']) && ($arTask['ID'] > 0))
		$taskId = $arTask['ID'];

	// We will mark this to false, if we send update message and log item already exists
	$bSocNetAddNewItem = true;

	$logDate = $DB->CurrentTimeFunction();
	$curTimeTimestamp = time() + CTimeZone::GetOffset();

	if (!$bCrmTask)
	{
		$arSoFields = array(
			'EVENT_ID' => 'tasks',
			'TITLE' => $arFields['TITLE'],
			'MESSAGE' => '',
			'MODULE_ID' => 'tasks'
		);
	}
	else
	{
		$arSoFields = array();
	}

	// If changes and task data given => we are prepare "update" message,
	// or "add" message otherwise
	if (is_array($arChanges) && is_array($arTask))
	{	// Prepare "update" message here
		if ($arFields["CHANGED_DATE"] <> '')
		{
			$createdDateTimestamp = MakeTimeStamp(
				$arFields["CHANGED_DATE"],
				$cachedSiteTimeFormat
			);

			if ($createdDateTimestamp > $curTimeTimestamp)
			{
				$logDate = BitrixTasksUtilDb::charToDateFunction(
					$arFields["CHANGED_DATE"],
					"FULL",
					SITE_ID
				);
			}
		}

		$arChangesFields = array_keys($arChanges);
		$arSoFields['TEXT_MESSAGE'] = str_replace(
			'#CHANGES#',
			implode(
				', ',
				CTaskNotifications::__Fields2Names($arChangesFields)
			),
			GetMessage('TASKS_SONET_TASK_CHANGED_MESSAGE')
		);

		if (!$bCrmTask)
		{
			if (
				(($arFields["GROUP_ID"] ?? null) === null && $arTask['GROUP_ID']) // If tasks has group and it not deleted
				|| ($arFields['GROUP_ID'] ?? null) // Or new group_id set
			)
			{
				$arSoFields["ENTITY_TYPE"] = SONET_ENTITY_GROUP;
				$arSoFields["ENTITY_ID"] = (($arFields["GROUP_ID"] ?? null) ?: $arTask['GROUP_ID']);
			}
			else
			{
				$arSoFields["ENTITY_TYPE"] = SONET_ENTITY_USER;
				$arSoFields["ENTITY_ID"] = ($arFields["CREATED_BY"] ?: $arTask["CREATED_BY"]);
			}
		}

		$arSoFields['PARAMS'] = serialize([
			'TYPE' => 'modify',
			'CHANGED_FIELDS' => $arChangesFields,
			'CREATED_BY'  => ($arFields["CREATED_BY"] ?: $arTask["CREATED_BY"]),
			'CHANGED_BY' => ($occurAsUserId ?: $arFields['CHANGED_BY']),
			'PREV_REAL_STATUS' => ($arTask['REAL_STATUS'] ?? false),
		]);

		if (!empty($arLogFilter))
		{
			// Determine, does item exists in sonet log
			$rsSocNetLogItems = CSocNetLog::GetList(
				array("ID" => "DESC"),
				$arLogFilter,
				false,
				false,
				array("ID", "ENTITY_TYPE", "ENTITY_ID")
			);

			if ($rsSocNetLogItems->Fetch())
			{
				$bSocNetAddNewItem = false;		// item already exists, update it, not create.
			}
		}
	}
	else	// Prepare "add" message here
	{
		if (($arFields["CREATED_DATE"] ?? null) <> '')
		{
			$createdDateTimestamp = MakeTimeStamp(
				$arFields["CREATED_DATE"],
				$cachedSiteTimeFormat
			);

			if ($createdDateTimestamp > $curTimeTimestamp)
			{
				$logDate = BitrixTasksUtilDb::charToDateFunction(
					$arFields["CREATED_DATE"],
					"FULL",
					SITE_ID
				);
			}
		}

		$arSoFields['TEXT_MESSAGE'] = GetMessage('TASKS_SONET_NEW_TASK_MESSAGE');

		if (isset($arFields["GROUP_ID"]) && $arFields["GROUP_ID"])
		{
			$arSoFields["ENTITY_TYPE"] = SONET_ENTITY_GROUP;
			$arSoFields["ENTITY_ID"] = $arFields["GROUP_ID"];
		}
		else
		{
			$arSoFields["ENTITY_TYPE"] = SONET_ENTITY_USER;
			$arSoFields["ENTITY_ID"] = $arFields["CREATED_BY"];
		}

		$arParamsLog = array(
			'TYPE' => 'create',
			'CREATED_BY' => ($arFields["CREATED_BY"] ?: $arTask["CREATED_BY"]),
			'PREV_REAL_STATUS' => $arTask['REAL_STATUS'] ?? false
		);

		if ($occurAsUserId)
		{
			$arParamsLog["CREATED_BY"] = $occurAsUserId;
		}

		$arSoFields['PARAMS'] = serialize($arParamsLog);
	}

	// rating entity id (ilike)
	$arSoFields["RATING_ENTITY_ID"] =  $taskId;
	$arSoFields["RATING_TYPE_ID"] = "TASK";

	if (IsModuleInstalled("webdav") || IsModuleInstalled("disk"))
	{
		$ufDocID = $GLOBALS["USER_FIELD_MANAGER"]->GetUserFieldValue("TASKS_TASK", "UF_TASK_WEBDAV_FILES", $taskId, LANGUAGE_ID);
		if ($ufDocID)
		{
			$arSoFields["UF_SONET_LOG_DOC"] = $ufDocID;
		}
	}

	// Do we need add new item to socnet?
	// We adds new item, if it is not exists.
	$logId = false;

	if ($bSocNetAddNewItem)
	{
		$arSoFields['=LOG_DATE']       = $logDate;
		$arSoFields['CALLBACK_FUNC']   = false;
		$arSoFields['SOURCE_ID']       = $taskId;
		$arSoFields['ENABLE_COMMENTS'] = 'Y';
		$arSoFields['URL']             = ''; // url is user-specific, cant keep in database
		$arSoFields['USER_ID']         = $arFields['CREATED_BY'];
		$arSoFields['TITLE_TEMPLATE']  = '#TITLE#';

		// Set all sites because any user from any site may be
		// added to task in future. For example, new auditor, etc.
		$arSoFields['SITE_ID'] = $cachedAllSitesIds;

		$logId = (int)CSocNetLog::Add($arSoFields, false);
		if ($logId > 0)
		{
			$logFields = [
				'TMP_ID' => $logId,
				'TAG' => [],
			];

			$tagsResult = CTaskTags::getList([], ['TASK_ID' => $taskId]);
			while ($row = $tagsResult->fetch())
			{
				$logFields['TAG'][] = $row['NAME'];
			}

			CSocNetLog::Update($logId, $logFields);

			$taskMembers = CTaskNotifications::GetRecipientsIDs($arFields, false);
			$logCanViewedBy = (
				self::$sonetLogNotifyAuthor
					? $taskMembers
					: array_diff($taskMembers, [$arFields['CREATED_BY']])
			);
			$rights = CTaskNotifications::__UserIDs2Rights($logCanViewedBy);

			if (isset($arFields['GROUP_ID']))
			{
				$rights = array_merge(
					$rights,
					self::prepareRightsCodesForViewInGroupLiveFeed($logId, $arFields['GROUP_ID'])
				);
			}

			CSocNetLogRights::Add($logId, $rights);
			CSocNetLog::SendEvent($logId, "SONET_NEW_EVENT", $logId);
		}
	}
	elseif (!empty($arLogFilter))	// Update existing log item
	{
		$arSoFields['=LOG_DATE']   = $logDate;
		$arSoFields['=LOG_UPDATE'] = $logDate;

		// All tasks posts in live feed should be from director
		if (isset($arFields['CREATED_BY']))
		{
			$arSoFields['USER_ID'] = $arFields['CREATED_BY'];
		}
		else if (isset($arTask['CREATED_BY']))
		{
			$arSoFields['USER_ID'] = $arTask['CREATED_BY'];
		}
		else if ($occurAsUserId)
		{
			$arSoFields['USER_ID'] = $occurAsUserId;
		}
		else
		{
			unset($arSoFields['USER_ID']);
		}

		$rsSocNetLogItems = CSocNetLog::GetList(
			["ID" => "DESC"],
			$arLogFilter,
			false,
			false,
			["ID", "ENTITY_TYPE", "ENTITY_ID"]
		);
		while ($log = $rsSocNetLogItems->Fetch())
		{
			$logId = (int)$log['ID'];

			$arSoFields['TAG'] = [];
			$tagsResult = CTaskTags::getList([], ['TASK_ID' => $taskId]);
			while ($tag = $tagsResult->fetch())
			{
				$arSoFields['TAG'][] = $tag['NAME'];
			}

			CSocNetLog::Update($logId, $arSoFields);

			$params = [
				'LOG_ID' => $logId,
				'EFFECTIVE_USER_ID' => $effectiveUserId,
			];
			self::setSonetLogRights($params, $arFields, $arTask);
		}
	}

	return ($logId);
}