| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393 |
- <?php
- /**
- * The control file of task module of ZenTaoPMS.
- *
- * @copyright Copyright 2009-2023 禅道软件(青岛)有限公司(ZenTao Software (Qingdao) Co., Ltd. www.cnezsoft.com)
- * @license ZPL(http://zpl.pub/page/zplv12.html) or AGPL(https://www.gnu.org/licenses/agpl-3.0.en.html)
- * @author Chunsheng Wang <chunsheng@cnezsoft.com>
- * @package task
- * @version $Id: control.php 5106 2013-07-12 01:28:54Z chencongzhi520@gmail.com $
- * @link https://www.zentao.net
- */
- class task extends control
- {
- /**
- * Construct function, load model of project and story modules.
- *
- * @access public
- * @return void
- */
- public function __construct($module = '', $method = '')
- {
- parent::__construct($module, $method);
- $this->loadModel('project');
- $this->loadModel('execution');
- $this->loadModel('story');
- $this->loadModel('tree');
- }
- /**
- * 创建一个任务。
- * Create a task.
- *
- * @param int $executionID
- * @param int $storyID
- * @param int $moduleID
- * @param int $taskID
- * @param int $todoID
- * @param string $cardPosition
- * @param int $bugID
- * @access public
- * @return void
- */
- public function create($executionID = 0, $storyID = 0, $moduleID = 0, $taskID = 0, $todoID = 0, $cardPosition = '', $bugID = 0)
- {
- /* Analytic parameter. */
- $cardPosition = str_replace(array(',', ' '), array('&', ''), $cardPosition);
- parse_str($cardPosition, $output);
- $this->session->set('executionStoryList', $this->app->getURI(true), 'execution');
- /* Set menu and get execution information. */
- $executionID = $this->taskZen->setMenu($executionID);
- $execution = $this->execution->getById($executionID);
- /* If you do not have permission to access any execution, go to the create execution page. */
- if(!$this->execution->checkPriv($executionID)) $this->locate($this->createLink('execution', 'create'));
- /* Check whether the execution has permission to create tasks. */
- if($this->taskZen->isLimitedInExecution($executionID)) return $this->send(array('load' => array('locate' => $this->createLink('execution', 'task', "executionID={$executionID}"), 'alert' => sprintf($this->lang->task->createDenied, $execution->multiple ? $this->lang->executionCommon : $this->lang->projectCommon))));
- /* Submit the data process after create the task form. */
- if(!empty($_POST))
- {
- $taskData = $this->taskZen->buildTaskForCreate($this->post->execution ? (int)$this->post->execution : $executionID);
- if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
- $this->dao->begin();
- if($this->post->type == 'test' && $this->post->selectTestStory == 'on')
- {
- /* Prepare to create the data for the test subtask and to check the data format. */
- $testTasks = $this->taskZen->buildTestTasksForCreate($taskData->execution);
- if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
- $taskIdList = $this->task->createTaskOfTest($taskData, $testTasks);
- }
- elseif($this->post->type == 'affair')
- {
- $taskIdList = $this->task->createTaskOfAffair($taskData, is_array($this->post->assignedTo) ? $this->post->assignedTo : array($this->post->assignedTo));
- }
- elseif($this->post->multiple)
- {
- $teamData = form::data($this->config->task->form->team->create)->get();
- $taskIdList = $this->task->createMultiTask($taskData, $teamData);
- }
- else
- {
- $taskIdList = $this->task->create($taskData);
- }
- if(dao::isError())
- {
- $this->dao->rollBack();
- return $this->send(array('result' => 'fail', 'message' => dao::getError()));
- }
- /* Update other data related to the task after it is created. */
- $columnID = isset($output['columnID']) ? (int)$output['columnID'] : 0;
- $taskIdList = (array)$taskIdList;
- $taskData->id = current($taskIdList);
- $this->task->afterCreate($taskData, $taskIdList, $bugID, $todoID);
- if($this->post->lane) $this->task->updateKanbanData($taskData->execution, $taskIdList, (int)$this->post->lane, $columnID);
- setCookie("lastTaskModule", (string)$this->post->module, $this->config->cookieLife, $this->config->webRoot, '', $this->config->cookieSecure, true);
- if(!empty($_POST['fileList']))
- {
- $fileList = $this->post->fileList;
- if($fileList) $fileList = json_decode($fileList, true);
- $this->loadModel('file')->saveDefaultFiles($fileList, 'task', $taskIdList);
- }
- /* Get the information returned after a task is created. */
- $response = $this->taskZen->responseAfterCreate($taskData, $execution, $this->post->after ? $this->post->after : '');
- return $this->send($response);
- }
- /* Shows the variables needed to create the task page. */
- $this->taskZen->assignCreateVars($execution, $storyID, $moduleID, $taskID, $todoID, $bugID, $output, $cardPosition);
- }
- /**
- * 批量创建任务。
- * Batch create tasks.
- *
- * @param int $executionID
- * @param int $storyID
- * @param int $moduleID
- * @param int $taskID
- * @param string $cardPosition
- * @access public
- * @return void
- */
- public function batchCreate($executionID, $storyID = 0, $moduleID = 0, $taskID = 0, $cardPosition = '')
- {
- /* Analytic parameter. */
- $cardPosition = str_replace(array(',', ' '), array('&', ''), $cardPosition);
- parse_str($cardPosition, $output);
- $this->taskZen->setMenu($executionID);
- $execution = $this->execution->getById($executionID);
- /* Check whether the execution has permission to create tasks. */
- if($this->taskZen->isLimitedInExecution($executionID)) return $this->send(array('load' => array('locate' => $this->createLink('execution', 'task', "executionID={$executionID}"), 'alert' => sprintf($this->lang->task->createDenied, $execution->multiple ? $this->lang->executionCommon : $this->lang->projectCommon))));
- if(!empty($_POST))
- {
- $parent = $taskID > 0 ? $this->task->fetchById($taskID) : null;
- /* Process the request data for the batch create tasks. */
- $taskData = $this->taskZen->buildTasksForBatchCreate($execution, $taskID, $output);
- if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
- $taskIdList = $this->task->batchCreate($taskData, $output);
- if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
- /* Update other data related to the task after it is created. */
- $this->task->afterBatchCreate($taskIdList, $parent);
- if(!isset($output['laneID']) || !isset($output['columnID'])) $this->loadModel('kanban')->updateLane($executionID, 'task');
- $response = $this->taskZen->responseAfterbatchCreate($taskIdList, $execution);
- return $this->send($response);
- }
- $this->taskZen->buildBatchCreateForm($execution, $storyID, $moduleID, $taskID, $output);
- }
- /**
- * 编辑一个任务。
- * Edit a task.
- *
- * @param int $taskID
- * @param string $from ''|taskkanban
- * @access public
- * @return void
- */
- public function edit($taskID, $from = '')
- {
- $this->taskZen->commonAction($taskID);
- if(!empty($_POST))
- {
- /* Prepare and check data. */
- $task = form::data($this->config->task->form->edit)->add('id', $taskID)->get();
- $task = $this->taskZen->buildTaskForEdit($task);
- if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
- /* For team task. */
- $teamData = $this->post->team ? form::data($this->config->task->form->team->edit)->get() : new stdclass();
- /* Update task. */
- $changes = $this->task->update($task, $teamData);
- if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
- /* Execute hooks and synchronize the status of related objects. */
- $message = $this->executeHooks($taskID);
- $message = $message ?: $this->lang->saveSuccess;
- if($task->status == 'doing') $this->loadModel('common')->syncPPEStatus($taskID);
- $response = $this->taskZen->responseAfterEdit($taskID, $from, $changes, $message);
- return $this->send($response);
- }
- $this->taskZen->buildEditForm($taskID);
- }
- /**
- * 批量编辑任务。
- * Batch edit tasks.
- *
- * @param int $executionID
- * @param string $from
- * @access public
- * @return void
- */
- public function batchEdit($executionID = 0, $from = '')
- {
- $this->taskZen->setMenu($executionID);
- if($this->post->name)
- {
- /* Batch edit tasks. */
- $taskData = form::batchData()->get();
- $oldTasks = $taskData ? $this->task->getByIdList(array_keys($taskData)) : array();
- $taskData = $this->taskZen->buildTasksForBatchEdit($taskData, $oldTasks);
- if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
- $allChanges = $this->task->batchUpdate($taskData);
- if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
- $this->task->afterBatchUpdate($taskData, $oldTasks);
- if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
- $response = $this->taskZen->responseAfterBatchEdit($allChanges);
- return $this->send($response);
- }
- if(!$this->post->taskIdList)
- {
- $url = !empty($this->session->taskList) ? $this->session->taskList : $this->createLink('execution', 'all');
- $this->locate($url);
- }
- if($this->app->tab == 'my' && $this->config->vision == 'rnd')
- {
- $this->loadModel('my');
- if($from == 'work' || $from == 'contribute')
- {
- $this->lang->my->menu->{$from}['subModule'] = 'task';
- $this->lang->my->menu->{$from}['subMenu']->task['subModule'] = 'task';
- }
- }
- $this->taskZen->assignBatchEditVars($executionID);
- }
- /**
- * 指派任务。
- * Update assign of task.
- *
- * @param int $executionID
- * @param int $taskID
- * @param string $from ''|taskkanban
- * @access public
- * @return void
- */
- public function assignTo($executionID, $taskID, $from = '')
- {
- $this->taskZen->commonAction($taskID);
- $task = $this->task->getByID($taskID);
- if(!empty($task->team) && $task->mode == 'multi' && strpos('done,cancel,closed', $task->status) === false)
- {
- echo $this->fetch('task', 'manageTeam', "executionID=$executionID&taskID=$taskID&from=$from");
- return;
- }
- if(!empty($_POST))
- {
- $task = form::data($this->config->task->form->assign, $taskID)->add('id', $taskID)->get();
- $this->task->assign($task);
- if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
- $message = $this->executeHooks($taskID);
- $message = $message ?: $this->lang->saveSuccess;
- $response = $this->taskZen->responseAfterAssignTo($taskID, $from, $message);
- return $this->send($response);
- }
- $this->view->task = $task;
- $this->view->title = $this->view->execution->name . $this->lang->hyphen . $this->lang->task->assign;
- $this->taskZen->buildUsersAndMembersToForm($executionID, $taskID);
- $this->display();
- }
- /**
- * 批量更改任务所属模块。
- * Batch change the module of task.
- *
- * @param int $moduleID
- * @access public
- * @return void
- */
- public function batchChangeModule($moduleID)
- {
- if($this->post->taskIdList)
- {
- $taskIdList = array_unique($this->post->taskIdList);
- $this->task->batchChangeModule($taskIdList, $moduleID);
- if(!dao::isError()) $this->loadModel('score')->create('ajax', 'batchOther');
- }
- if(dao::isError()) return array('result' => 'fail', 'message' => dao::getError());
- return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'load' => true));
- }
- /**
- * 批量指派任务。
- * Batch update assign of task.
- *
- * @param int $executionID
- * @param string $assignedTo
- * @access public
- * @return void
- */
- public function batchAssignTo($executionID, $assignedTo)
- {
- if($this->post->taskIdList)
- {
- $taskData = $this->taskZen->buildTasksForBatchAssignTo($this->post->taskIdList, $assignedTo);
- foreach($taskData as $task)
- {
- $this->task->assign($task);
- if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
- }
- if(!dao::isError()) $this->loadModel('score')->create('ajax', 'batchOther');
- }
- return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'load' => $this->createLink('execution', 'task', "executionID={$executionID}")));
- }
- /**
- * 查看一个任务。View a task.
- *
- * @param int $taskID
- * @access public
- * @return void
- */
- public function view($taskID)
- {
- $task = $this->task->getById($taskID, true, $vision = 'all'); // TODO: $vision is for compatibling with viewing drill data.
- if(!$task)
- {
- if(defined('RUN_MODE') && RUN_MODE == 'api') return $this->send(array('status' => 'fail', 'code' => 404, 'message' => '404 Not found'));
- return $this->sendError($this->lang->notFound, $this->config->vision == 'lite' ? $this->createLink('project', 'index') : $this->createLink('execution', 'all'));
- }
- if(!$this->loadModel('common')->checkPrivByObject('execution', $task->execution)) return $this->sendError($this->lang->execution->accessDenied, $this->createLink('execution', 'all'));
- /* 为视图设置常用的公共变量和设置菜单为任务所属执行. Set common variables to view and set menu to the execution of the task. */
- $this->session->project = $task->project;
- $this->taskZen->commonAction($taskID, $vision = 'all');
- $this->session->set('executionList', $this->app->getURI(true), 'execution'); // This allow get var of session as `$_SESSION['app-execution']['executionList']`.
- $execution = $this->view->execution ?? $this->execution->getById($task->execution);
- $isModalOrApi = helper::isAjaxRequest('modal') || (defined('RUN_MODE') && RUN_MODE == 'api');
- if(!$isModalOrApi && $execution->type == 'kanban')
- {
- helper::setcookie('taskToOpen', (string)$taskID);
- return $this->send(array('load' => $this->createLink('execution', 'kanban', "executionID=$execution->id")));
- }
- /* 检查和设置任务的相关信息如果它来自缺陷或需求。Check and set related info if the task came from bug or story. */
- if($task->fromBug != 0)
- {
- $bug = $this->loadModel('bug')->getById($task->fromBug);
- $task->bugSteps = '';
- if($bug)
- {
- $task->bugSteps = $this->loadModel('file')->setImgSize($bug->steps);
- foreach($bug->files as $file) $task->files[] = $file;
- }
- $this->view->fromBug = $bug;
- if($this->app->tab == 'qa') $this->view->productID = $bug->product;
- }
- else
- {
- $story = $this->story->getById($task->story, $task->storyVersion);
- $task->storySpec = empty($story) ? '' : $this->loadModel('file')->setImgSize($story->spec);
- $task->storyVerify = empty($story) ? '' : $this->loadModel('file')->setImgSize($story->verify);
- $task->storyFiles = zget($story, 'files', array());
- $task->storyTitle = !empty($story) ? $story->title : '';
- }
- if($task->team) $this->lang->task->assign = $this->lang->task->transfer;
- $this->lang->task->statusList['changed'] = $this->lang->task->storyChange;
- $this->view->title = "TASK#$task->id $task->name / $execution->name";
- $this->view->execution = $execution;
- $this->view->task = $task;
- $this->view->actions = $this->loadModel('action')->getList('task', $taskID);
- $this->view->users = $this->loadModel('user')->getPairs('noletter');
- $this->view->preAndNext = $this->loadModel('common')->getPreAndNextObject('task', $taskID);
- $this->view->product = $this->tree->getProduct($task->module);
- $this->view->modulePath = $this->tree->getParents($task->module);
- $this->view->linkMRTitles = $this->loadModel('mr')->getLinkedMRPairs($taskID, 'task');
- $this->view->linkCommits = $this->loadModel('repo')->getCommitsByObject($taskID, 'task');
- $this->view->linkedBugs = $this->loadModel('bug')->getLinkedBugsByTaskID($taskID);
- $this->view->hasGitRepo = $this->taskZen->checkGitRepo($execution->id);
- $this->display();
- }
- /**
- * 确认需求变更。
- * Confirm story change.
- *
- * @param int $taskID
- * @access public
- * @return void
- */
- public function confirmStoryChange($taskID)
- {
- $this->task->confirmStoryChange($taskID);
- $message = $this->executeHooks($taskID);
- return $this->send(array('result' => 'success', 'message' => $message ?: $this->lang->saveSuccess, 'load' => true));
- }
- /**
- * 开始一个任务。
- * Start a task.
- *
- * @param int $taskID
- * @param string $cardPosition
- * @access public
- * @return void
- */
- public function start($taskID, $cardPosition = '')
- {
- /* Analytic parameter. */
- $cardPosition = str_replace(array(',', ' '), array('&', ''), $cardPosition);
- parse_str($cardPosition, $output);
- /* Common actions of task module and task. */
- $this->taskZen->commonAction($taskID);
- $task = $this->task->getById($taskID);
- $currentTeam = !empty($task->team) ? $this->task->getTeamByAccount($task->team) : '';
- /* Submit the data process after start the task form. */
- if(!empty($_POST))
- {
- /* Prepare the data information before start the task. */
- $taskData = $this->taskZen->buildTaskForStart($task);
- if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
- /* Record task effort. */
- $effort = $this->buildEffortForStart($task, $taskData);
- if($this->post->comment) $effort->work = $this->post->comment;
- if($effort->consumed > 0) $effortID = $this->task->addTaskEffort($effort);
- if($task->mode == 'linear' && !empty($effortID)) $this->task->updateEffortOrder($effortID, $currentTeam->order);
- if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
- /* Start a task. */
- $changes = $this->task->start($task, $taskData);
- if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
- $message = $this->executeHooks($task->id);
- $message = $message ?: $this->lang->saveSuccess;
- /* Update other data related to the task after it is started. */
- $result = $this->task->afterStart($task, $changes, (float)$this->post->left, $output, $message);
- if(is_array($result)) $this->send($result);
- /* Get the information returned after a task is started. */
- $from = zget($output, 'from');
- $response = $this->taskZen->responseAfterChangeStatus($task, $from, $message);
- return $this->send($response);
- }
- /* Shows the variables needed to start the task page. */
- $assignedTo = empty($task->assignedTo) ? $this->app->user->account : $task->assignedTo;
- $this->view->title = $this->view->execution->name . $this->lang->hyphen .$this->lang->task->start;
- $this->view->assignedTo = !empty($task->team) ? $this->task->getAssignedTo4Multi($task->team, $task) : $assignedTo;
- $this->view->canRecordEffort = $this->task->canOperateEffort($task);
- $this->view->currentTeam = $currentTeam;
- $this->taskZen->buildUsersAndMembersToForm($task->execution, $taskID);
- $this->display();
- }
- /**
- * 任务查看工时/新增工时的方法。
- * View and add task's workhour.
- *
- * @param int $taskID
- * @param string $from
- * @param string $orderBy
- * @access public
- * @return void
- */
- public function recordWorkhour($taskID, $from = '', $orderBy = '')
- {
- $this->taskZen->commonAction($taskID);
- if(!empty($_POST))
- {
- $workhour = form::batchData($this->config->task->form->recordWorkhour)->get();
- $changes = $this->task->recordWorkhour($taskID, $workhour);
- if(dao::isError()) return $this->send(array('message' => dao::getError(), 'result' => 'fail'));
- /* 更新任务对应的项目集、项目和执行的状态。*/
- $this->loadModel('common')->syncPPEStatus($taskID);
- $task = $this->task->getById($taskID);
- $response = $this->taskZen->responseAfterRecord($task, $changes, $from);
- return $this->send($response);
- }
- $this->taskZen->buildRecordForm($taskID, $from, $orderBy);
- }
- /**
- * 编辑一条日志。
- * Edit a effort.
- *
- * @param int $effortID
- * @access public
- * @return void
- */
- public function editEffort($effortID)
- {
- $effort = $this->task->getEffortByID($effortID);
- if(!empty($_POST))
- {
- if($this->config->edition != 'open') $oldEffort = $this->loadModel('effort')->fetchByID($effortID);
- $this->lang->task->consumed = $this->lang->task->currentConsumed;
- $formData = form::data($this->config->task->form->editEffort)->add('id', $effortID)->get();
- $changes = $this->task->updateEffort($formData);
- if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
- $actionID = $this->loadModel('action')->create('task', $effort->objectID, 'EditEffort', $this->post->work);
- $this->action->logHistory($actionID, $changes);
- if($this->config->edition != 'open')
- {
- $effort = $this->effort->fetchByID($effortID);
- $actionID = $this->action->create('effort', $effortID, 'edited');
- $this->action->logHistory($actionID, common::createChanges($oldEffort, $effort));
- }
- $url = $this->createLink($this->app->rawModule, 'recordWorkhour', "taskID={$effort->objectID}");
- return $this->send(array(
- 'result' => 'success',
- 'message' => $this->lang->saveSuccess,
- 'callback' => "loadModal('$url')"
- ));
- }
- $this->view->title = $this->lang->task->editEffort;
- $this->view->effort = $effort;
- $this->view->task = $this->task->getByID($effort->objectID);
- $this->display();
- }
- /**
- * 删除任务工时。Delete the work hour from the task.
- *
- * @param int $effortID
- * @param string $confirm
- * @access public
- * @return void
- */
- public function deleteWorkhour($effortID, $confirm = 'no')
- {
- $effort = $this->task->getEffortByID($effortID);
- $taskID = $effort->objectID;
- $task = $this->task->getById($taskID);
- /* Show a confirm message if the task has no consumed effort. */
- if($confirm == 'no' && $task->consumed - $effort->consumed == 0)
- {
- $formUrl = $this->createLink('task', 'deleteWorkhour', "effortID=$effortID&confirm=yes");
- return $this->send(array('result' => 'fail', 'callback' => "zui.Modal.confirm('{$this->lang->task->confirmDeleteLastEffort}').then((res) => {if(res) $.ajaxSubmit({url: '$formUrl'});});"));
- }
- $changes = $this->task->deleteWorkhour($effortID);
- if(dao::isError() || empty($changes)) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
- $actionID = $this->loadModel('action')->create('task', $taskID, 'DeleteEstimate');
- $this->action->logHistory($actionID, $changes);
- /* Delete task burn. */
- if($this->config->edition != 'open')
- {
- $this->dao->update(TABLE_BURN)
- ->set("`consumed` = `consumed` - {$effort->consumed}")
- ->where('task')->eq($taskID)
- ->andWhere('date')->eq($effort->date)
- ->exec();
- }
- /* The task status will be set to wait as the consumed effort is set to 0. */
- if($task->consumed - $effort->consumed == 0) $this->action->create('task', $taskID, 'Adjusttasktowait');
- return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'callback' => "loadModal('" . inLink('recordworkhour', "taskID={$taskID}") . "', '#modal-record-hours-task-{$taskID}')"));
- }
- /**
- * 完成任务操作。
- * Finish a task.
- *
- * @param int $taskID
- * @param string $extra
- * @access public
- * @return void
- */
- public function finish($taskID, $extra = '')
- {
- $extra = str_replace(array(',', ' '), array('&', ''), $extra);
- parse_str($extra, $output);
- $this->taskZen->commonAction($taskID);
- $task = $this->view->task;
- $currentTeam = !empty($task->team) ? $this->task->getTeamByAccount($task->team) : '';
- $canRecordEffort = $this->task->canOperateEffort($task);
- if(!$canRecordEffort)
- {
- $deniedNotice = sprintf($this->lang->task->deniedNotice, $this->lang->task->teamMember, $this->lang->task->finish);
- if($task->assignedTo != $this->app->user->account && $task->mode == 'linear') $deniedNotice = sprintf($this->lang->task->deniedNotice, $task->assignedToRealName, $this->lang->task->finish);
- $this->view->deniedNotice = $deniedNotice;
- }
- if(!empty($_POST))
- {
- if(!$canRecordEffort) return $this->send(array('result' => 'fail', 'message' => $deniedNotice));
- $taskData = $this->taskZen->buildTaskForFinish($task);
- if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
- if($task->mode == 'linear' && $taskData->finishedBy != $task->assignedTo) return $this->send(array('result' => 'fail', 'message' => $this->lang->task->error->finishedBy));
- /* Get and record estimate for task. */
- $effort = $this->taskZen->buildEffortForFinish($task, $taskData);
- if($effort->consumed > 0) $effortID = $this->task->addTaskEffort($effort);
- if($task->mode == 'linear' && !empty($effortID)) $this->task->updateEffortOrder($effortID, isset($currentTeam->order) ? $currentTeam->order : 1);
- if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
- $changes = $this->task->finish($task, $taskData);
- if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
- $message = $this->executeHooks($taskID);
- $message = $message ?: $this->lang->saveSuccess;
- /* Update other data related to the task after it is started. */
- $result = $this->task->afterStart($task, $changes, 0, $output, $message);
- if(is_array($result)) return $this->send($result);
- if($taskData->status == 'done') $this->loadModel('score')->create('task', 'finish', $task->id);
- if($this->config->edition != 'open' && $task->feedback) $this->loadModel('feedback')->updateStatus('task', $task->feedback, $taskData->status, $task->status, $task->id);
- /* Get the information returned after a task is started. */
- $from = zget($output, 'from');
- $response = $this->taskZen->responseAfterChangeStatus($task, $from, $message);
- return $this->send($response);
- }
- $task = $this->view->task;
- $task->nextBy = $task->openedBy;
- if(!empty($task->team))
- {
- $task->nextBy = $this->task->getAssignedTo4Multi($task->team, $task, 'next');
- $task->myConsumed = zget($currentTeam, 'consumed', 0);
- }
- $this->taskZen->buildUsersAndMembersToForm($task->execution, $taskID);
- $this->view->title = $this->view->execution->name . $this->lang->hyphen .$this->lang->task->finish;
- $this->view->canRecordEffort = $canRecordEffort;
- $this->display();
- }
- /**
- * 暂停任务。
- * Pause task.
- *
- * @param int $taskID
- * @param string $extra
- * @access public
- * @return void
- */
- public function pause($taskID, $extra = '')
- {
- $this->taskZen->commonAction($taskID);
- $extra = str_replace(array(',', ' '), array('&', ''), $extra);
- parse_str($extra, $output);
- if(!empty($_POST))
- {
- $oldTask = $this->task->getByID($taskID);
- /* Init task data. */
- $task = form::data($this->config->task->form->pause, $taskID)->add('id', $taskID)->get();
- /* Pause task. */
- $changes = $this->task->pause($task, $output);
- if(dao::isError()) return array('result' => 'fail', 'message' => dao::getError());
- /* Record log. */
- if($this->post->comment != '' || !empty($changes))
- {
- $actionID = $this->loadModel('action')->create('task', $taskID, 'Paused', $this->post->comment);
- $this->action->logHistory($actionID, $changes);
- }
- $message = $this->executeHooks($taskID);
- $message = $message ?: $this->lang->saveSuccess;
- /* Get response after the suspended task. */
- $from = zget($output, 'from');
- $response = $this->taskZen->responseAfterChangeStatus($oldTask, $from, $message);
- return $this->send($response);
- }
- /* Show the variables associated. */
- $this->view->title = $this->view->execution->name . $this->lang->hyphen .$this->lang->task->pause;
- $this->view->users = $this->loadModel('user')->getPairs('noletter');
- $this->display();
- }
- /**
- * 重新开始一个任务。
- * Restart a task.
- *
- * @param int $taskID
- * @param string $from
- * @access public
- * @return void
- */
- public function restart($taskID, $from = '')
- {
- /* Common actions of task module and task. */
- $this->taskZen->commonAction($taskID);
- $task = $this->task->getById($taskID);
- $account = $this->app->user->account;
- $currentTeam = !empty($task->team) ? $this->task->getTeamByAccount($task->team, $account, array()) : '';
- if(!empty($_POST))
- {
- /* Prepare the data information before restart the task. */
- $taskData = $this->taskZen->buildTaskForStart($task);
- if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
- /* Record task effort. */
- $effort = $this->taskZen->buildEffortForStart($task, $taskData);
- if($this->post->comment) $effort->work = $this->post->comment;
- if($effort->consumed > 0) $effortID = $this->task->addTaskEffort($effort);
- if($task->mode == 'linear' && !empty($effortID)) $this->task->updateEffortOrder($effortID, $currentTeam->order);
- if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
- /* Restart a task. */
- $changes = $this->task->start($task, $taskData);
- if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
- $message = $this->executeHooks($taskID);
- $message = $message ?: $this->lang->saveSuccess;
- $result = $this->task->afterStart($task, $changes, (float)$this->post->left, array(), $message);
- if(is_array($result)) $this->send($result);
- $response = $this->taskZen->responseAfterChangeStatus($task, $from, $message);
- return $this->send($response);
- }
- $this->view->title = $this->view->execution->name . $this->lang->hyphen .$this->lang->task->restart;
- $this->view->users = $this->loadModel('user')->getPairs('noletter');
- $this->view->members = $this->loadModel('user')->getTeamMemberPairs($task->execution, 'execution', 'nodeleted');
- $this->view->assignedTo = $task->assignedTo == '' ? $this->app->user->account : $task->assignedTo;
- $this->view->canRecordEffort = $this->task->canOperateEffort($task);
- $this->view->currentTeam = $currentTeam;
- $this->display();
- }
- /**
- * 关闭一个任务。
- * Close a task.
- *
- * @param int $taskID
- * @param string $cardPosition
- * @access public
- * @return void
- */
- public function close($taskID, $cardPosition = '')
- {
- $cardPosition = str_replace(array(',', ' '), array('&', ''), $cardPosition);
- parse_str($cardPosition, $output);
- $this->taskZen->commonAction($taskID);
- if(!empty($_POST))
- {
- $task = $this->task->getById($taskID);
- /* Prepare the data information before start the task. */
- $taskData = $this->taskZen->buildTaskForClose($task);
- $result = $this->task->close($task, $taskData, $output);
- if(!$result) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
- if(is_array($result)) return $this->send($result);
- $message = $this->executeHooks($taskID);
- $message = $message ?: $this->lang->saveSuccess;
- /* Get the information returned after a task is started. */
- $from = zget($output, 'from');
- $response = $this->taskZen->responseAfterChangeStatus($task, $from, $message);
- return $this->send($response);
- }
- $this->view->title = $this->view->execution->name . $this->lang->hyphen .$this->lang->task->finish;
- $this->view->users = $this->loadModel('user')->getPairs('noletter');
- $this->display();
- }
- /**
- * 批量取消任务。
- * Batch cancel tasks.
- *
- * @access public
- * @return void
- */
- public function batchCancel()
- {
- $taskIdList = $this->post->taskIdList ? array_unique($this->post->taskIdList) : array();
- if($taskIdList) $taskIdList = array_filter(array_unique($taskIdList));
- if($taskIdList)
- {
- foreach($taskIdList as $taskID)
- {
- $task = $this->task->fetchById((int)$taskID);
- if(!in_array($task->status, $this->config->task->unfinishedStatus)) continue;
- $taskData = $this->taskZen->buildTaskForCancel($task);
- $this->task->cancel($task, $taskData);
- }
- }
- return $this->send(array('result' => 'success', 'load' => true));
- }
- /**
- * 批量关闭任务。
- * Batch close tasks.
- *
- * @param string $confirm yes|no
- * @access public
- * @return void
- */
- public function batchClose($confirm = 'no')
- {
- $skipTasks = array();
- $taskIdList = $this->post->taskIdList ? array_unique($this->post->taskIdList) : array();
- $taskList = $this->task->getByIdList($taskIdList);
- if($confirm == 'no')
- {
- foreach($taskList as $taskID => $task)
- {
- if(!in_array($task->status, array('done', 'cancel')))
- {
- $skipTasks[$taskID] = $taskID;
- }
- }
- if(!empty($skipTasks))
- {
- $skipTasks = implode(',', $skipTasks);
- $url = $this->createLink('task', 'batchClose', "confirm=yes");
- $confirm = sprintf($this->lang->task->error->skipClose, $skipTasks);
- $data['url'] = $url;
- $data['data'] = array('taskIdList[]' => $this->post->taskIdList);
- $data = json_encode($data);
- return $this->send(array('result' => 'fail', 'callback' => "zui.Modal.confirm('{$confirm}').then((res) => {if(res) $.ajaxSubmit($data);});"));
- }
- }
- foreach($taskList as $taskID => $task)
- {
- if($task->status == 'closed') continue;
- if($task->parent > 0 && isset($taskList[$task->parent])) continue; // 同时选中父子,关闭父的时候就关闭子了,不用重复关闭子
- $taskData = $this->taskZen->buildTaskForClose($task);
- $this->task->close($task, $taskData);
- }
- if(!dao::isError()) $this->loadModel('score')->create('ajax', 'batchOther');
- return $this->send(array('result' => 'success', 'load' => true));
- }
- /**
- * 取消一个任务。
- * Cancel a task.
- *
- * @param int $taskID
- * @param string $cardPosition
- * @param string $from
- * @access public
- * @return void
- */
- public function cancel($taskID, $cardPosition = '', $from = '')
- {
- $this->taskZen->commonAction($taskID);
- $cardPosition = str_replace(array(',', ' '), array('&', ''), $cardPosition);
- parse_str($cardPosition, $output);
- if(!empty($_POST))
- {
- $oldTask = $this->task->getByID($taskID);
- $task = $this->taskZen->buildTaskForCancel($oldTask);
- $result = $this->task->cancel($oldTask, $task, $output);
- if(!$result) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
- $message = $this->executeHooks($taskID);
- if(helper::isAjaxRequest('modal')) return $this->send($this->taskZen->responseModal($oldTask, $from, $message));
- return $this->send(array('result' => 'success', 'message' => $message ?: $this->lang->saveSuccess, 'closeModal' => true, 'load' => $this->createLink('task', 'view', "taskID=$taskID")));
- }
- $this->view->title = $this->view->execution->name . $this->lang->hyphen . $this->lang->task->cancel;
- $this->view->users = $this->loadModel('user')->getPairs('noletter');
- $this->display();
- }
- /**
- * 激活一个任务
- * Activate a task.
- *
- * @param int $taskID
- * @param string $cardPosition
- * @param string $from
- * @access public
- * @return void
- */
- public function activate($taskID, $cardPosition = '', $from = '')
- {
- /* Analytic parameter. */
- $cardPosition = str_replace(array(',', ' '), array('&', ''), $cardPosition);
- parse_str($cardPosition, $output);
- $this->taskZen->commonAction($taskID);
- if(!empty($_POST))
- {
- /* Prepare the data information before activate the task. */
- $task = $this->taskZen->buildTaskForActivate($taskID);
- if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
- $teamData = form::data($this->config->task->form->team->edit)->get();
- $this->task->activate($task, (string)$this->post->comment, $teamData, $output);
- if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
- $message = $this->executeHooks($taskID);
- $message = $message ?: $this->lang->saveSuccess;
- /* Get the information returned after a task is started. */
- $task = $this->task->fetchByID($taskID);
- $response = $this->taskZen->responseAfterChangeStatus($task, $from, $message);
- return $this->send($response);
- }
- if(!isset($this->view->members[$this->view->task->finishedBy])) $this->view->members[$this->view->task->finishedBy] = $this->view->task->finishedBy; // Ensure that the completion person is on the user list.
- /* Get task teammembers. */
- if(!empty($this->view->task->team))
- {
- $teamAccounts = array_column($this->view->task->team, 'account');
- $teamMembers = array();
- foreach($this->view->members as $account => $name)
- {
- if(!$account || in_array($account, $teamAccounts)) $teamMembers[$account] = $name;
- }
- $this->view->teamMembers = $teamMembers;
- }
- $this->view->title = $this->view->execution->name . $this->lang->hyphen . $this->lang->task->activate;
- $this->view->users = $this->loadModel('user')->getPairs('noletter');
- $this->view->isMultiple = !empty($this->view->task->team);
- $this->display();
- }
- /**
- * 删除一个任务。
- * Delete a task.
- *
- * @param int $taskID
- * @param string $from
- * @access public
- * @return void
- */
- public function delete($taskID, $from = '')
- {
- $task = $this->task->fetchByID($taskID);
- /* 如果是父任务,先删除所有子任务 */
- if($task->isParent)
- {
- dao::$filterTpl = 'never';
- $childIdList = $this->task->getAllChildId($taskID, false);
- $childTasks = $this->task->getByIdList($childIdList);
- foreach($childTasks as $childID => $childTask)
- {
- if(strpos(",{$childTask->path},", ",$taskID,") === false) continue;
- $this->task->delete(TABLE_TASK, $childID);
- if($childTask->fromBug != 0) $this->dao->update(TABLE_BUG)->set('toTask')->eq(0)->where('id')->eq($childTask->fromBug)->exec();
- if($childTask->story) $this->loadModel('story')->setStage($childTask->story);
- }
- }
- /* 删除当前任务 */
- $this->task->delete(TABLE_TASK, $taskID);
- if($task->parent > 0)
- {
- $this->task->updateParentStatus($task->id);
- $this->loadModel('action')->create('task', $task->parent, 'deleteChildrenTask', '', $taskID);
- }
- if($task->fromBug != 0) $this->dao->update(TABLE_BUG)->set('toTask')->eq(0)->where('id')->eq($task->fromBug)->exec();
- if($task->story) $this->loadModel('story')->setStage($task->story);
- $message = $this->executeHooks($taskID);
- $message = $message ?: $this->lang->saveSuccess;
- /* 在看板中删除任务时的返回。*/
- /* Respond when delete in kanban. */
- if($from == 'taskkanban') return $this->send(array('result' => 'success', 'closeModal' => true, 'callback' => "refreshKanban()"));
- if($from == 'view') return $this->send(array('result' => 'success', 'message' => $message, 'closeModal' => true, 'load' => true));
- $link = $this->session->taskList ? $this->session->taskList : $this->createLink('execution', 'task', "executionID={$task->execution}");
- $link = isInModal() ? true : $link;
- return $this->send(array('result' => 'success', 'message' => $message, 'load' => $link, 'closeModal' => true));
- }
- /**
- * AJAX: return tasks of a user in html select.
- *
- * @param int $userID
- * @param string $id
- * @param string $status
- * @param int $appendID
- * @access public
- * @return string
- */
- public function ajaxGetUserTasks($userID = 0, $id = '', $status = 'wait,doing', $appendID = 0)
- {
- if($userID == 0) $userID = $this->app->user->id;
- $user = $this->loadModel('user')->getById($userID, 'id');
- $account = $user->account;
- $tasks = $this->task->getUserTaskPairs($account, $status, array(), array($appendID));
- $suspendedTasks = $this->task->getUserSuspendedTasks($account);
- $items = array();
- foreach($tasks as $taskID => $taskName)
- {
- if(isset($suspendedTasks[$taskID]))
- {
- unset($tasks[$taskID]);
- continue;
- }
- $items[] = array('text' => $taskName, 'value' => $taskID);
- }
- $fieldName = $id ? "tasks[$id]" : 'task';
- return print(json_encode(array('name' => $fieldName, 'items' => $items)));
- }
- /**
- * AJAX: return execution tasks in html select.
- *
- * @param int $executionID
- * @access public
- * @return string
- */
- public function ajaxGetExecutionTasks($executionID)
- {
- $tasks = $this->task->getExecutionTaskPairs((int)$executionID);
- $items = array();
- foreach($tasks as $taskID => $taskName) $items[] = array('text' => $taskName, 'value' => $taskID, 'keys' => $taskName);
- return print(json_encode($items));
- }
- /**
- * 禅道客户端获取任务动态。
- * AJAX: get the actions of a task. for web app.
- *
- * @param int $taskID
- * @access public
- * @return void
- */
- public function ajaxGetDetail($taskID)
- {
- $this->view->actions = $this->loadModel('action')->getList('task', $taskID);
- $this->display();
- }
- /**
- * The report page.
- *
- * @param int $executionID
- * @param string $browseType
- * @param string $chartType default|pie|bar|line
- * @access public
- * @return void
- */
- public function report($executionID, $browseType = 'all', $chartType = 'default')
- {
- $this->loadModel('report');
- $this->view->charts = array();
- $this->execution->setMenu($executionID);
- /* Build chart data. */
- $chartList = array();
- $this->view->datas = array();
- if(!empty($_POST)) $chartList = $this->taskZen->buildChartData($chartType);
- /* If the project is non-execution, the chart of tasks by execution is not shown. */
- $execution = $this->loadModel('execution')->getByID($executionID);
- if(!$execution->multiple) unset($this->lang->task->report->charts['tasksPerExecution']);
- if($this->app->tab == 'project') $this->view->projectID = $execution->project;
- $this->view->title = $execution->name . $this->lang->hyphen . $this->lang->task->report->common;
- $this->view->executionID = $executionID;
- $this->view->execution = $execution;
- $this->view->browseType = $browseType;
- $this->view->chartType = $chartType;
- $this->view->charts = $chartList;
- $this->view->checkedCharts = $this->post->charts ? implode(',', $this->post->charts) : '';
- $this->display();
- }
- /**
- * 导出任务数据。
- * get data to export.
- *
- * @param int $executionID
- * @param string $orderBy
- * @param string $type browse type, such as: all,unclosed,assignedtome,myinvolved,assignedbyme,needconfirm,etc
- * @access public
- * @return void
- */
- public function export($executionID, $orderBy, $type)
- {
- /* Get execution info and export fields. */
- $execution = $this->execution->getByID($executionID);
- $allExportFields = $this->config->task->exportFields;
- if($execution->lifetime == 'ops' || in_array($execution->attribute, array('request', 'review'))) $allExportFields = str_replace(' story,', '', $allExportFields);
- if($_POST)
- {
- $this->loadModel('file');
- if($type == 'bysearch') $this->config->task->dtable->fieldList['module']['dataSource'] = array('module' => 'tree', 'method' => 'getAllModulePairs');
- /* Create field lists. */
- $fields = $this->taskZen->getExportFields($allExportFields);
- /* Get tasks. */
- $tasks = $this->task->getExportTasks($orderBy);
- if($type == 'group') $tasks = $this->taskZen->processExportGroup($executionID, $tasks, $orderBy);
- /* Process export data. */
- $tasks = $this->taskZen->processExportData($tasks, $execution->project);
- if($this->config->edition != 'open') list($fields, $tasks) = $this->loadModel('workflowfield')->appendDataFromFlow($fields, $tasks);
- $this->post->set('fields', $fields);
- $this->post->set('rows', $tasks);
- $this->post->set('kind', 'task');
- $this->fetch('file', 'export2' . $this->post->fileType, $_POST);
- }
- if(isset($this->lang->execution->featureBar['task'][$type]))
- {
- $browseType = $this->lang->execution->featureBar['task'][$type];
- }
- else
- {
- $browseType = isset($this->lang->execution->statusSelects[$type]) ? $this->lang->execution->statusSelects[$type] : '';
- }
- $this->view->fileName = $execution->name . $this->lang->dash . $browseType . $this->lang->task->common;
- $this->view->allExportFields = $allExportFields;
- $this->view->customExport = true;
- $this->view->orderBy = $orderBy;
- $this->view->type = $type;
- $this->view->executionID = $executionID;
- $this->view->execution = $execution;
- $this->display();
- }
- /**
- * AJAX: Get the json of the task by ID.
- * Note: This function is NOT used in open edition.
- *
- * @param int $taskID
- * @access public
- * @return void
- */
- public function ajaxGetByID($taskID)
- {
- $task = $this->dao->select('*')->from(TABLE_TASK)->where('id')->eq($taskID)->fetch();
- if(!$task) return;
- $realname = $this->dao->select('realname')->from(TABLE_USER)->where('account')->eq($task->assignedTo)->fetch('realname');
- $assignedTo = $task->assignedTo == 'closed' ? 'Closed' : $task->assignedTo;
- $task->assignedTo = $realname ? $realname : $assignedTo;
- if($task->story)
- {
- $this->app->loadLang('story');
- $stage = $this->dao->select('stage')->from(TABLE_STORY)->where('id')->eq($task->story)->andWhere('version')->eq($task->storyVersion)->fetch('stage');
- $task->storyStage = zget($this->lang->story->stageList, $stage);
- }
- return print(json_encode($task));
- }
- /**
- * 管理多人任务的团队。
- * Update assign of multi task.
- *
- * @param int $executionID
- * @param int $taskID
- * @param string $from ''|taskkanban
- * @access public
- * @return void
- */
- public function manageTeam($executionID, $taskID, $from = '')
- {
- $this->taskZen->commonAction($taskID);
- if(!empty($_POST))
- {
- /* Update assign of multi task. */
- $postData = form::data($this->config->task->form->manageTeam);
- $task = $this->taskZen->prepareManageTeam($postData, $taskID);
- $postData->team = $this->post->team;
- $postData->teamEstimate = $this->post->teamEstimate;
- $postData->teamConsumed = $this->post->teamConsumed;
- $postData->teamLeft = $this->post->teamLeft;
- $postData->teamSource = $this->post->teamSource;
- $changes = $this->task->updateTeam($task, $postData);
- if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
- /* Record log. */
- $actionID = $this->loadModel('action')->create('task', $taskID, 'Edited');
- $this->action->logHistory($actionID, $changes);
- $message = $this->executeHooks($taskID);
- $message = $message ?: $this->lang->saveSuccess;
- $response = $this->taskZen->responseAfterAssignTo($taskID, $from, $message);
- return $this->send($response);
- }
- if($this->app->rawMethod == 'assignto')
- {
- 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->manageLink = $manageLink;
- }
- $this->view->members = $this->loadModel('user')->getTeamMemberPairs($executionID, 'execution', 'nodeleted');
- $this->view->users = $this->loadModel('user')->getPairs();
- $this->display();
- }
- /**
- * AJAX: 返回一个html格式的需求选择列表用于创建测试类型的任务。该需求的名称将作为创建任务的子任务名称。
- * AJAX: Return the stories selection list in html format for create the task with test type. The child task has same name with the story.
- *
- * @param int $executionID
- * @param int $taskID The task ID which the task copy from. This will be used for creating a task from a existed task.
- * @access public
- * @return string
- */
- public function ajaxGetTestStories($executionID, $taskID = 0)
- {
- $stories = $this->story->getExecutionStoryPairs($executionID, 0, 'all', '', 'ignoreID', 'active', 'story', false);
- $testStoryIdList = $this->story->getTestStories(array_keys($stories), $executionID);
- $testStories = array();
- foreach($stories as $testStoryID => $storyTitle)
- {
- /**
- * 如果在执行中已经为该需求创建了测试类型任务,则跳过这个需求不再给前台展示。
- * If a test type task has already been created for the requirement during execution, the requirement is skipped and not shown to the foreground.
- */
- if(empty($testStoryID) || isset($testStoryIdList[$testStoryID])) continue;
- $testStories[$testStoryID] = $storyTitle;
- }
- $execution = $this->loadModel('execution')->fetchByID($executionID);
- if($execution->multiple) $manageLink = common::hasPriv('execution', 'manageMembers') ? $this->createLink('execution', 'manageMembers', "execution={$execution->id}") : '';
- if(!$execution->multiple) $manageLink = common::hasPriv('project', 'manageMembers') ? $this->createLink('project', 'manageMembers', "projectID={$execution->project}") : '';
- $this->view->testStories = $testStories;
- $this->view->task = $this->loadModel('task')->getByID($taskID);
- $this->view->members = $this->loadModel('user')->getTeamMemberPairs($executionID, 'execution', 'nodeleted');
- $this->view->manageLink = $manageLink;
- $this->display();
- }
- /**
- * AJAX: 获取批量创建任务的需求下拉列表。
- * AJAX: Get the stories selection list for batch create tasks.
- *
- * @param int $executionID
- * @param int $moduleID
- * @param string $zeroTaskStory
- * @access public
- * @return void
- */
- public function ajaxGetStories($executionID, $moduleID, $zeroTaskStory = 'false')
- {
- $moduleType = $moduleID ? $this->task->fetchByID($moduleID, 'module')->type : '';
- $stories = $this->loadModel('story')->getExecutionStoryPairs($executionID, 0, 'all', $moduleType == 'task' ? 0 : $moduleID, 'full', 'active', 'story', false);
- $taskCountList = $this->task->getStoryTaskCounts(array_keys($stories), $executionID);
- $items = array();
- foreach($stories as $storyID => $storyName)
- {
- if(empty($storyName)) continue;
- if($zeroTaskStory == 'true' && $taskCountList[$storyID] > 0) continue;
- $items[] = array('text' => $storyName, 'value' => $storyID, 'keys' => $storyName);
- }
- return print(json_encode($items));
- }
- /**
- * AJAX: 获取任务的开始时间和截止时间。
- * AJAX: Get the start time and end time of the task.
- *
- * @param int $taskID
- * @access public
- * @return void
- */
- public function ajaxGetTaskEstStartedAndDeadline($taskID)
- {
- $task = $this->task->fetchById($taskID);
- $overParentEstStartedLang = !empty($task) ? sprintf($this->lang->task->overParentEsStarted, $task->estStarted) : '';
- $overParentDeadlineLang = !empty($task) ? sprintf($this->lang->task->overParentDeadline, $task->deadline) : '';
- return print(json_encode(array('estStarted' => $task->estStarted, 'deadline' => $task->deadline, 'overParentEstStartedLang' => $overParentEstStartedLang, 'overParentDeadlineLang' => $overParentDeadlineLang)));
- }
- /**
- * 创建代码分支。
- * Create repo branch.
- *
- * @param int $taskID
- * @param int $repoID
- * @access public
- * @return void
- */
- public function createBranch($taskID, $repoID = 0)
- {
- return print($this->fetch('repo', 'createBranch', array('objectID' => $taskID, 'repoID' => $repoID)));
- }
- /**
- * 取消代码分支的关联。
- * Unlink code branch.
- *
- * @access public
- * @return void
- */
- public function unlinkBranch()
- {
- return print($this->fetch('repo', 'unlinkBranch'));
- }
- }
|