• Модуль: tasks
  • Путь к файлу: ~/bitrix/modules/tasks/lib/util/replicator/task/fromtemplate.php
  • Класс: BitrixTasksUtilReplicatorTaskFromTemplate
  • Вызов: FromTemplate::produceSub
public function produceSub($source, $destination, array $parameters = array(), $userId = 0)
{
	$result = new Result();

	Template::enterBatchState();

	$source = $this->getSourceInstance($source, $userId);
	$destination = $this->getDestinationInstance($destination, $userId);

	$created = new Collection();
	$wereErrors = false;

	$destinations = array(
		$destination // root task
	);

	// in case of multitasking create several destinations
	if($this->isMultitaskSource($source, $parameters))
	{
		// create duplicates of $destination for each sub-responsible
		foreach($source['RESPONSIBLES'] as $responsibleId)
		{
			if($responsibleId == $destination['CREATED_BY'])
			{
				continue; // skip creator itself
			}

			$subResult = $this->saveItemFromSource($source, array(
				'PARENT_ID' => $destination->getId(),
				'RESPONSIBLE_ID' => $responsibleId,
			), $userId);

			if($subResult->isSuccess())
			{
				$destinations[] = $subResult->getInstance();
			}
			else
			{
				$wereErrors = true;
			}

			$created->push($subResult);
		}
	}

	// now for each destination create sub-tasks according to the sub-templates, if any
	$data = $this->getSubItemData($source->getId());

	if (empty($data))
	{
		Template::leaveBatchState();
		return $result;
	}

	$order = $this->getCreationOrder($data, $source->getId());

	if(!$order)
	{
		$result->getErrors()->add('ILLEGAL_STRUCTURE.LOOP', Loc::getMessage('TASKS_REPLICATOR_SUBTREE_LOOP'));
	}
	else
	{
		// disable copying disk files for each sub-task
		// todo: impove this later
		$this->getConverter()->setConfig('UF.FILTER', array('!=USER_TYPE_ID' => 'disk_file'));

		foreach($destinations as $destination)
		{
			//////////////////////////////

			$src2dstId = array($source->getId() => $destination->getId());

			$cTree = $order;

			$walkQueue = array($source->getId());
			while(!empty($walkQueue)) // walk sub-item tree
			{
				$topTemplate = array_shift($walkQueue);

				if(is_array($cTree[$topTemplate] ?? null))
				{
					// create all sub template on that tree level
					foreach($cTree[$topTemplate] as $template)
					{
						$dataMixin = array_merge(array(
							'PARENT_ID' => $src2dstId[$topTemplate],
						), $parameters);

						$creationResult = $this->saveItemFromSource($data[$template], $dataMixin, $userId);
						if($creationResult->isSuccess())
						{
							$walkQueue[] = $template; // walk further on that template
							$src2dstId[$template] = $creationResult->getInstance()->getId();
						}
						else
						{
							$wereErrors = true;

							$errors = $creationResult->getErrors();
							$neededError = $errors->find(array('CODE' => 'ACCESS_DENIED.RESPONSIBLE_AND_ORIGINATOR_NOT_ALLOWED'));

							if ($errors->count() == 1 && !$neededError->isEmpty())
							{
								$data[$template]['CREATED_BY'] = $userId;

								$creationResult->getErrors()->clear();
								$creationResult = $this->saveItemFromSource($data[$template], $dataMixin, $userId);
								if ($creationResult->isSuccess())
								{
									$walkQueue[] = $template;
									$src2dstId[$template] = $creationResult->getInstance()->getId();

									$wereErrors = false;
								}
							}
						}

						$created->push($creationResult); // add sub-item creation result
					}
				}
				unset($cTree[$topTemplate]);
			}

			//////////////////////////////
		}

		if($wereErrors)
		{
			$result->addError('SUB_ITEMS_CREATION_FAILURE', 'Some of the sub-tasks was not properly created');
		}

		$result->setData($created);
	}


	Template::leaveBatchState();

	return $result;
}