* adjust for project release link story and bug.

This commit is contained in:
wangyidong
2022-11-11 10:47:01 +08:00
parent ca0d6b9c36
commit 8a178c72fe
7 changed files with 103 additions and 52 deletions
+2 -1
View File
@@ -3263,11 +3263,12 @@ class ztSessionHandler
public function write($id, $sessData)
{
$sessFile = $this->getSessionFile($id);
touch($sessFile);
touch($this->rawFile);
if(md5_file($sessFile) == md5($sessData)) return true;
if(file_put_contents($sessFile, $sessData))
{
if(!file_exists($this->rawFile)) touch($this->rawFile);
if(strpos($sessData, 'user|') !== false)
{
$rawSessContent = (string) file_get_contents($this->rawFile);
+36 -12
View File
@@ -1969,25 +1969,40 @@ class bugModel extends model
*/
public function getProductLeftBugs($build, $productID, $branch = '', $linkedBugs = '', $pager = null)
{
$build = $this->dao->select('*')->from(TABLE_BUILD)->where('id')->eq($build)->fetch();
if(empty($build->execution)) return array();
$builds = $this->dao->select('*')->from(TABLE_BUILD)->where('id')->in($build)->fetchAll('id');
$executionIdList = array();
foreach($builds as $build)
{
if(empty($build->execution)) continue;
$executionIdList[$build->execution] = $build->execution;
}
if(empty($executionIdList)) return array();
$executions = $this->dao->select('*')->from(TABLE_EXECUTION)->where('id')->in($executionIdList)->fetch();
$minBegin = '';
$maxEnd = '';
foreach($executions as $execution)
{
if(empty($minBegin) or $minBegin > $execution->begin) $minBegin = $execution->begin;
if(empty($maxEnd) or $maxEnd < $execution->end) $maxEnd = $execution->end;
}
$execution = $this->dao->select('*')->from(TABLE_EXECUTION)->where('id')->eq($build->execution)->fetch();
$beforeBuilds = $this->dao->select('t1.id')->from(TABLE_BUILD)->alias('t1')
->leftJoin(TABLE_EXECUTION)->alias('t2')->on('t1.execution=t2.id')
->where('t1.product')->eq($productID)
->andWhere('t2.status')->ne('done')
->andWhere('t2.deleted')->eq(0)
->andWhere('t1.deleted')->eq(0)
->andWhere('t1.date')->lt($execution->begin)
->andWhere('t1.date')->lt($minBegin)
->fetchPairs('id', 'id');
$bugs = $this->dao->select('*')->from(TABLE_BUG)->where('deleted')->eq(0)
->andWhere('product')->eq($productID)
->andWhere('toStory')->eq(0)
->andWhere('openedDate')->ge($execution->begin)
->andWhere('openedDate')->le($execution->end)
->andWhere("(status = 'active' OR resolvedDate > '{$execution->end}')")
->andWhere('openedDate')->ge($minBegin)
->andWhere('openedDate')->le($maxEnd)
->andWhere("(status = 'active' OR resolvedDate > '{$maxEnd}')")
->andWhere('openedBuild')->notin($beforeBuilds)
->beginIF($linkedBugs)->andWhere('id')->notIN($linkedBugs)->fi()
->beginIF($branch !== '')->andWhere('branch')->in("0,$branch")->fi()
@@ -2067,17 +2082,26 @@ class bugModel extends model
*/
public function getReleaseBugs($buildID, $productID, $branch = 0, $linkedBugs = '', $pager = null)
{
$execution = $this->dao->select('t1.id,t1.begin')->from(TABLE_EXECUTION)->alias('t1')
$executions = $this->dao->select('t1.id,t1.begin')->from(TABLE_EXECUTION)->alias('t1')
->leftJoin(TABLE_BUILD)->alias('t2')->on('t1.id = t2.execution')
->where('t2.id')->eq($buildID)
->fetch();
->where('t2.id')->in($buildID)
->fetchAll('id');
$condition = 'execution NOT ' . helper::dbIN(array_keys($executions));
$minBegin = '';
foreach($executions as $execution)
{
if(empty($minBegin) or $minBegin > $execution->begin) $minBegin = $execution->begin;
$condition .= " OR (execution = '{$execution->id}' AND openedDate < '{$execution->begin}')";
}
$bugs = $this->dao->select('*')->from(TABLE_BUG)
->where('resolvedDate')->ge($execution->begin)
->where('resolvedDate')->ge($minBegin)
->andWhere('resolution')->ne('postponed')
->andWhere('product')->eq($productID)
->beginIF($linkedBugs)->andWhere('id')->notIN($linkedBugs)->fi()
->beginIF($branch)->andWhere('branch')->in("0,$branch")->fi()
->andWhere("(execution != '$execution->id' OR (execution = '$execution->id' and openedDate < '$execution->begin'))")
->andWhere("$condition)")
->andWhere('deleted')->eq(0)
->orderBy('openedDate ASC')
->page($pager)
+10 -5
View File
@@ -440,7 +440,7 @@ class productModel extends model
->from(TABLE_PROJECTPRODUCT)->alias('t1')
->leftJoin(TABLE_PRODUCT)->alias('t2')->on('t1.product = t2.id')
->where('t2.deleted')->eq(0)
->beginIF(!empty($projectID))->andWhere('t1.project')->eq($projectID)->fi()
->beginIF(!empty($projectID))->andWhere('t1.project')->in($projectID)->fi()
->beginIF(!$this->app->user->admin and $this->config->vision == 'rnd')->andWhere('t2.id')->in($views)->fi()
->andWhere('t2.vision')->eq($this->config->vision)
->beginIF(strpos($status, 'noclosed') !== false)->andWhere('t2.status')->ne('closed')->fi()
@@ -1398,15 +1398,20 @@ class productModel extends model
{
if(empty($productID)) return array();
$project = $this->loadModel('project')->getByID($projectID);
$orderBy = $project && $project->model == 'waterfall' ? 't2.begin_asc,t2.id_asc' : 't2.begin_desc,t2.id_desc';
$projects = $this->loadModel('project')->getByIdList($projectID);
$hasWaterfall = false;
foreach($projects as $project)
{
if($project->model == 'waterfall') $hasWaterfall = true;
}
$orderBy = $hasWaterfall ? 't2.begin_asc,t2.id_asc' : 't2.begin_desc,t2.id_desc';
$executions = $this->dao->select('t2.id,t2.name,t2.grade,t2.parent,t2.attribute,t2.multiple,t3.name as projectName')->from(TABLE_PROJECTPRODUCT)->alias('t1')
->leftJoin(TABLE_EXECUTION)->alias('t2')->on('t1.project = t2.id')
->leftJoin(TABLE_PROJECT)->alias('t3')->on('t2.project = t3.id')
->where('t1.product')->eq($productID)
->andWhere('t2.type')->in('sprint,kanban,stage')
->beginIF($projectID)->andWhere('t2.project')->eq($projectID)->fi()
->beginIF($projectID)->andWhere('t2.project')->in($projectID)->fi()
->beginIF($branch !== '')->andWhere('t1.branch')->in($branch)->fi()
->beginIF(!$this->app->user->admin)->andWhere('t2.id')->in($this->app->user->view->sprints)->fi()
->beginIF(strpos($mode, 'noclosed') !== false)->andWhere('t2.status')->ne('closed')->fi()
@@ -1417,7 +1422,7 @@ class productModel extends model
/* The waterfall project needs to show the hierarchy and remove the parent stage. */
$executionPairs = array('0' => '');
if($project && $project->model == 'waterfall')
if($hasWaterfall)
{
foreach($executions as $id => $execution)
{
+39 -24
View File
@@ -281,11 +281,11 @@ class projectrelease extends control
->fetchAll();
$this->loadModel('common')->saveQueryCondition($this->dao->get(), 'leftBugs');
$this->commonAction($release->project, $release->product);
$this->commonAction($this->session->project, $release->product);
$product = $this->product->getById($release->product);
/* Set menu. */
$this->project->setMenu($release->project);
$this->project->setMenu($this->session->project);
$this->executeHooks($releaseID);
@@ -305,7 +305,6 @@ class projectrelease extends control
$this->view->storyPager = $storyPager;
$this->view->bugPager = $bugPager;
$this->view->leftBugPager = $leftBugPager;
$this->view->projectID = $release->project;
$this->display();
}
@@ -332,7 +331,7 @@ class projectrelease extends control
}
$release = $this->release->getByID($releaseID);
$project = $this->loadModel('project')->getByID($release->project);
$project = $this->loadModel('project')->getByID($this->session->project);
if(!$project->hasProduct)
{
@@ -366,11 +365,15 @@ class projectrelease extends control
}
else
{
$this->loadModel('build');
$this->release->delete(TABLE_RELEASE, $releaseID);
$release = $this->dao->select('*')->from(TABLE_RELEASE)->where('id')->eq((int)$releaseID)->fetch();
$build = $this->dao->select('*')->from(TABLE_BUILD)->where('id')->eq((int)$release->build)->fetch();
if(empty($build->execution)) $this->loadModel('build')->delete(TABLE_BUILD, $build->id);
$builds = $this->dao->select('*')->from(TABLE_BUILD)->where('id')->in($release->build)->fetchAll('id');
foreach($builds as $build)
{
if(empty($build->execution)) $this->build->delete(TABLE_BUILD, $build->id);
}
$message = $this->executeHooks($releaseID);
if($message) $response['message'] = $message;
@@ -387,8 +390,7 @@ class projectrelease extends control
{
$response['result'] = 'success';
$response['message'] = '';
$release = $this->release->getById($releaseID);
$this->dao->update(TABLE_BUILD)->set('deleted')->eq(1)->where('id')->eq($release->build)->andWhere('name')->eq($release->name)->exec();
$this->dao->update(TABLE_BUILD)->set('deleted')->eq(1)->where('id')->in($release->build)->andWhere('name')->eq($release->name)->exec();
}
return $this->send($response);
}
@@ -527,9 +529,11 @@ class projectrelease extends control
$this->session->set('storyList', inlink('view', "releaseID=$releaseID&type=story&link=true&param=" . helper::safe64Encode("&browseType=$browseType&queryID=$param")), $this->app->tab);
$release = $this->projectrelease->getByID($releaseID);
$build = $this->loadModel('build')->getByID($release->build);
$project = $this->loadModel('project')->getByID($release->project);
$this->commonAction($release->project, $release->product);
if(!$this->session->project) $this->session->set('project', explode(',', trim($release->project, ','))[0], 'project');
$builds = $this->loadModel('build')->getByList($release->build);
$project = $this->loadModel('project')->getByIdList($this->session->project);
$this->commonAction($this->session->project, $release->product);
$this->loadModel('story');
$this->loadModel('tree');
$this->loadModel('product');
@@ -557,20 +561,29 @@ class projectrelease extends control
else
{
$this->config->product->search['fields']['branch'] = sprintf($this->lang->product->branch, $this->lang->product->branchName[$release->productType]);
$branchName = $this->loadModel('branch')->getById($release->branch);
$branches = array('' => '', BRANCH_MAIN => $this->lang->branch->main, $release->branch => $branchName);
$allBranchs = $this->loadModel('branch')->getPairs($release->product);
$branches = array('' => '', BRANCH_MAIN => $this->lang->branch->main);
foreach(explode(',', trim($release->branch, ',')) as $branchID) $branches[$branchID] = zget($allBranchs, $branchID);
$this->config->product->search['params']['branch']['values'] = $branches;
}
if($this->view->project->model == 'waterfall' && empty($this->view->project->hasProduct)) unset($this->config->product->search['fields']['plan']);
$this->loadModel('search')->setSearchParams($this->config->product->search);
$executionIdList = array();
foreach($builds as $build)
{
if(empty($build->execution)) continue;
$executionIdList[$build->execution] = $build->execution;
}
$allStories = array();
if($browseType == 'bySearch')
{
$allStories = $this->story->getBySearch($release->product, $release->branch, $queryID, 'id', $build->execution ? $build->execution : '', 'story', $release->stories, $pager);
$allStories = $this->story->getBySearch($release->product, $release->branch, $queryID, 'id', $executionIdList, 'story', $release->stories, $pager);
}
else
{
$allStories = $this->story->getExecutionStories($build->execution, $release->product, 0, 't1.`order`_desc', 'byBranch', $release->branch, 'story', $release->stories, $pager);
$allStories = $this->story->getExecutionStories($executionIdList, $release->product, 0, 't1.`order`_desc', 'byBranch', $release->branch, 'story', $release->stories, $pager);
}
$this->view->allStories = $allStories;
@@ -580,7 +593,6 @@ class projectrelease extends control
$this->view->browseType = $browseType;
$this->view->param = $param;
$this->view->pager = $pager;
$this->view->projectID = $release->project;
$this->display();
}
@@ -651,9 +663,11 @@ class projectrelease extends control
$this->session->set('bugList', inlink('view', "releaseID=$releaseID&type=$type&link=true&param=" . helper::safe64Encode("&browseType=$browseType&queryID=$param")), 'qa');
/* Set menu. */
$release = $this->projectrelease->getByID($releaseID);
$build = $this->loadModel('build')->getByID($release->build);
$project = $this->loadModel('project')->getByID($release->project);
$this->commonAction($release->project, $release->product);
if(!$this->session->project) $this->session->set('project', explode(',', trim($release->project, ','))[0], 'project');
$builds = $this->loadModel('build')->getByList($release->build);
$project = $this->loadModel('project')->getByID($this->session->project);
$this->commonAction($this->session->project, $release->product);
/* Load pager. */
$this->app->loadClass('pager', $static = true);
@@ -681,8 +695,9 @@ class projectrelease extends control
else
{
$this->config->bug->search['fields']['branch'] = sprintf($this->lang->product->branch, $this->lang->product->branchName[$release->productType]);
$branchName = $this->loadModel('branch')->getById($release->branch);
$branches = array('' => '', BRANCH_MAIN => $this->lang->branch->main, $release->branch => $branchName);
$allBranchs = $this->loadModel('branch')->getPairs($release->product);
$branches = array('' => '', BRANCH_MAIN => $this->lang->branch->main);
foreach(explode(',', trim($release->branch, ',')) as $branchID) $branches[$branchID] = zget($allBranchs, $branchID);
$this->config->bug->search['params']['branch']['values'] = $branches;
}
if($this->view->project->model == 'waterfall' && empty($this->view->project->hasProduct)) unset($this->config->bug->search['fields']['plan']);
@@ -694,15 +709,15 @@ class projectrelease extends control
{
$allBugs = $this->bug->getBySearch($release->product, $release->branch, $queryID, 'id_desc', $releaseBugs, $pager);
}
elseif($build->execution)
else
{
if($type == 'bug')
{
$allBugs = $this->bug->getReleaseBugs($build->id, $release->product, $release->branch, $releaseBugs, $pager);
$allBugs = $this->bug->getReleaseBugs(array_keys($builds), $release->product, $release->branch, $releaseBugs, $pager);
}
elseif($type == 'leftBug')
{
$allBugs = $this->bug->getProductLeftBugs($build->id, $release->product, $release->branch, $releaseBugs, $pager);
$allBugs = $this->bug->getProductLeftBugs(array_keys($builds), $release->product, $release->branch, $releaseBugs, $pager);
}
}
@@ -51,7 +51,7 @@
<td class='text-left nobr c-name' title='<?php echo $story->title?>'>
<?php
if($story->parent > 0) echo "<span class='label label-badge label-light'>{$lang->story->childrenAB}</span>";
echo html::a($this->createLink('story', 'view', "storyID={$story->id}&version=0&param=$projectID", '', true), $story->title, '', "data-toggle='modal' data-type='iframe' data-width='90%'");
echo html::a($this->createLink('story', 'view', "storyID={$story->id}&version=0&param={$this->session->project}", '', true), $story->title, '', "data-toggle='modal' data-type='iframe' data-width='90%'");
?>
</td>
<td><?php echo zget($users, $story->openedBy);?></td>
+1 -1
View File
@@ -80,7 +80,7 @@
</thead>
<tbody>
<?php foreach($stories as $storyID => $story):?>
<?php $storyLink = $this->createLink('story', 'view', "storyID=$story->id&version=0&param=$projectID", '', true);?>
<?php $storyLink = $this->createLink('story', 'view', "storyID=$story->id&version=0&param={$this->session->project}", '', true);?>
<tr>
<td class='c-id text-left'>
<?php if(($canBatchUnlink or $canBatchClose) and $canBeChanged):?>
+14 -8
View File
@@ -3189,15 +3189,22 @@ class storyModel extends model
if(defined('TUTORIAL')) return $this->loadModel('tutorial')->getExecutionStories();
if(!$executionID) return array();
$execution = $this->dao->findById($executionID)->from(TABLE_PROJECT)->fetch();
$executions = $this->dao->select('*')->from(TABLE_PROJECT)->where('id')->in($executionID)->fetchAll('id');
$hasProject = false;
$hasExecution = false;
foreach($executions as $execution)
{
if($execution->type == 'project') $hasProject = true;
if($execution->type != 'project') $hasExecution = true;
}
$orderBy = str_replace('branch_', 't2.branch_', $orderBy);
$type = strtolower($type);
$products = $this->loadModel('product')->getProducts($executionID);
if($type == 'bysearch')
{
$queryID = (int)$param;
$products = $this->loadModel('product')->getProducts($executionID);
if($this->session->executionStoryQuery == false) $this->session->set('executionStoryQuery', ' 1 = 1');
if($queryID)
@@ -3228,7 +3235,6 @@ class storyModel extends model
}
$storyQuery = preg_replace('/`(\w+)`/', 't2.`$1`', $storyQuery);
$products = $this->loadModel('product')->getProducts($executionID);
if($products) $productID = key($products);
$review = $this->getRevertStoryIDList($productID);
@@ -3250,7 +3256,7 @@ class storyModel extends model
->leftJoin(TABLE_PRODUCT)->alias('t3')->on('t2.product = t3.id')
->beginIF(strpos($storyQuery, 'result') !== false)->leftJoin(TABLE_STORYREVIEW)->alias('t4')->on('t2.id = t4.story and t2.version = t4.version')->fi()
->where($storyQuery)
->andWhere('t1.project')->eq((int)$executionID)
->andWhere('t1.project')->in($executionID)
->andWhere('t2.deleted')->eq(0)
->andWhere('t3.deleted')->eq(0)
->andWhere('t2.type')->eq($storyType)
@@ -3289,18 +3295,18 @@ class storyModel extends model
$stories = $this->dao->select("distinct t1.*, t2.*, IF(t2.`pri` = 0, {$this->config->maxPriValue}, t2.`pri`) as priOrder, t3.type as productType, t2.version as version")->from(TABLE_PROJECTSTORY)->alias('t1')
->leftJoin(TABLE_STORY)->alias('t2')->on('t1.story = t2.id')
->leftJoin(TABLE_PRODUCT)->alias('t3')->on('t2.product = t3.id')
->where('t1.project')->eq((int)$executionID)
->where('t1.project')->in($executionID)
->andWhere('t2.type')->eq($storyType)
->beginIF($excludeStories)->andWhere('t2.id')->notIN($excludeStories)->fi()
->beginIF($execution->type == 'project')
->beginIF(!empty($productID))->andWhere('t1.product')->eq($productID)
->beginIF($hasProject)
->beginIF(!empty($productID))->andWhere('t1.product')->eq($productID)->fi()
->beginIF($type == 'bybranch' and $branchParam !== '')->andWhere('t2.branch')->in("0,$branchParam")->fi()
->beginIF(strpos('draft|reviewing|changing|closed', $type) !== false)->andWhere('t2.status')->eq($type)->fi()
->beginIF($type == 'unclosed')->andWhere('t2.status')->in(array_keys($unclosedStatus))->fi()
->beginIF($type == 'linkedexecution')->andWhere('t2.id')->in($storyIdList)->fi()
->beginIF($type == 'unlinkedexecution')->andWhere('t2.id')->notIn($storyIdList)->fi()
->fi()
->beginIF($execution->type != 'project')
->beginIF($hasExecution)
->beginIF(!empty($productParam))->andWhere('t1.product')->eq($productParam)->fi()
->beginIF($this->session->executionStoryBrowseType and strpos('changing|', $this->session->executionStoryBrowseType) !== false)->andWhere('t2.status')->in(array_keys($unclosedStatus))->fi()
->fi()