* adjust code for storyModel getProductStories method.
This commit is contained in:
+44
-120
@@ -98,22 +98,23 @@ class storyModel extends model
|
||||
/**
|
||||
* Get stories by idList.
|
||||
*
|
||||
* @param int|array|string $storyIdList
|
||||
* @param string $type requirement|story
|
||||
* @param string $mode all
|
||||
* @param array|string $storyIdList
|
||||
* @param string $type requirement|story
|
||||
* @param string $mode all
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function getByList($storyIdList = 0, $type = 'story', $mode = '')
|
||||
public function getByList(array|string $storyIdList, string $type = 'story', string $mode = ''): array
|
||||
{
|
||||
if(empty($storyIdList)) return array();
|
||||
return $this->dao->select('t1.*, t2.spec, t2.verify, t3.name as productTitle, t3.deleted as productDeleted')
|
||||
->from(TABLE_STORY)->alias('t1')
|
||||
->leftJoin(TABLE_STORYSPEC)->alias('t2')->on('t1.id=t2.story')
|
||||
->leftJoin(TABLE_PRODUCT)->alias('t3')->on('t1.product=t3.id')
|
||||
->where('t1.version=t2.version')
|
||||
->andWhere('t1.id')->in($storyIdList)
|
||||
->andWhere('t1.type')->eq($type)
|
||||
->beginIF($mode != 'all')->andWhere('t1.deleted')->eq(0)->fi()
|
||||
->beginIF($storyIdList)->andWhere('t1.id')->in($storyIdList)->fi()
|
||||
->beginIF(!$storyIdList)->andWhere('t1.type')->eq($type)->fi()
|
||||
->fetchAll('id');
|
||||
}
|
||||
|
||||
@@ -2961,57 +2962,26 @@ class storyModel extends model
|
||||
/**
|
||||
* Get stories list of a product.
|
||||
*
|
||||
* @param int $productID
|
||||
* @param int $branch
|
||||
* @param array|string $moduleIdList
|
||||
* @param string $status
|
||||
* @param string $type requirement|story
|
||||
* @param string $orderBy
|
||||
* @param array|string $excludeStories
|
||||
* @param object $pager
|
||||
* @param bool $hasParent
|
||||
* @param string|int $productID
|
||||
* @param array|string|int $branch
|
||||
* @param array|string $moduleIdList
|
||||
* @param string $status
|
||||
* @param string $type requirement|story
|
||||
* @param string $orderBy
|
||||
* @param array|string $excludeStories
|
||||
* @param object|null $pager
|
||||
* @param bool $hasParent
|
||||
*
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function getProductStories($productID = 0, $branch = 0, $moduleIdList = 0, $status = 'all', $type = 'story', $orderBy = 'id_desc', $hasParent = true, $excludeStories = '', $pager = null)
|
||||
public function getProductStories(string|int $productID = 0, array|string|int $branch = 0, array|string $moduleIdList = '', string $status = 'all', string $type = 'story', string $orderBy = 'id_desc', bool $hasParent = true, array|string $excludeStories = '', object|null $pager = null): array
|
||||
{
|
||||
if(defined('TUTORIAL')) return $this->loadModel('tutorial')->getStories();
|
||||
|
||||
$stories = array();
|
||||
$branchProducts = array();
|
||||
$normalProducts = array();
|
||||
$productList = $this->dao->select('*')->from(TABLE_PRODUCT)->where('id')->in($productID)->fetchAll('id');
|
||||
foreach($productList as $product)
|
||||
{
|
||||
if($product->type != 'normal')
|
||||
{
|
||||
$branchProducts[$product->id] = $product->id;
|
||||
continue;
|
||||
}
|
||||
|
||||
$normalProducts[$product->id] = $product->id;
|
||||
}
|
||||
|
||||
$productQuery = '(';
|
||||
if(!empty($normalProducts)) $productQuery .= '`product` ' . helper::dbIN(array_keys($normalProducts));
|
||||
if(!empty($branchProducts))
|
||||
{
|
||||
if(!empty($normalProducts)) $productQuery .= " OR ";
|
||||
$productQuery .= "(`product` " . helper::dbIN(array_keys($branchProducts));
|
||||
|
||||
if($branch !== 'all')
|
||||
{
|
||||
if(is_array($branch)) $branch = join(',', $branch);
|
||||
$productQuery .= " AND `branch` " . helper::dbIN($branch);
|
||||
}
|
||||
$productQuery .= ')';
|
||||
}
|
||||
if(empty($normalProducts) and empty($branchProducts)) $productQuery .= '1 = 1';
|
||||
$productQuery .= ') ';
|
||||
|
||||
$stories = $this->dao->select("*, IF(`pri` = 0, {$this->config->maxPriValue}, `pri`) as priOrder")->from(TABLE_STORY)
|
||||
->where('product')->in($productID)
|
||||
$productQuery = $this->storyTao->buildProductsCondition($productID, $branch);
|
||||
$stories = $this->dao->select("*, IF(`pri` = 0, {$this->config->maxPriValue}, `pri`) as priOrder")->from(TABLE_STORY)
|
||||
->where('deleted')->eq(0)
|
||||
->andWhere($productQuery)
|
||||
->beginIF(!$hasParent)->andWhere("parent")->ge(0)->fi()
|
||||
->beginIF(!empty($moduleIdList))->andWhere('module')->in($moduleIdList)->fi()
|
||||
@@ -3019,12 +2989,11 @@ class storyModel extends model
|
||||
->beginIF($status and $status != 'all')->andWhere('status')->in($status)->fi()
|
||||
->andWhere('vision')->eq($this->config->vision)
|
||||
->andWhere('type')->eq($type)
|
||||
->andWhere('deleted')->eq(0)
|
||||
->orderBy($orderBy)
|
||||
->page($pager)
|
||||
->fetchAll('id');
|
||||
|
||||
return $this->mergePlanTitle($productID, $stories, $branch, $type);
|
||||
return $this->mergePlanTitle($productID, $stories, $type);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3245,7 +3214,7 @@ class storyModel extends model
|
||||
->orderBy($orderBy)
|
||||
->page($pager)
|
||||
->fetchAll('id');
|
||||
return $this->mergePlanTitle($productID, $stories, $branch, $type);
|
||||
return $this->mergePlanTitle($productID, $stories, $type);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3274,7 +3243,7 @@ class storyModel extends model
|
||||
->orderBy($orderBy)
|
||||
->page($pager)
|
||||
->fetchAll('id');
|
||||
return $this->mergePlanTitle($productID, $stories, $branch, $type);
|
||||
return $this->mergePlanTitle($productID, $stories, $type);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3643,7 +3612,7 @@ class storyModel extends model
|
||||
}
|
||||
|
||||
$this->dao->sqlobj->sql = $query;
|
||||
return $this->mergePlanTitle($productID, $stories, $branch, $storyType);
|
||||
return $this->mergePlanTitle($productID, $stories, $storyType);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3841,7 +3810,7 @@ class storyModel extends model
|
||||
$productIdList = array();
|
||||
foreach($stories as $story) $productIdList[$story->product] = $story->product;
|
||||
|
||||
return $this->mergePlanTitle($productIdList, $stories, 0, $storyType);
|
||||
return $this->mergePlanTitle($productIdList, $stories, $storyType);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -4838,83 +4807,38 @@ class storyModel extends model
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function mergePlanTitle($productID, $stories, $branch = 0, $type = 'story')
|
||||
public function mergePlanTitle(string|int $productID, array $stories, string $type = 'story'): array
|
||||
{
|
||||
$query = $this->dao->get();
|
||||
if(is_array($branch))
|
||||
$rawQuery = $this->dao->get();
|
||||
|
||||
/* Get plans. */
|
||||
$plans = $this->dao->select('id,title')->from(TABLE_PRODUCTPLAN)->Where('deleted')->eq(0)->andWhere('product')->in($productID)->fetchPairs('id', 'title');
|
||||
|
||||
/* Get parent stories and children. */
|
||||
$stories = $this->storyTao->mergeChildren($stories, $type);
|
||||
$parents = $this->storyTao->extractParents($stories);
|
||||
if($parents)
|
||||
{
|
||||
unset($branch[0]);
|
||||
$branch = join(',', $branch);
|
||||
if($branch) $branch = "0,$branch";
|
||||
$parents = $this->dao->select('id,title')->from(TABLE_STORY)->where('id')->in($parents)->andWhere('deleted')->eq(0)->fetchAll('id');
|
||||
$children = $this->dao->select('id,title')->from(TABLE_STORY)->where('parent')->in($parents)->andWhere('deleted')->eq(0)->fetchGroup('parent', 'id');
|
||||
}
|
||||
$plans = $this->dao->select('id,title')->from(TABLE_PRODUCTPLAN)
|
||||
->Where('deleted')->eq(0)
|
||||
->beginIF($productID)->andWhere('product')->in($productID)->fi()
|
||||
->fetchPairs('id', 'title');
|
||||
|
||||
/* For requirement children. */
|
||||
if($type == 'requirement')
|
||||
{
|
||||
$relations = $this->dao->select('DISTINCT AID, BID')->from(TABLE_RELATION)
|
||||
->where('AType')->eq('requirement')
|
||||
->andWhere('BType')->eq('story')
|
||||
->andWhere('relation')->eq('subdivideinto')
|
||||
->andWhere('AID')->in(array_keys($stories))
|
||||
->fetchAll();
|
||||
|
||||
$group = array();
|
||||
foreach($relations as $relation) $group[$relation->AID][] = $relation->BID;
|
||||
foreach($stories as $story)
|
||||
{
|
||||
if(!isset($group[$story->id])) continue;
|
||||
$story->children = $this->getByList($group[$story->id]);
|
||||
|
||||
/* export requirement linkstories. */
|
||||
foreach($story->children as $child) $story->linkStories .= $child->title . ',';
|
||||
}
|
||||
}
|
||||
|
||||
$parents = array();
|
||||
$tmpStories = array();
|
||||
$childStories = array();
|
||||
foreach($stories as $story)
|
||||
{
|
||||
$tmpStories[$story->id] = $story;
|
||||
if($story->parent > 0) $parents[$story->parent] = $story->parent;
|
||||
}
|
||||
$parents = $this->dao->select('*')->from(TABLE_STORY)->where('id')->in($parents)->fetchAll('id');
|
||||
|
||||
foreach($stories as $storyID => $story)
|
||||
{
|
||||
/* export story linkstories. */
|
||||
if($story->parent == -1)
|
||||
{
|
||||
$childrenTitle = $this->dao->select('title')->from(TABLE_STORY)->where('parent')->eq($story->id)->fetchAll();
|
||||
$childrenTitle = array_column($childrenTitle, 'title');
|
||||
$story->linkStories = implode(',', $childrenTitle);
|
||||
}
|
||||
/* Export story linkstories. */
|
||||
if(isset($children[$story->id])) $story->linkStories = implode(',', array_column($children[$story->id], 'title'));
|
||||
|
||||
if($story->parent > 0)
|
||||
{
|
||||
if(isset($stories[$story->parent]))
|
||||
{
|
||||
$stories[$story->parent]->children[$story->id] = $story;
|
||||
unset($stories[$storyID]);
|
||||
}
|
||||
else
|
||||
{
|
||||
$parent = $parents[$story->parent];
|
||||
$story->parentName = $parent->title;
|
||||
}
|
||||
}
|
||||
/* Merge parent story title. */
|
||||
if($story->parent > 0 and isset($parents[$story->parent]) $story->parentName = $parents[$story->parent]->title;
|
||||
|
||||
/* Merge plan title. */
|
||||
$story->planTitle = '';
|
||||
$storyPlans = explode(',', trim($story->plan, ','));
|
||||
$storyPlans = explode(',', trim($story->plan, ','));
|
||||
foreach($storyPlans as $planID) $story->planTitle .= zget($plans, $planID, '') . ' ';
|
||||
}
|
||||
|
||||
/* For save session query. */
|
||||
$this->dao->sqlobj->sql = $query;
|
||||
$this->dao->sqlobj->sql = $rawQuery;
|
||||
return $stories;
|
||||
}
|
||||
|
||||
|
||||
+119
-32
@@ -105,38 +105,6 @@ class storyTao extends storyModel
|
||||
->fetchPairs('BID', 'BID');
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建研发需求的跟踪矩阵信息。
|
||||
* Build story track.
|
||||
*
|
||||
* @param object $story
|
||||
* @param int $projectID
|
||||
* @access protected
|
||||
* @return object
|
||||
*/
|
||||
protected function buildStoryTrack(object $story, int $projectID = 0): object
|
||||
{
|
||||
/* 获取关联需求的用例、Bug、任务。 */
|
||||
$track = new stdclass();
|
||||
$track->parent = $story->parent;
|
||||
$track->title = $story->title;
|
||||
$track->cases = $this->loadModel('testcase')->getStoryCases($story->id);
|
||||
$track->bugs = $this->loadModel('bug')->getStoryBugs($story->id);
|
||||
$track->tasks = $this->loadModel('task')->getListByStory($story->id, 0, $projectID);
|
||||
if($this->config->edition != 'max') return $track;
|
||||
|
||||
/* 获取关联需求的设计、关联版本库提交。 */
|
||||
$track->designs = $this->dao->select('id, name')->from(TABLE_DESIGN)->where('story')->eq($story->id)->andWhere('deleted')->eq('0')->fetchAll('id');
|
||||
$track->revisions = $this->dao->select('BID, t2.comment')->from(TABLE_RELATION)->alias('t1')
|
||||
->leftjoin(TABLE_REPOHISTORY)->alias('t2')->on('t1.BID = t2.id')
|
||||
->where('t1.AType')->eq('design')
|
||||
->andWhere('t1.BType')->eq('commit')
|
||||
->andWhere('t1.AID')->in(array_keys($track->designs))
|
||||
->fetchPairs();
|
||||
|
||||
return $track;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户需求细分的研发需求,或者研发需求关联的用户需求。
|
||||
* Get associated requirements.
|
||||
@@ -291,4 +259,123 @@ class storyTao extends storyModel
|
||||
->groupBy('product')
|
||||
->fetchPairs();
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建研发需求的跟踪矩阵信息。
|
||||
* Build story track.
|
||||
*
|
||||
* @param object $story
|
||||
* @param int $projectID
|
||||
* @access protected
|
||||
* @return object
|
||||
*/
|
||||
protected function buildStoryTrack(object $story, int $projectID = 0): object
|
||||
{
|
||||
/* 获取关联需求的用例、Bug、任务。 */
|
||||
$track = new stdclass();
|
||||
$track->parent = $story->parent;
|
||||
$track->title = $story->title;
|
||||
$track->cases = $this->loadModel('testcase')->getStoryCases($story->id);
|
||||
$track->bugs = $this->loadModel('bug')->getStoryBugs($story->id);
|
||||
$track->tasks = $this->loadModel('task')->getListByStory($story->id, 0, $projectID);
|
||||
if($this->config->edition != 'max') return $track;
|
||||
|
||||
/* 获取关联需求的设计、关联版本库提交。 */
|
||||
$track->designs = $this->dao->select('id, name')->from(TABLE_DESIGN)->where('story')->eq($story->id)->andWhere('deleted')->eq('0')->fetchAll('id');
|
||||
$track->revisions = $this->dao->select('BID, t2.comment')->from(TABLE_RELATION)->alias('t1')
|
||||
->leftjoin(TABLE_REPOHISTORY)->alias('t2')->on('t1.BID = t2.id')
|
||||
->where('t1.AType')->eq('design')
|
||||
->andWhere('t1.BType')->eq('commit')
|
||||
->andWhere('t1.AID')->in(array_keys($track->designs))
|
||||
->fetchPairs();
|
||||
|
||||
return $track;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据产品 ID 列表和分支参数,构建查询条件。
|
||||
* Build products condition.
|
||||
*
|
||||
* @param string|int $productIdList
|
||||
* @param array|string|int $branch
|
||||
* @access protected
|
||||
* @return string
|
||||
*/
|
||||
protected function buildProductsCondition(string|int $productIdList, array|string|int $branch): string
|
||||
{
|
||||
/* 如果查询所有分支,直接用 idList 条件。 */
|
||||
if(empty($productIdList)) return '1=1';
|
||||
if($branch === 'all') return '`product` ' . helper::dbIN($productIdList);
|
||||
|
||||
/* 将产品分类为正常产品和多分支产品。 */
|
||||
$branchProducts = array();
|
||||
$normalProducts = array();
|
||||
$productList = $this->dao->select('*')->from(TABLE_PRODUCT)->where('id')->in($productIdList)->fetchAll('id');
|
||||
foreach($productList as $product)
|
||||
{
|
||||
if($product->type != 'normal') $branchProducts[$product->id] = $product->id;
|
||||
if($product->type == 'normal') $normalProducts[$product->id] = $product->id;
|
||||
}
|
||||
|
||||
/* 如果没有多分支产品,直接返回正常产品 ID 列表。*/
|
||||
if(empty($branchProducts)) return '`product` ' . helper::dbIN($normalProducts);
|
||||
|
||||
/* 构造多分支产品和正常产品的复合条件。 */
|
||||
$productQuery = "(`product` " . helper::dbIN($branchProducts) . " AND `branch` " . helper::dbIN($branch) . ')';
|
||||
if(!empty($normalProducts)) $productQuery .= ' OR `product` ' . helper::dbIN($normalProducts);
|
||||
return "({$productQuery}) ";
|
||||
}
|
||||
|
||||
/**
|
||||
* 将需求列表中的子需求合并到列表中的父需求下。
|
||||
* Merge children to parent.
|
||||
*
|
||||
* @param array $stories
|
||||
* @param string $type
|
||||
* @access protected
|
||||
* @return int[]
|
||||
*/
|
||||
protected function mergeChildren(array $stories, string $type = 'story'): array
|
||||
{
|
||||
/* For requirement children. */
|
||||
$relationGroups = array();
|
||||
if($type == 'requirement') $relationGroups = $this->storyTao->batchGetRelations(array_keys($stories), $type, array('*'));
|
||||
|
||||
foreach($stories as $storyID => $story)
|
||||
{
|
||||
/* Merge to parent and unset in list. */
|
||||
if($story->parent > 0 and isset($stories[$story->parent]))
|
||||
{
|
||||
$stories[$story->parent]->children[$story->id] = $story;
|
||||
unset($stories[$storyID]);
|
||||
}
|
||||
|
||||
/* Merge subdivided stories for requirement. */
|
||||
if(!empty($relationGroups[$story->id]))
|
||||
{
|
||||
$story->children = $relationGroups[$story->id];
|
||||
$story->linkStories = implode(',', array_column($story->children, 'title'));
|
||||
}
|
||||
}
|
||||
return $stories;
|
||||
}
|
||||
|
||||
/**
|
||||
* 提取需求列表中的父需求 ID 列表。
|
||||
* Extract parents from stories.
|
||||
*
|
||||
* @param array $stories
|
||||
* @access protected
|
||||
* @return int[]
|
||||
*/
|
||||
protected function extractParents(array $stories): array
|
||||
{
|
||||
$parent = array_map(function($story)
|
||||
{
|
||||
if($story->parent == '-1') return $story->id;
|
||||
if($story->parent > '0') return $story->parent;
|
||||
return false;
|
||||
}, $stories);
|
||||
return array_values(array_unique(array_filter($parent)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,4 +33,4 @@ r(count($tracks['noRequirement'][2]->cases)) && p() && e('4');
|
||||
r($tracks['noRequirement'][2]->bugs) && p('1:title') && e('BUG1'); // 获取产品1的需求2的关联Bug名称
|
||||
r($tracks['noRequirement'][2]->bugs) && p('101:title') && e('BUG101'); // 获取产品1的需求2的关联Bug名称
|
||||
r($tracks['noRequirement'][2]->cases) && p('1:title') && e('这个是测试用例1'); // 获取产品1的需求2的关联Case名称
|
||||
r($tracks['noRequirement'][2]->cases) && p('2:title') && e('这个是测试用例2'); // 获取产品1的需求2的关联Case名称
|
||||
r($tracks['noRequirement'][2]->cases) && p('2:title') && e('这个是测试用例2'); // 获取产品1的需求2的关联Case名称
|
||||
|
||||
Reference in New Issue
Block a user