* Rewrite story batchtotask method. Code for task #102982.

This commit is contained in:
wangyidong
2023-10-08 08:28:51 +08:00
parent 2c3619f508
commit 56150d3106
20 changed files with 290 additions and 302 deletions
+1 -1
View File
@@ -78,7 +78,7 @@ class executionEntry extends entry
$execution->builds = $this->loadModel('build')->getBuildPairs(array($productID), 'all', 'noempty,noterminate,nodone', $executionID, 'execution');
break;
case 'moduleoptionmenu':
$execution->moduleOptionMenu = $this->loadModel('tree')->getTaskOptionMenu($executionID, 0, 0, 'allModule');
$execution->moduleOptionMenu = $this->loadModel('tree')->getTaskOptionMenu($executionID, 0, 'allModule');
break;
case 'members':
$execution->members = $this->loadModel('user')->getTeamMemberPairs($executionID, 'execution', 'nodeleted');;
+1 -1
View File
@@ -176,7 +176,7 @@ class execution extends control
$this->view->status = $status;
$this->view->param = $param;
$this->view->moduleID = $moduleID;
$this->view->modules = $this->loadModel('tree')->getTaskOptionMenu($executionID, 0, 0, $showModule);
$this->view->modules = $this->loadModel('tree')->getTaskOptionMenu($executionID, 0, $showModule);
$this->view->moduleTree = $this->tree->getTaskTreeMenu($executionID, $productID, 0, array('treeModel', 'createTaskLink'), $showModule);
$this->view->memberPairs = $memberPairs;
$this->display();
+1 -1
View File
@@ -3916,7 +3916,7 @@ class executionModel extends model
$this->config->execution->search['params']['execution']['values'] = array(''=>'', $executionID => $executions[$executionID], 'all' => $this->lang->execution->allExecutions);
$showAllModule = isset($this->config->execution->task->allModule) ? $this->config->execution->task->allModule : '';
$this->config->execution->search['params']['module']['values'] = $this->loadModel('tree')->getTaskOptionMenu($executionID, 0, 0, $showAllModule ? 'allModule' : '');
$this->config->execution->search['params']['module']['values'] = $this->loadModel('tree')->getTaskOptionMenu($executionID, 0, $showAllModule ? 'allModule' : '');
$this->loadModel('search')->setSearchParams($this->config->execution->search);
}
+1 -1
View File
@@ -1211,7 +1211,7 @@ class executionTest
$execution = $this->executionModel->getByID($executionID);
$bugs = $this->executionModel->loadModel('bug')->getByIdList(array_keys($postData));
$showAllModule = isset($this->executionModel->config->execution->task->allModule) ? $this->executionModel->config->execution->task->allModule : '';
$modules = $this->executionModel->loadModel('tree')->getTaskOptionMenu($execution->id, 0, 0, $showAllModule ? 'allModule' : '');
$modules = $this->executionModel->loadModel('tree')->getTaskOptionMenu($execution->id, 0, $showAllModule ? 'allModule' : '');
$now = helper::now();
foreach($postData as $bugID => $task)
{
+1 -1
View File
@@ -687,7 +687,7 @@ class executionZen extends execution
$tasks = array();
$bugs = $this->loadModel('bug')->getByIdList(array_keys($postData));
$showAllModule = isset($this->config->execution->task->allModule) ? $this->config->execution->task->allModule : '';
$modules = $this->loadModel('tree')->getTaskOptionMenu($execution->id, 0, 0, $showAllModule ? 'allModule' : '');
$modules = $this->loadModel('tree')->getTaskOptionMenu($execution->id, 0, $showAllModule ? 'allModule' : '');
$now = helper::now();
$requiredFields = str_replace(',story,', ',', ',' . $this->config->task->create->requiredFields . ',');
$requiredFields = trim($requiredFields, ',');
+1 -1
View File
@@ -32,7 +32,7 @@ $taskRepoModule = 0;
$taskMembers = array('' => '');
if($repoExecution)
{
$taskModules = $this->loadModel('tree')->getTaskOptionMenu($repoExecution, 0, 0, '');
$taskModules = $this->loadModel('tree')->getTaskOptionMenu($repoExecution);
$taskRepoModule = (!empty($lastReview->task) && $lastReview->task->execution == $repoExecution) ? $lastReview->task->module : '';
$taskMembers = $this->loadModel('user')->getTeamMemberPairs($repoExecution, 'execution', 'nodeleted');
}
+15
View File
@@ -162,3 +162,18 @@ $config->story->form->close['closeSync'] = array('type' => 'string', 'req
$config->story->form->submitReview = array();
$config->story->form->submitReview['reviewer'] = array('type' => 'array', 'control' => 'multi-select', 'required' => false, 'default' => '');
$config->story->form->submitReview['reviewedBy'] = array('type' => 'string', 'control' => 'hidden', 'required' => false, 'default' => '');
$config->story->form->batchToTask['module'] = array('type' => 'int', 'required' => false, 'default' => 0);
$config->story->form->batchToTask['story'] = array('type' => 'int', 'required' => false, 'default' => 0);
$config->story->form->batchToTask['name'] = array('type' => 'string', 'required' => false, 'default' => '', 'base' => true, 'filter' => 'trim');
$config->story->form->batchToTask['type'] = array('type' => 'string', 'required' => false, 'default' => '');
$config->story->form->batchToTask['assignedTo'] = array('type' => 'string', 'required' => false, 'default' => '');
$config->story->form->batchToTask['estimate'] = array('type' => 'float', 'required' => false, 'default' => 0);
$config->story->form->batchToTask['estStarted'] = array('type' => 'date', 'required' => false, 'default' => '');
$config->story->form->batchToTask['deadline'] = array('type' => 'date', 'required' => false, 'default' => '');
$config->story->form->batchToTask['pri'] = array('type' => 'int', 'required' => false, 'default' => 3);
$config->story->form->batchToTask['status'] = array('type' => 'string', 'required' => false, 'default' => 'wait');
$config->story->form->batchToTask['vision'] = array('type' => 'string', 'required' => false, 'default' => 'rnd');
$config->story->form->batchToTask['openedBy'] = array('type' => 'string', 'required' => false, 'default' => $app->user->account);
$config->story->form->batchToTask['openedDate'] = array('type' => 'string', 'required' => false, 'default' => $now);
$config->story->form->batchToTask['version'] = array('type' => 'int', 'required' => false, 'default' => 1);
+10 -7
View File
@@ -935,7 +935,7 @@ class story extends control
* @access public
* @return void
*/
public function batchToTask($executionID = 0, $projectID = 0)
public function batchToTask(int $executionID = 0, int $projectID = 0)
{
if($this->app->tab == 'execution' and $executionID) $this->loadModel('execution')->setMenu($executionID);
if($this->app->tab == 'project' and $executionID) $this->loadModel('execution')->setMenu($executionID);
@@ -945,10 +945,13 @@ class story extends control
$response['result'] = 'success';
$response['message'] = $this->lang->story->successToTask;
$tasks = $this->story->batchToTask($executionID, $projectID);
$tasks = $this->storyZen->buildDataForBatchToTask($executionID, $projectID);
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
if($this->viewType == 'json') return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'idList' => $tasks));
$taskIdList = $this->story->batchToTask($executionID, $tasks);
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
if($this->viewType == 'json') return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'idList' => $taskIdList));
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'load' => $this->createLink('execution', 'task', "executionID=$executionID")));
}
@@ -969,12 +972,12 @@ class story extends control
$this->view->title = $this->lang->story->batchToTask;
$this->view->executionID = $executionID;
$this->view->syncFields = empty($_POST['fields']) ? array() : $_POST['fields'];
$this->view->hourPointValue = empty($_POST['hourPointValue']) ? 0 : $_POST['hourPointValue'];
$this->view->taskType = empty($_POST['type']) ? '' : $_POST['type'];
$this->view->syncFields = empty($_POST['fields']) ? array() : $_POST['fields'];
$this->view->hourPointValue = empty($_POST['hourPointValue']) ? 0 : $_POST['hourPointValue'];
$this->view->taskType = empty($_POST['type']) ? '' : $_POST['type'];
$this->view->stories = $activeStories;
$this->view->storyPairs = $storyPairs;
$this->view->modules = $this->loadModel('tree')->getTaskOptionMenu($executionID, 0, 0, 'allModule');
$this->view->modules = $this->loadModel('tree')->getTaskOptionMenu($executionID, 0, 'allModule');
$this->view->members = $this->loadModel('user')->getTeamMemberPairs($executionID, 'execution', 'nodeleted');
$this->view->storyTasks = $this->loadModel('task')->getStoryTaskCounts(array_keys($stories), $executionID);
+6 -136
View File
@@ -1684,150 +1684,21 @@ class storyModel extends model
* Batch to task.
*
* @param int $executionID
* @param int $projectID
* @param array $tasks
* @access public
* @return bool|array
* @return array|false
*/
public function batchToTask($executionID, $projectID = 0)
public function batchToTask(int $executionID, array $tasks): array|false
{
/* load Module and get the data from the post and get the current time. */
$this->loadModel('action');
$this->loadModel('task');
$now = helper::now();
$account = $this->app->user->account;
$tasks = fixer::input('post')
->remove('syncFields')
->get();
if(!empty($_POST['syncFields'])) $stories = empty($tasks->story) ? array() : $this->getByList($tasks->story);
/* Create tasks. */
$preStory = 0;
$storyIDs = array();
$taskNames = array();
foreach($tasks->story as $key => $storyID)
{
$tasks->name[$key] = trim($tasks->name[$key]);
if(empty($tasks->name[$key])) continue;
if($tasks->type[$key] == 'affair') continue;
if($tasks->type[$key] == 'ditto' and isset($tasks->type[$key - 1]) and $tasks->type[$key - 1] == 'affair') continue;
if($storyID == 'ditto') $storyID = $preStory;
$preStory = $storyID;
if(!isset($tasks->story[$key - 1]) and $key > 1 and !empty($tasks->name[$key - 1]))
{
$storyIDs[] = 0;
$taskNames[] = $tasks->name[$key - 1];
}
$inNames = in_array($tasks->name[$key], $taskNames);
if(!$inNames or ($inNames && !in_array($storyID, $storyIDs)))
{
$storyIDs[] = $storyID;
$taskNames[] = $tasks->name[$key];
}
else
{
dao::$errors['message'][] = sprintf($this->lang->duplicate, $this->lang->task->common) . ' ' . $tasks->name[$key];
return false;
}
}
$story = 0;
$module = 0;
$type = '';
$assignedTo = '';
$estStarted = null;
$deadline = null;
$data = array();
$requiredFields = "," . $this->config->task->create->requiredFields . ",";
foreach($tasks->name as $i => $task)
{
$module = (!isset($tasks->module[$i]) or $tasks->module[$i] == 'ditto') ? $module : $tasks->module[$i];
$story = (!isset($tasks->story[$i]) or $tasks->story[$i] == 'ditto') ? $story : $tasks->story[$i];
$type = (!isset($tasks->type[$i]) or $tasks->type[$i] == 'ditto') ? $type : $tasks->type[$i];
$assignedTo = (!isset($tasks->assignedTo[$i]) or $tasks->assignedTo[$i] == 'ditto') ? $assignedTo : $tasks->assignedTo[$i];
$estStarted = (!isset($tasks->estStarted[$i]) or isset($tasks->estStartedDitto[$i])) ? $estStarted : $tasks->estStarted[$i];
$deadline = (!isset($tasks->deadline[$i]) or isset($tasks->deadlineDitto[$i])) ? $deadline : $tasks->deadline[$i];
if(empty($tasks->name[$i])) continue;
$data[$i] = new stdclass();
$data[$i]->story = (int)$story;
$data[$i]->type = $type;
$data[$i]->module = (int)$module;
$data[$i]->assignedTo = $assignedTo;
$data[$i]->color = $tasks->color[$i];
$data[$i]->name = $tasks->name[$i];
$data[$i]->pri = $tasks->pri[$i];
$data[$i]->estimate = $tasks->estimate[$i];
$data[$i]->left = $tasks->estimate[$i];
$data[$i]->project = $projectID;
$data[$i]->execution = $executionID;
$data[$i]->estStarted = $estStarted;
$data[$i]->deadline = $deadline;
$data[$i]->status = 'wait';
$data[$i]->openedBy = $account;
$data[$i]->openedDate = $now;
$data[$i]->vision = 'rnd';
if($story)
{
$data[$i]->storyVersion = $stories[$story]->version;
if(strpos(",{$_POST['syncFields']},", ',spec,') !== false) $data[$i]->desc = $stories[$story]->spec;
if(strpos(",{$_POST['syncFields']},", 'mailto') !== false) $data[$i]->mailto = $stories[$story]->mailto;
}
if($assignedTo) $data[$i]->assignedDate = $now;
if(strpos($requiredFields, ',estStarted,') !== false and empty($estStarted)) $data[$i]->estStarted = '';
if(strpos($requiredFields, ',deadline,') !== false and empty($deadline)) $data[$i]->deadline = '';
}
/* check data. */
foreach($data as $i => $task)
{
if(!helper::isZeroDate($task->deadline) and $task->deadline < $task->estStarted)
{
dao::$errors['message'][] = $this->lang->task->error->deadlineSmall;
return false;
}
if($task->estimate and !preg_match("/^[0-9]+(.[0-9]{1,3})?$/", $task->estimate))
{
dao::$errors['message'][] = $this->lang->task->error->estimateNumber;
return false;
}
foreach(explode(',', $requiredFields) as $field)
{
$field = trim($field);
if(empty($field)) continue;
if(!isset($task->$field)) continue;
if(!empty($task->$field)) continue;
if($field == 'estimate' and strlen(trim($task->estimate)) != 0) continue;
dao::$errors['message'][] = sprintf($this->lang->error->notempty, $this->lang->task->$field);
return false;
}
if(!empty($this->config->limitTaskDate))
{
$this->task->checkEstStartedAndDeadline($executionID, $task->estStarted, $task->deadline);
if(dao::isError()) return false;
}
if($task->estimate) $task->estimate = (float)$task->estimate;
}
$taskIdList = array();
foreach($data as $i => $task)
foreach($tasks as $task)
{
$task->version = 1;
$this->dao->insert(TABLE_TASK)->data($task)
->autoCheck()
->checkIF($task->estimate != '', 'estimate', 'float')
$this->dao->insert(TABLE_TASK)->data($task)->autoCheck()
->batchCheck($this->config->task->create->requiredFields, 'notempty')
->exec();
if(dao::isError()) return false;
@@ -1846,7 +1717,6 @@ class storyModel extends model
if(dao::isError()) return false;
if($task->story) $this->setStage($task->story);
$this->action->create('task', $taskID, 'Opened', '');
}
+7 -18
View File
@@ -10,26 +10,15 @@ title=测试 storyModel->batchToTask();
cid=1
pid=1
6个需求批量转任务,查看转化后的数量 >> 5
查看从需求转化过来的任务的名称、状态、优先级等字段 >> 11,101,软件需求66,wait,0,test,
查看从需求转化过来的任务的名称、状态、优先级等字段 >> 11,101,软件需求68,wait,0,test,
查看从需求转化过来的任务的名称、状态、优先级等字段 >> 11,101,软件需求70,wait,0,test,
查看从需求转化过来的任务的名称、状态、优先级等字段 >> 11,101,软件需求102,wait,0,test,
查看从需求转化过来的任务的名称、状态、优先级等字段 >> 11,101,软件需求220,wait,0,test,
2个需求批量转任务,查看转化后的数量 >> 2
查看从需求转化过来的任务的名称、状态、类型等字段 >> 11,101,软件需求66,wait,0,test,
查看从需求转化过来的任务的名称、状态、类型等字段 >> 11,101,软件需求68,wait,0,test,
*/
$story = new storyTest();
$tasks = $story->batchToTaskTest();
$params['storyIdList'] = array(66, 68, 70, 102, 220, 320);
$params['type'] = 'test';
$params['fields'] = array('assignedTo');
$tasks = $story->batchToTaskTest(101, 11, $params);
r(count($tasks)) && p() && e('5'); //6个需求批量转任务,查看转化后的数量
r($tasks) && p('911:project,execution,name,status,pri,type,assignedTo') && e('11,101,软件需求66,wait,0,test,'); //查看从需求转化过来的任务的名称、状态、优先级等字段
r($tasks) && p('912:project,execution,name,status,pri,type,assignedTo') && e('11,101,软件需求68,wait,0,test,'); //查看从需求转化过来的任务的名称、状态、优先级等字段
r($tasks) && p('913:project,execution,name,status,pri,type,assignedTo') && e('11,101,软件需求70,wait,0,test,'); //查看从需求转化过来的任务的名称、状态、优先级等字段
r($tasks) && p('914:project,execution,name,status,pri,type,assignedTo') && e('11,101,软件需求102,wait,0,test,'); //查看从需求转化过来的任务的名称、状态、优先级等字段
r($tasks) && p('915:project,execution,name,status,pri,type,assignedTo') && e('11,101,软件需求220,wait,0,test,'); //查看从需求转化过来的任务的名称、状态、优先级等字段
r(count($tasks)) && p() && e('2'); //2个需求批量转任务,查看转化后的数量
r(array_shift($tasks)) && p('project,execution,name,status,type') && e('11,101,软件需求1,wait,devel'); //查看从需求转化过来的任务的名称、状态、类型等字段
r(array_shift($tasks)) && p('project,execution,name,status,type') && e('11,101,软件需求2,wait,devel'); //查看从需求转化过来的任务的名称、状态、类型等字段
+33 -10
View File
@@ -514,22 +514,45 @@ class storyTest
/**
* Test story batch to task.
*
* @param int $executionID
* @param int $projectID
* @param array $params
* @access public
* @return void
* @return array
*/
public function batchToTaskTest($executionID, $projectID = 0, $params = '')
public function batchToTaskTest(): array
{
$_POST = $params;
$taskIdList = $this->objectModel->batchToTask($executionID, $projectID);
unset($params);
$task = new stdclass();
$task->module = 0;
$task->story = 0;
$task->name = '软件需求1';
$task->type = 'devel';
$task->assignedTo = '';
$task->estimate = 0;
$task->estStarted = date('Y-m-d');
$task->deadline = date('Y-m-d');
$task->pri = 3;
$task->status = 'wait';
$task->vision = 'rnd';
$task->openedBy = 'admin';
$task->openedDate = date('Y-m-d H:i:s');
$task->version = 1;
$task->project = 11;
$task->execution = 101;
$task->left = 0;
$task->storyVersion = 1;
$task->desc = '';
$task->mailto = '';
$tasks = array();
$tasks[0] = clone $task;
$tasks[0]->name = '软件需求1';
$tasks[0]->story = 1;
$tasks[1] = clone $task;
$tasks[1]->name = '软件需求2';
$tasks[1]->story = 3;
$taskIdList = $this->objectModel->batchToTask($task->execution, $tasks);
if(dao::isError()) return dao::getError();
global $tester;
return $tester->loadModel('task')->getByIdList($taskIdList);
return $this->objectModel->dao->select('*')->from(TABLE_TASK)->where('id')->in($taskIdList)->orderBy('id')->fetchAll();
}
/**
+55
View File
@@ -1219,6 +1219,61 @@ class storyZen extends story
return $this->loadModel('file')->processImgURL($story, $editorFields, $this->post->uid);
}
/**
* 构建需求转化任务的数据。
* Build data for batchToTask.
*
* @param int $executionID
* @param int $projectID
* @access protected
* @return array|false
*/
protected function buildDataForBatchToTask(int $executionID, int $projectID = 0): array|false
{
$this->loadModel('task');
$now = helper::now();
$fields = $this->config->story->form->batchToTask;
$requiredFields = "," . $this->config->task->create->requiredFields . ",";
foreach(explode(',', trim($requiredFields, ',')) as $field)
{
if(isset($fields[$field])) $fields[$field]['required'] = true;
}
$syncFields = zget($_POST, 'syncFields', '');
$stories = array();
if(!empty($syncFields)) $stories = empty($_POST['story']) ? array() : $this->story->getByList($_POST['story']);
$tasks = form::batchData($fields)->get();
$taskNames = array();
foreach($tasks as $task)
{
$task->project = $projectID;
$task->execution = $executionID;
$task->left = $task->estimate;
if($task->assignedTo) $task->assignedDate = $now;
if($task->story)
{
$story = zget($stories, $task->story, null);
if($story)
{
$task->storyVersion = $story->version;
if(str_contains(",{$syncFields},", ',spec,')) $task->desc = $story->spec;
if(str_contains(",{$syncFields},", ',mailto,')) $task->mailto = $story->mailto;
}
}
if(in_array($task->name, $taskNames)) dao::$errors['message'][] = sprintf($this->lang->duplicate, $this->lang->task->common) . ' ' . $task->name;
if(!helper::isZeroDate($task->deadline) and $task->deadline < $task->estStarted) dao::$errors['message'][] = $this->lang->task->error->deadlineSmall;
if($task->estimate and !preg_match("/^[0-9]+(.[0-9]{1,3})?$/", $task->estimate)) dao::$errors['message'][] = $this->lang->task->error->estimateNumber;
if(!empty($this->config->limitTaskDate)) $this->task->checkEstStartedAndDeadline($executionID, $task->estStarted, $task->deadline);
$taskNames[] = $task->name;
}
if(dao::isError()) return false;
return $tasks;
}
/**
* 处理编辑需求数据。
* Process data for edit.
+1 -1
View File
@@ -83,7 +83,7 @@ js::set('requiredFields', $config->task->edit->requiredFields);
if(!isset($execution))
{
$prjInfo = $this->execution->getById($task->execution);
$modules = $this->tree->getTaskOptionMenu($task->execution, 0, 0, 'allModule');
$modules = $this->tree->getTaskOptionMenu($task->execution, 0, 'allModule');
foreach($modules as $moduleID => $moduleName) $modules[$moduleID] = $prjInfo->name. $moduleName;
$modules = array('ditto' => $this->lang->task->ditto) + $modules;
}
+3 -3
View File
@@ -177,7 +177,7 @@ class taskZen extends task
$this->view->title = $execution->name . $this->lang->colon . $this->lang->task->batchEdit;
$this->view->execution = $execution;
$this->view->modules = $this->tree->getTaskOptionMenu($executionID, 0, 0, !empty($this->config->task->allModule) ? 'allModule' : '');
$this->view->modules = $this->tree->getTaskOptionMenu($executionID, 0, !empty($this->config->task->allModule) ? 'allModule' : '');
}
else
{
@@ -263,7 +263,7 @@ class taskZen extends task
$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, 0, $this->view->showAllModule ? 'allModule' : '');
$this->view->modules = $this->tree->getTaskOptionMenu($task->execution, 0, $this->view->showAllModule ? 'allModule' : '');
$this->view->executions = $executions;
$this->view->contactLists = $this->loadModel('user')->getContactLists($this->app->user->account, 'withnote');
$this->display();
@@ -327,7 +327,7 @@ class taskZen extends task
/* 获取模块和需求下拉数据。 Get module and story dropdown data. */
$showAllModule = !empty($this->config->execution->task->allModule) ? 'allModule' : '';
$modules = $this->loadModel('tree')->getTaskOptionMenu($execution->id, 0, 0, $showAllModule);
$modules = $this->loadModel('tree')->getTaskOptionMenu($execution->id, 0, $showAllModule);
$story = $this->story->getByID($storyID);
$stories = $this->story->getExecutionStoryPairs($execution->id, 0, 'all', $story ? $story->module : 0, 'short', 'active');
+1 -1
View File
@@ -591,7 +591,7 @@ class tree extends control
{
if($viewType == 'task')
{
$optionMenu = $this->tree->getTaskOptionMenu($rootID, 0, 0, $extra);
$optionMenu = $this->tree->getTaskOptionMenu($rootID, 0, $extra);
}
else
{
+34 -54
View File
@@ -271,13 +271,12 @@ class treeModel extends model
* Create an option menu of task in html.
*
* @param int $rootID
* @param int $productID
* @param int $startModule
* @param string $extra
* @access public
* @return void
*/
public function getTaskOptionMenu(int $rootID, int $productID = 0, int $startModule = 0, string $extra = '')
public function getTaskOptionMenu(int $rootID, int $startModule = 0, string $extra = '')
{
/* If createdVersion <= 4.1, go to getOptionMenu(). */
$products = $this->loadModel('product')->getProductPairsByProject($rootID);
@@ -290,23 +289,17 @@ class treeModel extends model
if($startModule > 0)
{
$startModule = $this->getById($startModule);
if($startModule)
{
$startModulePath = $startModule->path . '%';
$modulePaths = explode(",", $startModulePath);
$rootModule = $this->getById($modulePaths[0]);
}
if($startModule) $startModulePath = $startModule->path . '%';
}
$treeMenu = array();
$lastMenu[] = '/';
$executionModules = $this->getTaskTreeModules($rootID, true);
$noProductModules = $this->dao->select('*')->from(TABLE_MODULE)
->where('root')->eq((int)$rootID)
->andWhere('type')->eq('task')
->andWhere('parent')->eq(0)
->andWhere('deleted')->eq(0)
->orderBy('grade desc, branch, `order`, type')
->fetchPairs('id', 'name');
$noProductModules = $this->dao->select('*')->from(TABLE_MODULE)->where('root')->eq($rootID)
->andWhere('type')->eq('task')
->andWhere('parent')->eq(0)
->andWhere('deleted')->eq(0)
->orderBy('grade desc, branch, `order`, type')
->fetchPairs('id', 'name');
/* Fix for not in product modules. */
$productNum = count($products);
@@ -961,64 +954,56 @@ class treeModel extends model
* @access public
* @return array
*/
public function getTaskTreeModules($executionID, $parent = false, $linkObject = 'story', $extra = array())
public function getTaskTreeModules(int $executionID, bool $parent = false, string $linkObject = 'story', array $extra = array()): array
{
$executionModules = array();
$field = $parent ? 'path' : 'id';
if($linkObject == 'story')
{
$table1 = TABLE_PROJECTSTORY;
$table2 = TABLE_STORY;
}
if($linkObject == 'case')
{
$table1 = TABLE_PROJECTCASE;
$table2 = TABLE_CASE;
}
$paths = array();
if($linkObject)
{
$branch = zget($extra, 'branchID', 0);
/* Get object paths of this execution. */
if(strpos(',story,case,', ",$linkObject,") !== false)
if(str_contains(',story,case,', ",$linkObject,"))
{
$paths = $this->dao->select('DISTINCT t3.' . $field)->from($table1)->alias('t1')
$table1 = TABLE_PROJECTSTORY;
$table2 = TABLE_STORY;
if($linkObject == 'case')
{
$table1 = TABLE_PROJECTCASE;
$table2 = TABLE_CASE;
}
$paths = $this->dao->select("t3.{$field}")->from($table1)->alias('t1')
->leftJoin($table2)->alias('t2')->on('t1.' . $linkObject . ' = t2.id')
->leftJoin(TABLE_MODULE)->alias('t3')->on('t2.module = t3.id')
->leftJoin(TABLE_PROJECT)->alias('t4')->on('t1.project = t4.id')
->where('(t1.project')->eq($executionID)
->orWhere('t4.project')->eq($executionID)->markRight(1)
->andWhere('t3.deleted')->eq(0)
->where('t3.deleted')->eq(0)
->andWhere('t2.deleted')->eq(0)
->andWhere("(t1.project = '{$executionID}' OR t4.project = '{$executionID}')")
->beginIF(isset($extra['branchID']) and $branch !== 'all')->andWhere('t2.branch')->eq($branch)->fi()
->fetchPairs();
->fetchPairs($field, $field);
}
elseif($linkObject == 'bug' and strpos(',project,execution,', ",{$this->app->tab},") !== false)
elseif($linkObject == 'bug' and str_contains(',project,execution,', ",{$this->app->tab},"))
{
$paths = $this->dao->select('DISTINCT t2.' . $field)->from(TABLE_BUG)->alias('t1')
$paths = $this->dao->select("t2.{$field}")->from(TABLE_BUG)->alias('t1')
->leftJoin(TABLE_MODULE)->alias('t2')->on('t1.module = t2.id')
->where('t1.deleted')->eq(0)
->andWhere('t2.deleted')->eq(0)
->beginIF(isset($extra['branchID']) and $branch !== 'all')->andWhere('t1.branch')->eq($branch)->fi()
->andWhere("t1.{$this->app->tab}")->eq($executionID)
->fetchPairs();
->fetchPairs($field, $field);
}
else
{
return array();
return $paths;
}
}
else
{
$productGroups = $this->dao->select('product,branch')->from(TABLE_PROJECTPRODUCT)->where('project')->eq($executionID)->fetchGroup('product', 'branch');
$modules = $this->dao->select('id,root,branch')->from(TABLE_MODULE)
->where('root')->in(array_keys($productGroups))
->andWhere('type')->eq('story')
->andWhere('deleted')->eq(0)
->fetchAll();
$modules = $this->dao->select('id,root,branch')->from(TABLE_MODULE)->where('root')->in(array_keys($productGroups))->andWhere('type')->eq('story')->andWhere('deleted')->eq(0)->fetchAll();
$paths = array();
foreach($modules as $module)
{
if(empty($module->branch)) $paths[$module->id] = $module->id;
@@ -1026,33 +1011,28 @@ class treeModel extends model
}
}
if(strpos(',case,bug,', ",$linkObject,") === false)
if(!str_contains(',case,bug,', ",$linkObject,"))
{
/* Add task paths of this execution.*/
$paths += $this->dao->select($field)->from(TABLE_MODULE)
->where('root')->eq($executionID)
->andWhere('type')->eq('task')
->andWhere('deleted')->eq(0)
->fetchPairs();
$paths += $this->dao->select($field)->from(TABLE_MODULE)->where('root')->eq($executionID)->andWhere('type')->eq('task')->andWhere('deleted')->eq(0)->fetchPairs($field, $field);
/* Add task paths of this execution for has existed. */
$paths += $this->dao->select('DISTINCT t1.' . $field)->from(TABLE_MODULE)->alias('t1')
$paths += $this->dao->select("t1.{$field}")->from(TABLE_MODULE)->alias('t1')
->leftJoin(TABLE_TASK)->alias('t2')->on('t1.id=t2.module')
->where('t2.module')->ne(0)
->andWhere('t2.execution')->eq($executionID)
->andWhere('t2.deleted')->eq(0)
->andWhere('t1.type')->eq('story')
->andWhere('t1.deleted')->eq(0)
->fetchPairs();
->fetchPairs($field, $field);
}
/* Get all modules from paths. */
foreach($paths as $path)
{
$modules = explode(',', $path);
foreach($modules as $module) $executionModules[$module] = $module;
foreach(explode(',', $path) as $module) $executionModules[$module] = $module;
}
return $executionModules;
return array_filter($executionModules);
}
/**
+48 -11
View File
@@ -4,6 +4,49 @@ include dirname(__FILE__, 5) . '/test/lib/init.php';
include dirname(__FILE__, 2) . '/tree.class.php';
su('admin');
$project = zdTable('project');
$project->id->range('1-30');
$project->type->range('sprint');
$projectProduct = zdTable('projectproduct');
$projectProduct->project->range('1-30');
$projectProduct->product->range('1-30');
$projectProduct->gen(20);
$story = zdTable('story');
$story->module->range('1-100');
$story->type->range('story');
$story->gen(20);
$projectStory = zdTable('projectstory');
$projectStory->project->range('1-15');
$projectStory->story->range('1-30');
$projectStory->gen(20);
$case = zdTable('case');
$case->execution->range('1-30');
$case->module->range('1-100');
$case->gen(20);
$projectCase = zdTable('projectcase');
$projectCase->project->range('1-30');
$projectCase->gen(20);
$task = zdTable('task');
$task->execution->range('1-30');
$task->module->range('1-100');
$task->gen(20);
$bug = zdTable('bug');
$bug->execution->range('1-30');
$bug->module->range('1-100');
$bug->gen(20);
$module = zdTable('module');
$module->root->range('1-30');
$module->type->range('story{30},task{30},case{30},bug{30}');
$module->gen(120);
/**
title=测试 treeModel->getTaskOptionMenu();
@@ -24,9 +67,8 @@ pid=1
测试获取 root 103 task目录 >> ,/,/正常产品3/产品模块12,/正常产品3/产品模块10,/模块7,/模块8,/模块9
*/
$root = array(1, 2, 3, 41, 42, 43, 101, 102, 103);
$productID = 1;
$startModule = 3021;
$root = array(0, 1, 2, 3, 4);
$startModule = 100;
$extra = 'allModule';
$tree = new treeTest();
@@ -35,11 +77,6 @@ r($tree->getTaskOptionMenuTest($root[0])) && p
r($tree->getTaskOptionMenuTest($root[1])) && p() && e(',/'); // 测试获取 root 2 task目录
r($tree->getTaskOptionMenuTest($root[2])) && p() && e(',/'); // 测试获取 root 3 task目录
r($tree->getTaskOptionMenuTest($root[3])) && p() && e(',/,/已关闭的正常产品31/产品模块122,/已关闭的正常产品31/产品模块124'); // 测试获取 root 41 task目录
r($tree->getTaskOptionMenuTest($root[4])) && p() && e(',/,/已关闭的正常产品32/产品模块126,/已关闭的正常产品32/产品模块128'); // 测试获取 root 42 task目录
r($tree->getTaskOptionMenuTest($root[5])) && p() && e(',/,/已关闭的正常产品33/产品模块132,/已关闭的正常产品33/产品模块130'); // 测试获取 root 43 task目录
r($tree->getTaskOptionMenuTest($root[6])) && p() && e(',/,/正常产品1/产品模块2,/正常产品1/产品模块4,/模块1,/模块1/执行子模块1,/模块2,/模块3'); // 测试获取 root 101 task目录
r($tree->getTaskOptionMenuTest($root[6], $productID)) && p() && e(',/,/正常产品1/产品模块2,/正常产品1/产品模块4,/模块1,/模块1/执行子模块1,/模块2,/模块3'); // 测试获取 root 101 product 1 task目录
r($tree->getTaskOptionMenuTest($root[6], $productID, $startModule)) && p() && e(',/,/正常产品1/产品模块2,/正常产品1/产品模块4,/模块1,/模块1/执行子模块1,/模块2,/模块3'); // 测试获取 root 101 product 1 startModule 3021 task目录
r($tree->getTaskOptionMenuTest($root[6], $productID, $startModule, $extra)) && p() && e(',/,/正常产品1/产品模块2,/正常产品1/产品模块4,/模块1,/模块1/执行子模块1,/模块2,/模块3'); // 测试获取 root 101 product 1 startModule 3021 allModule task目录
r($tree->getTaskOptionMenuTest($root[7])) && p() && e(',/,/正常产品2/产品模块6,/正常产品2/产品模块8,/模块4,/模块5,/模块6'); // 测试获取 root 102 task目录
r($tree->getTaskOptionMenuTest($root[8])) && p() && e(',/,/正常产品3/产品模块12,/正常产品3/产品模块10,/模块7,/模块8,/模块9'); // 测试获取 root 103 task目录
r($tree->getTaskOptionMenuTest($root[4])) && p() && e(',/,/已关闭的正常产品33/产品模块132,/已关闭的正常产品33/产品模块130'); // 测试获取 root 43 task目录
r($tree->getTaskOptionMenuTest($root[4], $startModule)) && p() && e(',/,/正常产品1/产品模块2,/正常产品1/产品模块4,/模块1,/模块1/执行子模块1,/模块2,/模块3'); // 测试获取 root 101 product 1 startModule 3021 task目录
r($tree->getTaskOptionMenuTest($root[4], $startModule, $extra)) && p() && e(',/,/正常产品1/产品模块2,/正常产品1/产品模块4,/模块1,/模块1/执行子模块1,/模块2,/模块3'); // 测试获取 root 101 product 1 startModule 3021 allModule task目录
+50 -35
View File
@@ -4,49 +4,64 @@ include dirname(__FILE__, 5) . '/test/lib/init.php';
include dirname(__FILE__, 2) . '/tree.class.php';
su('admin');
$project = zdTable('project');
$project->id->range('1-30');
$project->type->range('sprint');
$projectProduct = zdTable('projectproduct');
$projectProduct->project->range('1-30');
$projectProduct->product->range('1-30');
$projectProduct->gen(20);
$story = zdTable('story');
$story->module->range('1-100');
$story->type->range('story');
$story->gen(20);
$projectStory = zdTable('projectstory');
$projectStory->project->range('1-30');
$projectStory->story->range('1-30');
$projectStory->gen(20);
$case = zdTable('case');
$case->execution->range('1-30');
$case->module->range('1-100');
$case->gen(20);
$projectCase = zdTable('projectcase');
$projectCase->project->range('1-30');
$projectCase->gen(20);
$task = zdTable('task');
$task->execution->range('1-30');
$task->module->range('1-100');
$task->gen(20);
$bug = zdTable('bug');
$bug->execution->range('1-30');
$bug->module->range('1-100');
$bug->gen(20);
$module = zdTable('module');
$module->root->range('1-30');
$module->type->range('story{30},task{30},case{30},bug{30}');
$module->gen(120);
/**
title=测试 treeModel->getTaskTreeModules();
cid=1
pid=1
测试获取 execution 101 parent false story 的树 >> ,1822,1824,21,22,23,3021
测试获取 execution 102 parent false story 的树 >> ,1826,1828,24,25,26,3022
测试获取 execution 103 parent false story 的树 >> ,1830,1832,27,28,29,3023
测试获取 execution 104 parent false story 的树 >> ,1834,1836,30,31,32,3024
测试获取 execution 101 parent true story 的树 >> ,,1822,1824,21,22,23,3021
测试获取 execution 102 parent true story 的树 >> ,,1826,1828,24,25,26,23,3022
测试获取 execution 103 parent true story 的树 >> ,,1830,1832,27,28,29,25,3023
测试获取 execution 104 parent true story 的树 >> ,,1834,1836,30,31,32,27,3024
测试获取 execution 101 parent false case 的树 >> ,21,22,23,3021
测试获取 execution 102 parent false case 的树 >> ,24,25,26,3022
测试获取 execution 103 parent false case 的树 >> ,27,28,29,3023
测试获取 execution 104 parent false case 的树 >> ,30,31,32,3024
测试获取 execution 101 parent true case 的树 >> ,,21,22,23,3021
测试获取 execution 102 parent true case 的树 >> ,,24,25,26,23,3022
测试获取 execution 103 parent true case 的树 >> ,,27,28,29,25,3023
测试获取 execution 104 parent true case 的树 >> ,,30,31,32,27,3024
*/
$executionID = array(101, 102, 103, 104);
$executionID = array(1, 2, 3, 4);
$parent = array(false, true);
$linkObject = array('story', 'case');
$linkObject = array('story', 'case', 'bug', '');
$tree = new treeTest();
r($tree->getTaskTreeModulesTest($executionID[0], $parent[0], $linkObject[0])) && p() && e(',1822,1824,21,22,23,3021'); // 测试获取 execution 101 parent false story 的树
r($tree->getTaskTreeModulesTest($executionID[1], $parent[0], $linkObject[0])) && p() && e(',1826,1828,24,25,26,3022'); // 测试获取 execution 102 parent false story 的树
r($tree->getTaskTreeModulesTest($executionID[2], $parent[0], $linkObject[0])) && p() && e(',1830,1832,27,28,29,3023'); // 测试获取 execution 103 parent false story 的树
r($tree->getTaskTreeModulesTest($executionID[3], $parent[0], $linkObject[0])) && p() && e(',1834,1836,30,31,32,3024'); // 测试获取 execution 104 parent false story 的树
r($tree->getTaskTreeModulesTest($executionID[0], $parent[1], $linkObject[0])) && p() && e(',,1822,1824,21,22,23,3021'); // 测试获取 execution 101 parent true story 的树
r($tree->getTaskTreeModulesTest($executionID[1], $parent[1], $linkObject[0])) && p() && e(',,1826,1828,24,25,26,23,3022'); // 测试获取 execution 102 parent true story 的树
r($tree->getTaskTreeModulesTest($executionID[2], $parent[1], $linkObject[0])) && p() && e(',,1830,1832,27,28,29,25,3023'); // 测试获取 execution 103 parent true story 的树
r($tree->getTaskTreeModulesTest($executionID[3], $parent[1], $linkObject[0])) && p() && e(',,1834,1836,30,31,32,27,3024'); // 测试获取 execution 104 parent true story 的树
r($tree->getTaskTreeModulesTest($executionID[0], $parent[0], $linkObject[1])) && p() && e(',21,22,23,3021'); // 测试获取 execution 101 parent false case 的树
r($tree->getTaskTreeModulesTest($executionID[1], $parent[0], $linkObject[1])) && p() && e(',24,25,26,3022'); // 测试获取 execution 102 parent false case 的树
r($tree->getTaskTreeModulesTest($executionID[2], $parent[0], $linkObject[1])) && p() && e(',27,28,29,3023'); // 测试获取 execution 103 parent false case 的树
r($tree->getTaskTreeModulesTest($executionID[3], $parent[0], $linkObject[1])) && p() && e(',30,31,32,3024'); // 测试获取 execution 104 parent false case 的树
r($tree->getTaskTreeModulesTest($executionID[0], $parent[1], $linkObject[1])) && p() && e(',,21,22,23,3021'); // 测试获取 execution 101 parent true case 的树
r($tree->getTaskTreeModulesTest($executionID[1], $parent[1], $linkObject[1])) && p() && e(',,24,25,26,23,3022'); // 测试获取 execution 102 parent true case 的树
r($tree->getTaskTreeModulesTest($executionID[2], $parent[1], $linkObject[1])) && p() && e(',,27,28,29,25,3023'); // 测试获取 execution 103 parent true case 的树
r($tree->getTaskTreeModulesTest($executionID[3], $parent[1], $linkObject[1])) && p() && e(',,30,31,32,27,3024'); // 测试获取 execution 104 parent true case 的树
r($tree->getTaskTreeModulesTest($executionID[0], $parent[0], $linkObject[0])) && p() && e('1,31'); // 测试获取 execution 1 parent false story 的树
r($tree->getTaskTreeModulesTest($executionID[1], $parent[1], $linkObject[0])) && p() && e('2,32'); // 测试获取 execution 2 parent true story 的树
r($tree->getTaskTreeModulesTest($executionID[2], $parent[0], $linkObject[2])) && p() && e('3'); // 测试获取 execution 3 parent false bug 的树
r($tree->getTaskTreeModulesTest($executionID[3], $parent[0], $linkObject[1])) && p() && e('4'); // 测试获取 execution 4 parent false case 的树
r($tree->getTaskTreeModulesTest($executionID[3], $parent[0], $linkObject[3])) && p() && e('4,34'); // 测试获取 execution 4 parent false 的树
+15 -11
View File
@@ -4,34 +4,38 @@ include dirname(__FILE__, 5) . '/test/lib/init.php';
include dirname(__FILE__, 2) . '/tree.class.php';
su('admin');
$product = zdTable('product');
$product->createdVersion->range('4.0,12.5.3{30}');
$product->gen(10);
$project = zdTable('project');
$project->id->range('1-50');
$project->openedVersion->range('4.0,12.5.3{30}');
$project->gen(10);
/**
title=测试 treeModel->isMergeModule();
cid=1
pid=1
测试检查root 1 type bug 合并模块版本 >> 1
测试检查root 1 type bug 合并模块版本 >> 2
测试检查root 2 type bug 合并模块版本 >> 1
测试检查root 3 type bug 合并模块版本 >> 1
测试检查root 1 type case 合并模块版本 >> 1
测试检查root 1 type case 合并模块版本 >> 2
测试检查root 2 type case 合并模块版本 >> 1
测试检查root 3 type case 合并模块版本 >> 1
测试检查root 101 type task 合并模块版本 >> 1
测试检查root 102 type task 合并模块版本 >> 1
测试检查root 103 type task 合并模块版本 >> 1
测试检查root 1 type task 合并模块版本 >> 2
*/
$root = array(1, 2, 3, 101, 102, 103);
$root = array(1, 2, 3, 4);
$type = array('bug', 'case', 'task');
$tree = new treeTest();
r($tree->isMergeModuleTest($root[0], $type[0])) && p() && e('1'); // 测试检查root 1 type bug 合并模块版本
r($tree->isMergeModuleTest($root[0], $type[0])) && p() && e('2'); // 测试检查root 1 type bug 合并模块版本
r($tree->isMergeModuleTest($root[1], $type[0])) && p() && e('1'); // 测试检查root 2 type bug 合并模块版本
r($tree->isMergeModuleTest($root[2], $type[0])) && p() && e('1'); // 测试检查root 3 type bug 合并模块版本
r($tree->isMergeModuleTest($root[0], $type[1])) && p() && e('1'); // 测试检查root 1 type case 合并模块版本
r($tree->isMergeModuleTest($root[0], $type[1])) && p() && e('2'); // 测试检查root 1 type case 合并模块版本
r($tree->isMergeModuleTest($root[1], $type[1])) && p() && e('1'); // 测试检查root 2 type case 合并模块版本
r($tree->isMergeModuleTest($root[2], $type[1])) && p() && e('1'); // 测试检查root 3 type case 合并模块版本
r($tree->isMergeModuleTest($root[3], $type[2])) && p() && e('1'); // 测试检查root 101 type task 合并模块版本
r($tree->isMergeModuleTest($root[4], $type[2])) && p() && e('1'); // 测试检查root 102 type task 合并模块版本
r($tree->isMergeModuleTest($root[5], $type[2])) && p() && e('1'); // 测试检查root 103 type task 合并模块版本
r($tree->isMergeModuleTest($root[0], $type[2])) && p() && e('2'); // 测试检查root 4 type task 合并模块版本
+6 -9
View File
@@ -100,15 +100,14 @@ class treeTest
* Test create an option menu of task in html.
*
* @param int $rootID
* @param int $productID
* @param int $startModule
* @param string $extra
* @access public
* @return string
*/
public function getTaskOptionMenuTest($rootID, $productID = 0, $startModule = 0, $extra = '')
public function getTaskOptionMenuTest($rootID, $startModule = 0, $extra = '')
{
$objects = $this->objectModel->getTaskOptionMenu($rootID, $productID = 0, $startModule = 0, $extra = '');
$objects = $this->objectModel->getTaskOptionMenu($rootID, $startModule, $extra);
if(dao::isError()) return dao::getError();
@@ -192,15 +191,13 @@ class treeTest
* @access public
* @return string
*/
public function getTaskTreeModulesTest($executionID, $parent = false, $linkObject = 'story')
public function getTaskTreeModulesTest(int $executionID, bool $parent = false, string $linkObject = 'story', array $extra = array()): string
{
$objects = $this->objectModel->getTaskTreeModules($executionID, $parent, $linkObject);
$this->objectModel->app->tab = 'execution';
$objects = $this->objectModel->getTaskTreeModules($executionID, $parent, $linkObject, $extra);
if(dao::isError()) return dao::getError();
$ids = '';
foreach($objects as $object) $ids .= ',' . $object;
return $ids;
return implode(',', $objects);
}
/**