Files
EasySoft-ZenTaoPMS/module/build/control.php
2025-03-06 14:47:11 +08:00

726 lines
29 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
declare(strict_types=1);
/**
* The control file of build module of ZenTaoPMS.
*
* @copyright Copyright 2009-2023 禅道软件(青岛)有限公司(ZenTao Software (Qingdao) Co., Ltd. www.cnezsoft.com)
* @license ZPL(http://zpl.pub/page/zplv12.html) or AGPL(https://www.gnu.org/licenses/agpl-3.0.en.html)
* @author Chunsheng Wang <chunsheng@cnezsoft.com>
* @package build
* @version $Id: control.php 4992 2013-07-03 07:21:59Z chencongzhi520@gmail.com $
* @link https://www.zentao.net
*/
class build extends control
{
/**
* 公共函数,设置产品型项目属性。
* Common actions.
*
* @param int $projectID
* @access public
* @return void
*/
public function commonActions(int $projectID = 0)
{
$hidden = '';
if($projectID)
{
$project = $this->loadModel('project')->getByID($projectID);
if(!$project->hasProduct) $hidden = 'hide';
$this->view->multipleProject = $project->multiple;
}
$this->view->hidden = $hidden;
$this->view->projectID = $projectID;
}
/**
* 创建一个版本。
* Create a build.
*
* @param int $executionID
* @param int $productID
* @param int $projectID
* @access public
* @return void
*/
public function create(int $executionID = 0, int $productID = 0, int $projectID = 0)
{
$this->loadModel('execution');
$this->loadModel('project');
$this->loadModel('file');
/* Set menu. */
if($this->app->tab == 'project')
{
$this->project->setMenu($projectID);
}
elseif(in_array($this->app->tab, array('execution', 'qa')))
{
$execution = $this->execution->getByID($executionID);
$projectID = $execution ? $execution->project : 0;
}
if($this->app->tab == 'execution') $this->execution->setMenu($executionID);
if(!empty($_POST))
{
$build = $this->buildZen->buildBuildForCreate();
if(!empty($_FILES['buildFiles'])) $_FILES['files'] = $_FILES['buildFiles'];
unset($_FILES['buildFiles']);
if(dao::isError()) return $this->sendError(dao::getError());
if(commonModel::isTutorialMode()) return $this->sendSuccess(array('closeModal' => true)); // Fix bug #21095.
$buildID = $this->build->create($build);
if(dao::isError()) return $this->sendError(dao::getError());
$message = $this->executeHooks($buildID);
if($message) $this->lang->saveSuccess = $message;
if(helper::isAjaxRequest('modal')) return $this->sendSuccess(array('closeModal' => true, 'callback' => 'refreshExecutionBuild()'));
return $this->sendSuccess(array('load' => $this->createLink($this->app->rawModule, 'view', "buildID=$buildID"), 'id' => $buildID));
}
if(in_array($this->app->tab, array('execution', 'project'))) $this->session->set('project', $projectID);
$status = empty($this->config->CRProduct) ? 'noclosed' : '';
$this->buildZen->assignCreateData($productID, $executionID, $projectID, $status);
}
/**
* 编辑一个版本。
* Edit a build.
*
* @param int $buildID
* @access public
* @return void
*/
public function edit(int $buildID)
{
if(!empty($_POST))
{
$build = $this->buildZen->buildBuildForEdit($buildID);
$changes = $this->build->update($buildID, $build);
if(dao::isError()) return $this->sendError(dao::getError());
$change[$buildID] = $changes;
$this->unlinkOldBranch($change);
if($changes)
{
$actionID = $this->loadModel('action')->create('build', $buildID, 'Edited');
if(!empty($changes)) $this->action->logHistory($actionID, $changes);
}
$message = $this->executeHooks($buildID);
if($message) $this->lang->saveSuccess = $message;
return $this->sendSuccess(array('locate' => $this->createLink($this->app->rawModule, 'view', "buildID=$buildID") . "#app={$this->app->tab}"));
}
$this->loadModel('execution');
$this->loadModel('product');
$build = $this->build->getById($buildID);
/* Set menu. */
if($this->app->tab == 'project') $this->loadModel('project')->setMenu($build->project);
if($this->app->tab == 'execution')
{
$this->execution->setMenu((int)$build->execution);
$this->view->executionID = $build->execution;
}
$this->commonActions($build->project);
$this->buildZen->assignEditData($build);
}
/**
* 版本详情。
* View a build.
*
* @param int $buildID
* @param string $type
* @param string $link
* @param string $param
* @param string $orderBy
* @param int $recTotal
* @param int $recPerPage
* @param int $pageID
* @access public
* @return void
*/
public function view(int $buildID, string $type = 'story', string $link = 'false', string $param = '', string $orderBy = 'id_desc', int $recTotal = 0, int $recPerPage = 100, int $pageID = 1)
{
$build = $this->build->getByID($buildID, true);
if(!$build)
{
if(defined('RUN_MODE') && RUN_MODE == 'api') return $this->send(array('status' => 'fail', 'code' => 404, 'message' => '404 Not found'));
return $this->send(array('result' => 'success', 'load' => array('alert' => $this->lang->notFound, 'locate' => $this->createLink('execution', 'all'))));
}
/* Load pager. */
$this->app->loadClass('pager', true);
if($this->app->getViewType() == 'mhtml') $recPerPage = 10;
$sort = common::appendOrder($orderBy);
if(strpos($sort, 'pri_') !== false && $type == 'story') $sort = str_replace('pri_', 'priOrder_', $sort);
$bugPager = new pager($type == 'bug' ? $recTotal : 0, $recPerPage, $type == 'bug' ? $pageID : 1);
$generatedBugPager = new pager($type == 'generatedBug' ? $recTotal : 0, $recPerPage, $type == 'generatedBug' ? $pageID : 1);
$this->buildZen->assignBugVarsForView($build, $type, $sort, $param, $bugPager, $generatedBugPager);
$storyPager = new pager($type == 'story' ? $recTotal : 0, $recPerPage, $type == 'story' ? $pageID : 1);
$this->buildZen->assignProductVarsForView($build, $type, $sort, $storyPager);
/* Set menu. */
$this->buildZen->setMenuForView($build);
$this->commonActions($build->project);
$this->executeHooks($buildID);
/* Assign. */
$this->view->canBeChanged = common::canBeChanged('build', $build); // Determines whether an object is editable.
$this->view->users = $this->loadModel('user')->getPairs('noletter');
$this->view->build = $build;
$this->view->actions = $this->loadModel('action')->getList('build', $buildID);
$this->view->link = $link;
$this->view->orderBy = $orderBy;
$this->view->grades = $this->loadModel('story')->getGradePairs('story', 'all');
$this->view->showGrade = $this->config->edition == 'ipd';
$this->view->execution = $this->loadModel('execution')->getByID((int)$build->execution);
$this->view->childBuilds = empty($build->builds) ? array() : $this->build->getByList(explode(',', $build->builds));
$this->view->productID = $build->product;
$this->view->systemList = $this->loadModel('system')->getPairs();
$this->display();
}
/**
* 删除一个版本。
* Delete a build.
*
* @param int $buildID
* @param string $from execution|project
* @access public
* @return void
*/
public function delete(int $buildID, string $from = 'execution')
{
$build = $this->build->getById($buildID);
$this->build->delete(TABLE_BUILD, $buildID);
$message = $this->executeHooks($buildID);
if($message) $this->lang->saveSuccess = $message;
if(dao::isError()) return $this->sendError(dao::getError());
$moduleName = $from == 'project' ? 'projectbuild' : $from;
$methodName = $from == 'project' ? 'browse' : 'build';
return $this->sendSuccess(array('load' => $this->createLink($moduleName, $methodName, "executionID={$build->$from}")));
}
/**
* 重构获取产品下的版本下拉列表。
* AJAX: get builds of a product in html select.
*
* @param int $productID
* @param string $varName the name of the select object to create
* @param string $build build to selected
* @param string $branch
* @param string $type get all builds or some builds belong to normal releases and executions are not done.
* @access public
* @return string
*/
public function ajaxGetProductBuilds(int $productID, string $varName, string $build = '', string $branch = 'all', string $type = 'normal')
{
$isJsonView = $this->app->getViewType() == 'json';
if($varName == 'openedBuild' )
{
$params = $type == 'all' ? 'withbranch,noreleased,noreplace' : 'noterminate,nodone,withbranch,noreleased';
$builds = $this->build->getBuildPairs(array($productID), $branch, $params, 0, 'project', $build);
if($isJsonView) return print(json_encode($builds));
$builds = $this->build->addReleaseLabelForBuilds($productID, $builds);
return print(json_encode($builds));
}
if($varName == 'openedBuilds' )
{
$builds = $this->build->getBuildPairs(array($productID), $branch, 'noempty,noreleased', 0, 'project', $build);
$builds = $this->build->addReleaseLabelForBuilds($productID, $builds);
return $this->send($builds);
}
if($varName == 'resolvedBuild')
{
$params = $type == 'all' ? 'withbranch,noreleased' : 'noterminate,nodone,withbranch,noreleased';
$builds = $this->build->getBuildPairs(array($productID), $branch, $params, 0, 'project', $build);
if($isJsonView) return print(json_encode($builds));
$builds = $this->build->addReleaseLabelForBuilds($productID, $builds);
return print(json_encode($builds));
}
$builds = $this->build->getBuildPairs(array($productID), $branch, $type, 0, 'project', $build, false);
if($isJsonView) return print(json_encode($builds));
$builds = $this->build->addReleaseLabelForBuilds($productID, $builds);
return print(json_encode($builds));
}
/**
* 获取项目下的版本下拉列表。
* AJAX: get builds of a project in html select.
*
* @param int $projectID
* @param string $varName the name of the select object to create
* @param string $build build to selected
* @param string|int $branch
* @param bool $needCreate if need to append the link of create build
* @param string $type get all builds or some builds belong to normal releases and executions are not done.
* @access public
* @return string
*/
public function ajaxGetProjectBuilds(int $projectID, int $productID, string $varName, string $build = '', string|int $branch = 'all', $needCreate = false, $type = 'normal', int $system = 0)
{
$isJsonView = $this->app->getViewType() == 'json';
if($varName == 'openedBuild')
{
if(empty($projectID)) return $this->ajaxGetProductBuilds($productID, $varName, $build, $branch, $type);
$params = $type == 'all' ? 'noempty,withbranch,noreleased' : 'noempty,noterminate,nodone,withbranch,noreleased';
$builds = $this->build->getBuildPairs(array($productID), $branch, $params, $projectID, 'project', $build);
if($isJsonView) return print(json_encode($builds));
$builds = $this->build->addReleaseLabelForBuilds($productID, $builds);
return print(json_encode($builds));
}
if($varName == 'resolvedBuild')
{
if(empty($projectID)) return $this->ajaxGetProductBuilds($productID, $varName, $build, $branch, $type);
$params = ($type == 'all') ? 'withbranch,noreleased' : 'noterminate,nodone,withbranch,noreleased';
$builds = $this->build->getBuildPairs(array($productID), $branch, $params, $projectID, 'project', $build);
if($isJsonView) return print(json_encode($builds));
$builds = $this->build->addReleaseLabelForBuilds($productID, $builds);
return print(json_encode($builds));
}
if(empty($projectID)) return $this->ajaxGetProductBuilds($productID, $varName, $build, $branch, $type);
$builds = $this->build->getBuildPairs(array($productID), $branch, $type, $projectID, 'project', $build, false, (int)$system);
if($isJsonView) return print(json_encode($builds));
$builds = $this->build->addReleaseLabelForBuilds($productID, $builds);
return print(json_encode($builds));
}
/**
* 获取执行下的版本下拉列表。
* AJAX: get builds of an execution in html select.
*
* @param int $executionID
* @param int $productID
* @param string $varName the name of the select object to create
* @param string $build build to selected
* @param string $branch
* @param bool $needCreate if need to append the link of create build
* @param string $type get all builds or some builds belong to normal releases and executions are not done.
* @access public
* @return string
*/
public function ajaxGetExecutionBuilds(int $executionID, int $productID, string $varName, string $build = '', string $branch = 'all', bool $needCreate = false, string $type = 'normal')
{
$isJsonView = $this->app->getViewType() == 'json';
if($varName == 'openedBuild')
{
if(empty($executionID)) return $this->ajaxGetProductBuilds($productID, $varName, $build, $branch, $type);
$params = ($type == 'all') ? 'noempty,noreleased' : 'noempty,noterminate,nodone,noreleased';
$builds = $this->build->getBuildPairs(array($productID), $branch, $params, $executionID, 'execution', $build);
if($isJsonView) return print(json_encode($builds));
$builds = $this->build->addReleaseLabelForBuilds($productID, $builds);
return print(json_encode($builds));
}
if($varName == 'openedBuilds')
{
if(empty($executionID)) return $this->ajaxGetProductBuilds($productID, $varName, $build, $branch, $type);
$builds = $this->build->getBuildPairs(array($productID), $branch, 'noempty,noreleased', $executionID, 'execution', $build);
$buildList = array();
foreach($builds as $buildID => $buildName) $buildList[] = array('value' => $buildID, 'text' => $buildName);
return $this->send($buildList);
}
if($varName == 'resolvedBuild')
{
if(empty($executionID)) return $this->ajaxGetProductBuilds($productID, $varName, $build, $branch, $type);
$params = ($type == 'all') ? ',noreleased' : 'noterminate,nodone,noreleased';
$builds = $this->build->getBuildPairs(array($productID), $branch, $params, $executionID, 'execution', $build);
if($isJsonView) return print(json_encode($builds));
return print(html::select($varName, $builds, $build, "class='form-control'"));
}
if($varName == 'testTaskBuild')
{
$builds = $this->build->getBuildPairs(array($productID), $branch, 'noempty,notrunk', $executionID, 'execution', '', false);
if($isJsonView) return print(json_encode($builds));
$builds = $this->build->addReleaseLabelForBuilds($productID, $builds);
return print(json_encode($builds));
}
if($varName == 'dropdownList')
{
$builds = $this->build->getBuildPairs(array($productID), $branch, 'noempty,notrunk', $executionID, 'execution');
if($isJsonView) return print(json_encode($builds));
$list = "<div class='list-group'>";
foreach($builds as $buildID => $buildName) $list .= html::a(inlink('view', "buildID={$buildID}"), $buildName);
$list .= '</div>';
return print($list);
}
}
/**
* 获取最后一次创建的版本。
* Ajax get last build.
*
* @param int $projectID
* @param int $executionID
* @access public
* @return string
*/
public function ajaxGetLastBuild(int $projectID, int $executionID)
{
$lastBuild = $this->build->getLast($executionID, $projectID);
if(!$lastBuild) return print('');
echo "<div class='help-block'> &nbsp; " . $this->lang->build->last . ": <a class='code label light' id='lastBuildBtn'>" . $lastBuild->name . "</a></div>";
}
/**
* 版本关联需求。
* Link stories to build.
*
* @param int $buildID
* @param string $browseType
* @param int $param
* @param string $orderBy
* @param int $recTotal
* @param int $recPerPage
* @param int $pageID
* @access public
* @return void
*/
public function linkStory(int $buildID = 0, string $browseType = '', int $param = 0, string $orderBy = 'id_desc', int $recTotal = 0, int $recPerPage = 100, int $pageID = 1)
{
if(!empty($_POST['stories']))
{
if($this->post->stories) $this->build->linkStory($buildID, $this->post->stories);
if(dao::isError()) return $this->sendError(dao::getError());
return $this->send(array('result' => 'success', 'load' => $this->createLink($this->app->rawModule, 'view', "buildID=$buildID&type=story")));
}
$this->session->set('storyList', $this->createLink($this->app->rawModule, 'view', "buildID=$buildID&type=story&link=true&param=" . helper::safe64Encode("&browseType=$browseType&queryID=$param")), $this->app->tab);
$build = $this->build->getById($buildID);
$product = $this->loadModel('product')->getById($build->product);
if($this->app->tab == 'project')
{
$this->loadModel('project')->setMenu($build->project);
$this->view->projectID = $build->project;
}
if($build->execution) $this->loadModel('execution')->setMenu((int)$build->execution);
/* Load pager. */
$this->app->loadClass('pager', $static = true);
$pager = new pager($recTotal, $recPerPage, $pageID);
/* Build search form. */
$this->buildZen->buildLinkStorySearchForm($build, $browseType == 'bySearch' ? (int)$param : 0, isset($product->type) ? $product->type : 'normal');
$this->loadModel('story');
$executionID = $build->execution ? (int)$build->execution : (int)$build->project;
$excludeStoryIdList = $this->buildZen->getExcludeStoryIdList($build);
if($browseType == 'bySearch')
{
$allStories = $this->story->getBySearch($build->product, $build->branch, (int)$param, $orderBy, $executionID, 'story', $excludeStoryIdList, '', $pager);
}
else
{
$allStories = $this->story->getExecutionStories($executionID, $build->product, $orderBy, 'byBranch', $build->branch, 'story', $excludeStoryIdList, $pager);
}
$checkedRows = array();
foreach($allStories as $story)
{
if(in_array($story->stage, array('developed', 'tested', 'closed'))) $checkedRows[] = $story->id;
}
$this->view->allStories = $allStories;
$this->view->checkedRows = $checkedRows;
$this->view->build = $build;
$this->view->buildStories = empty($build->stories) ? array() : $this->story->getByList($build->stories);
$this->view->users = $this->loadModel('user')->getPairs('noletter');
$this->view->browseType = $browseType;
$this->view->param = $param;
$this->view->pager = $pager;
$this->view->grades = $this->story->getGradePairs('story', 'all');
$this->view->showGrade = $this->config->edition == 'ipd';
$this->view->orderBy = $orderBy;
$this->display();
}
/**
* 解除需求关联。
* Unlink story.
*
* @param int $buildID
* @param int $storyID
* @access public
* @return bool
*/
public function unlinkStory(int $buildID, int $storyID)
{
$this->build->unlinkStory($buildID, $storyID);
$this->loadModel('action')->create($this->app->rawModule, $buildID, 'unlinkstory', '', $storyID);
return $this->sendSuccess(array('load' => $this->createLink($this->app->rawModule, 'view', "buildID=$buildID&type=story")));
}
/**
* 检查并输出移除移除需求和Bug分支的提示信息。
* AJAX: Get unlinkBranch story and bug.
*
* @param int $buildID
* @param int $newBranch
* @access public
* @return void
*/
public function ajaxGetBranch(int $buildID, int $newBranch)
{
$build = $this->build->getByID($buildID);
if(!$build) return '';
$buildStories = $build->allStories ? $this->loadModel('story')->getByList($build->allStories) : array();
$buildBugs = $build->allBugs ? $this->loadModel('bug')->getByIdList($build->allBugs) : array();
$branchPairs = $this->loadModel('branch')->getPairs($build->product);
$typeName = $this->lang->product->branchName[$build->productType];
$removeBranches = '';
foreach(explode(',', $build->branch) as $oldBranchID)
{
if($oldBranchID && strpos(",$newBranch,", ",$oldBranchID,") === false) $removeBranches .= "{$branchPairs[$oldBranchID]},";
}
$unlinkStoryCounts = 0;
$unlinkBugCounts = 0;
if($build->branch)
{
foreach($buildStories as $storyID => $story)
{
if($story->branch && strpos(",$newBranch,", ",$story->branch,") === false) $unlinkStoryCounts ++;
}
foreach($buildBugs as $bugID => $bug)
{
if($bug->branch && strpos(",$newBranch,", ",$bug->branch,") === false) $unlinkBugCounts ++;
}
}
if($unlinkStoryCounts && $unlinkBugCounts)
{
printf($this->lang->build->confirmChangeBuild, $typeName, trim($removeBranches, ','), $typeName, $unlinkStoryCounts, $unlinkBugCounts);
}
elseif($unlinkStoryCounts)
{
printf($this->lang->build->confirmRemoveStory, $typeName, trim($removeBranches, ','), $typeName, $unlinkStoryCounts);
}
elseif($unlinkBugCounts)
{
printf($this->lang->build->confirmRemoveBug, $typeName, trim($removeBranches, ','), $typeName, $unlinkBugCounts);
}
}
/**
* 批量解除需求关联。
* Batch unlink story.
*
* @param int $buildID
* @access public
* @return bool
*/
public function batchUnlinkStory(int $buildID)
{
if($this->post->storyIdList) $this->build->batchUnlinkStory($buildID, $this->post->storyIdList);
return $this->sendSuccess(array('load' => $this->createLink($this->app->rawModule, 'view', "buildID=$buildID&type=story")));
}
/**
* 编辑版本时解除跟未关联分支的需求和Bug的关联。
* Unlink story and bug when edit branch of build.
*
* @param array $changes
* @access pulic
* @return void
*/
public function unlinkOldBranch(array $changes)
{
foreach($changes as $buildID => $changeList)
{
$oldBranch = '';
$newBranch = '';
foreach($changeList as $change)
{
if($change['field'] == 'branch')
{
$oldBranch = $change['old'];
$newBranch = $change['new'];
break;
}
}
$build = $this->build->getByID($buildID);
$planStories = $build->allStories ? $this->loadModel('story')->getByList($build->allStories) : array();
$planBugs = $build->allBugs ? $this->loadModel('bug')->getByIdList($build->allBugs) : array();
if($oldBranch)
{
foreach($planStories as $storyID => $story)
{
if($story->branch and strpos(",$newBranch,", ",$story->branch,") === false) $this->build->unlinkStory($buildID, $storyID);
}
foreach($planBugs as $bugID => $bug)
{
if($bug->branch and strpos(",$newBranch,", ",$bug->branch,") === false) $this->build->unlinkBug($buildID, $bugID);
}
}
}
}
/**
* 版本关联Bug。
* Link bug.
*
* @param int $buildID
* @param string $browseType
* @param int $param
* @param int $recTotal
* @param int $recPerPage
* @param int $pageID
* @access public
* @return void
*/
public function linkBug(int $buildID = 0, string $browseType = '', int $param = 0, int $recTotal = 0, int $recPerPage = 100, int $pageID = 1)
{
if(!empty($_POST['bugs']))
{
$this->build->linkBug($buildID, $this->post->bugs, (array)$this->post->resolvedBy);
return $this->send(array('result' => 'success', 'load' => $this->createLink($this->app->rawModule, 'view', "buildID=$buildID&type=bug")));
}
$this->session->set('bugList', $this->createLink($this->app->rawModule, 'view', "buildID=$buildID&type=bug&link=true&param=" . helper::safe64Encode("&browseType=$browseType&queryID=$param")), 'qa');
/* Set menu. */
$build = $this->build->getByID($buildID);
$product = $this->loadModel('product')->getByID($build->product);
if($this->app->tab == 'project')
{
$this->loadModel('project')->setMenu($build->project);
$this->view->projectID = $build->project;
}
if($build->execution) $this->loadModel('execution')->setMenu($build->execution);
/* Build the search form. */
$queryID = $browseType == 'bySearch' ? $param : 0;
$this->buildZen->buildLinkBugSearchForm($build, $queryID, isset($product->type) ? $product->type : 'normal');
/* Load pager. */
$this->app->loadClass('pager', $static = true);
$pager = new pager($recTotal, $recPerPage, $pageID);
$this->loadModel('bug');
$executionID = $build->execution ? $build->execution : $build->project;
if($browseType == 'bySearch')
{
$allBugs = $this->bug->getBySearch('bug', $build->product, $build->branch, $build->project, $build->execution, $queryID, $build->allBugs, 'id_desc', $pager);
}
else
{
$allBugs = $this->bug->getExecutionBugs($executionID, 0, 'all', array($buildID), 'noclosed', 0, 'status_desc,id_desc', $build->allBugs, $pager);
}
$this->view->allBugs = $allBugs;
$this->view->build = $build;
$this->view->users = $this->loadModel('user')->getPairs('noletter');
$this->view->browseType = $browseType;
$this->view->param = $param;
$this->view->pager = $pager;
$this->display();
}
/**
* 解除Bug跟版本的关联关系。
* Unlink bug.
*
* @param int $buildID
* @param int $bugID
* @access public
* @return void
*/
public function unlinkBug(int $buildID, int $bugID)
{
$this->build->unlinkBug($buildID, $bugID);
return $this->sendSuccess(array('load' => $this->createLink($this->app->rawModule, 'view', "buildID=$buildID&type=bug")));
}
/**
* 批量解除Bug跟版本的关联关系。
* Batch unlink bugs.
*
* @param int $buildID
* @access public
* @return void
*/
public function batchUnlinkBug(int $buildID)
{
if($this->post->bugIdList) $this->build->batchUnlinkBug($buildID, $this->post->bugIdList);
return $this->sendSuccess(array('load' => $this->createLink($this->app->rawModule, 'view', "buildID=$buildID&type=bug")));
}
/**
* 根据选择的产品获取应用列表。
* Get system list by product.
*
* @param int $productID
* @access public
* @return string
*/
public function ajaxGetSystemList(int $productID)
{
$systemList = $this->loadModel('system')->getPairs($productID, '0', 'active');
$system = array();
foreach($systemList as $systemID => $systemName) $system[] = array('text' => $systemName, 'value' => $systemID);
echo json_encode($system);
}
/**
* 根据选择的系统获取版本列表。
* Get build list by system.
*
* @param int $productID
* @param int $systemID
* @access public
* @return void
*/
public function ajaxGetSystemBuilds(int $productID, int $systemID)
{
$builds = $this->build->getBuildPairs(array($productID), 'all', 'noterminate, nodone, notrunk', 0, 'product', '', false, (int)$systemID);
$buildList = array();
foreach($builds as $buildID => $buildName) $buildList[] = array('text' => $buildName, 'value' => $buildID);
echo json_encode($buildList);
}
}