* Rewrite story view page. Code for task #102973.

This commit is contained in:
wangyidong
2023-09-27 15:01:26 +08:00
parent 2cb0ad1df4
commit 4f0b716a01
17 changed files with 510 additions and 172 deletions
+1
View File
@@ -234,6 +234,7 @@ class model extends baseModel
*/
public function fetchByID(int $objectID, string $moduleName = ''): object|bool
{
if(empty($objectID)) return false;
if(empty($moduleName)) $moduleName = $this->getModuleName();
$table = $this->config->objectTables[$moduleName];
+3 -2
View File
@@ -247,11 +247,12 @@ class buildModel extends model
* @access public
* @return array
*/
public function getStoryBuilds($storyID)
public function getStoryBuilds(int $storyID): array
{
if(empty($storyID)) return array();
return $this->dao->select('*')->from(TABLE_BUILD)
->where('deleted')->eq(0)
->andWhere("CONCAT(stories, ',')")->like("%,$storyID,%")
->andWhere("CONCAT(',', stories, ',')")->like("%,$storyID,%")
->orderBy('id_desc')
->fetchAll('id');
}
@@ -0,0 +1,29 @@
#!/usr/bin/env php
<?php
include dirname(__FILE__, 5) . '/test/lib/init.php';
include dirname(__FILE__, 2) . '/build.class.php';
su('admin');
$build = zdTable('build');
$build->builds->range('``');
$build->stories->range('1-20{2}');
$build->createdBy->range('admin');
$build->createdDate->range('`' . date('Y-m-d H:i:s') . '`');
$build->gen(20);
/**
title=测试 buildModel->getStoryBuilds();
cid=1
pid=1
项目版本查询 >> 项目版本版本7
执行版本查询 >> 执行版本版本17
无id查询 >> 0
图片字段传字符串测试 >> 17
*/
global $tester;
$build = $tester->loadModel('build');
r(count($build->getStoryBuilds(1))) && p() && e('2'); //项目版本查询
+6 -102
View File
@@ -2140,14 +2140,13 @@ EOF;
/**
* Get the previous and next object.
*
* @param string $type story|task|bug|case
* @param string $type story|task|bug|case
* @param int $objectID
* @access public
* @return object
*/
public function getPreAndNextObject($type, $objectID)
public function getPreAndNextObject(string $type, int $objectID): object
{
/* Get SQL. */
$queryCondition = $type . 'QueryCondition';
$typeOnlyCondition = $type . 'OnlyCondition';
$queryCondition = $this->session->$queryCondition;
@@ -2157,105 +2156,10 @@ EOF;
$preAndNextObject->next = '';
if(empty($queryCondition)) return $preAndNextObject;
$table = $this->config->objectTables[$type];
$orderBy = $type . 'OrderBy';
$orderBy = $this->session->$orderBy;
$select = '';
if($this->session->$typeOnlyCondition)
{
if(strpos($orderBy, 'priOrder') !== false) $select .= ", IF(`pri` = 0, {$this->config->maxPriValue}, `pri`) as priOrder";
if(strpos($orderBy, 'severityOrder') !== false) $select .= ", IF(`severity` = 0, {$this->config->maxPriValue}, `severity`) as severityOrder";
$queryCondition = str_replace('t4.status', 'status', $queryCondition);
$sql = $this->dao->select("*$select")->from($table)
->where($queryCondition)
->beginIF($orderBy != false)->orderBy($orderBy)->fi()
->get();
}
else
{
$sql = $queryCondition . (empty($orderBy) ? '' : " ORDER BY $orderBy");
}
/* Get objectIDList. */
$objectIdListKey = $type . 'BrowseList';
$existsObjectList = $this->session->$objectIdListKey;
if(empty($existsObjectList) or $existsObjectList['sql'] != $sql)
{
$queryObjects = $this->dao->query($sql);
$objectList = array();
$key = 'id';
while($queryObjects && $object = $queryObjects->fetch())
{
if(!$this->session->$typeOnlyCondition and $type == 'testcase' and isset($object->case)) $key = 'case';
$id = $object->$key;
$objectList[$id] = $id;
}
$this->session->set($objectIdListKey, array('sql' => $sql, 'idkey' => $key, 'objectList' => $objectList), $this->app->tab);
$existsObjectList = $this->session->$objectIdListKey;
}
$preObj = false;
if(isset($existsObjectList['objectList']))
{
foreach($existsObjectList['objectList'] as $id)
{
/* Get next object. */
if($preObj === true)
{
$preAndNextObject->next = $id;
break;
}
/* Get pre object. */
if($id == $objectID)
{
if($preObj) $preAndNextObject->pre = $preObj;
$preObj = true;
}
if($preObj !== true) $preObj = $id;
}
if(empty($queryCondition) or $this->session->$typeOnlyCondition)
{
if(!empty($preAndNextObject->pre)) $preAndNextObject->pre = $this->dao->select('*')->from($table)->where('id')->eq($preAndNextObject->pre)->fetch();
if(!empty($preAndNextObject->next)) $preAndNextObject->next = $this->dao->select('*')->from($table)->where('id')->eq($preAndNextObject->next)->fetch();
}
else
{
$isObject = false;
$objects = array();
$key = $existsObjectList['idkey'];
$queryObjects = $this->dao->query($existsObjectList['sql']);
while($object = $queryObjects->fetch())
{
$objects[$object->$key] = $object;
if(!empty($preAndNextObject->pre) and is_numeric($preAndNextObject->pre) and $object->$key == $preAndNextObject->pre) $preAndNextObject->pre = $object;
if(!empty($preAndNextObject->next) and is_numeric($preAndNextObject->next) and $object->$key == $preAndNextObject->next) $preAndNextObject->next = $object;
if((empty($preAndNextObject->pre) or is_object($preAndNextObject->pre)) and (empty($preAndNextObject->next) or is_object($preAndNextObject->next)))
{
$isObject = true;
break;
}
}
/* If the pre object or next object is number type, then continue to find the pre or next. */
if(!$isObject)
{
$objectIdList = array_keys($objects);
$objectIdIndex = array_search($objectID, $objectIdList);
if(is_numeric($preAndNextObject->pre))
{
$preAndNextObject->pre = $objectIdIndex - 1 >= 0 ? $objects[$objectIdList[$objectIdIndex - 1]] : '';
}
if(is_numeric($preAndNextObject->next))
{
$preAndNextObject->next = $objectIdIndex + 1 < count($objectIdList) ? $objects[$objectIdList[$objectIdIndex + 1]] : '';
}
}
}
}
$sql = $this->commonTao->getPreAndNextSQL($type);
$objectList = $this->commonTao->queryListForPreAndNext($type, $sql);
$preAndNextObject = $this->commonTao->searchPreAndNextFromList($objectID, $objectList);
$preAndNextObject = $this->commonTao->fetchPreAndNextObject($type, $objectID, $preAndNextObject);
return $preAndNextObject;
}
+176
View File
@@ -0,0 +1,176 @@
<?php
declare(strict_types=1);
/**
* The tao file of common module of ZenTaoPMS.
*
* @copyright Copyright 2009-2023 禅道软件(青岛)有限公司(ZenTao Software (Qingdao) Co., Ltd. www.zentao.net)
* @license ZPL(https://zpl.pub/page/zplv12.html) or AGPL(https://www.gnu.org/licenses/agpl-3.0.en.html)
* @author Yidong Wang<yidong@easycorp.ltd>
* @package common
* @link https://www.zentao.net
*/
class commonTao extends commonModel
{
/**
* Get SQL for preAndNext.
*
* @param string $type
* @access protected
* @return string
*/
protected function getPreAndNextSQL(string $type): string
{
$queryCondition = $type . 'QueryCondition';
$typeOnlyCondition = $type . 'OnlyCondition';
$queryCondition = $this->session->$queryCondition;
$table = zget($this->config->objectTables, $type, '');
if(empty($table)) return '';
$orderBy = $type . 'OrderBy';
$orderBy = $this->session->$orderBy;
$select = '';
if($this->session->$typeOnlyCondition)
{
if($orderBy and str_contains($orderBy, 'priOrder')) $select .= ", IF(`pri` = 0, {$this->config->maxPriValue}, `pri`) as priOrder";
if($orderBy and str_contains($orderBy, 'severityOrder')) $select .= ", IF(`severity` = 0, {$this->config->maxPriValue}, `severity`) as severityOrder";
$queryCondition = str_replace('t4.status', 'status', $queryCondition);
$sql = $this->dao->select("*$select")->from($table)
->where($queryCondition)
->beginIF($orderBy != false)->orderBy($orderBy)->fi()
->get();
}
else
{
$sql = $queryCondition . (empty($orderBy) ? '' : " ORDER BY $orderBy");
}
return $sql;
}
/**
* Query list for preAndNext.
*
* @param string $type
* @param string $sql
* @access protected
* @return array
*/
protected function queryListForPreAndNext(string $type, string $sql): array
{
$objectIdListKey = strtolower($type . $this->app->getModuleName() . $this->app->getMethodName()) . 'BrowseList';
$existsObjectList = $this->session->$objectIdListKey;
if(empty($existsObjectList) or trim($existsObjectList['sql']) != trim($sql))
{
$queryObjects = $this->dao->query($sql);
$objectList = array();
$key = 'id';
if($queryObjects)
{
while($object = $queryObjects->fetch())
{
if(!$this->session->$typeOnlyCondition and $type == 'testcase' and isset($object->case)) $key = 'case';
$id = $object->$key;
$objectList[$id] = $id;
}
}
$this->session->set($objectIdListKey, array('sql' => $sql, 'idkey' => $key, 'objectList' => $objectList), $this->app->tab);
$existsObjectList = $this->session->$objectIdListKey;
}
return $existsObjectList;
}
/**
* Search preAndNext from list.
*
* @param int $objectID
* @param array $objectList
* @access protected
* @return object
*/
protected function searchPreAndNextFromList(int $objectID, array $objectList): object
{
$preAndNextObject = new stdClass();
$preAndNextObject->pre = '';
$preAndNextObject->next = '';
if(!isset($objectList['objectList'])) return $preAndNextObject;
$preObj = false;
foreach($objectList['objectList'] as $id)
{
/* Get next object. */
if($preObj === true)
{
$preAndNextObject->next = $id;
break;
}
/* Get pre object. */
if($id == $objectID)
{
if($preObj) $preAndNextObject->pre = $preObj;
$preObj = true;
}
if($preObj !== true) $preObj = $id;
}
return $preAndNextObject;
}
/**
* Fetch preAndNextObject.
*
* @param string $type
* @param int $objectID
* @param object $preAndNextObject
* @access protected
* @return object
*/
protected function fetchPreAndNextObject(string $type, int $objectID, object $preAndNextObject): object
{
$queryCondition = $type . 'QueryCondition';
$typeOnlyCondition = $type . 'OnlyCondition';
$objectIdListKey = strtolower($type . $this->app->getModuleName() . $this->app->getMethodName()) . 'BrowseList';
$queryCondition = $this->session->$queryCondition;
$existsObjectList = $this->session->$objectIdListKey;
$table = zget($this->config->objectTables, $type, '');
if(empty($table)) return $preAndNextObject;
if(empty($preAndNextObject->pre) and empty($preAndNextObject->next)) return $preAndNextObject;
if(empty($queryCondition) or $this->session->$typeOnlyCondition)
{
if(!empty($preAndNextObject->pre)) $preAndNextObject->pre = $this->dao->select('*')->from($table)->where('id')->eq($preAndNextObject->pre)->fetch();
if(!empty($preAndNextObject->next)) $preAndNextObject->next = $this->dao->select('*')->from($table)->where('id')->eq($preAndNextObject->next)->fetch();
return $preAndNextObject;
}
$searched = false;
$objects = array();
$key = $existsObjectList['idkey'];
$queryObjects = $this->dao->query($existsObjectList['sql']);
while($object = $queryObjects->fetch())
{
$objects[$object->$key] = $object;
if(!empty($preAndNextObject->pre) and is_numeric($preAndNextObject->pre) and $object->$key == $preAndNextObject->pre) $preAndNextObject->pre = $object;
if(!empty($preAndNextObject->next) and is_numeric($preAndNextObject->next) and $object->$key == $preAndNextObject->next) $preAndNextObject->next = $object;
if((empty($preAndNextObject->pre) or is_object($preAndNextObject->pre)) and (empty($preAndNextObject->next) or is_object($preAndNextObject->next)))
{
$searched = true;
break;
}
}
/* If the pre object or next object is number type, then continue to find the pre or next. */
if(!$searched)
{
$objectIdList = array_keys($objects);
$objectIdIndex = (int)array_search($objectID, $objectIdList);
if(is_numeric($preAndNextObject->pre)) $preAndNextObject->pre = $objectIdIndex - 1 >= 0 ? $objects[$objectIdList[$objectIdIndex - 1]] : '';
if(is_numeric($preAndNextObject->next)) $preAndNextObject->next = $objectIdIndex + 1 < count($objectIdList) ? $objects[$objectIdList[$objectIdIndex + 1]] : '';
}
return $preAndNextObject;
}
}
@@ -0,0 +1,36 @@
#!/usr/bin/env php
<?php
include dirname(__FILE__, 5) . '/test/lib/init.php';
su('admin');
zdTable('story')->gen(10);
/**
title=测试 commonModel->getPreAndNextObject();
cid=1
pid=1
*/
global $tester;
$tester->loadModel('common');
r((array)$tester->common->getPreAndNextObject('', 3)) && p('pre,next') && e('~~,~~');
r((array)$tester->common->getPreAndNextObject('story', 3)) && p('pre,next') && e('~~,~~');
$tester->common->app->moduleName = 'product';
$tester->common->app->methodName = 'browse';
$_SESSION['storyQueryCondition'] = 'id < 5';
$_SESSION['storyOnlyCondition'] = true;
$_SESSION['storyOrderBy'] = 'id';
$preAndNextObject = $tester->common->getPreAndNextObject('story', 3);
r($preAndNextObject->pre) && p('id') && e('2');
r($preAndNextObject->next) && p('id') && e('4');
$_SESSION['storyQueryCondition'] = 'SELECT * FROM `zt_story` WHERE id <= 4';
$_SESSION['storyOnlyCondition'] = false;
$preAndNextObject = $tester->common->getPreAndNextObject('story', 3);
r($preAndNextObject->pre) && p('id') && e('2');
r($preAndNextObject->next) && p('id') && e('4');
+1 -1
View File
@@ -30,7 +30,7 @@ $doc->gen(1);
/**
title=测试 storyModel->activate();
title=测试 commonModel->removeDuplicate();
cid=1
pid=1
@@ -0,0 +1,49 @@
#!/usr/bin/env php
<?php
include dirname(__FILE__, 5) . '/test/lib/init.php';
su('admin');
zdTable('story')->gen(10);
/**
title=测试 commonTao->fetchPreAndNextObject();
cid=1
pid=1
*/
global $tester;
$tester->loadModel('common');
$_SESSION['storyQueryCondition'] = 'id < 40';
$_SESSION['storyOnlyCondition'] = true;
$preAndNextObject = new stdclass();
$preAndNextObject->pre = '';
$preAndNextObject->next = '';
r((array)$tester->common->fetchPreAndNextObject('', 3, $preAndNextObject)) && p('pre,next') && e('~~,~~');
r((array)$tester->common->fetchPreAndNextObject('story', 3, $preAndNextObject)) && p('pre,next') && e('~~,~~');
$preAndNextObject->pre = 2;
$preAndNextObject->next = 4;
$preAndNextObject = $tester->common->fetchPreAndNextObject('story', 3, $preAndNextObject);
r($preAndNextObject->pre) && p('id') && e('2');
r($preAndNextObject->next) && p('id') && e('4');
$tester->common->app->moduleName = 'product';
$tester->common->app->methodName = 'browse';
$_SESSION['storyOnlyCondition'] = false;
$_SESSION['storyproductbrowseBrowseList'] = array('sql' => 'SELECT * FROM `zt_story` WHERE id <= 5', 'idkey' => 'id', 'objectList' => array(1 => 1, 2 => 2, 3 => 3, 4 => 4));
$preAndNextObject->pre = 2;
$preAndNextObject->next = 4;
$preAndNextObject = $tester->common->fetchPreAndNextObject('story', 3, $preAndNextObject);
r($preAndNextObject->pre) && p('id') && e('2');
r($preAndNextObject->next) && p('id') && e('4');
$preAndNextObject->pre = 0;
$preAndNextObject->next = 6;
$preAndNextObject = $tester->common->fetchPreAndNextObject('story', 3, $preAndNextObject);
r($preAndNextObject->pre) && p('id') && e('2');
r($preAndNextObject->next) && p('id') && e('4');
@@ -0,0 +1,31 @@
#!/usr/bin/env php
<?php
include dirname(__FILE__, 5) . '/test/lib/init.php';
su('admin');
/**
title=测试 commonTao->getPreAndNextSQL();
cid=1
pid=1
*/
global $tester;
$tester->loadModel('common');
$_SESSION['storyQueryCondition'] = 'id < 40';
$_SESSION['storyOnlyCondition'] = true;
r(trim($tester->common->getPreAndNextSQL('story'))) && p() && e('SELECT * FROM `zt_story` WHERE id < 40');
$_SESSION['storyOrderBy'] = 'id desc, priOrder, severityOrder';
r(trim($tester->common->getPreAndNextSQL('story'))) && p() && e('SELECT *, IF(`pri` = 0, 256, `pri`) as priOrder, IF(`severity` = 0, 256, `severity`) as severityOrder FROM `zt_story` WHERE id < 40 ORDER BY `id` desc,`priOrder`,`severityOrder`');
$_SESSION['storyQueryCondition'] = 'SELECT t1.* FROM `zt_story` AS t1 LEFT JOIN `zt_storyspec` AS t2 on t1.id=t2.story WHERE t1.id < 40 AND t1.version = t2.version';
$_SESSION['storyOnlyCondition'] = false;
unset($_SESSION['storyOrderBy']);
r(trim($tester->common->getPreAndNextSQL('story'))) && p() && e('SELECT t1.* FROM `zt_story` AS t1 LEFT JOIN `zt_storyspec` AS t2 on t1.id=t2.story WHERE t1.id < 40 AND t1.version = t2.version');
$_SESSION['storyOrderBy'] = 't1.id desc';
r(trim($tester->common->getPreAndNextSQL('story'))) && p() && e('SELECT t1.* FROM `zt_story` AS t1 LEFT JOIN `zt_storyspec` AS t2 on t1.id=t2.story WHERE t1.id < 40 AND t1.version = t2.version ORDER BY t1.id desc');
@@ -0,0 +1,35 @@
#!/usr/bin/env php
<?php
include dirname(__FILE__, 5) . '/test/lib/init.php';
su('admin');
zdTable('story')->gen(10);
/**
title=测试 commonTao->queryListForPreAndNext();
cid=1
pid=1
*/
global $tester;
$tester->loadModel('common');
$_SESSION['storyQueryCondition'] = 'id < 5';
$_SESSION['storyOnlyCondition'] = true;
$sql = $tester->common->getPreAndNextSQL('story');
$list = $tester->common->queryListForPreAndNext('story', $sql);
r(implode('|', $list['objectList'])) && p() && e('1|2|3|4');
$_SESSION['storyQueryCondition'] = 'id <= 5';
$sql = $tester->common->getPreAndNextSQL('story');
$list = $tester->common->queryListForPreAndNext('story', $sql);
r(implode('|', $list['objectList'])) && p() && e('1|2|3|4|5');
$tester->common->app->tab = 'my';
$tester->common->app->moduleName = 'product';
$tester->common->app->methodName = 'browse';
$_SESSION['app-my']['storyproductbrowseBrowseList'] = array('sql' => 'SELECT * FROM `zt_story` WHERE id <= 5', 'idkey' => 'id', 'objectList' => array(1 => 1, 2 => 2, 3 => 3, 4 => 4));
$list = $tester->common->queryListForPreAndNext('story', $sql);
r(implode('|', $list['objectList'])) && p() && e('1|2|3|4');
@@ -0,0 +1,21 @@
#!/usr/bin/env php
<?php
include dirname(__FILE__, 5) . '/test/lib/init.php';
su('admin');
/**
title=测试 commonTao->searchPreAndNextFromList();
cid=1
pid=1
*/
global $tester;
$tester->loadModel('common');
$objectList = array('sql' => 'SELECT * FROM `zt_story` WHERE id < 5', 'idkey' => 'id', 'objectList' => array(1 => 1, 2 => 2, 3 => 3, 4 => 4));
r((array)$tester->common->searchPreAndNextFromList(0, array())) && p('pre,next') && e('~~,~~');
r((array)$tester->common->searchPreAndNextFromList(3, array())) && p('pre,next') && e('~~,~~');
r((array)$tester->common->searchPreAndNextFromList(3, $objectList)) && p('pre,next') && e('2,4');
+3 -2
View File
@@ -171,11 +171,12 @@ class releaseModel extends model
* @access public
* @return array
*/
public function getStoryReleases($storyID)
public function getStoryReleases(int $storyID): array
{
if(empty($storyID)) return array();
return $this->dao->select('*')->from(TABLE_RELEASE)
->where('deleted')->eq(0)
->andWhere("CONCAT(stories, ',')")->like("%,$storyID,%")
->andWhere("CONCAT(',', stories, ',')")->like("%,$storyID,%")
->orderBy('id_desc')
->fetchAll('id');
}
@@ -0,0 +1,27 @@
#!/usr/bin/env php
<?php
include dirname(__FILE__, 5) . '/test/lib/init.php';
include dirname(__FILE__, 2) . '/build.class.php';
su('admin');
$build = zdTable('release');
$build->stories->range('1-20{2}');
$build->createdBy->range('admin');
$build->createdDate->range('`' . date('Y-m-d H:i:s') . '`');
$build->gen(20);
/**
title=测试 buildModel->getStoryBuilds();
cid=1
pid=1
项目版本查询 >> 项目版本版本7
执行版本查询 >> 执行版本版本17
无id查询 >> 0
图片字段传字符串测试 >> 17
*/
global $tester;
$release = $tester->loadModel('release');
r(count($release->getStoryReleases(1))) && p() && e('2'); //项目版本查询
+3 -47
View File
@@ -485,60 +485,16 @@ class story extends control
$this->app->loadLang('bug');
$this->commonAction($storyID, $param);
$bugs = $this->dao->select('id,title,status,pri,severity')->from(TABLE_BUG)->where('story')->eq($storyID)->andWhere('deleted')->eq(0)->fetchAll();
$fromBug = $this->dao->select('id,title')->from(TABLE_BUG)->where('id')->eq($story->fromBug)->fetch();
$cases = $this->dao->select('id,title,status,pri')->from(TABLE_CASE)->where('story')->eq($storyID)->andWhere('deleted')->eq(0)->fetchAll();
$linkedMRs = $this->loadModel('mr')->getLinkedMRPairs($storyID, 'story');
$linkedCommits = $this->loadModel('repo')->getCommitsByObject($storyID, 'story');
$modulePath = $this->tree->getParents($story->module);
$storyModule = empty($story->module) ? '' : $this->tree->getById($story->module);
$linkedStories = isset($story->linkStoryTitles) ? array_keys($story->linkStoryTitles) : array();
$storyProducts = $this->dao->select('id,product')->from(TABLE_STORY)->where('id')->in($linkedStories)->fetchPairs();
$this->view->hiddenPlan = false;
$this->view->hiddenURS = false;
if(!empty($product->shadow))
{
$projectInfo = $this->dao->select('t2.model, t2.multiple')->from(TABLE_PROJECTPRODUCT)->alias('t1')
->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.project = t2.id')
->where('t1.product')->eq($product->id)
->andWhere('t2.type')->eq('project')
->fetch();
if($projectInfo->model == 'waterfall') $this->view->hiddenPlan = true;
if($projectInfo->model == 'kanban')
{
$this->view->hiddenPlan = true;
$this->view->hiddenURS = true;
}
if(!$projectInfo->multiple) $this->view->hiddenPlan = true;
}
$this->storyZen->getLinkedObjects($story);
$this->storyZen->setHiddenFieldsForView($product);
if($product->type != 'normal') $this->lang->product->branch = sprintf($this->lang->product->branch, $this->lang->product->branchName[$product->type]);
$reviewers = $this->story->getReviewerPairs($storyID, $story->version);
$execution = empty($story->execution) ? array() : $this->dao->findById($story->execution)->from(TABLE_EXECUTION)->fetch();
$project = $param ? $this->dao->findById($param)->from(TABLE_PROJECT)->fetch() : array();
$this->view->title = "STORY #$story->id $story->title - $product->name";
$this->view->branches = $product->type == 'normal' ? array() : $this->loadModel('branch')->getPairs($product->id);
$this->view->twins = !empty($story->twins) ? $this->story->getByList($story->twins) : array();
$this->view->bugs = $bugs;
$this->view->fromBug = $fromBug;
$this->view->cases = $cases;
$this->view->story = $story;
$this->view->linkedMRs = $linkedMRs;
$this->view->linkedCommits = $linkedCommits;
$this->view->users = $this->user->getPairs('noletter');
$this->view->reviewers = $reviewers;
$this->view->relations = $this->story->getStoryRelation($story->id, $story->type);
$this->view->executions = $this->execution->getPairs(0, 'all', 'nocode');
$this->view->execution = $execution;
$this->view->project = $project;
$this->view->storyModule = $storyModule;
$this->view->modulePath = $modulePath;
$this->view->storyProducts = $storyProducts;
$this->view->project = $this->project->fetchByID($param);
$this->view->version = $version;
$this->view->preAndNext = $this->loadModel('common')->getPreAndNextObject('story', $storyID);
$this->view->builds = $this->loadModel('build')->getStoryBuilds($storyID);
+1 -1
View File
@@ -3342,7 +3342,7 @@ class storyModel extends model
* @access public
* @return array|object
*/
public function mergeReviewer($stories, $isObject = false)
public function mergeReviewer(object|array $stories, $isObject = false)
{
$rawQuery = $this->dao->get();
if($isObject)
+36 -17
View File
@@ -4,31 +4,50 @@ include dirname(__FILE__, 5) . '/test/lib/init.php';
include dirname(__FILE__, 2) . '/story.class.php';
su('admin');
$story = zdTable('story');
$story->product->range(1);
$story->plan->range('0,1,0{100}');
$story->duplicateStory->range('0,4,0{100}');
$story->linkStories->range('0,6,0{100}');
$story->linkRequirements->range('3,0{100}');
$story->childStories->range('0,8,0{100}');
$story->toBug->range('0{9},1,0{100}');
$story->parent->range('0{17},`-1`,0,18,0{100}');
$story->twins->range('``{27},30,``,28');
$story->version->range('1');
$story->gen(30);
$storyReview = zdTable('storyreview');
$storyReview->story->range('1-30{3}');
$storyReview->reviewer->range('admin,user1,user2');
$storyReview->result->range('``{2}, pass');
$storyReview->version->range('1');
$storyReview->gen(90);
/**
title=测试 storyModel->mergeReviewer();
cid=1
pid=1
获取需求301的评审人 >> admin
获取需求301的待评审人 >> admin
获取产品76下的需求评审人 >> admin
获取产品76下的需求待评审人 >> admin
获取产品76下的需求评审人 >> admin
获取产品76下的需求待评审人 >> admin
*/
global $tester;
$story = $tester->loadModel('story')->getById(301);
$story = $tester->story->mergeReviewer($story, true);
$story = $tester->loadModel('story')->getById(2);
$story = $tester->story->mergeReviewer($story, true);
r(implode('|', $story->reviewer)) && p() && e('admin|user1|user2'); // 获取需求2的评审人
r(implode('|', $story->notReview)) && p() && e('admin|user1'); // 获取需求2的待评审人
$stories = $tester->story->getProductStories(76);
$stories = $tester->story->mergeReviewer($stories);
$story = $tester->loadModel('story')->getById(18);
$story = $tester->story->mergeReviewer($story, true);
r(implode('|', $story->reviewer)) && p() && e('admin|user1|user2'); // 获取需求18的评审人
r(implode('|', $story->notReview)) && p() && e('admin|user1'); // 获取需求18的待评审人
r(implode('|', $story->children[20]->reviewer)) && p() && e('admin|user1|user2'); // 获取需求18子需求的评审人
r(implode('|', $story->children[20]->notReview)) && p() && e('admin|user1'); // 获取需求18子需求的待评审人
r($story) && p('reviewer:0') && e('admin'); // 获取需求301的评审人
r($story) && p('notReview:0') && e('admin'); // 获取需求301的待评审人
r($stories[302]->reviewer[0]) && p() && e('admin'); // 获取产品76下的需求评审人
r($stories[302]->notReview[0]) && p() && e('admin'); // 获取产品76下的需求待评审人
r($stories[304]->reviewer[0]) && p() && e('admin'); // 获取产品76下的需求评审人
r($stories[304]->notReview[0]) && p() && e('admin'); // 获取产品76下的需求待评审人
$stories = $tester->story->mergeReviewer(array(18 => $story));
r(implode('|', $stories[18]->reviewer)) && p() && e('admin|user1|user2'); // 批量获取需求18的评审人
r(implode('|', $stories[18]->notReview)) && p() && e('admin|user1'); // 批量获取需求18的待评审人
r(implode('|', $stories[18]->children[20]->reviewer)) && p() && e('admin|user1|user2'); // 批量获取需求18子需求的评审人
r(implode('|', $stories[18]->children[20]->notReview)) && p() && e('admin|user1'); // 批量获取需求18子需求的待评审人
+52
View File
@@ -1704,4 +1704,56 @@ class storyZen extends story
$story = $this->loadModel('file')->processImgURL($postData, $this->config->story->editor->activate['id'], $this->post->uid);
return $story;
}
/**
* Get linked objects. e.g. bugs,cases,linkedMRs,linkedCommits,twins,reviewers,relations.
*
* @param object $story
* @access protected
* @return void
*/
protected function getLinkedObjects(object $story)
{
$linkedStories = isset($story->linkStoryTitles) ? array_keys($story->linkStoryTitles) : array();
$this->view->bugs = $this->dao->select('id,title,status,pri,severity')->from(TABLE_BUG)->where('story')->eq($story->id)->andWhere('deleted')->eq(0)->fetchAll();
$this->view->fromBug = $story->fromBug ? $this->dao->select('id,title')->from(TABLE_BUG)->where('id')->eq($story->fromBug)->fetch() : '';
$this->view->cases = $this->dao->select('id,title,status,pri')->from(TABLE_CASE)->where('story')->eq($story->id)->andWhere('deleted')->eq(0)->fetchAll();
$this->view->linkedMRs = $this->loadModel('mr')->getLinkedMRPairs($story->id, 'story');
$this->view->linkedCommits = $this->loadModel('repo')->getCommitsByObject($story->id, 'story');
$this->view->modulePath = $this->tree->getParents($story->module);
$this->view->storyModule = empty($story->module) ? '' : $this->tree->getById($story->module);
$this->view->storyProducts = $this->dao->select('id,product')->from(TABLE_STORY)->where('id')->in($linkedStories)->fetchPairs();
$this->view->twins = !empty($story->twins) ? $this->story->getByList($story->twins) : array();
$this->view->reviewers = $this->story->getReviewerPairs($story->id, $story->version);
$this->view->relations = $this->story->getStoryRelation($story->id, $story->type);
}
/**
* Set hidden fields for view. like: hiddenPlan,hiddenURS.
*
* @param object $product
* @access protected
* @return void
*/
protected function setHiddenFieldsForView(object $product)
{
$this->view->hiddenPlan = false;
$this->view->hiddenURS = false;
if(empty($product->shadow)) return;
$projectInfo = $this->dao->select('t2.model, t2.multiple')->from(TABLE_PROJECTPRODUCT)->alias('t1')
->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.project = t2.id')
->where('t1.product')->eq($product->id)
->andWhere('t2.type')->eq('project')
->fetch();
if($projectInfo->model == 'waterfall') $this->view->hiddenPlan = true;
if($projectInfo->model == 'kanban')
{
$this->view->hiddenPlan = true;
$this->view->hiddenURS = true;
}
if(!$projectInfo->multiple) $this->view->hiddenPlan = true;
}
}