[sync story #73251] Sync code to this branch from feature/deliverable.
This commit is contained in:
+131
-62
@@ -70,6 +70,7 @@ class taskZen extends task
|
||||
$this->view->showFields = $this->config->task->custom->createFields;
|
||||
$this->view->gobackLink = (isset($output['from']) && $output['from'] == 'global') ? $this->createLink('execution', 'task', "executionID={$executionID}") : '';
|
||||
$this->view->execution = $execution;
|
||||
$this->view->project = $this->loadModel('project')->fetchById($execution->project);
|
||||
$this->view->storyID = $storyID;
|
||||
$this->view->blockID = helper::isAjaxRequest('modal') ? $this->loadModel('block')->getSpecifiedBlockID('my', 'assigntome', 'assigntome') : 0;
|
||||
$this->view->hideStory = $this->task->isNoStoryExecution($execution);
|
||||
@@ -195,6 +196,7 @@ class taskZen extends task
|
||||
|
||||
$this->view->title = $execution->name . $this->lang->hyphen . $this->lang->task->batchEdit;
|
||||
$this->view->execution = $execution;
|
||||
$this->view->project = $this->loadModel('project')->fetchById($execution->project);
|
||||
$this->view->modules = $this->tree->getTaskOptionMenu($executionID, 0, !empty($this->config->task->allModule) ? 'allModule' : '');
|
||||
}
|
||||
else
|
||||
@@ -247,6 +249,18 @@ class taskZen extends task
|
||||
}
|
||||
|
||||
list($childTasks, $nonStoryChildTasks) = $this->task->getChildTasksByList(array_keys($tasks));
|
||||
$childrenDateLimit = array();
|
||||
foreach($childTasks as $parent => $children)
|
||||
{
|
||||
$childDateLimit = array('estStarted' => '', 'deadline' => '');
|
||||
foreach($children as $child)
|
||||
{
|
||||
if(!helper::isZeroDate($child->estStarted) && (empty($childDateLimit['estStarted']) || $childDateLimit['estStarted'] > $child->estStarted)) $childDateLimit['estStarted'] = $child->estStarted;
|
||||
if(!helper::isZeroDate($child->deadline) && (empty($childDateLimit['deadline']) || $childDateLimit['deadline'] < $child->deadline)) $childDateLimit['deadline'] = $child->deadline;
|
||||
}
|
||||
$childrenDateLimit[$parent] = $childDateLimit;
|
||||
}
|
||||
|
||||
$storyPairs = $this->story->getExecutionStoryPairs($executionID, 0, 'all', '', 'full', 'active', 'story', false);;
|
||||
$storyList = $this->story->getByList(array_keys($storyPairs));
|
||||
$stories = array();
|
||||
@@ -268,6 +282,7 @@ class taskZen extends task
|
||||
$this->view->moduleGroup = $moduleGroup;
|
||||
$this->view->childTasks = $childTasks;
|
||||
$this->view->nonStoryChildTasks = $nonStoryChildTasks;
|
||||
$this->view->childrenDateLimit = $childrenDateLimit;
|
||||
$this->view->stories = $stories;
|
||||
$this->view->parentTasks = $this->task->getByIdList($parentTaskIdList);
|
||||
$this->view->noSprintPairs = $this->loadModel('project')->getProjectExecutionPairs();
|
||||
@@ -301,7 +316,7 @@ class taskZen extends task
|
||||
$executions = !empty($task->project) ? $this->execution->getByProject($task->project, 'all', 0, true) : array();
|
||||
|
||||
/* Get task members. */
|
||||
$taskMembers = array();
|
||||
$taskMembers = $this->view->members;
|
||||
if(!empty($task->team))
|
||||
{
|
||||
foreach($task->members as $teamAccount)
|
||||
@@ -310,10 +325,6 @@ class taskZen extends task
|
||||
$taskMembers[$teamAccount] = $this->view->members[$teamAccount];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$taskMembers = $this->view->members;
|
||||
}
|
||||
|
||||
/* Get execution stories. */
|
||||
$moduleID = $task->module;
|
||||
@@ -324,29 +335,34 @@ class taskZen extends task
|
||||
}
|
||||
$stories = $this->story->getExecutionStoryPairs($this->view->execution->id, 0, 'all', $moduleID, 'full', 'active', 'story', false);
|
||||
|
||||
$syncChildren = array();
|
||||
$syncChildren = array();
|
||||
$childDateLimit = array('estStarted' => '', 'deadline' => '');
|
||||
if(!empty($task->children))
|
||||
{
|
||||
foreach($task->children as $child)
|
||||
{
|
||||
if(empty($child->story)) $syncChildren[] = $child->id;
|
||||
if(!helper::isZeroDate($child->estStarted) && (empty($childDateLimit['estStarted']) || $childDateLimit['estStarted'] > $child->estStarted)) $childDateLimit['estStarted'] = $child->estStarted;
|
||||
if(!helper::isZeroDate($child->deadline) && (empty($childDateLimit['deadline']) || $childDateLimit['deadline'] < $child->deadline)) $childDateLimit['deadline'] = $child->deadline;
|
||||
}
|
||||
}
|
||||
|
||||
if($this->view->execution->multiple) $manageLink = common::hasPriv('execution', 'manageMembers') ? $this->createLink('execution', 'manageMembers', "execution={$this->view->execution->id}") : '';
|
||||
if(!$this->view->execution->multiple) $manageLink = common::hasPriv('project', 'manageMembers') ? $this->createLink('project', 'manageMembers', "projectID={$this->view->execution->project}") : '';
|
||||
|
||||
$this->view->title = $this->lang->task->edit . 'TASK' . $this->lang->hyphen . $this->view->task->name;
|
||||
$this->view->stories = $this->story->addGradeLabel($stories);
|
||||
$this->view->tasks = $tasks;
|
||||
$this->view->taskMembers = $taskMembers;
|
||||
$this->view->users = $this->loadModel('user')->getPairs('nodeleted|noclosed', "{$task->openedBy},{$task->canceledBy},{$task->closedBy}");
|
||||
$this->view->showAllModule = isset($this->config->execution->task->allModule) ? $this->config->execution->task->allModule : '';
|
||||
$this->view->modules = $this->tree->getTaskOptionMenu($task->execution, 0, $this->view->showAllModule ? 'allModule' : '');
|
||||
$this->view->executions = $executions;
|
||||
$this->view->syncChildren = $syncChildren;
|
||||
$this->view->parentTask = !empty($task->parent) ? $this->task->getById($task->parent) : null;
|
||||
$this->view->manageLink = $manageLink;
|
||||
$this->view->title = $this->lang->task->edit . 'TASK' . $this->lang->hyphen . $this->view->task->name;
|
||||
$this->view->stories = $this->story->addGradeLabel($stories);
|
||||
$this->view->tasks = $tasks;
|
||||
$this->view->taskMembers = $taskMembers;
|
||||
$this->view->users = $this->loadModel('user')->getPairs('nodeleted|noclosed', "{$task->openedBy},{$task->canceledBy},{$task->closedBy}");
|
||||
$this->view->showAllModule = isset($this->config->execution->task->allModule) ? $this->config->execution->task->allModule : '';
|
||||
$this->view->modules = $this->tree->getTaskOptionMenu($task->execution, 0, $this->view->showAllModule ? 'allModule' : '');
|
||||
$this->view->executions = $executions;
|
||||
$this->view->syncChildren = $syncChildren;
|
||||
$this->view->childDateLimit = $childDateLimit;
|
||||
$this->view->parentTask = !empty($task->parent) ? $this->task->getById($task->parent) : null;
|
||||
$this->view->manageLink = $manageLink;
|
||||
$this->view->project = $task->project ? $this->loadModel('project')->fetchById($task->project) : null;
|
||||
$this->display();
|
||||
}
|
||||
|
||||
@@ -437,6 +453,7 @@ class taskZen extends task
|
||||
|
||||
$this->view->title = $this->lang->task->batchCreate;
|
||||
$this->view->execution = $execution;
|
||||
$this->view->project = $this->loadModel('project')->fetchById($execution->project);
|
||||
$this->view->modules = $modules;
|
||||
$this->view->parent = $taskID;
|
||||
$this->view->storyID = $storyID;
|
||||
@@ -558,12 +575,13 @@ class taskZen extends task
|
||||
->stripTags($this->config->task->editor->edit['id'], $this->config->allowedTags)
|
||||
->get();
|
||||
|
||||
$project = $this->loadModel('project')->fetchById($oldTask->project);
|
||||
$parents = $this->getParentEstStartedAndDeadline(array($task->parent));
|
||||
$this->checkLegallyDate($task, $project->taskDateLimit == 'limit', isset($parents[$task->parent]) ? $parents[$task->parent] : null);
|
||||
|
||||
$team = $this->post->team ? array_filter($this->post->team) : array();
|
||||
if($task->mode && empty($team))
|
||||
{
|
||||
dao::$errors['assignedTo'] = $this->lang->task->teamNotEmpty;
|
||||
return false;
|
||||
}
|
||||
if($task->mode && empty($team)) dao::$errors['assignedTo'] = $this->lang->task->teamNotEmpty;
|
||||
if(dao::isError()) return false;
|
||||
|
||||
return $this->loadModel('file')->processImgURL($task, $this->config->task->editor->edit['id'], (string)$this->post->uid);
|
||||
}
|
||||
@@ -1006,6 +1024,31 @@ class taskZen extends task
|
||||
$this->setMenu($this->view->execution->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查任务的开始时间和截止时间是否合法。
|
||||
* Check if the start and end time of the task is legal.
|
||||
*
|
||||
* @param object $task
|
||||
* @param bool $isDateLimit
|
||||
* @param object $parent
|
||||
* @param int|null $rowID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function checkLegallyDate(object $task, bool $isDateLimit, object|null $parent, int|null $rowID = null): void
|
||||
{
|
||||
$beginIndex = $rowID === null ? 'estStarted' : "estStarted[$rowID]";
|
||||
$endIndex = $rowID === null ? 'deadline' : "deadline[$rowID]";
|
||||
|
||||
$beginIsZeroDate = helper::isZeroDate($task->estStarted);
|
||||
$endIsZeroDate = helper::isZeroDate($task->deadline);
|
||||
if(!$beginIsZeroDate and !$endIsZeroDate and $task->deadline < $task->estStarted) dao::$errors[$endIndex] = $this->lang->task->error->deadlineSmall;
|
||||
|
||||
if(!$isDateLimit || empty($parent)) return;
|
||||
if(!$beginIsZeroDate && !helper::isZeroDate($parent->estStarted) && $task->estStarted < $parent->estStarted) dao::$errors[$beginIndex] = sprintf($this->lang->task->overParentEsStarted, $parent->estStarted);
|
||||
if(!$endIsZeroDate && !helper::isZeroDate($parent->deadline) && $task->deadline > $parent->deadline) dao::$errors[$endIndex] = sprintf($this->lang->task->overParentDeadline, $parent->deadline);
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查传入的创建数据是否符合要求。
|
||||
* Check if the input post meets the requirements.
|
||||
@@ -1018,17 +1061,9 @@ class taskZen extends task
|
||||
protected function checkCreateTask(object $task, array $team): bool
|
||||
{
|
||||
/* Check if the estimate is positive. */
|
||||
if($task->estimate < 0)
|
||||
{
|
||||
dao::$errors['estimate'] = $this->lang->task->error->recordMinus;
|
||||
return false;
|
||||
}
|
||||
|
||||
if($this->post->multiple && empty($team))
|
||||
{
|
||||
dao::$errors['assignedTo'] = $this->lang->task->teamNotEmpty;
|
||||
return false;
|
||||
}
|
||||
if($task->estimate < 0) dao::$errors['estimate'] = $this->lang->task->error->recordMinus;
|
||||
if($this->post->multiple && empty($team)) dao::$errors['assignedTo'] = $this->lang->task->teamNotEmpty;
|
||||
if(dao::isError()) return false;
|
||||
|
||||
/* If the task start and end date must be between the execution start and end date, check if the task start and end date accord with the conditions. */
|
||||
if(!empty($this->config->limitTaskDate))
|
||||
@@ -1037,12 +1072,9 @@ class taskZen extends task
|
||||
if(dao::isError()) return false;
|
||||
}
|
||||
|
||||
/* Check start and end date. */
|
||||
if(!helper::isZeroDate($task->deadline) && $task->estStarted > $task->deadline)
|
||||
{
|
||||
dao::$errors['deadline'] = $this->lang->task->error->deadlineSmall;
|
||||
return false;
|
||||
}
|
||||
$project = $this->dao->findById($task->project)->from(TABLE_PROJECT)->fetch();
|
||||
$parents = $this->getParentEstStartedAndDeadline(array($task->parent));
|
||||
$this->checkLegallyDate($task, $project->taskDateLimit == 'limit', isset($parents[$task->parent]) ? $parents[$task->parent] : null);
|
||||
|
||||
return !dao::isError();
|
||||
}
|
||||
@@ -1060,26 +1092,26 @@ class taskZen extends task
|
||||
{
|
||||
/* Set required fields. */
|
||||
$requiredFields = $this->config->task->create->requiredFields;
|
||||
$execution = $this->loadModel('execution')->getById($executionID);
|
||||
$execution = $this->loadModel('execution')->fetchById($executionID);
|
||||
if($this->task->isNoStoryExecution($execution)) $requiredFields = str_replace(',story,', ',', ',' . $requiredFields . ',');
|
||||
$requiredFields = array_filter(explode(',', $requiredFields));
|
||||
|
||||
$levels = array();
|
||||
$project = $this->loadModel('project')->fetchById($execution->project);
|
||||
$parentIdList = array_filter(array_column($tasks, 'parent', 'parent'));
|
||||
$parents = $this->getParentEstStartedAndDeadline($parentIdList);
|
||||
foreach($tasks as $rowIndex => $task)
|
||||
{
|
||||
if(mb_strlen($task->name) > 255)
|
||||
{
|
||||
dao::$errors["name[$rowIndex]"] = sprintf($this->lang->task->error->length, 255);
|
||||
}
|
||||
$levels[$task->level] = $rowIndex;
|
||||
|
||||
if(mb_strlen($task->name) > 255) dao::$errors["name[$rowIndex]"] = sprintf($this->lang->task->error->length, 255);
|
||||
if(!empty($this->post->estimate[$rowIndex]) and !preg_match("/^[0-9]+(.[0-9]+)?$/", (string)$this->post->estimate[$rowIndex]))
|
||||
{
|
||||
dao::$errors["estimate[$rowIndex]"] = $this->lang->task->error->estimateNumber;
|
||||
}
|
||||
|
||||
/* If the task start and end date must be between the execution start and end date, check if the task start and end date accord with the conditions. */
|
||||
if(!empty($this->config->limitTaskDate))
|
||||
{
|
||||
$this->task->checkEstStartedAndDeadline($executionID, (string)$task->estStarted, (string)$task->deadline);
|
||||
}
|
||||
if(!empty($this->config->limitTaskDate)) $this->task->checkEstStartedAndDeadline($executionID, (string)$task->estStarted, (string)$task->deadline);
|
||||
|
||||
/* Check start and end date. */
|
||||
if(!helper::isZeroDate($task->deadline) && $task->deadline < $task->estStarted)
|
||||
@@ -1087,24 +1119,21 @@ class taskZen extends task
|
||||
dao::$errors["deadline[$rowIndex]"] = $this->lang->task->error->deadlineSmall;
|
||||
}
|
||||
|
||||
$parentTask = isset($parents[$task->parent]) ? $parents[$task->parent] : null;
|
||||
if($task->level > 0 && isset($levels[$task->level - 1])) $parentTask = zget($tasks, $levels[$task->level - 1], null);
|
||||
$this->checkLegallyDate($task, $project->taskDateLimit == 'limit', $parentTask, $rowIndex);
|
||||
|
||||
/* Check if the estimate is positive. */
|
||||
if($task->estimate < 0)
|
||||
{
|
||||
dao::$errors["estimate[$rowIndex]"] = $this->lang->task->error->recordMinus;
|
||||
}
|
||||
if($task->estimate < 0) dao::$errors["estimate[$rowIndex]"] = $this->lang->task->error->recordMinus;
|
||||
|
||||
/* Check if the required fields are empty. */
|
||||
foreach($requiredFields as $field)
|
||||
{
|
||||
if(empty($task->$field))
|
||||
{
|
||||
dao::$errors[$field . "[$rowIndex]"] = sprintf($this->lang->error->notempty, $this->lang->task->$field);
|
||||
}
|
||||
if(empty($task->$field)) dao::$errors[$field . "[$rowIndex]"] = sprintf($this->lang->error->notempty, $this->lang->task->$field);
|
||||
}
|
||||
}
|
||||
|
||||
if(dao::isError()) return false;
|
||||
return true;
|
||||
return !dao::isError();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1118,6 +1147,10 @@ class taskZen extends task
|
||||
*/
|
||||
protected function checkBatchEditTask(array $tasks, array $oldTasks): bool
|
||||
{
|
||||
$oldTask = reset($oldTasks);
|
||||
$project = $this->loadModel('project')->fetchById($oldTask->project);
|
||||
$parentIdList = array_filter(array_column($tasks, 'parent', 'parent'));
|
||||
$parents = $this->getParentEstStartedAndDeadline($parentIdList);
|
||||
foreach($tasks as $taskID => $task)
|
||||
{
|
||||
$oldTask = $oldTasks[$taskID];
|
||||
@@ -1131,11 +1164,12 @@ class taskZen extends task
|
||||
if($task->consumed < 0 ) dao::$errors["consumed[{$taskID}]"] = (array)sprintf($this->lang->task->error->recordMinus, $this->lang->task->consumedThisTime);
|
||||
if($task->left < 0) dao::$errors["left[$taskID]"] = (array)sprintf($this->lang->task->error->recordMinus, $this->lang->task->leftAB);
|
||||
|
||||
if(!empty($this->config->limitTaskDate)) $this->task->checkEstStartedAndDeadline($oldTask->execution, (string)$task->estStarted, (string)$task->deadline, "task:{$taskID} ");
|
||||
if(!empty($this->config->limitTaskDate)) $this->task->checkEstStartedAndDeadline($oldTask->execution, (string)$task->estStarted, (string)$task->deadline, $taskID);
|
||||
|
||||
if($task->status == 'cancel') continue;
|
||||
if($task->status == 'done' && !$task->consumed) dao::$errors["consumed[{$taskID}]"] = (array)sprintf($this->lang->error->notempty, $this->lang->task->consumedThisTime);
|
||||
if(!empty($task->deadline) && $task->estStarted > $task->deadline) dao::$errors["deadline[{$taskID}]"] = (array)$this->lang->task->error->deadlineSmall;
|
||||
|
||||
$this->checkLegallyDate($task, $project->taskDateLimit == 'limit', isset($parents[$task->parent]) ? $parents[$task->parent] : null, $taskID);
|
||||
}
|
||||
return !dao::isError();
|
||||
}
|
||||
@@ -1485,11 +1519,11 @@ class taskZen extends task
|
||||
unset($task->team);
|
||||
}
|
||||
|
||||
if($task->isParent)
|
||||
if($task->isParent && strpos($task->name, "[{$this->lang->task->parentAB}]") === false)
|
||||
{
|
||||
$task->name = '[' . $this->lang->task->parentAB . '] ' . $task->name;
|
||||
}
|
||||
elseif($task->parent > 0)
|
||||
elseif($task->parent > 0 && strpos($task->name, "[{$this->lang->task->childrenAB}]") === false)
|
||||
{
|
||||
$task->name = '[' . $this->lang->task->childrenAB . '] ' . $task->name;
|
||||
}
|
||||
@@ -2047,4 +2081,39 @@ class taskZen extends task
|
||||
|
||||
return $options;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取父任务的开始时间和截止时间。
|
||||
* Get the start and end time of the parent task.
|
||||
*
|
||||
* @param array $parentIdList
|
||||
* @access protected
|
||||
* @return array
|
||||
*/
|
||||
protected function getParentEstStartedAndDeadline(array $parentIdList): array
|
||||
{
|
||||
$pathPairs = $this->dao->select('id,path')->from(TABLE_TASK)->where('id')->in($parentIdList)->fetchPairs();
|
||||
if(empty($pathPairs)) return array();
|
||||
|
||||
$allParentIdList = array_filter(array_unique(explode(',', implode(',', $pathPairs))));
|
||||
$allParents = $this->dao->select('id,estStarted,deadline')->from(TABLE_TASK)->where('id')->in($allParentIdList)->fetchAll('id');
|
||||
$parents = array();
|
||||
foreach($pathPairs as $parentID => $path)
|
||||
{
|
||||
$parent = new stdClass();
|
||||
$parent->estStarted = null;
|
||||
$parent->deadline = null;
|
||||
foreach(array_reverse(array_filter(explode(',', $path))) as $taskID)
|
||||
{
|
||||
if(!isset($allParents[$taskID])) continue;
|
||||
|
||||
$task = $allParents[$taskID];
|
||||
if(empty($parent->estStarted) && !helper::isZeroDate($task->estStarted)) $parent->estStarted = $task->estStarted;
|
||||
if(empty($parent->deadline) && !helper::isZeroDate($task->deadline)) $parent->deadline = $task->deadline;
|
||||
if(!empty($parent->estStarted) && !empty($parent->deadline)) break;
|
||||
}
|
||||
$parents[$parentID] = $parent;
|
||||
}
|
||||
return $parents;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user