* Rewrite story view page. Code for task #102973.
This commit is contained in:
@@ -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];
|
||||
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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');
|
||||
@@ -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');
|
||||
@@ -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'); //项目版本查询
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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子需求的待评审人
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user