* adjust for project release link story and bug.
This commit is contained in:
@@ -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
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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¶m=" . 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¶m=" . 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¶m=$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¶m={$this->session->project}", '', true), $story->title, '', "data-toggle='modal' data-type='iframe' data-width='90%'");
|
||||
?>
|
||||
</td>
|
||||
<td><?php echo zget($users, $story->openedBy);?></td>
|
||||
|
||||
@@ -80,7 +80,7 @@
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach($stories as $storyID => $story):?>
|
||||
<?php $storyLink = $this->createLink('story', 'view', "storyID=$story->id&version=0¶m=$projectID", '', true);?>
|
||||
<?php $storyLink = $this->createLink('story', 'view', "storyID=$story->id&version=0¶m={$this->session->project}", '', true);?>
|
||||
<tr>
|
||||
<td class='c-id text-left'>
|
||||
<?php if(($canBatchUnlink or $canBatchClose) and $canBeChanged):?>
|
||||
|
||||
+14
-8
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user