* product: refactor browse function.
This commit is contained in:
+42
-204
@@ -102,10 +102,10 @@ class product extends control
|
||||
* Browse requirements list of product.
|
||||
*
|
||||
* @param int $productID
|
||||
* @param int|stirng $branch
|
||||
* @param int|stirng $branch all|''|0
|
||||
* @param string $browseType
|
||||
* @param int $param
|
||||
* @param string $storyType requirement|story
|
||||
* @param int $param Story Module ID
|
||||
* @param string $storyType requirement|story
|
||||
* @param string $orderBy
|
||||
* @param int $recTotal
|
||||
* @param int $recPerPage
|
||||
@@ -122,214 +122,50 @@ class product extends control
|
||||
$recPerPage = (int)$recPerPage;
|
||||
$pageID = (int)$pageID;
|
||||
$projectID = (int)$projectID;
|
||||
|
||||
$productID = $this->app->tab != 'project' ? $this->product->saveVisitState($productID, $this->products) : $productID;
|
||||
$product = $this->product->getById($productID);
|
||||
|
||||
if($product && !isset($this->products[$product->id])) $this->products[$product->id] = $product->name;
|
||||
|
||||
if($product and $product->type != 'normal')
|
||||
{
|
||||
$branchPairs = $this->loadModel('branch')->getPairs($productID, 'all');
|
||||
$branch = ($this->cookie->preBranch !== '' and $branch === '' and isset($branchPairs[$this->cookie->preBranch])) ? $this->cookie->preBranch : $branch;
|
||||
$branchID = $branch;
|
||||
}
|
||||
else
|
||||
{
|
||||
$branchID = $branch = 'all';
|
||||
}
|
||||
|
||||
/* Set menu. */
|
||||
if($this->app->tab == 'project')
|
||||
{
|
||||
$this->session->set('storyList', $this->app->getURI(true), 'project');
|
||||
$this->loadModel('project')->setMenu($projectID);
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->session->set('storyList', $this->app->getURI(true), 'product');
|
||||
$this->session->set('productList', $this->app->getURI(true), 'product');
|
||||
|
||||
$this->product->setMenu($productID, $branch, 0, '', "storyType=$storyType");
|
||||
}
|
||||
|
||||
/* Lower browse type. */
|
||||
$browseType = strtolower($browseType);
|
||||
|
||||
/* Load datatable and execution. */
|
||||
/* Pre process. */
|
||||
$isProjectStory = $this->app->rawModule == 'projectstory';
|
||||
$this->loadModel('datatable');
|
||||
$this->loadModel('execution');
|
||||
|
||||
/* Set product, module and query. */
|
||||
setcookie('preProductID', $productID, $this->config->cookieLife, $this->config->webRoot, '', $this->config->cookieSecure, true);
|
||||
setcookie('preBranch', $branch, $this->config->cookieLife, $this->config->webRoot, '', $this->config->cookieSecure, true);
|
||||
/* Generate data. */
|
||||
$showModule = !empty($this->config->datatable->productBrowse->showModule) ? $this->config->datatable->productBrowse->showModule : '';
|
||||
$productName = ($isProjectStory and empty($productID)) ? $this->lang->product->all : $this->products[$productID];
|
||||
$productID = $this->app->tab != 'project' ? $this->product->saveVisitState($productID, $this->products) : $productID;
|
||||
$product = $this->productZen->getBrowseProduct($productID);
|
||||
$project = $this->loadModel('project')->getByID($projectID);
|
||||
list($branch, $branchID) = $this->productZen->getBranchAndBranchID($product, $branch);
|
||||
$orderBy = $orderBy ?? ($this->cookie->productStoryOrder ? $this->cookie->productStoryOrder : 'id_desc');
|
||||
|
||||
if($this->cookie->preProductID != $productID or $this->cookie->preBranch != $branch or $browseType == 'bybranch')
|
||||
{
|
||||
$_COOKIE['storyModule'] = 0;
|
||||
setcookie('storyModule', 0, 0, $this->config->webRoot, '', $this->config->cookieSecure, false);
|
||||
}
|
||||
/* ATTENTION: be careful to change the order of follow sentencies. */
|
||||
$this->productZen->setMenu4Browse($projectID, $productID, $branch, $storyType);
|
||||
$this->productZen->saveAndModifyCookie4Browse($productID, $branch, $param, $browseType, $orderBy);
|
||||
|
||||
if($browseType == 'bymodule' or $browseType == '')
|
||||
{
|
||||
setcookie('storyModule', (int)$param, 0, $this->config->webRoot, '', $this->config->cookieSecure, false);
|
||||
if($this->app->tab == 'project') setcookie('storyModuleParam', (int)$param, 0, $this->config->webRoot, '', $this->config->cookieSecure, false);
|
||||
$_COOKIE['storyBranch'] = 'all';
|
||||
setcookie('storyBranch', 'all', 0, $this->config->webRoot, '', $this->config->cookieSecure, false);
|
||||
if($browseType == '') setcookie('treeBranch', $branch, 0, $this->config->webRoot, '', $this->config->cookieSecure, false);
|
||||
}
|
||||
if($browseType == 'bybranch') setcookie('storyBranch', $branch, 0, $this->config->webRoot, '', $this->config->cookieSecure, false);
|
||||
|
||||
$cookieModule = $this->app->tab == 'project' ? $this->cookie->storyModuleParam : $this->cookie->storyModule;
|
||||
|
||||
$moduleID = 0;
|
||||
if($browseType == 'bymodule') $moduleID = (int)$param;
|
||||
elseif($browseType != 'bysearch' and $browseType != 'bybranch' and $cookieModule) $moduleID = $cookieModule;
|
||||
|
||||
$queryID = ($browseType == 'bysearch') ? (int)$param : 0;
|
||||
|
||||
/* Set moduleTree. */
|
||||
$createModuleLink = $storyType == 'story' ? 'createStoryLink' : 'createRequirementLink';
|
||||
if($browseType == '')
|
||||
{
|
||||
setcookie('treeBranch', $branch, 0, $this->config->webRoot, '', $this->config->cookieSecure, false);
|
||||
$browseType = 'unclosed';
|
||||
}
|
||||
else
|
||||
{
|
||||
$branch = $this->cookie->treeBranch;
|
||||
}
|
||||
|
||||
$isProjectStory = $this->app->rawModule == 'projectstory';
|
||||
|
||||
/* If in project story and not chose product, get project story mdoules. */
|
||||
if($isProjectStory and empty($productID))
|
||||
{
|
||||
$moduleTree = $this->tree->getProjectStoryTreeMenu($projectID, 0, array('treeModel', $createModuleLink));
|
||||
}
|
||||
else
|
||||
{
|
||||
$moduleTree = $this->tree->getTreeMenu($productID, 'story', $startModuleID = 0, array('treeModel', $createModuleLink), array('projectID' => $projectID, 'productID' => $productID), $branch, "¶m=$param&storyType=$storyType");
|
||||
}
|
||||
|
||||
if($browseType != 'bymodule' and $browseType != 'bybranch') $this->session->set('storyBrowseType', $browseType);
|
||||
if(($browseType == 'bymodule' or $browseType == 'bybranch') and $this->session->storyBrowseType == 'bysearch') $this->session->set('storyBrowseType', 'unclosed');
|
||||
|
||||
/* Process the order by field. */
|
||||
if(!$orderBy) $orderBy = $this->cookie->productStoryOrder ? $this->cookie->productStoryOrder : 'id_desc';
|
||||
setcookie('productStoryOrder', $orderBy, 0, $this->config->webRoot, '', $this->config->cookieSecure, true);
|
||||
|
||||
/* Append id for secend sort. */
|
||||
$sort = common::appendOrder($orderBy);
|
||||
if(strpos($sort, 'pri_') !== false) $sort = str_replace('pri_', 'priOrder_', $sort);
|
||||
|
||||
/* Load pager. */
|
||||
$this->app->loadClass('pager', $static = true);
|
||||
if($this->app->getViewType() == 'xhtml') $recPerPage = 10;
|
||||
$pager = new pager($recTotal, $recPerPage, $pageID);
|
||||
|
||||
/* Display of branch label. */
|
||||
$showBranch = $this->loadModel('branch')->showBranch($productID);
|
||||
|
||||
/* Get stories. */
|
||||
$projectProducts = array();
|
||||
if($isProjectStory and $storyType == 'story')
|
||||
{
|
||||
$showBranch = $this->loadModel('branch')->showBranch($productID, 0, $projectID);
|
||||
|
||||
if(!empty($product)) $this->session->set('currentProductType', $product->type);
|
||||
|
||||
$this->products = $this->product->getProducts($projectID, 'all', '', false);
|
||||
$projectProducts = $this->product->getProducts($projectID);
|
||||
$productPlans = $this->execution->getPlans($projectProducts, 'skipParent,unexpired,noclosed', $projectID);
|
||||
|
||||
if($browseType == 'bybranch') $param = $branchID;
|
||||
$stories = $this->story->getExecutionStories($projectID, $productID, $branchID, $sort, $browseType, $param, $storyType, '', $pager);
|
||||
}
|
||||
else
|
||||
{
|
||||
$stories = $this->product->getStories($productID, $branchID, $browseType, $queryID, $moduleID, $storyType, $sort, $pager);
|
||||
}
|
||||
$queryCondition = $this->story->dao->get();
|
||||
|
||||
/* Display status of branch. */
|
||||
$branchOption = array();
|
||||
$branchTagOption = array();
|
||||
if(!$product and $isProjectStory)
|
||||
{
|
||||
/* Get branch display under multiple products. */
|
||||
$branchOptions = array();
|
||||
foreach($projectProducts as $projectProduct)
|
||||
{
|
||||
if($projectProduct and $projectProduct->type != 'normal')
|
||||
{
|
||||
$branches = $this->loadModel('branch')->getList($projectProduct->id, $projectID, 'all');
|
||||
foreach($branches as $branchInfo) $branchOptions[$projectProduct->id][$branchInfo->id] = $branchInfo->name;
|
||||
}
|
||||
}
|
||||
|
||||
$this->view->branchOptions = $branchOptions;
|
||||
}
|
||||
else
|
||||
{
|
||||
if($product and $product->type != 'normal')
|
||||
{
|
||||
$branches = $this->loadModel('branch')->getList($productID, $projectID, 'all');
|
||||
foreach($branches as $branchInfo)
|
||||
{
|
||||
$branchOption[$branchInfo->id] = $branchInfo->name;
|
||||
$branchTagOption[$branchInfo->id] = $branchInfo->name . ($branchInfo->status == 'closed' ? ' (' . $this->lang->branch->statusList['closed'] . ')' : '');
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Generate data. */
|
||||
$moduleID = $this->productZen->getModuleId4Browse($param, $browseType);
|
||||
$moduleTree = $this->productZen->getModuleTree4BrowseTODO($projectID, $productID, $branch, $param, $storyType, $browseType);
|
||||
$showBranch = $this->productZen->getShowBranch4Browse($projectID, $productID, $storyType, $isProjectStory);
|
||||
$projectProducts = $this->productZen->getProjectProducts4Browse($projectID, $storyType, $isProjectStory);
|
||||
$productPlans = $this->productZen->getProductPlans4Browse($projectProducts, $projectID, $storyType, $isProjectStory);
|
||||
list($stories, $pager) = $this->productZen->getStoriesAndPager4Browse($projectID, $productID, $branchID, $moduleID, $param, $storyType, $browseType, $orderBy, $recTotal, $recPerPage, $pageID);
|
||||
|
||||
/* Process the sql, get the conditon partion, save it to session. */
|
||||
$queryCondition = $this->story->dao->get();
|
||||
$this->loadModel('common')->saveQueryCondition($queryCondition, 'story', (strpos('bysearch,reviewbyme,bymodule', $browseType) === false and !$isProjectStory));
|
||||
|
||||
if(!empty($stories)) $stories = $this->story->mergeReviewer($stories);
|
||||
/* Collect story ID list. */
|
||||
$storyIdList = $this->productZen->getStoryIdList($stories);
|
||||
|
||||
/* Get related tasks, bugs, cases count of each story. */
|
||||
$storyIdList = array();
|
||||
foreach($stories as $story)
|
||||
{
|
||||
$storyIdList[$story->id] = $story->id;
|
||||
if(!empty($story->children))
|
||||
{
|
||||
foreach($story->children as $child) $storyIdList[$child->id] = $child->id;
|
||||
}
|
||||
}
|
||||
$storyTasks = $this->loadModel('task')->getStoryTaskCounts($storyIdList);
|
||||
$storyBugs = $this->loadModel('bug')->getStoryBugCounts($storyIdList);
|
||||
$storyCases = $this->loadModel('testcase')->getStoryCaseCounts($storyIdList);
|
||||
|
||||
/* Change for requirement story title. */
|
||||
if($storyType == 'requirement')
|
||||
{
|
||||
$this->lang->story->title = str_replace($this->lang->SRCommon, $this->lang->URCommon, $this->lang->story->title);
|
||||
$this->lang->story->create = str_replace($this->lang->SRCommon, $this->lang->URCommon, $this->lang->story->create);
|
||||
$this->config->product->search['fields']['title'] = $this->lang->story->title;
|
||||
unset($this->config->product->search['fields']['plan']);
|
||||
unset($this->config->product->search['fields']['stage']);
|
||||
}
|
||||
|
||||
$project = $this->loadModel('project')->getByID($projectID);
|
||||
if(isset($project->hasProduct) && empty($project->hasProduct))
|
||||
{
|
||||
if($isProjectStory && !$productID && !empty($this->products)) $productID = key($this->products); // If toggle a project by the #swapper component on the story page of the projectstory module, the $productID may be empty. Make sure it has value.
|
||||
unset($this->config->product->search['fields']['product']); // The none-product project don't need display the product in the search form.
|
||||
if($project->model != 'scrum') unset($this->config->product->search['fields']['plan']); // The none-product and none-scrum project don't need display the plan in the search form.
|
||||
}
|
||||
/* Generate data. */
|
||||
list($branchOpt, $branchTagOpt) = $this->productZen->getBranchAndTagOption4Browse($projectID, $product, $isProjectStory);
|
||||
$branchOptions = (empty($product) && $isProjectStory) ? $this->productZen->getBranchOptions4Browse($projectProducts, $projectID) : array();
|
||||
$storyTasks = $this->loadModel('task')->getStoryTaskCounts($storyIdList);
|
||||
$storyBugs = $this->loadModel('bug')->getStoryBugCounts($storyIdList);
|
||||
$storyCases = $this->loadModel('testcase')->getStoryCaseCounts($storyIdList);
|
||||
|
||||
/* Build search form. */
|
||||
$params = $isProjectStory ? "projectID=$projectID&" : '';
|
||||
$actionURL = $this->createLink($this->app->rawModule, $this->app->rawMethod, $params . "productID=$productID&branch=$branch&browseType=bySearch&queryID=myQueryID&storyType=$storyType");
|
||||
|
||||
$this->config->product->search['onMenuBar'] = 'yes';
|
||||
$this->product->buildSearchForm($productID, $this->products, $queryID, $actionURL, $branch, $projectID);
|
||||
|
||||
$showModule = !empty($this->config->datatable->productBrowse->showModule) ? $this->config->datatable->productBrowse->showModule : '';
|
||||
|
||||
$productName = ($isProjectStory and empty($productID)) ? $this->lang->product->all : $this->products[$productID];
|
||||
$this->productZen->buildSearchForm4Browse($project, $projectID, $productID, $branch, $param, $storyType, $browseType, $isProjectStory);
|
||||
|
||||
/* Assign. */
|
||||
$this->view->title = $productName . $this->lang->colon . ($storyType === 'story' ? $this->lang->product->browse : $this->lang->product->requirement);
|
||||
@@ -341,7 +177,7 @@ class product extends control
|
||||
$this->view->moduleID = $moduleID;
|
||||
$this->view->stories = $stories;
|
||||
$this->view->plans = $this->loadModel('productplan')->getPairs($productID, ($branch === 'all' or empty($branch)) ? '' : $branch, 'unexpired,noclosed', true);
|
||||
$this->view->productPlans = isset($productPlans) ? array(0 => '') + $productPlans : array();
|
||||
$this->view->productPlans = !empty($productPlans) ? array(0 => '') + $productPlans : array();
|
||||
$this->view->summary = $this->product->summary($stories, $storyType);
|
||||
$this->view->moduleTree = $moduleTree;
|
||||
$this->view->parentModules = $this->tree->getParents($moduleID);
|
||||
@@ -354,8 +190,9 @@ class product extends control
|
||||
$this->view->moduleName = ($moduleID and $moduleID !== 'all') ? $this->tree->getById($moduleID)->name : $this->lang->tree->all;
|
||||
$this->view->branch = $branch;
|
||||
$this->view->branchID = $branchID;
|
||||
$this->view->branchOption = $branchOption;
|
||||
$this->view->branchTagOption = $branchTagOption;
|
||||
$this->view->branchOptions = $branchOptions;
|
||||
$this->view->branchOption = $branchOpt;
|
||||
$this->view->branchTagOption = $branchTagOpt;
|
||||
$this->view->showBranch = $showBranch;
|
||||
$this->view->storyStages = $this->product->batchGetStoryStage($stories);
|
||||
$this->view->setModule = true;
|
||||
@@ -365,14 +202,14 @@ class product extends control
|
||||
$this->view->param = $param;
|
||||
$this->view->projectID = $projectID;
|
||||
$this->view->products = $this->products;
|
||||
$this->view->projectProducts = isset($projectProducts) ? $projectProducts : array();
|
||||
$this->view->projectProducts = !empty($projectProducts) ? $projectProducts : array();
|
||||
$this->view->storyType = $storyType;
|
||||
$this->view->from = $this->app->tab;
|
||||
$this->view->modulePairs = $showModule ? $this->tree->getModulePairs($productID, 'story', $showModule) : array();
|
||||
$this->view->project = $project;
|
||||
$this->view->recTotal = $pager->recTotal;
|
||||
|
||||
$this->render();
|
||||
$this->display();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -691,8 +528,9 @@ class product extends control
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function dashboard($productID = 0)
|
||||
public function dashboard(string $productID = '0')
|
||||
{
|
||||
$productID = (int)$productID;
|
||||
$uri = $this->app->getURI(true);
|
||||
$this->session->set('productPlanList', $uri, 'product');
|
||||
$this->session->set('releaseList', $uri, 'product');
|
||||
@@ -705,7 +543,7 @@ class product extends control
|
||||
$this->product->setMenu($productID);
|
||||
|
||||
/* Load pager. */
|
||||
$this->app->loadClass('pager', $static = true);
|
||||
$this->app->loadClass('pager', true);
|
||||
$pager = new pager(0, 30, 1);
|
||||
|
||||
$this->view->title = $product->name . $this->lang->colon . $this->lang->product->view;
|
||||
|
||||
@@ -786,4 +786,407 @@ class productZen extends product
|
||||
|
||||
return $fields;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取研发需求列表页面关联的产品信息。
|
||||
* Get the product of the browse page.
|
||||
*
|
||||
* @param int $productID
|
||||
* @access protected
|
||||
* @return object|false
|
||||
*/
|
||||
protected function getBrowseProduct(int $productID): object|false
|
||||
{
|
||||
$product = $this->product->getById($productID);
|
||||
|
||||
/* If product does not exist in $this->products list, then attach it to the list. */
|
||||
if($product && !isset($this->products[$product->id])) $this->products[$product->id] = $product->name;
|
||||
|
||||
return $product ?? false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取产品的分支和分支ID。
|
||||
* Get branch and branchID.
|
||||
*
|
||||
* @param object $product
|
||||
* @param string $branch
|
||||
* @access protected
|
||||
* @return object
|
||||
*/
|
||||
protected function getBranchAndBranchID(object|bool $product, string $branch): array
|
||||
{
|
||||
if(empty($product) || $product->type == 'normal') return ['all', 'all'];
|
||||
|
||||
/* 获取分支和分支ID。*/
|
||||
$branchPairs = $this->loadModel('branch')->getPairs($product->id, 'all');
|
||||
$branch = ($this->cookie->preBranch !== '' and $branch === '' and isset($branchPairs[$this->cookie->preBranch])) ? $this->cookie->preBranch : $branch;
|
||||
$branchID = $branch;
|
||||
|
||||
return [$branch, $branchID];
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置导航菜单。
|
||||
* Set navigation menu.
|
||||
*
|
||||
* @param int $projectID
|
||||
* @param int $productID
|
||||
* @param string $branch
|
||||
* @param string $storyType
|
||||
* @access protected
|
||||
* @return void
|
||||
*/
|
||||
protected function setMenu4Browse(int $projectID, int $productID, string $branch, string $storyType): void
|
||||
{
|
||||
if($this->app->tab == 'project')
|
||||
{
|
||||
$this->session->set('storyList', $this->app->getURI(true), 'project');
|
||||
$this->loadModel('project')->setMenu($projectID);
|
||||
return;
|
||||
}
|
||||
|
||||
$this->session->set('storyList', $this->app->getURI(true), 'product');
|
||||
$this->session->set('productList', $this->app->getURI(true), 'product');
|
||||
|
||||
$this->product->setMenu($productID, $branch, 0, '', "storyType=$storyType");
|
||||
}
|
||||
|
||||
/**
|
||||
* browse方法保存并修改cookie数据。
|
||||
* Save and modify cookies for browse function.
|
||||
*
|
||||
* @param int $productID
|
||||
* @param string $branch
|
||||
* @param int $param
|
||||
* @param string $storyType
|
||||
* @param string $orderBy
|
||||
* @access protected
|
||||
* @return void
|
||||
*/
|
||||
protected function saveAndModifyCookie4Browse(int $productID, string $branch, int $param, string $browseType, string $orderBy): void
|
||||
{
|
||||
/* Set product ID and branch of the pre visited product. */
|
||||
setcookie('preProductID', (string)$productID, $this->config->cookieLife, $this->config->webRoot, '', $this->config->cookieSecure, true);
|
||||
setcookie('preBranch', $branch, $this->config->cookieLife, $this->config->webRoot, '', $this->config->cookieSecure, true);
|
||||
|
||||
/* Set module ID of story. */
|
||||
if($this->cookie->preProductID != $productID or $this->cookie->preBranch != $branch or $browseType == 'bybranch')
|
||||
{
|
||||
$_COOKIE['storyModule'] = 0;
|
||||
setcookie('storyModule', '0', 0, $this->config->webRoot, '', $this->config->cookieSecure, false);
|
||||
}
|
||||
|
||||
if($browseType == 'bymodule' or $browseType == '')
|
||||
{
|
||||
setcookie('storyModule', (string)$param, 0, $this->config->webRoot, '', $this->config->cookieSecure, false);
|
||||
|
||||
/* The module ID from project app. */
|
||||
if($this->app->tab == 'project') setcookie('storyModuleParam', (string)$param, 0, $this->config->webRoot, '', $this->config->cookieSecure, false);
|
||||
|
||||
/* Re-init the story branch. */
|
||||
$_COOKIE['storyBranch'] = 'all';
|
||||
setcookie('storyBranch', 'all', 0, $this->config->webRoot, '', $this->config->cookieSecure, false);
|
||||
|
||||
/* For rendering module tree. */
|
||||
if($browseType == '') setcookie('treeBranch', $branch, 0, $this->config->webRoot, '', $this->config->cookieSecure, false);
|
||||
}
|
||||
|
||||
if($browseType == 'bybranch') setcookie('storyBranch', $branch, 0, $this->config->webRoot, '', $this->config->cookieSecure, false);
|
||||
|
||||
/* Save sort order of product stories list. */
|
||||
setcookie('productStoryOrder', $orderBy, 0, $this->config->webRoot, '', $this->config->cookieSecure, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取模块ID。
|
||||
* Get module ID.
|
||||
*
|
||||
* @param int $param
|
||||
* @param string $browseType
|
||||
* @access protected
|
||||
* @return int
|
||||
*/
|
||||
protected function getModuleId4Browse(int $param, string $browseType): int
|
||||
{
|
||||
$cookieModule = $this->app->tab == 'project' ? $this->cookie->storyModuleParam : $this->cookie->storyModule;
|
||||
|
||||
$moduleID = 0;
|
||||
if($browseType == 'bymodule') $moduleID = $param;
|
||||
elseif($browseType != 'bysearch' and $browseType != 'bybranch' and $cookieModule) $moduleID = $cookieModule;
|
||||
|
||||
return $moduleID;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取模块的树形数据结构。
|
||||
* Get the tree structure of modules.
|
||||
* TODO return pure HTML string, we need array.
|
||||
*
|
||||
* @param int $projectID
|
||||
* @param int $productID
|
||||
* @param string $branch
|
||||
* @param int $param
|
||||
* @param string $storyType
|
||||
* @param string $browseType
|
||||
* @access protected
|
||||
* @return string
|
||||
*/
|
||||
protected function getModuleTree4BrowseTODO(int $projectID, int $productID, string &$branch, int $param, string $storyType, string $browseType): string
|
||||
{
|
||||
/* Set moduleTree. */
|
||||
$createModuleLink = $storyType == 'story' ? 'createStoryLink' : 'createRequirementLink';
|
||||
if($browseType == '') $browseType = 'unclosed';
|
||||
else $branch = $this->cookie->treeBranch;
|
||||
|
||||
/* If in project story and not chose product, get project story mdoules. */
|
||||
if(empty($productID) && $this->app->rawModule == 'projectstory')
|
||||
{
|
||||
return $this->tree->getProjectStoryTreeMenu($projectID, 0, array('treeModel', $createModuleLink));
|
||||
}
|
||||
|
||||
return $this->tree->getTreeMenu(
|
||||
$productID,
|
||||
'story',
|
||||
0,
|
||||
array('treeModel', $createModuleLink),
|
||||
array('projectID' => $projectID, 'productID' => $productID),
|
||||
$branch,
|
||||
"¶m=$param&storyType=$storyType"
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取是否展示分支。
|
||||
* Get the tree structure of modules.
|
||||
*
|
||||
* @param int $projectID
|
||||
* @param int $productID
|
||||
* @param string $storyType
|
||||
* @param bool $isProjectStory
|
||||
* @access protected
|
||||
* @return bool
|
||||
*/
|
||||
protected function getShowBranch4Browse(int $projectID, int $productID, string $storyType, bool $isProjectStory): bool
|
||||
{
|
||||
if($isProjectStory and $storyType == 'story') return $this->loadModel('branch')->showBranch($productID, 0, $projectID);
|
||||
|
||||
return $this->loadModel('branch')->showBranch($productID);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取项目下的产品列表。
|
||||
* Get products of the project.
|
||||
*
|
||||
* @param int $projectID
|
||||
* @param string $storyType
|
||||
* @param bool $isProjectStory
|
||||
* @access protected
|
||||
* @return array
|
||||
*/
|
||||
protected function getProjectProducts4Browse(int $projectID, string $storyType, bool $isProjectStory): array
|
||||
{
|
||||
$projectProducts = array();
|
||||
if($isProjectStory && $storyType == 'story') $projectProducts = $this->product->getProducts($projectID);
|
||||
|
||||
return $projectProducts;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取产品计划。
|
||||
* Get product plans of the project.
|
||||
*
|
||||
* @param array $projectProducts
|
||||
* @param int $projectID
|
||||
* @param string $storyType
|
||||
* @param bool $isProjectStory
|
||||
* @access protected
|
||||
* @return array
|
||||
*/
|
||||
protected function getProductPlans4Browse(array $projectProducts, int $projectID, string $storyType, bool $isProjectStory): array
|
||||
{
|
||||
$this->loadModel('execution');
|
||||
|
||||
$plans = array();
|
||||
if($isProjectStory && $storyType == 'story') $plans = $this->execution->getPlans($projectProducts, 'skipParent,unexpired,noclosed', $projectID);
|
||||
|
||||
return $plans;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取需求列表及分页对象。
|
||||
* Get stories and the pager object.
|
||||
*
|
||||
* @param int $projectID
|
||||
* @param int $productID
|
||||
* @param string $branchID
|
||||
* @param string $moduleID
|
||||
* @param int $param
|
||||
* @param string $storyType
|
||||
* @param string $browseType
|
||||
* @param string $orderBy
|
||||
* @param int $recTotal
|
||||
* @param int $recPerPage
|
||||
* @param int $pageID
|
||||
* @access protected
|
||||
* @return array
|
||||
*/
|
||||
protected function getStoriesAndPager4Browse(int $projectID, int $productID, string $branchID, int $moduleID, int $param, string $storyType, string $browseType, string $orderBy, int $recTotal, int $recPerPage, int $pageID): array
|
||||
{
|
||||
/* Append id for secend sort. */
|
||||
$sort = common::appendOrder($orderBy);
|
||||
if(strpos($sort, 'pri_') !== false) $sort = str_replace('pri_', 'priOrder_', $sort);
|
||||
|
||||
/* Load pager. */
|
||||
$this->app->loadClass('pager', true);
|
||||
if($this->app->getViewType() == 'xhtml') $recPerPage = 10;
|
||||
$pager = new pager($recTotal, $recPerPage, $pageID);
|
||||
|
||||
$isProjectStory = $this->app->rawModule == 'projectstory';
|
||||
|
||||
/* Get stories. */
|
||||
if($isProjectStory and $storyType == 'story')
|
||||
{
|
||||
if(!empty($product)) $this->session->set('currentProductType', $product->type);
|
||||
|
||||
$this->products = $this->product->getProducts($projectID, 'all', '', false);
|
||||
|
||||
if($browseType == 'bybranch') $param = $branchID;
|
||||
$stories = $this->story->getExecutionStories($projectID, $productID, $branchID, $sort, $browseType, $param, $storyType, '', $pager);
|
||||
}
|
||||
else
|
||||
{
|
||||
$queryID = ($browseType == 'bysearch') ? $param : 0;
|
||||
$stories = $this->product->getStories($productID, $branchID, $browseType, $queryID, $moduleID, $storyType, $sort, $pager);
|
||||
}
|
||||
|
||||
if(!empty($stories)) $stories = $this->story->mergeReviewer($stories);
|
||||
|
||||
return [$stories, $pager];
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取分支的配置数据。
|
||||
* Get branch options.
|
||||
*
|
||||
* @param array $projectProducts
|
||||
* @param int $projectID
|
||||
* @access protected
|
||||
* @return array
|
||||
*/
|
||||
protected function getBranchOptions4Browse(array $projectProducts, int $projectID): array
|
||||
{
|
||||
$branchOptions = array();
|
||||
|
||||
foreach($projectProducts as $product)
|
||||
{
|
||||
if($product and $product->type != 'normal')
|
||||
{
|
||||
$branches = $this->loadModel('branch')->getList($product->id, $projectID, 'all');
|
||||
foreach($branches as $branchInfo) $branchOptions[$product->id][$branchInfo->id] = $branchInfo->name;
|
||||
}
|
||||
}
|
||||
|
||||
return $branchOptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取分支和分支标签的显示项。
|
||||
* Get options of branch and branch tag.
|
||||
*
|
||||
* @param int $productID
|
||||
* @param object|bool $product
|
||||
* @param bool $isProjectStory
|
||||
* @access protected
|
||||
* @return [array, array]
|
||||
*/
|
||||
protected function getBranchAndTagOption4Browse(int $projectID, object|bool $product, bool $isProjectStory): array
|
||||
{
|
||||
$branchOption = array();
|
||||
$branchTagOption = array();
|
||||
|
||||
if(empty($product) and $isProjectStory) return [$branchOption, $branchTagOption];
|
||||
|
||||
if($product and $product->type != 'normal')
|
||||
{
|
||||
$branches = $this->loadModel('branch')->getList($product->id, $projectID, 'all');
|
||||
foreach($branches as $branchInfo)
|
||||
{
|
||||
$branchOption[$branchInfo->id] = $branchInfo->name;
|
||||
$branchTagOption[$branchInfo->id] = $branchInfo->name . ($branchInfo->status == 'closed' ? ' (' . $this->lang->branch->statusList['closed'] . ')' : '');
|
||||
}
|
||||
}
|
||||
|
||||
return [$branchOption, $branchTagOption];
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建搜索表单。
|
||||
* Build search form.
|
||||
*
|
||||
* @param object|bool $project
|
||||
* @param int $projectID
|
||||
* @param int $productID
|
||||
* @param string $branch
|
||||
* @param int $param
|
||||
* @param string $storyType
|
||||
* @param string $browseType
|
||||
* @param bool $isProjectStory
|
||||
* @access protected
|
||||
* @return void
|
||||
*/
|
||||
protected function buildSearchForm4Browse(object|bool $project,int $projectID, int &$productID, string $branch, int $param, string $storyType, string $browseType, bool $isProjectStory): void
|
||||
{
|
||||
/* Save browse type into session. */
|
||||
if($browseType != 'bymodule' and $browseType != 'bybranch') $this->session->set('storyBrowseType', $browseType);
|
||||
if(($browseType == 'bymodule' or $browseType == 'bybranch') and $this->session->storyBrowseType == 'bysearch') $this->session->set('storyBrowseType', 'unclosed');
|
||||
|
||||
/* Change for requirement story title. */
|
||||
if($storyType == 'requirement')
|
||||
{
|
||||
$this->lang->story->title = str_replace($this->lang->SRCommon, $this->lang->URCommon, $this->lang->story->title);
|
||||
$this->lang->story->create = str_replace($this->lang->SRCommon, $this->lang->URCommon, $this->lang->story->create);
|
||||
$this->config->product->search['fields']['title'] = $this->lang->story->title;
|
||||
unset($this->config->product->search['fields']['plan']);
|
||||
unset($this->config->product->search['fields']['stage']);
|
||||
}
|
||||
|
||||
if(isset($project->hasProduct) && empty($project->hasProduct))
|
||||
{
|
||||
if($isProjectStory && !$productID && !empty($this->products)) $productID = (int)key($this->products); // If toggle a project by the #swapper component on the story page of the projectstory module, the $productID may be empty. Make sure it has value.
|
||||
unset($this->config->product->search['fields']['product']); // The none-product project don't need display the product in the search form.
|
||||
if($project->model != 'scrum') unset($this->config->product->search['fields']['plan']); // The none-product and none-scrum project don't need display the plan in the search form.
|
||||
}
|
||||
|
||||
/* Build search form. */
|
||||
$params = $isProjectStory ? "projectID=$projectID&" : '';
|
||||
$actionURL = $this->createLink($this->app->rawModule, $this->app->rawMethod, $params . "productID=$productID&branch=$branch&browseType=bySearch&queryID=myQueryID&storyType=$storyType");
|
||||
|
||||
$this->config->product->search['onMenuBar'] = 'yes';
|
||||
$queryID = ($browseType == 'bysearch') ? $param : 0;
|
||||
$this->product->buildSearchForm($productID, $this->products, $queryID, $actionURL, $branch, $projectID);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取需求的ID列表。
|
||||
* Get ID list of stories.
|
||||
*
|
||||
* @param array $stories
|
||||
* @access protected
|
||||
* @return array
|
||||
*/
|
||||
protected function getStoryIdList(array $stories): array
|
||||
{
|
||||
$storyIdList = array();
|
||||
foreach($stories as $story)
|
||||
{
|
||||
$storyIdList[$story->id] = $story->id;
|
||||
if(!empty($story->children))
|
||||
{
|
||||
foreach($story->children as $child) $storyIdList[$child->id] = $child->id;
|
||||
}
|
||||
}
|
||||
|
||||
return $storyIdList;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user