• Модуль: tasks
  • Путь к файлу: ~/bitrix/modules/tasks/classes/general/taskitem.php
  • Класс: CTaskItem
  • Вызов: CTaskItem::proceedAction
private function proceedAction($actionId, $arActionArguments = null)
{
	$accessParams = null;
	$skipAccessControl = false;
	if (
		is_array($arActionArguments)
		&& isset($arActionArguments['PARAMETERS']['SKIP_ACCESS_CONTROL'])
		&& $arActionArguments['PARAMETERS']['SKIP_ACCESS_CONTROL']
	)
	{
		$skipAccessControl = true;
	}

	$actionId = ActionDictionary::getActionByLegacyId((int) $actionId);

	if (
		isset($arActionArguments['FIELDS']['RESPONSIBLE_ID'])
		&& count($arActionArguments['FIELDS']) === 1
	)
	{
		$actionId = ActionDictionary::ACTION_TASK_CHANGE_RESPONSIBLE;
		$arActionArguments['RESPONSIBLE_ID'] = $arActionArguments['FIELDS']['RESPONSIBLE_ID'];
	}

	if (
		isset($arActionArguments['FIELDS']['MARK'])
		&& count($arActionArguments['FIELDS']) === 1
	)
	{
		$actionId = ActionDictionary::ACTION_TASK_RATE;
	}

	if (
		isset($arActionArguments['FIELDS']['STATUS'])
		&& count($arActionArguments['FIELDS']) === 1
	)
	{
		$actionId = ActionDictionary::ACTION_TASK_CHANGE_STATUS;
	}

	if (
		isset($arActionArguments['FIELDS']['ACCOMPLICES'])
		&& count($arActionArguments['FIELDS']) === 1
	)
	{
		$actionId = ActionDictionary::ACTION_TASK_CHANGE_ACCOMPLICES;
	}

	if (
		in_array($actionId, [
			ActionDictionary::ACTION_TASK_FAVORITE,
			ActionDictionary::ACTION_TASK_FAVORITE_ADD,
			ActionDictionary::ACTION_TASK_FAVORITE_DELETE
		])
	)
	{
		return $this->proceedActionFavorite($arActionArguments);
	}

	try
	{
		$arTaskData = $this->getData($bSpecialChars = false, [], !$skipAccessControl);
	}
	catch (TasksException $e)
	{
		throw new TasksException(Loc::getMessage('TASKS_ACTION_NOT_ALLOWED'), TasksException::TE_ACTION_NOT_ALLOWED | TasksException::TE_ACCESS_DENIED);
	}

	$arNewFields = null;

	if ($actionId === ActionDictionary::ACTION_TASK_REMOVE)
	{
		return $this->proceedActionRemove($arActionArguments);
	}
	elseif ($actionId === ActionDictionary::ACTION_TASK_EDIT)
	{
		return $this->proceedActionEdit($arActionArguments, $arTaskData);
	}

	switch ($actionId)
	{
		case ActionDictionary::ACTION_TASK_ACCEPT:
			$arNewFields['STATUS'] = Status::PENDING;
		break;

		case ActionDictionary::ACTION_TASK_CHANGE_STATUS:
			$arNewFields['STATUS'] = $arActionArguments['FIELDS']['STATUS'];
		break;

		case ActionDictionary::ACTION_TASK_DECLINE:
			$arNewFields['STATUS'] = Status::DECLINED;

			if (isset($arActionArguments['DECLINE_REASON']))
				$arNewFields['DECLINE_REASON'] = $arActionArguments['DECLINE_REASON'];
			else
				$arNewFields['DECLINE_REASON'] = '';
		break;

		case ActionDictionary::ACTION_TASK_COMPLETE:
			$isAdmin = User::isSuper($this->executiveUserId);
			$isCreator = $arTaskData['CREATED_BY'] == $this->executiveUserId;
			$isOnePersonTask = $arTaskData['CREATED_BY'] == $arTaskData['RESPONSIBLE_ID'];
			$isCreatorDirector = User::isBoss($arTaskData['CREATED_BY'], $this->executiveUserId);

			if (
				(($isAdmin || $isCreatorDirector) && (int)$arTaskData['STATUS'] === Status::SUPPOSEDLY_COMPLETED)
				|| $isOnePersonTask
				|| $isCreator
				|| $arTaskData['TASK_CONTROL'] === 'N'
			)
			{
				$arNewFields['STATUS'] = Status::COMPLETED;
			}
			else
			{
				$arNewFields['STATUS'] = Status::SUPPOSEDLY_COMPLETED;
			}

			if (
				($isAdmin || $isCreator || $isCreatorDirector)
				&& $arTaskData['TASK_CONTROL'] == 'Y'
				&& $this->checkAccess(ActionDictionary::ACTION_TASK_APPROVE)
			)
			{
				$skipAccessControl = true;
			}

			break;

		case ActionDictionary::ACTION_TASK_APPROVE:
			$arNewFields['STATUS'] = Status::COMPLETED;
		break;

		case ActionDictionary::ACTION_TASK_START:
			$arNewFields['STATUS'] = Status::IN_PROGRESS;
		break;

		case ActionDictionary::ACTION_TASK_PAUSE:
			$arNewFields['STATUS'] = Status::PENDING;
		break;

		case ActionDictionary::ACTION_TASK_DELEGATE:
		case ActionDictionary::ACTION_TASK_CHANGE_RESPONSIBLE:
			$newResponsibleId = $arActionArguments['RESPONSIBLE_ID'];
			$oldResponsibleId = $arTaskData['RESPONSIBLE_ID'];

			if (!isset($newResponsibleId))
			{
				throw new TasksException(
					'Expected $arActionArguments['RESPONSIBLE_ID']',
					TasksException::TE_WRONG_ARGUMENTS
				);
			}

			$arNewFields['STATUS'] = Status::PENDING;
			$arNewFields['RESPONSIBLE_ID'] = $newResponsibleId;

			$isScrumTask = false;
			if (Loader::includeModule('socialnetwork'))
			{
				$currentGroupId = (($arNewFields['GROUP_ID'] ?? null) > 0 ? $arNewFields['GROUP_ID'] : $arTaskData['GROUP_ID']);
				$group = Workgroup::getById($currentGroupId);
				$isScrumTask = ($group && $group->isScrumProject());
			}

			if (isset($arTaskData['AUDITORS']) && count($arTaskData['AUDITORS']))
			{
				if (!in_array($oldResponsibleId, $arTaskData['AUDITORS']))
				{
					$arNewFields['AUDITORS'] = $arTaskData['AUDITORS'];
					if (!$isScrumTask)
					{
						$arNewFields['AUDITORS'][] = $oldResponsibleId;
					}
				}
			}
			else
			{
				if (!$isScrumTask)
				{
					$arNewFields['AUDITORS'] = [$oldResponsibleId];
				}
			}

			$accessParams = BitrixTasksAccessModelTaskModel::createFromArray($arNewFields, $arTaskData);

		break;

		case ActionDictionary::ACTION_TASK_CHANGE_ACCOMPLICES:
			if (!$arNewFields || !array_key_exists('ACCOMPLICES', $arNewFields))
			{
				$arNewFields['ACCOMPLICES'] = [];
			}

			foreach ($arActionArguments['FIELDS']['ACCOMPLICES'] as $acc)
			{
				$arNewFields['ACCOMPLICES'][] = $acc;
			}

			$accessParams = BitrixTasksAccessModelTaskModel::createFromArray($arNewFields, $arTaskData);

		break;

		case ActionDictionary::ACTION_TASK_RATE:
			$arNewFields['MARK'] = $arActionArguments['FIELDS']['MARK'];
		break;

		case ActionDictionary::ACTION_TASK_DEFER:
			$arNewFields['STATUS'] = Status::DEFERRED;
		break;

		case ActionDictionary::ACTION_TASK_DISAPPROVE:
		case ActionDictionary::ACTION_TASK_RENEW:
			$arNewFields['STATUS'] = Status::PENDING;
		break;

		default:
		break;
	}

	if ($arNewFields === null)
	{
		throw new TasksException();
	}

	// Don't update task, if nothing changed
	$bNeedUpdate = false;

	foreach ($arNewFields as $fieldName => $newValue)
	{
		$curValue = $arTaskData[$fieldName];

		// Convert task data arrays to strings, for comparing
		if (is_array($curValue))
		{
			sort($curValue);
			sort($newValue);
			$curValue = implode('|', $curValue);
			$newValue = implode('|', $newValue);
		}

		if ($curValue != $newValue)
		{
			$bNeedUpdate = true;
			break;
		}
	}

	if ($bNeedUpdate)
	{
		if (!$skipAccessControl && !$this->checkAccess($actionId, $accessParams))
		{
			throw new TasksException(Loc::getMessage('TASKS_ACTION_NOT_ALLOWED'), TasksException::TE_ACTION_NOT_ALLOWED | TasksException::TE_ACCESS_DENIED);
		}

		$arParams = array_merge($arActionArguments['PARAMETERS'], ['USER_ID' => $this->executiveUserId]);
		$o = new CTasks();
		/** @noinspection PhpDeprecationInspection */

		$this->markCacheAsDirty(); // for ->getData() called inside onAfterUpdate inside CTasks::Update()
		if ($o->Update($this->taskId, $arNewFields, $arParams) !== true)
		{
			static::throwExceptionVerbose($o->GetErrors());
		}
		$this->markCacheAsDirty(); // for the rest of the code below
	}
}