Merge pull request '* Refactor the edit method of the bug module.' (#30) from daitingting_bug_control_edit into master

Reviewed-on: https://git.zcorp.cc/easycorp/zentaopms/pulls/30
This commit is contained in:
綦新志
2023-05-08 15:31:51 +08:00
9 changed files with 574 additions and 393 deletions
+38 -1
View File
@@ -40,6 +40,43 @@ $config->bug->form->create['status'] = array('required' => false, 'type' => 's
$config->bug->form->create['issueKey'] = array('required' => false, 'type' => 'string', 'default' => '');
$config->bug->form->create['uid'] = array('required' => false, 'type' => 'string', 'default' => '');
$config->bug->form->edit = array();
$config->bug->form->edit['title'] = array('required' => true, 'type' => 'string', 'filter' => 'trim');
$config->bug->form->edit['openedBuild'] = array('required' => true, 'type' => 'array', 'filter' => 'join');
$config->bug->form->edit['product'] = array('required' => false, 'type' => 'int', 'default' => 0);
$config->bug->form->edit['branch'] = array('required' => false, 'type' => 'int', 'default' => 0);
$config->bug->form->edit['project'] = array('required' => false, 'type' => 'int', 'default' => 0);
$config->bug->form->edit['execution'] = array('required' => false, 'type' => 'int', 'default' => 0);
$config->bug->form->edit['plan'] = array('required' => false, 'type' => 'int', 'default' => 0);
$config->bug->form->edit['module'] = array('required' => false, 'type' => 'int', 'default' => 0);
$config->bug->form->edit['story'] = array('required' => false, 'type' => 'int', 'default' => 0);
$config->bug->form->edit['task'] = array('required' => false, 'type' => 'int', 'default' => 0);
$config->bug->form->edit['case'] = array('required' => false, 'type' => 'int', 'default' => 0);
$config->bug->form->edit['testtask'] = array('required' => false, 'type' => 'int', 'default' => 0);
$config->bug->form->edit['duplicateBug'] = array('required' => false, 'type' => 'int', 'default' => 0);
$config->bug->form->edit['severity'] = array('required' => false, 'type' => 'int', 'default' => 3);
$config->bug->form->edit['pri'] = array('required' => false, 'type' => 'int', 'default' => 3);
$config->bug->form->edit['type'] = array('required' => false, 'type' => 'string', 'default' => '');
$config->bug->form->edit['status'] = array('required' => false, 'type' => 'string', 'default' => 'active');
$config->bug->form->edit['keywords'] = array('required' => false, 'type' => 'string', 'default' => '');
$config->bug->form->edit['steps'] = array('required' => false, 'type' => 'string', 'default' => $lang->bug->tplStep . $lang->bug->tplResult . $lang->bug->tplExpect);
$config->bug->form->edit['resolution'] = array('required' => false, 'type' => 'string', 'default' => '');
$config->bug->form->edit['resolvedBuild'] = array('required' => false, 'type' => 'string', 'default' => '');
$config->bug->form->edit['assignedTo'] = array('required' => false, 'type' => 'string', 'default' => '');
$config->bug->form->edit['feedbackBy'] = array('required' => false, 'type' => 'string', 'default' => '');
$config->bug->form->edit['resolvedBy'] = array('required' => false, 'type' => 'string', 'default' => '');
$config->bug->form->edit['closedBy'] = array('required' => false, 'type' => 'string', 'default' => '');
$config->bug->form->edit['notifyEmail'] = array('required' => false, 'type' => 'string', 'default' => '');
$config->bug->form->edit['uid'] = array('required' => false, 'type' => 'string', 'default' => '');
$config->bug->form->edit['os'] = array('required' => false, 'type' => 'array', 'default' => array(''), 'filter' => 'join');
$config->bug->form->edit['browser'] = array('required' => false, 'type' => 'array', 'default' => array(''), 'filter' => 'join');
$config->bug->form->edit['linkBug'] = array('required' => false, 'type' => 'array', 'default' => array(''), 'filter' => 'join');
$config->bug->form->edit['mailto'] = array('required' => false, 'type' => 'array', 'default' => array(''), 'filter' => 'join');
$config->bug->form->edit['deadline'] = array('required' => false, 'type' => 'date', 'default' => NULL);
$config->bug->form->edit['resolvedDate'] = array('required' => false, 'type' => 'date', 'default' => NULL);
$config->bug->form->edit['closedDate'] = array('required' => false, 'type' => 'date', 'default' => NULL);
$config->bug->form->edit['lastEditedDate'] = array('required' => false, 'type' => 'date', 'default' => helper::now());
global $app;
$config->bug->form->close = array();
$config->bug->form->close['status'] = array('required' => false, 'type' => 'string', 'default' => 'closed');
@@ -49,4 +86,4 @@ $config->bug->form->close['lastEditedBy'] = array('required' => false, 'type'
$config->bug->form->close['lastEditedDate'] = array('required' => false, 'type' => 'string', 'default' => helper::now());
$config->bug->form->close['closedBy'] = array('required' => false, 'type' => 'string', 'default' => $app->user->account);
$config->bug->form->close['closedDate'] = array('required' => false, 'type' => 'string', 'default' => helper::now());
$config->bug->form->close['comment'] = array('required' => false, 'type' => 'string', 'default' => '');;
$config->bug->form->close['comment'] = array('required' => false, 'type' => 'string', 'default' => '');
+41 -242
View File
@@ -12,6 +12,7 @@
class bug extends control
{
/**
* 所有产品。
* All products.
*
* @var array
@@ -20,6 +21,7 @@ class bug extends control
public $products = array();
/**
* 当前项目编号。
* Project id.
*
* @var int
@@ -28,16 +30,25 @@ class bug extends control
public $projectID = 0;
/**
* Construct function, load some modules auto.
* 构造函数
* 1.加载其他模块model类。
* 2.获取产品,并输出到视图
* The construct function.
*
* 1. Load model of other modules.
* 2. Get products and assign to view.
*
* @param string $moduleName
* @param string $methodName
* @access public
* @return void
*/
public function __construct($moduleName = '', $methodName = '')
public function __construct(string $moduleName = '', string $methodName = '')
{
parent::__construct($moduleName, $methodName);
$this->loadModel('product');
$this->loadModel('tree');
$this->loadModel('user');
@@ -48,27 +59,28 @@ class bug extends control
/* Get product data. */
$products = array();
$objectID = 0;
$tab = ($this->app->tab == 'project' or $this->app->tab == 'execution') ? $this->app->tab : 'qa';
if(!isonlybody())
{
if($this->app->tab == 'project' or $this->app->tab == 'execution')
$tab = ($this->app->tab == 'project' or $this->app->tab == 'execution') ? $this->app->tab : 'qa';
$mode = (strpos(',create,edit,', ",{$this->app->methodName},") !== false and empty($this->config->CRProduct)) ? 'noclosed' : '';
$objectID = ($tab == 'project' or $tab == 'execution') ? $this->session->{$tab} : 0;
if($tab == 'project' or $tab == 'execution')
{
$objectID = $this->app->tab == 'project' ? $this->session->project : $this->session->execution;
$products = $this->product->getProducts($objectID, 'all', '', false);
$products = $this->product->getProducts($objectID, $mode, $orderBy = '', $withBranch = false);
}
else
{
$mode = ($this->app->methodName == 'create' and empty($this->config->CRProduct)) ? 'noclosed' : '';
$products = $this->product->getPairs($mode, 0, '', 'all');
$products = $this->product->getPairs($mode, $programID = 0, $append = '', $shadow = 'all');
}
if(empty($products) and !helper::isAjaxRequest()) return print($this->locate($this->createLink('product', 'showErrorNone', "moduleName=$tab&activeMenu=bug&objectID=$objectID")));
}
else
{
$mode = (empty($this->config->CRProduct)) ? 'noclosed' : '';
$mode = empty($this->config->CRProduct) ? 'noclosed' : '';
$products = $this->product->getPairs($mode, 0, '', 'all');
}
$this->view->products = $this->products = $products;
}
@@ -645,259 +657,46 @@ class bug extends control
}
/**
* 更新bug信息。
* Edit a bug.
*
* @param int $bugID
* @param bool $comment
* @param string $bugID
* @param bool $comment true|false
* @param string $kanbanGroup
* @access public
* @return void
*/
public function edit($bugID, $comment = false, $kanbanGroup = 'default')
public function edit(string $bugID, bool $comment = false, string $kanbanGroup = 'default')
{
if(!empty($_POST))
{
$oldBug = $this->bug->getByID($bugID);
$formData = form::data($this->config->bug->form->edit);
$bug = $this->bugZen->prepareEditExtras($formData, $oldBug);
if(!$bug) return $this->send($this->bugZen->errorEdit());
$changes = array();
$files = array();
if($comment == false)
if(!$comment)
{
$changes = $this->bug->update($bugID);
if(dao::isError())
{
if(defined('RUN_MODE') && RUN_MODE == 'api') return $this->send(array('status' => 'error', 'message' => dao::getError()));
return print(js::error(dao::getError()));
}
$changes = $this->bug->update($bug, $oldBug);
if(!$changes) return $this->send($this->bugZen->errorEdit());
}
if($this->post->comment != '' or !empty($changes))
{
$action = !empty($changes) ? 'Edited' : 'Commented';
$actionID = $this->action->create('bug', $bugID, $action, $this->post->comment);
$this->action->logHistory($actionID, $changes);
}
if(defined('RUN_MODE') && RUN_MODE == 'api') return $this->send(array('status' => 'success', 'data' => $bugID));
$bug = $this->bug->getById($bugID);
$this->bugZen->processAfterEdit($bugID, $this->post->comment, $changes);
$this->executeHooks($bugID);
if($bug->toTask != 0)
{
foreach($changes as $change)
{
if($change['field'] == 'status')
{
$confirmURL = $this->createLink('task', 'view', "taskID=$bug->toTask");
$cancelURL = $this->server->HTTP_REFERER;
return print(js::confirm(sprintf($this->lang->bug->remindTask, $bug->Task), $confirmURL, $cancelURL, 'parent', 'parent'));
}
}
}
if(isonlybody())
{
$execution = $this->loadModel('execution')->getByID($bug->execution);
if($this->app->tab == 'execution')
{
$execLaneType = $this->session->execLaneType ? $this->session->execLaneType : 'all';
$execGroupBy = $this->session->execGroupBy ? $this->session->execGroupBy : 'default';
if(isset($execution->type) and $execution->type == 'kanban')
{
$rdSearchValue = $this->session->rdSearchValue ? $this->session->rdSearchValue : '';
$kanbanData = $this->loadModel('kanban')->getRDKanban($bug->execution, $execLaneType, 'id_desc', 0, $kanbanGroup, $rdSearchValue);
$kanbanData = json_encode($kanbanData);
return print(js::closeModal('parent.parent', '', "parent.parent.updateKanban($kanbanData)"));
}
else
{
$taskSearchValue = $this->session->taskSearchValue ? $this->session->taskSearchValue : '';
$kanbanData = $this->loadModel('kanban')->getExecutionKanban($bug->execution, $execLaneType, $execGroupBy, $taskSearchValue);
$kanbanType = $execLaneType == 'all' ? 'bug' : key($kanbanData);
$kanbanData = $kanbanData[$kanbanType];
$kanbanData = json_encode($kanbanData);
return print(js::closeModal('parent.parent', '', "parent.parent.updateKanban(\"bug\", $kanbanData)"));
}
}
else
{
return print(js::closeModal('parent.parent'));
}
}
return print(js::locate($this->createLink('bug', 'view', "bugID=$bugID"), 'parent'));
return $this->send($this->bugZen->responseAfterEdit($bugID, $changes, $kanbanGroup));
}
/* Get the info of bug, current product and modue. */
$bug = $this->bug->getById($bugID);
$productID = $bug->product;
$executionID = $bug->execution;
$projectID = $bug->project;
$currentModuleID = $bug->module;
$product = $this->loadModel('product')->getByID($productID);
$execution = $this->loadModel('execution')->getByID($executionID);
$bug = $this->bug->getByID($bugID);
$this->bug->checkBugExecutionPriv($bug);
if(!isset($this->products[$bug->product]))
{
$this->products[$bug->product] = $product->name;
$this->view->products = $this->products;
}
$this->bugZen->setEditMenu($bug);
/* Set the menu. */
if($this->app->tab == 'project') $this->loadModel('project')->setMenu($bug->project);
if($this->app->tab == 'execution') $this->loadModel('execution')->setMenu($bug->execution);
if($this->app->tab == 'qa') $this->qa->setMenu($this->products, $productID, $bug->branch);
if($this->app->tab == 'devops')
{
session_write_close();
$repos = $this->loadModel('repo')->getRepoPairs('project', $bug->project);
$this->repo->setMenu($repos);
$this->lang->navGroup->bug = 'devops';
}
/* Unset discarded types. */
foreach($this->config->bug->discardedTypes as $type)
{
if($bug->type != $type) unset($this->lang->bug->typeList[$type]);
}
if($this->app->tab == 'qa')
{
$this->view->products = $this->config->CRProduct ? $this->products : $this->product->getPairs('noclosed');
}
if($this->app->tab == 'project')
{
$products = array();
$productList = $this->config->CRProduct ? $this->product->getOrderedProducts('all', 40, $bug->project) : $this->product->getOrderedProducts('normal', 40, $bug->project);
foreach($productList as $productInfo) $products[$productInfo->id] = $productInfo->name;
$this->view->products = $products;
}
/* Set header and position. */
$this->view->title = $this->lang->bug->edit . "BUG #$bug->id $bug->title - " . $this->products[$productID];
$this->view->position[] = html::a($this->createLink('bug', 'browse', "productID=$productID"), $this->products[$productID]);
$this->view->position[] = $this->lang->bug->edit;
/* Assign. */
$allBuilds = $this->loadModel('build')->getBuildPairs($productID, 'all', 'noempty');
if($executionID)
{
$openedBuilds = $this->build->getBuildPairs($productID, $bug->branch, 'noempty,noterminate,nodone,withbranch,noreleased', $executionID, 'execution');
}
elseif($projectID)
{
$openedBuilds = $this->build->getBuildPairs($productID, $bug->branch, 'noempty,noterminate,nodone,withbranch,noreleased', $projectID, 'project');
}
else
{
$openedBuilds = $this->build->getBuildPairs($productID, $bug->branch, 'noempty,noterminate,nodone,withbranch,noreleased');
}
/* Set the openedBuilds list. */
$oldOpenedBuilds = array();
$bugOpenedBuilds = explode(',', $bug->openedBuild);
foreach($bugOpenedBuilds as $buildID)
{
if(isset($allBuilds[$buildID])) $oldOpenedBuilds[$buildID] = $allBuilds[$buildID];
}
$openedBuilds = $openedBuilds + $oldOpenedBuilds;
/* Set the resolvedBuilds list. */
$oldResolvedBuild = array();
if(($bug->resolvedBuild) and isset($allBuilds[$bug->resolvedBuild])) $oldResolvedBuild[$bug->resolvedBuild] = $allBuilds[$bug->resolvedBuild];
$projectID = $this->lang->navGroup->bug == 'project' ? $this->session->project : 0;
if($this->app->tab == 'execution' or $this->app->tab == 'project')
{
$objectID = $this->app->tab == 'project' ? $bug->project : $bug->execution;
}
/* Display status of branch. */
$branches = $this->loadModel('branch')->getList($productID, isset($objectID) ? $objectID : 0, 'all');
$branchOption = array();
$branchTagOption = array();
foreach($branches as $branchInfo)
{
$branchOption[$branchInfo->id] = $branchInfo->name;
$branchTagOption[$branchInfo->id] = $branchInfo->name . ($branchInfo->status == 'closed' ? ' (' . $this->lang->branch->statusList['closed'] . ')' : '');
}
if(!isset($branchTagOption[$bug->branch]))
{
$bugBranch = $this->branch->getById($bug->branch, $bug->product, '');
$branchTagOption[$bug->branch] = $bug->branch == BRANCH_MAIN ? $bugBranch : ($bugBranch->name . ($bugBranch->status == 'closed' ? ' (' . $this->lang->branch->statusList['closed'] . ')' : ''));
}
$moduleOptionMenu = $this->tree->getOptionMenu($productID, $viewType = 'bug', $startModuleID = 0, $bug->branch);
if(!isset($moduleOptionMenu[$bug->module])) $moduleOptionMenu += $this->tree->getModulesName($bug->module);
$cases = $this->loadmodel('testcase')->getPairsByProduct($bug->product, array(0, $bug->branch));
/* Get assigned to member. */
if($bug->execution)
{
$assignedToList = $this->user->getTeamMemberPairs($bug->execution, 'execution');
}
elseif($bug->project)
{
$assignedToList = $this->loadModel('project')->getTeamMemberPairs($bug->project);
}
else
{
$assignedToList = $this->bug->getProductMemberPairs($bug->product, $bug->branch);
$assignedToList = array_filter($assignedToList);
if(empty($assignedToList)) $assignedToList = $this->user->getPairs('devfirst|noclosed');
}
if($bug->assignedTo and !isset($assignedToList[$bug->assignedTo]) and $bug->assignedTo != 'closed')
{
/* Fix bug #28378. */
$assignedTo = $this->user->getById($bug->assignedTo);
$assignedToList[$bug->assignedTo] = $assignedTo->realname;
}
if($bug->status == 'closed') $assignedToList['closed'] = 'Closed';
$branch = $product->type == 'branch' ? ($bug->branch > 0 ? $bug->branch . ',0' : '0') : '';
$productBugs = $this->bug->getProductBugPairs($productID, $branch);
unset($productBugs[$bugID]);
$executions = array(0 => '') + $this->product->getExecutionPairsByProduct($bug->product, $bug->branch, 'id_desc', $bug->project);
if(!empty($bug->execution) and empty($executions[$bug->execution])) $executions[$execution->id] = $execution->name . "({$this->lang->bug->deleted})";
$projects = array(0 => '') + $this->product->getProjectPairsByProduct($productID, $bug->branch);
if(!empty($bug->project) and empty($projects[$bug->project]))
{
$project = $this->loadModel('project')->getByID($bug->project);
$projects[$project->id] = $project->name . "({$this->lang->bug->deleted})";
}
if($product->shadow) $this->view->project = $this->loadModel('project')->getByShadowProduct($bug->product);
$this->view->bug = $bug;
$this->view->product = $product;
$this->view->execution = $execution;
$this->view->productBugs = $productBugs;
$this->view->productName = $this->products[$productID];
$this->view->plans = $this->loadModel('productplan')->getPairs($productID, $bug->branch, '', true);
$this->view->projects = $projects;
$this->view->projectExecutionPairs = $this->loadModel('project')->getProjectExecutionPairs();
$this->view->moduleOptionMenu = $moduleOptionMenu;
$this->view->currentModuleID = $currentModuleID;
$this->view->executions = $executions;
$this->view->stories = $bug->execution ? $this->story->getExecutionStoryPairs($bug->execution) : $this->story->getProductStoryPairs($bug->product, $bug->branch, 0, 'all', 'id_desc', 0, 'full', 'story', false);
$this->view->branchOption = $branchOption;
$this->view->branchTagOption = $branchTagOption;
$this->view->tasks = $this->task->getExecutionTaskPairs($bug->execution);
$this->view->testtasks = $this->loadModel('testtask')->getPairs($bug->product, $bug->execution, $bug->testtask);
$this->view->users = $this->user->getPairs('', "$bug->assignedTo,$bug->resolvedBy,$bug->closedBy,$bug->openedBy");
$this->view->assignedToList = $assignedToList;
$this->view->cases = array('' => '') + $cases;
$this->view->openedBuilds = $openedBuilds;
$this->view->resolvedBuilds = array('' => '') + $openedBuilds + $oldResolvedBuild;
$this->view->actions = $this->action->getList('bug', $bugID);
$this->display();
$this->bugZen->buildEditForm($bug);
}
/**
+29 -120
View File
@@ -174,7 +174,7 @@ class bugModel extends model
foreach($extendFields as $extendField)
{
$bug->{$extendField->field} = $this->post->{$extendField->field}[$i];
if(is_array($bug->{$extendField->field})) $bug->{$extendField->field} = join(',', $bug->{$extendField->field});
if(is_array($bug->{$extendField->field})) $bug->{$extendField->field} = implode(',', $bug->{$extendField->field});
$bug->{$extendField->field} = htmlSpecialString($bug->{$extendField->field});
}
@@ -397,7 +397,7 @@ class bugModel extends model
* @access public
* @return object|false
*/
public function getByID(int $bugID, bool $setImgSize = false): object|false
public function getByID(string $bugID, bool $setImgSize = false): object|false
{
$bug = $this->bugTao->fetchBugInfo($bugID);
if(!$bug) return false;
@@ -532,121 +532,33 @@ class bugModel extends model
}
/**
* 更新bug信息。
* Update a bug.
*
* @param int $bugID
* @param object $bug
* @param object $oldBug
* @access public
* @return void
* @return array|false
*/
public function update($bugID)
public function update(object $bug, object $oldBug): array|false
{
$oldBug = $this->getById($bugID);
if(!empty($_POST['lastEditedDate']) and $oldBug->lastEditedDate != $this->post->lastEditedDate)
{
dao::$errors[] = $this->lang->error->editedByOther;
return false;
}
$now = helper::now();
$bug = fixer::input('post')
->add('id', $bugID)
->cleanInt('product,module,severity,project,execution,story,task,branch')
->stripTags($this->config->bug->editor->edit['id'], $this->config->allowedTags)
->setDefault('module,execution,story,task,duplicateBug,branch', 0)
->setDefault('product', $oldBug->product)
->setDefault('openedBuild', '')
->setDefault('os', '')
->setDefault('browser', '')
->setDefault('plan', 0)
->setDefault('deadline', '0000-00-00')
->setDefault('resolvedDate', '')
->setDefault('lastEditedBy', $this->app->user->account)
->setDefault('mailto', '')
->setDefault('deleteFiles', array())
->add('lastEditedDate', $now)
->setIF(strpos($this->config->bug->edit->requiredFields, 'deadline') !== false, 'deadline', $this->post->deadline)
->join('openedBuild', ',')
->join('mailto', ',')
->join('linkBug', ',')
->join('os', ',')
->join('browser', ',')
->setIF($this->post->assignedTo != $oldBug->assignedTo, 'assignedDate', $now)
->setIF($this->post->resolvedBy != '' and $this->post->resolvedDate == '', 'resolvedDate', $now)
->setIF($this->post->resolution != '' and $this->post->resolvedDate == '', 'resolvedDate', $now)
->setIF($this->post->resolution != '' and $this->post->resolvedBy == '', 'resolvedBy', $this->app->user->account)
->setIF($this->post->closedBy != '' and $this->post->closedDate == '', 'closedDate', $now)
->setIF($this->post->closedDate != '' and $this->post->closedBy == '', 'closedBy', $this->app->user->account)
->setIF($this->post->closedBy != '' or $this->post->closedDate != '', 'assignedTo', 'closed')
->setIF($this->post->closedBy != '' or $this->post->closedDate != '', 'assignedDate', $now)
->setIF($this->post->resolution != '' or $this->post->resolvedDate != '', 'status', 'resolved')
->setIF($this->post->closedBy != '' or $this->post->closedDate != '', 'status', 'closed')
->setIF(($this->post->resolution != '' or $this->post->resolvedDate != '') and $this->post->assignedTo == '', 'assignedTo', $oldBug->openedBy)
->setIF(($this->post->resolution != '' or $this->post->resolvedDate != '') and $this->post->assignedTo == '', 'assignedDate', $now)
->setIF($this->post->assignedTo == '' and $oldBug->status == 'closed', 'assignedTo', 'closed')
->setIF($this->post->resolution == '' and $this->post->resolvedDate =='', 'status', 'active')
->setIF($this->post->resolution != '', 'confirmed', 1)
->setIF($this->post->resolution != '' and $this->post->resolution != 'duplicate', 'duplicateBug', 0)
->setIF($this->post->story != false and $this->post->story != $oldBug->story, 'storyVersion', $this->loadModel('story')->getVersion($this->post->story))
->setIF(!$this->post->linkBug, 'linkBug', '')
->setIF($this->post->case === '', 'case', 0)
->remove('comment,files,labels,uid,contactListMenu')
->get();
$bug = $this->loadModel('file')->processImgURL($bug, $this->config->bug->editor->edit['id'], $this->post->uid);
$this->dao->update(TABLE_BUG)->data($bug, 'deleteFiles')
->autoCheck()
->batchCheck($this->config->bug->edit->requiredFields, 'notempty')
->checkIF($bug->resolvedBy, 'resolution', 'notempty')
->checkIF($bug->closedBy, 'resolution', 'notempty')
->checkIF($bug->notifyEmail, 'notifyEmail', 'email')
->checkIF($bug->notifyEmail,'notifyEmail', 'email')
->checkIF($bug->resolution == 'duplicate', 'duplicateBug', 'notempty')
->checkIF($bug->resolution == 'fixed', 'resolvedBuild','notempty')
->checkFlow()
->where('id')->eq((int)$bugID)
->where('id')->eq($bug->id)
->exec();
if(!dao::isError())
{
/* Link bug to build and release. */
if($bug->resolution == 'fixed' and !empty($bug->resolvedBuild) and $oldBug->resolvedBuild != $bug->resolvedBuild)
{
if(!empty($oldBug->resolvedBuild)) $this->loadModel('build')->unlinkBug($oldBug->resolvedBuild, (int)$bugID);
$this->linkBugToBuild($bugID, $bug->resolvedBuild);
}
if(dao::isError()) return false;
if($bug->plan != $oldBug->plan)
{
$this->loadModel('action');
if(!empty($oldBug->plan)) $this->action->create('productplan', $oldBug->plan, 'unlinkbug', '', $bugID);
if(!empty($bug->plan)) $this->action->create('productplan', $bug->plan, 'linkbug', '', $bugID);
}
if(!$this->bugTao->afterUpdate($bug, $oldBug)) return false;
$linkBugs = explode(',', $bug->linkBug);
$oldLinkBugs = explode(',', $oldBug->linkBug);
$addBugs = array_diff($linkBugs, $oldLinkBugs);
$removeBugs = array_diff($oldLinkBugs, $linkBugs);
$changeBugs = array_merge($addBugs, $removeBugs);
$changeBugs = $this->dao->select('id,linkbug')->from(TABLE_BUG)->where('id')->in(array_filter($changeBugs))->fetchPairs();
foreach($changeBugs as $changeBugID => $changeBug)
{
if(in_array($changeBugID, $addBugs) and empty($changeBug)) $this->dao->update(TABLE_BUG)->set('linkBug')->eq($bugID)->where('id')->eq((int)$changeBugID)->exec();
if(in_array($changeBugID, $addBugs) and !empty($changeBug)) $this->dao->update(TABLE_BUG)->set('linkBug')->eq("$changeBug,$bugID")->where('id')->eq((int)$changeBugID)->exec();
if(in_array($changeBugID, $removeBugs))
{
$linkBugs = explode(',', $changeBug);
unset($linkBugs[array_search($bugID, $linkBugs)]);
$this->dao->update(TABLE_BUG)->set('linkBug')->eq(implode(',', $linkBugs))->where('id')->eq((int)$changeBugID)->exec();
}
}
if(!empty($bug->resolvedBy)) $this->loadModel('score')->create('bug', 'resolve', $bugID);
if($bug->execution and $bug->status != $oldBug->status) $this->loadModel('kanban')->updateLane($bug->execution, 'bug');
if(($this->config->edition == 'biz' || $this->config->edition == 'max') && $oldBug->feedback) $this->loadModel('feedback')->updateStatus('bug', $oldBug->feedback, $bug->status, $oldBug->status);
$this->file->processFile4Object('bug', $oldBug, $bug);
return common::createChanges($oldBug, $bug);
}
return common::createChanges($oldBug, $bug);
}
/**
@@ -739,7 +651,7 @@ class bugModel extends model
foreach($extendFields as $extendField)
{
$bug->{$extendField->field} = $this->post->{$extendField->field}[$bugID];
if(is_array($bug->{$extendField->field})) $bug->{$extendField->field} = join(',', $bug->{$extendField->field});
if(is_array($bug->{$extendField->field})) $bug->{$extendField->field} = implode(',', $bug->{$extendField->field});
$bug->{$extendField->field} = htmlSpecialString($bug->{$extendField->field});
}
@@ -846,7 +758,7 @@ class bugModel extends model
{
$postFieldData = $this->post->{$extendField->field};
if(is_array($postFieldData[$bugID])) $postFieldData[$bugID] = join(',', $postFieldData[$bugID]);
if(is_array($postFieldData[$bugID])) $postFieldData[$bugID] = implode(',', $postFieldData[$bugID]);
$activateBugs[$bugID][$extendField->field] = htmlSpecialString($postFieldData[$bugID]);
}
@@ -1524,7 +1436,7 @@ class bugModel extends model
$builds = $this->loadModel('build')->getBuildPairs(array_unique($productIdList), 'all', $params = '');
/* Process the openedBuild and resolvedBuild fields. */
foreach($bugs as $key => $bug)
foreach($bugs as $bug)
{
$openBuildIdList = explode(',', $bug->openedBuild);
$openedBuild = '';
@@ -1618,7 +1530,7 @@ class bugModel extends model
}
else
{
if($this->session->$queryName == false) $this->session->set($queryName, ' 1 = 1');
if($this->session->$queryName === false) $this->session->set($queryName, ' 1 = 1');
}
$query = $this->session->$queryName;
$query = preg_replace('/`(\w+)`/', 't1.`$1`', $query);
@@ -1711,7 +1623,7 @@ class bugModel extends model
if($type == 'bysearch')
{
$queryID = (int)$param;
if($this->session->projectBugQuery == false) $this->session->set('projectBugQuery', ' 1 = 1');
if($this->session->projectBugQuery === false) $this->session->set('projectBugQuery', ' 1 = 1');
if($queryID)
{
$query = $this->loadModel('search')->getQuery($queryID);
@@ -1782,7 +1694,7 @@ class bugModel extends model
if($type == 'bysearch')
{
$queryID = (int)$param;
if($this->session->executionBugQuery == false) $this->session->set('executionBugQuery', ' 1 = 1');
if($this->session->executionBugQuery === false) $this->session->set('executionBugQuery', ' 1 = 1');
if($queryID)
{
$query = $this->loadModel('search')->getQuery($queryID);
@@ -1818,7 +1730,7 @@ class bugModel extends model
{
if($build) $conditions[] = "FIND_IN_SET('$build', t1.openedBuild)";
}
$condition = join(' OR ', $conditions);
$condition = implode(' OR ', $conditions);
$condition = "($condition)";
}
$bugs = $this->dao->select("t1.*, IF(t1.`pri` = 0, {$this->config->maxPriValue}, t1.`pri`) as priOrder, IF(t1.`severity` = 0, {$this->config->maxPriValue}, t1.`severity`) as severityOrder")->from(TABLE_BUG)->alias('t1')
@@ -1876,7 +1788,7 @@ class bugModel extends model
->andWhere('t1.date')->lt($minBegin)
->fetchPairs('id', 'id');
$bugs = $this->dao->select('*')->from(TABLE_BUG)->where('deleted')->eq(0)
return $this->dao->select('*')->from(TABLE_BUG)->where('deleted')->eq(0)
->andWhere('product')->eq($productID)
->andWhere('toStory')->eq(0)
->andWhere('openedDate')->ge($minBegin)
@@ -1887,8 +1799,6 @@ class bugModel extends model
->beginIF($branch !== '')->andWhere('branch')->in("0,$branch")->fi()
->page($pager)
->fetchAll();
return $bugs;
}
/**
@@ -1976,7 +1886,7 @@ class bugModel extends model
$condition .= " OR (`execution` = '{$execution->id}' AND openedDate < '{$execution->begin}')";
}
$bugs = $this->dao->select('*')->from(TABLE_BUG)
return $this->dao->select('*')->from(TABLE_BUG)
->where('resolvedDate')->ge($minBegin)
->andWhere('resolution')->ne('postponed')
->andWhere('product')->eq($productID)
@@ -1987,7 +1897,6 @@ class bugModel extends model
->orderBy('openedDate ASC')
->page($pager)
->fetchAll('id');
return $bugs;
}
/**
@@ -2394,7 +2303,7 @@ class bugModel extends model
{
$datas = $this->dao->select('pri AS name, COUNT(*) AS value')->from(TABLE_BUG)->where($this->reportCondition())->groupBy('name')->orderBy('value DESC')->fetchAll('name');
if(!$datas) return array();
foreach($datas as $status => $data) $data->name = $this->lang->bug->report->bugsPerPri->graph->xAxisName . ':' . zget($this->lang->bug->priList, $data->name);
foreach($datas as $data) $data->name = $this->lang->bug->report->bugsPerPri->graph->xAxisName . ':' . zget($this->lang->bug->priList, $data->name);
return $datas;
}
@@ -2528,7 +2437,7 @@ class bugModel extends model
}
else
{
if($this->session->bugQuery == false) $this->session->set('bugQuery', ' 1 = 1');
if($this->session->bugQuery === false) $this->session->set('bugQuery', ' 1 = 1');
}
$bugQuery = $this->getBugQuery($this->session->bugQuery);
@@ -2557,7 +2466,7 @@ class bugModel extends model
if($branch !== 'all' and strpos($bugQuery, '`branch` =') === false) $bugQuery .= " AND `branch` in('0','$branch')";
if(strpos($bugQuery, $allBranch) !== false) $bugQuery = str_replace($allBranch, '1', $bugQuery);
$bugs = $this->dao->select("*, IF(`pri` = 0, {$this->config->maxPriValue}, `pri`) as priOrder, IF(`severity` = 0, {$this->config->maxPriValue}, `severity`) as severityOrder")->from(TABLE_BUG)->where($bugQuery)
return $this->dao->select("*, IF(`pri` = 0, {$this->config->maxPriValue}, `pri`) as priOrder, IF(`severity` = 0, {$this->config->maxPriValue}, `severity`) as severityOrder")->from(TABLE_BUG)->where($bugQuery)
->beginIF(!$this->app->user->admin)->andWhere('execution')->in('0,' . $this->app->user->view->sprints)->fi()
->beginIF($excludeBugs)->andWhere('id')->notIN($excludeBugs)->fi()
@@ -2570,8 +2479,8 @@ class bugModel extends model
->andWhere('deleted')->eq(0)
->beginIF(!$this->app->user->admin)->andWhere('project')->in('0,' . $this->app->user->view->projects)->fi()
->orderBy($orderBy)->page($pager)->fetchAll();
return $bugs;
->orderBy($orderBy)->page($pager)
->fetchAll();
}
/**
@@ -2749,13 +2658,13 @@ class bugModel extends model
public function linkBugToBuild($bugs, $resolvedBuild)
{
if(empty($resolvedBuild) or $resolvedBuild == 'trunk') return true;
if(is_array($bugs)) $bugs = join(',', $bugs);
if(is_array($bugs)) $bugs = implode(',', $bugs);
$build = $this->dao->select('id,product,bugs')->from(TABLE_BUILD)->where('id')->eq($resolvedBuild)->fetch();
$buildBugs = $build->bugs . ',' . $bugs;
$buildBugs = explode(',', trim($buildBugs, ','));
$buildBugs = array_unique($buildBugs);
$this->dao->update(TABLE_BUILD)->set('bugs')->eq(join(',', $buildBugs))->where('id')->eq($resolvedBuild)->exec();
$this->dao->update(TABLE_BUILD)->set('bugs')->eq(implode(',', $buildBugs))->where('id')->eq($resolvedBuild)->exec();
$release = $this->dao->select('id,bugs')->from(TABLE_RELEASE)->where('product')->eq($build->product)->andWhere("(FIND_IN_SET('$resolvedBuild', build) or shadow = $resolvedBuild)")->andWhere('deleted')->eq('0')->fetch();
if($release)
@@ -2763,7 +2672,7 @@ class bugModel extends model
$releaseBugs = $release->bugs . ',' . $bugs;
$releaseBugs = explode(',', trim($releaseBugs, ','));
$releaseBugs = array_unique($releaseBugs);
$this->dao->update(TABLE_RELEASE)->set('bugs')->eq(join(',', $releaseBugs))->where('id')->eq($release->id)->exec();
$this->dao->update(TABLE_RELEASE)->set('bugs')->eq(implode(',', $releaseBugs))->where('id')->eq($release->id)->exec();
}
return true;
+93 -2
View File
@@ -10,7 +10,7 @@ class bugTao extends bugModel
* @access protected
* @return object|false
*/
protected function fetchBugInfo(int $bugID): object|false
protected function fetchBugInfo(string $bugID): object|false
{
return $this->dao->select('t1.*, t2.name AS executionName, t3.title AS storyTitle, t3.status AS storyStatus, t3.version AS latestStoryVersion, t4.name AS taskName, t5.title AS planName')
->from(TABLE_BUG)->alias('t1')
@@ -136,7 +136,7 @@ class bugTao extends bugModel
* @access protected
* @return array
*/
protected function getCasesFromBug(int $bugID): array
protected function getCasesFromBug(string $bugID): array
{
return $this->dao->select('id, title')->from(TABLE_CASE)->where('`fromBug`')->eq($bugID)->fetchPairs();
}
@@ -169,6 +169,97 @@ class bugTao extends bugModel
return $this->dao->findById($objectID)->from($table)->fields($field)->fetch($field);
}
/**
* 更新完bug后的相关处理。
* Relevant processing after updating bug.
*
* @param object $bug
* @param object $oldBug
* @access protected
* @return void
*/
protected function afterUpdate(object $bug, object $oldBug)
{
/* 解除旧的版本关联关系,关联新的版本。*/
/* Link bug to build and release. */
if($bug->resolution == 'fixed' && !empty($bug->resolvedBuild) && $bug->resolvedBuild != $oldBug->resolvedBuild)
{
if(!empty($oldBug->resolvedBuild)) $this->loadModel('build')->unlinkBug($oldBug->resolvedBuild, $bug->id);
$this->linkBugToBuild($bug->id, $bug->resolvedBuild);
}
/* 解除旧的计划关联关系,关联新的计划。*/
/* Link new plan, unlink old plan. */
if($bug->plan != $oldBug->plan)
{
$this->loadModel('action');
if(!empty($oldBug->plan)) $this->action->create('productplan', $oldBug->plan, 'unlinkbug', '', $bug->id);
if(!empty($bug->plan)) $this->action->create('productplan', $bug->plan, 'linkbug', '', $bug->id);
}
$this->updateLinkBug($bug->id, $bug->linkBug, $oldBug->linkBug);
/* 给bug解决者积分奖励。*/
/* Add score to resolvedby. */
if(!empty($bug->resolvedBy)) $this->loadModel('score')->create('bug', 'resolve', $bug->id);
/* 更新bug所属看板的泳道。*/
/* Update the lane of the bug kanban. */
if($bug->execution and $bug->status != $oldBug->status) $this->loadModel('kanban')->updateLane($bug->execution, 'bug');
/* 更新反馈的状态。*/
/* Update the status of feedback. */
if(($this->config->edition != 'open') && $oldBug->feedback) $this->loadModel('feedback')->updateStatus('bug', $oldBug->feedback, $bug->status, $oldBug->status);
/* 更新bug的附件。*/
/* Update the files of bug. */
$this->loadModel('file')->processFile4Object('bug', $oldBug, $bug);
return !dao::isError();
}
/**
* 更新相关bug。
* Update the linked bug.
*
* @param int $bugID
* @param string $linkBug
* @param string $oldLinkBug
* @access private
* @return bool
*/
private function updateLinkBug(int $bugID, string $linkBug, string $oldLinkBug): bool
{
return false;
$linkBugs = explode(',', $linkBug);
$oldLinkBugs = explode(',', $oldLinkBug);
$addedLinkBugs = array_diff($linkBugs, $oldLinkBugs);
$removedLinkBugs = array_diff($oldLinkBugs, $linkBugs);
$changedLinkBugs = array_merge($addedLinkBugs, $removedLinkBugs);
$changedLinkBugs = $this->dao->select('id, linkbug')->from(TABLE_BUG)->where('id')->in(array_filter($changedLinkBugs))->fetchPairs();
foreach($changedLinkBugs as $changedBugID => $linkBugs)
{
if(in_array($changeBugID, $addedLinkBugs))
{
$currentLinkBug = $bugID;
if(!empty($linkBugs)) $currentLinkBug = trim($linkBugs, ',') . ',' . $bugID;
}
else
{
$linkBugs = explode(',', $linkBugs);
unset($linkBugs[array_search($bugID, $linkBugs)]);
$currentLinkBug = implode(',', $linkBugs);
}
$this->dao->update(TABLE_BUG)->set('linkBug')->eq($linkBug)->where('id')->eq($changeBugID)->exec();
}
return !dao::isError();
}
/**
* Call checkDelayBug in foreach to check if the bug is delay.
* 循环调用checkDelayBug,检查bug是否延期
+3 -2
View File
@@ -795,10 +795,11 @@ class bugTest
$_POST[$field] = $value;
}
}
$_POST['closedDate'] = '';
$_POST['deleteFiles'] = array();
$object->files = array();
$change = $this->objectModel->update($bugID);
$change = $this->objectModel->update((object)$_POST, $object);
if($change == array()) $change = '没有数据更新';
unset($_POST);
+4 -4
View File
@@ -45,7 +45,7 @@ $tester->loadModel('bug');
initData();
r($tester->bug->getByID(2)) && p('pri,type') && e('1,codeerror'); //获取ID等于2的bug
r($tester->bug->getByID(3)) && p('title,status') && e('bug3,active'); //获取ID等于3的bug
r($tester->bug->getByID(4)) && p('severity,openedBuild') && e('3,trunk'); //获取ID等于4的bug
r($tester->bug->getByID(1)) && p('title') && e('0'); //获取不存在的bug
r($tester->bug->getByID(2)) && p('pri,type') && e('1,codeerror'); //获取ID等于2的bug
r($tester->bug->getByID(3)) && p('title,status') && e('bug3,active'); //获取ID等于3的bug
r($tester->bug->getByID(4)) && p('severity,openedBuild') && e('3,trunk'); //获取ID等于4的bug
r($tester->bug->getByID(1)) && p('title') && e('0'); //获取不存在的bug
+48 -19
View File
@@ -1,33 +1,62 @@
#!/usr/bin/env php
<?php
include dirname(__FILE__, 5) . "/test/lib/init.php"; su('admin');
include dirname(__FILE__, 5) . "/test/lib/init.php";
include dirname(__FILE__, 2) . '/bug.class.php';
su('admin');
function initData()
{
$data = zdTable('bug');
$data->id->range('1-5');
$data->product->range('1-5');
$data->branch->range('0-1');
$data->project->range('0-5');
$data->execution->range('0-5');
$data->title->prefix("BUG")->range('1-5');
$data->openedBuild->range('1-5');
$data->type->range("[codeerror]");
$data->status->range("[active]");
$data->pri->range("[3]");
$data->severity->range("[3]");
$data->gen(4);
}
/**
title=bugModel->update();
timeout=0
cid=1
pid=1
测试更新bug名称 >> title,BUG1,john
测试更新bug类型 >> type,codeerror,config
测试更新bug名称和类型 >> title,john,jack;type,config,install
测试不更改bug名称 >> 没有数据更新
测试不更改bug类型 >> 没有数据更新
- 测试更新bug名称
- 第0条的field属性 @title
- 第0条的old属性 @BUG1
- 第0条的new属性 @john
- 测试更新bug类型
- 第0条的field属性 @type
- 第0条的old属性 @codeerror
- 第0条的new属性 @config
- 测试不更改bug名称 @没有数据更新
- 测试不更改bug类型 @没有数据更新
*/
$projectIdList = array('1', '2');
initData();
$t_uptitle = array('title' => 'john');
$t_uptype = array('type' => 'config');
$t_typetitle = array('title' => 'jack', 'type' => 'install');
$t_untitle = array('title' => 'jack');
$t_untype = array('type' => 'install');
$bugIdList = array('1', '2');
$bug=new bugTest();
r($bug->updateObject($projectIdList[0], $t_uptitle)) && p('0:field,old,new') && e('title,BUG1,john'); // 测试更新bug名称
r($bug->updateObject($projectIdList[0], $t_uptype)) && p('0:field,old,new') && e('type,codeerror,config'); // 测试更新bug类型
r($bug->updateObject($projectIdList[0], $t_typetitle)) && p('0:field,old,new;1:field,old,new') && e('title,john,jack;type,config,install'); // 测试更新bug名称和类型
r($bug->updateObject($projectIdList[0], $t_untitle)) && p() && e('没有数据更新'); // 测试不更改bug名称
r($bug->updateObject($projectIdList[0], $t_untype)) && p() && e('没有数据更新'); // 测试不更改bug类型
$t_uptitle = array('title' => 'john');
$t_uptype = array('type' => 'config');
$t_untitle = array('title' => 'john');
$t_untype = array('type' => 'config');
$bug = new bugTest();
r($bug->updateObject($bugIdList[0], $t_uptitle)) && p('0:field,old,new') && e('title,BUG1,john'); // 测试更新bug名称
r($bug->updateObject($bugIdList[0], $t_uptype)) && p('0:field,old,new') && e('type,codeerror,config'); // 测试更新bug类型
r($bug->updateObject($bugIdList[0], $t_untitle)) && p() && e('没有数据更新'); // 测试不更改bug名称
r($bug->updateObject($bugIdList[0], $t_untype)) && p() && e('没有数据更新'); // 测试不更改bug类型
+2 -2
View File
@@ -37,7 +37,7 @@ if($this->app->tab == 'project') js::set('objectID', $bug->project);
?>
<div class='main-content' id='mainContent'>
<form method='post' target='hiddenwin' enctype='multipart/form-data' id='dataform'>
<form method='post' target='hiddenwin' enctype='multipart/form-data' id='dataform ajaxForm' class='form-ajax'>
<div class='main-header'>
<h2>
<span class='label label-id'><?php echo $bug->id;?></span>
@@ -112,7 +112,7 @@ if($this->app->tab == 'project') js::set('objectID', $bug->project);
<td>
<div class='input-group' id='moduleIdBox'>
<?php
echo html::select('module', $moduleOptionMenu, $currentModuleID, "onchange='loadModuleRelated()' class='form-control chosen'");
echo html::select('module', $moduleOptionMenu, $bug->module, "onchange='loadModuleRelated()' class='form-control chosen'");
if(count($moduleOptionMenu) == 1)
{
echo "<span class='input-group-addon'>";
+316 -1
View File
@@ -29,7 +29,6 @@ class bugZen extends bug
return $bug;
}
/**
* 创建bug。
* Create a bug.
@@ -100,6 +99,159 @@ class bugZen extends bug
if($from && is_callable(array($this, $this->config->bug->fromObjects[$from]['callback']))) call_user_func(array($this, $this->config->bug->fromObjects[$from]['callback']), $bugID);
}
/**
* 处理更新请求数据。
* Processing request data.
*
* @param string $bugID
* @param form $formData
* @access protected
* @return object|false
*/
protected function prepareEditExtras(form $formData, object $oldBug): object|false
{
if($oldBug->lastEditedDate != $formData->data->lastEditedDate)
{
dao::$errors[] = $this->lang->error->editedByOther;
return false;
}
$now = helper::now();
$bug = $formData->add('id', $oldBug->id)
->setDefault('product', $oldBug->product)
->setDefault('deleteFiles', array())
->setDefault('lastEditedBy', $this->app->user->account)
->add('lastEditedDate', $now)
->join('openedBuild,mailto,linkBug,os,browser', ',')
->setIF($formData->data->assignedTo != $oldBug->assignedTo, 'assignedDate', $now)
->setIF($formData->data->resolvedBy != '' && $formData->data->resolvedDate == '', 'resolvedDate', $now)
->setIF($formData->data->resolution != '' && $formData->data->resolvedDate == '', 'resolvedDate', $now)
->setIF($formData->data->resolution != '' && $formData->data->resolvedBy == '', 'resolvedBy', $this->app->user->account)
->setIF($formData->data->closedDate != '' && $formData->data->closedBy == '', 'closedBy', $this->app->user->account)
->setIF($formData->data->closedBy != '' && $formData->data->closedDate == '', 'closedDate', $now)
->setIF($formData->data->closedBy != '' || $formData->data->closedDate != '', 'assignedTo', 'closed')
->setIF($formData->data->closedBy != '' || $formData->data->closedDate != '', 'assignedDate', $now)
->setIF($formData->data->resolution != '' || $formData->data->resolvedDate != '', 'status', 'resolved')
->setIF($formData->data->closedBy != '' || $formData->data->closedDate != '', 'status', 'closed')
->setIF(($formData->data->resolution != '' || $formData->data->resolvedDate != '') && $formData->data->assignedTo == '', 'assignedTo', $oldBug->openedBy)
->setIF(($formData->data->resolution != '' || $formData->data->resolvedDate != '') && $formData->data->assignedTo == '', 'assignedDate', $now)
->setIF($formData->data->resolution == '' && $formData->data->resolvedDate == '', 'status', 'active')
->setIF($formData->data->resolution != '' && $formData->data->resolution != 'duplicate', 'duplicateBug', 0)
->setIF($formData->data->assignedTo == '' && $oldBug->status == 'closed', 'assignedTo', 'closed')
->setIF($formData->data->resolution != '', 'confirmed', 1)
->setIF($formData->data->story && $formData->data->story != $oldBug->story, 'storyVersion', $this->loadModel('story')->getVersion($formData->data->story))
->stripTags($this->config->bug->editor->edit['id'], $this->config->allowedTags)
->get();
$bug = $this->loadModel('file')->processImgURL($bug, $this->config->bug->editor->create['id'], $bug->uid);
return $bug;
}
/**
* 返回错误信息。
* return error.
*
* @access protected
* @return array|viod
*/
protected function errorEdit()
{
if(defined('RUN_MODE') && RUN_MODE == 'api') return array('status' => 'error', 'message' => dao::getError());
return array('result' => 'fail', 'message' => dao::getError());
}
/**
* 更新成功后的相关处理。
* Relevant processing after updating bug.
*
* @param int $bugID
* @param string $comment
* @param array $changes
* @access protected
* @return void
*/
protected function processAfterEdit(int $bugID, string $comment, array $changes)
{
if($this->post->comment || !empty($changes))
{
$action = !empty($changes) ? 'Edited' : 'Commented';
$actionID = $this->action->create('bug', $bugID, $action, $comment);
$this->action->logHistory($actionID, $changes);
}
}
/**
* 返回不同的结果。
* Response after updating bug.
*
* @param string $bugID
* @param array $changes
* @param string $kanbanGroup
* @access protected
* @return array
*/
protected function responseAfterEdit(string $bugID, array $changes, string $kanbanGroup): array
{
if(defined('RUN_MODE') && RUN_MODE == 'api') return array('status' => 'success', 'data' => $bugID);
/* 如果bug转任务,如果bug的状态发生变化,提示是否更新任务状态。*/
/* This bug has been converted to a task, update the status of the relatedtask or not. */
$bug = $this->bug->getByID($bugID);
if($bug->toTask and !empty($changes))
{
foreach($changes as $change)
{
if($change['field'] != 'status') continue;
return array('result' => 'success', 'confirm' => array('note' => $this->lang->bug->remindTask, 'confirmURL' => $this->createLink('task', 'view', "taskID=$bug->toTask"), 'cancelURL' => $this->server->HTTP_REFERER));
}
}
/* 弹窗里编辑bug的返回。*/
/* Response when edit in modal. */
if(isonlybody())
{
/* 在执行应用下,编辑看板中的bug数据时,更新看板数据。*/
/* Update kanban data after edited bug in kanban. */
if($this->app->tab == 'execution')
{
$this->loadModel('kanban');
$execution = $this->loadModel('execution')->getByID($bug->execution);
$execLaneType = $this->session->execLaneType ? $this->session->execLaneType : 'all';
/* 1.看板类型的执行。*/
/* 1.The kanban exectuion. */
if(isset($execution->type) && $execution->type == 'kanban')
{
$rdSearchValue = $this->session->rdSearchValue ? $this->session->rdSearchValue : '';
$kanbanData = $this->kanban->getRDKanban($bug->execution, $execLaneType, 'id_desc', 0, $kanbanGroup, $rdSearchValue);
$kanbanData = json_encode($kanbanData);
return array('result' => 'success', 'closeModal' => true, 'callback' => "updateKanban($kanbanData)");
}
/* 2.执行中的看板。*/
/* 2.The kanban of execution. */
else
{
$execGroupBy = $this->session->execGroupBy ? $this->session->execGroupBy : 'default';
$taskSearchValue = $this->session->taskSearchValue ? $this->session->taskSearchValue : '';
$kanbanData = $this->kanban->getExecutionKanban($bug->execution, $execLaneType, $execGroupBy, $taskSearchValue);
$kanbanType = $execLaneType == 'all' ? 'bug' : key($kanbanData);
$kanbanData = json_encode($kanbanData[$kanbanType]);
return array('result' => 'success', 'closeModal' => true, 'callback' => "updateKanban(\"bug\", $kanbanData)");
}
}
return array('result' => 'success', 'closeModal' => true);
}
return array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => $this->createLink('bug', 'view', "bugID=$bugID"));
}
/**
* 为create方法添加动态。
* Add action for create function.
@@ -625,6 +777,169 @@ class bugZen extends bug
$this->app->loadLang('release');
}
/**
* 设置编辑页面的导航。
* Set edit menu.
*
* @param object $bug
* @access protected
* @return void
*/
protected function setEditMenu(object $bug)
{
if($this->app->tab == 'project') $this->project->setMenu($bug->project);
if($this->app->tab == 'execution') $this->execution->setMenu($bug->execution);
if($this->app->tab == 'qa') $this->qa->setMenu($this->products, $bug->product, $bug->branch);
/* 是否有用?*/
if($this->app->tab == 'devops')
{
session_write_close();
$repoPairs = $this->loadModel('repo')->getRepoPairs('project', $bug->project);
$this->repo->setMenu($repoPairs);
$this->lang->navGroup->bug = 'devops';
}
}
/**
* 获取页面所需的变量, 并输出到前台。
* Get the data required by the view page and output.
*
* @param object $bug
* @access protected
* @return void
*/
protected function buildEditForm(object $bug)
{
/* 删掉当前bug类型不属于的并且已经弃用的类型。*/
/* Unset discarded types. */
foreach($this->config->bug->discardedTypes as $type)
{
if($bug->type != $type) unset($this->lang->bug->typeList[$type]);
}
$this->loadModel('project');
$this->loadModel('branch');
$this->loadModel('execution');
$this->loadModel('build');
$product = $this->product->getByID($bug->product);
$execution = $this->execution->getByID($bug->execution);
/* 获取影响版本列表和解决版本列表。*/
/* Get the openedBuilds and resolvedBuilds. */
$objectID = $bug->execution ? $bug->execution : $bug->project;
$objectType = $bug->project ? 'project' : '';
$objectType = $bug->execution ? 'execution' : $objectType;
$allBuilds = $this->loadModel('build')->getBuildPairs($bug->product, 'all', 'noempty');
$openedBuilds = $this->build->getBuildPairs($bug->product, $bug->branch, $params = 'noempty,noterminate,nodone,withbranch,noreleased', $objectID, $objectType, $bug->openedBuild);
$resolvedBuilds = $openedBuilds;
if(($bug->resolvedBuild) && isset($allBuilds[$bug->resolvedBuild])) $resolvedBuilds[$bug->resolvedBuild] = $allBuilds[$bug->resolvedBuild];
/* 获取分支列表。*/
/* Get the branch options. */
if($this->app->tab == 'execution' || $this->app->tab == 'project') $objectID = $this->app->tab == 'project' ? $bug->project : $bug->execution;
$branches = $this->branch->getList($bug->product, isset($objectID) ? $objectID : 0, 'all');
$branchTagOption = array();
foreach($branches as $branchInfo) $branchTagOption[$branchInfo->id] = $branchInfo->name . ($branchInfo->status == 'closed' ? ' (' . $this->lang->branch->statusList['closed'] . ')' : '');
if(!isset($branchTagOption[$bug->branch]))
{
$bugBranch = $this->branch->getById($bug->branch, $bug->product, '');
if($bug->branch == BRANCH_MAIN) $branchTagName = $bugBranch;
if($bug->branch != BRANCH_MAIN)
{
$branchTagName = $bugBranch->name;
if($bugBranch->status == 'closed') $branchTagName .= " ({$this->lang->branch->statusList['closed']})";
}
$branchTagOption[$bug->branch] = $branchTagName;
}
/* 获取moduleOptionMenu。*/
/* Get moduleOptionMenu. */
$moduleOptionMenu = $this->tree->getOptionMenu($bug->product, $viewType = 'bug', $startModuleID = 0, $bug->branch);
if(!isset($moduleOptionMenu[$bug->module])) $moduleOptionMenu += $this->tree->getModulesName($bug->module);
/* 获取指派给用户列表。*/
/* Get assigned to member. */
if($bug->execution)
{
$assignedToList = $this->user->getTeamMemberPairs($bug->execution, 'execution');
}
elseif($bug->project)
{
$assignedToList = $this->project->getTeamMemberPairs($bug->project);
}
else
{
$assignedToList = $this->bug->getProductMemberPairs($bug->product, $bug->branch);
$assignedToList = array_filter($assignedToList);
if(empty($assignedToList)) $assignedToList = $this->user->getPairs('devfirst|noclosed');
}
if($bug->assignedTo and !isset($assignedToList[$bug->assignedTo]) and $bug->assignedTo != 'closed')
{
$assignedTo = $this->user->getById($bug->assignedTo);
$assignedToList[$bug->assignedTo] = $assignedTo->realname;
}
if($bug->status == 'closed') $assignedToList['closed'] = 'Closed';
/* 获取该bug关联产品和分支下的bug列表。*/
/* Get bugs of current product. */
$branch = '';
if($product->type == 'branch') $branch = $bug->branch > 0 ? "{$bug->branch},0" : '0';
$productBugs = $this->bug->getProductBugPairs($bug->product, $branch);
unset($productBugs[$bug->id]);
/* 获取执行列表。*/
/* Get execution pairs. */
$executions = array('') + $this->product->getExecutionPairsByProduct($bug->product, $bug->branch, 'id_desc', $bug->project);
if(!empty($bug->execution) and empty($executions[$bug->execution])) $executions[$execution->id] = $execution->name . "({$this->lang->bug->deleted})";
/* 获取项目列表。*/
/* Get project pairs. */
$projects = array('') + $this->product->getProjectPairsByProduct($bug->product, $bug->branch);
if(!empty($bug->project) and empty($projects[$bug->project]))
{
$project = $this->project->getByID($bug->project);
$projects[$project->id] = $project->name . "({$this->lang->bug->deleted})";
}
/* 如果产品列表没有bug相关的产品,把该产品加入产品列表。*/
/* Add product related by the bug when it is not in the products. */
if(!isset($this->products[$bug->product]))
{
$this->products[$bug->product] = $product->name;
$this->view->products = $this->products;
}
if($product->shadow) $this->view->project = $this->project->getByShadowProduct($bug->product);
$this->view->title = $this->lang->bug->edit . "BUG #$bug->id $bug->title - " . $this->products[$bug->product];
$this->view->bug = $bug;
$this->view->product = $product;
$this->view->execution = $execution;
$this->view->branchTagOption = $branchTagOption;
$this->view->moduleOptionMenu = $moduleOptionMenu;
$this->view->plans = $this->loadModel('productplan')->getPairs($bug->product, $bug->branch, '', true);
$this->view->projects = $projects;
$this->view->executions = $executions;
$this->view->projectExecutionPairs = $this->project->getProjectExecutionPairs();
$this->view->stories = $bug->execution ? $this->story->getExecutionStoryPairs($bug->execution) : $this->story->getProductStoryPairs($bug->product, $bug->branch, 0, 'all', 'id_desc', 0, 'full', 'story', false);
$this->view->tasks = $this->task->getExecutionTaskPairs($bug->execution);
$this->view->testtasks = $this->loadModel('testtask')->getPairs($bug->product, $bug->execution, $bug->testtask);
$this->view->cases = array('') + $this->loadModel('testcase')->getPairsByProduct($bug->product, array(0, $bug->branch));
$this->view->productBugs = $productBugs;
$this->view->openedBuilds = $openedBuilds;
$this->view->resolvedBuilds = array('') + $resolvedBuilds;
$this->view->users = $this->user->getPairs('', "$bug->assignedTo,$bug->resolvedBy,$bug->closedBy,$bug->openedBy");
$this->view->assignedToList = $assignedToList;
$this->view->actions = $this->action->getList('bug', $bug->id);
$this->display();
}
/**
* 如果不是弹窗,调用该方法为查看bug设置导航。
* If it's not a iframe, call this method to set menu for view bug page.