Your IP : 3.144.251.83


Current Path : /var/www/axolotl/data/www/kirov.axolotls.ru/bitrix/modules/tasks/lib/processor/task/
Upload File :
Current File : /var/www/axolotl/data/www/kirov.axolotls.ru/bitrix/modules/tasks/lib/processor/task/autocloser.php

<?
/**
 * This class could be changed (removed, renamed, relocated) in any time, so do not use it in public code
 *
 * @internal
 * @access private
 */

namespace Bitrix\Tasks\Processor\Task;

use Bitrix\Tasks\Internals\Helper\Task\Dependence;
use Bitrix\Tasks\Internals\RunTime;
use Bitrix\Tasks\Processor\Task\AutoCloser\Result\Impact;

final class AutoCloser extends \Bitrix\Tasks\Processor
{
	const STATUS_COMPLETE = 5;

	/**
	 * Get task parent tree, and complete some of sub-tasks
	 *
	 * @param $id int task
	 * @param mixed[] changed fields
	 * @param mixed[] $settings
	 * @return \Bitrix\Tasks\Processor\Task\Result
	 */
	public function processEntity($id, $data = array(), array $settings = array())
	{
		$result = parent::processEntity($id, $data, $settings);

		// todo: this code will not work if someone creates already closed sub-task with this auto_close = on
		$id = intval($id);
		if(!$id || $data['STATUS'] != static::STATUS_COMPLETE)
		{
			return $result;
		}

		// todo: Impact class is TEMPORAL, it should be replaced with (or at least inherited from) \Bitrix\Tasks\Item\Task when ready
		//$taskImpact = new Impact($id, $this->getUserId());

		$worker = $this;

		$globalTree = $this->getParentTree($id);
		$prevData = $globalTree->getNodeData($id);

		if($prevData)
		{
			// close sub-tasks, if current task (and\or sub tasks) has AUTO_CLOSE == Y
			if($prevData['AUTO_CLOSE'] == 'Y')
			{
				$subTree = $globalTree->getSubTree($id);
				$subTree->walkWidth(function($item, $itemId, $itemData, $parentId) use($subTree, $id, $worker) {

					//_print_r($itemData['TASK_ID'].' '.$itemData['TITLE'].' <- '.$parentId);

					$impactData = null;

					$parentData = $subTree->getNodeData($parentId);
					$parentImpact = $worker->getImpactById($parentId);
					if($parentImpact)
					{
						$parentData = $parentImpact;
					}

					if($parentData && $parentData['AUTO_CLOSE'] == 'Y')
					{
						if($itemData['STATUS'] != 5)
						{
							$itemData['ID'] = $itemData['__ID'];
							$impact = new Impact($itemData, $worker->getUserId());
							$impact->setDataUpdated(array('STATUS' => 5));

							$worker->addImpact($impact);
						}
					}
				});
			}

			// close parent tasks, if they have AUTO_CLOSE == Y
			$closeIndex = array();
			$globalTree->walkDepth(function($item, $itemId, $itemData, $parentId) use(&$closeIndex, $worker, $globalTree) {

				//_print_r($itemData['TASK_ID'].' '.$itemData['TITLE'].' <- '.$parentId);

				if(!array_key_exists($parentId, $closeIndex))
				{
					$closeIndex[$parentId] = $globalTree->getChildrenCount($parentId);
				}

				$impact = $worker->getImpactById($itemId);
				if($impact)
				{
					$itemData = $impact->getUpdatedData();
				}

				if($itemData['STATUS'] == 5) // was closed before or just closed
				{
					$closeIndex[$parentId]--;
				}

				if($parentId && !$closeIndex[$parentId] && !$worker->hasImpact($parentId))
				{
					// all children task closed
					$parentTaskData = $globalTree->getNodeData($parentId);

					if($parentTaskData['AUTO_CLOSE'] == 'Y')
					{
						$parentTaskData['ID'] = $parentTaskData['__ID'];
						$impact = new Impact($parentTaskData, $worker->getUserId());
						$impact->setDataUpdated(array('STATUS' => 5));

						$worker->addImpact($impact);
					}
				}
			});
		}

		$result->setData($this->affected);

		return $result;
	}

	private function getParentTree($id)
	{
		return Dependence::getParentTree($id, Runtime::apply(array(
			'select' => array(
				'TASK_ID',
				'PARENT_TASK_ID',
				'TITLE' => 'TASK.TITLE', // tmp
				'PARENT_ID' => 'TASK.PARENT_ID',
				'AUTO_CLOSE' => 'PARAMETER.VALUE',
				'STATUS' => 'TASK.STATUS',
			),
			'group' => array(
				'AUTO_CLOSE', // ensure we will not get duplicates in the result
			)
		), array(
			RunTime\Task::getTask(array('REF_FIELD' => 'TASK_ID', 'JOIN_TYPE' => 'inner')),
			RunTime\Task\Parameter::getParameter(array('REF_FIELD' => 'TASK_ID', 'CODE' => 2)),
		)));
	}
}