zen.php 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434
  1. <?php
  2. /**
  3. * The zen file of build module of ZenTaoPMS.
  4. *
  5. * @copyright Copyright 2009-2023 禅道软件(青岛)有限公司(ZenTao Software (Qingdao) Co., Ltd. www.zentao.net)
  6. * @license ZPL(https://zpl.pub/page/zplv12.html) or AGPL(https://www.gnu.org/licenses/agpl-3.0.en.html)
  7. * @author Yanyi Cao <caoyanyi@easycorp.ltd>
  8. * @package build
  9. * @link https://www.zentao.net
  10. */
  11. class buildZen extends build
  12. {
  13. /**
  14. * 生成创建版本的页面数据。
  15. * Generate the page data for creating a plan.
  16. *
  17. * @param int $productID
  18. * @param int $executionID
  19. * @param int $projectID
  20. * @param string $status
  21. * @access protected
  22. * @return void
  23. */
  24. protected function assignCreateData($productID, $executionID, $projectID, $status)
  25. {
  26. $productGroups = $branchGroups = array();
  27. $noClosedParam = (isset($this->config->CRExecution) && $this->config->CRExecution == 0) ? '|noclosed' : '';
  28. $executions = $this->loadModel('execution')->getPairs($projectID, 'all', 'stagefilter|leaf|order_asc' . $noClosedParam);
  29. $executionID = empty($executionID) && !empty($executions) ? (int)key($executions) : $executionID;
  30. if($executionID || $projectID)
  31. {
  32. $productGroups = $this->loadModel('product')->getProducts($executionID ? $executionID : $projectID, $status);
  33. $branchGroups = $this->loadModel('project')->getBranchesByProject($executionID ? $executionID : $projectID);
  34. }
  35. $this->commonActions($projectID);
  36. $productID = $productID ? $productID : key($productGroups);
  37. $branches = $products = array();
  38. /* Set branches and products. */
  39. if(!empty($productGroups[$productID]) && $productGroups[$productID]->type != 'normal' && !empty($branchGroups[$productID]))
  40. {
  41. $branchPairs = $this->loadModel('branch')->getPairs($productID, 'active');
  42. foreach($branchGroups[$productID] as $branchID => $branch)
  43. {
  44. if(isset($branchPairs[$branchID])) $branches[$branchID] = $branchPairs[$branchID];
  45. }
  46. }
  47. foreach($productGroups as $product) $products[$product->id] = $product->name;
  48. $this->view->title = $this->lang->build->create;
  49. $this->view->users = $this->loadModel('user')->getPairs('nodeleted|noclosed');
  50. $this->view->product = isset($productGroups[$productID]) ? $productGroups[$productID] : '';
  51. $this->view->branches = $branches;
  52. $this->view->products = $products;
  53. $this->view->executionID = $executionID;
  54. $this->view->executions = $executions;
  55. $this->view->lastBuild = $this->build->getLast($executionID, $projectID);
  56. $this->view->project = $this->project->getByID($projectID);
  57. $this->view->productID = $productID;
  58. $this->display();
  59. }
  60. /**
  61. * 生成编辑版本的页面数据。
  62. * Generate the page data for editing a plan.
  63. *
  64. * @param object $build
  65. * @access protected
  66. * @return void
  67. */
  68. protected function assignEditData($build)
  69. {
  70. $builds = array();
  71. $status = empty($this->config->CRProduct) ? 'noclosed' : '';
  72. $projectID = $build->execution ? (int)$build->execution : (int)$build->project;
  73. $productGroups = $this->loadModel('product')->getProducts($projectID, $status);
  74. $branches = $this->loadModel('branch')->getList($build->product, $projectID, 'all');
  75. if(!$build->execution) $builds = $this->build->getBuildPairs(array($build->product), 'all', 'noempty,notrunk,singled,separate', $build->project, 'project', $build->builds, false, $build->system);
  76. /* Get execution info. */
  77. $executions = $this->product->getExecutionPairsByProduct($build->product, $build->branch, (int)$this->session->project, 'stagefilter');
  78. $execution = $build->execution ? $this->loadModel('execution')->getByID((int)$build->execution) : '';
  79. if($build->execution && !isset($executions[$build->execution]))
  80. {
  81. $execution = $this->loadModel('execution')->getByID($build->execution);
  82. $executions[$build->execution] = $execution ? $execution->name : '';
  83. }
  84. if($build->product && !isset($productGroups[$build->product]))
  85. {
  86. $product = $this->product->getById($build->product);
  87. $product->branch = $build->branch;
  88. $productGroups[$build->product] = $product;
  89. }
  90. /* Display status of branch. */
  91. $branchTagOption = array();
  92. foreach($branches as $branchInfo)
  93. {
  94. $branchTagOption[$branchInfo->id] = $branchInfo->name . ($branchInfo->status == 'closed' ? ' (' . $this->lang->branch->statusList['closed'] . ')' : '');
  95. }
  96. foreach(explode(',', $build->branch) as $buildBranch)
  97. {
  98. if(!isset($branchTagOption[$buildBranch])) $branchTagOption[$buildBranch] = $this->branch->getById($buildBranch, 0, 'name');
  99. }
  100. $products = array();
  101. foreach($productGroups as $product) $products[$product->id] = $product->name;
  102. $this->view->title = $build->name . $this->lang->hyphen . $this->lang->build->edit;
  103. $this->view->products = $products;
  104. $this->view->product = isset($productGroups[$build->product]) ? $productGroups[$build->product] : '';
  105. $this->view->users = $this->loadModel('user')->getPairs('noletter', $build->builder);
  106. $this->view->branchTagOption = $branchTagOption;
  107. $this->view->build = $build;
  108. $this->view->testtask = $this->loadModel('testtask')->getByBuild($build->id);
  109. $this->view->builds = $builds;
  110. $this->view->executions = $executions;
  111. $this->view->executionType = !empty($execution) && $execution->type == 'stage' ? 1 : 0;
  112. $this->view->orderBy = 'status_asc, stage_asc, id_desc';
  113. $this->view->systemList = $this->loadModel('system')->getPairs(zget($this->view->product, 'id', 0), '0', 'active');
  114. $this->display();
  115. }
  116. /**
  117. * 生成的版本详情页面的产品数据。
  118. * Generate the product data for the build view page.
  119. *
  120. * @param object $build
  121. * @param string $type
  122. * @param string $sort
  123. * @param object $storyPager
  124. * @access protected
  125. * @return void
  126. */
  127. protected function assignProductVarsForView($build, $type, $sort, $storyPager)
  128. {
  129. $this->loadModel('branch');
  130. $product = $this->loadModel('product')->getByID($build->product);
  131. if($product && $product->type != 'normal') $this->lang->product->branch = sprintf($this->lang->product->branch, $this->lang->product->branchName[$product->type]);
  132. $stories = $this->build->getStoryList($build->allStories, (int)$build->branch, $type == 'story' ? $sort : '', $storyPager);
  133. $branchName = '';
  134. if($build->productType != 'normal')
  135. {
  136. foreach(explode(',', $build->branch) as $buildBranch)
  137. {
  138. $branchName .= $buildBranch == BRANCH_MAIN ?$this->lang->branch->main : $this->loadModel('branch')->getById($buildBranch);
  139. $branchName .= ',';
  140. }
  141. $branchName = trim($branchName, ',');
  142. }
  143. $this->view->branchName = empty($branchName) ? $this->lang->branch->main : $branchName;
  144. $this->view->stories = $stories;
  145. $this->view->storyPager = $storyPager;
  146. if($this->app->getViewType() == 'json') unset($this->view->storyPager);
  147. }
  148. /**
  149. * 生成的版本详情页面的Bug数据。
  150. * Generate the Bug data for the build view page.
  151. *
  152. * @param object $build
  153. * @param string $type
  154. * @param string $sort
  155. * @param string $param
  156. * @param object $bugPager
  157. * @param object $generatedBugPager
  158. * @access protected
  159. * @return void
  160. */
  161. protected function assignBugVarsForView($build, $type, $sort, $param, $bugPager, $generatedBugPager)
  162. {
  163. $this->view->type = $type;
  164. $this->view->param = $param;
  165. $this->view->bugPager = $bugPager;
  166. $this->view->generatedBugPager = $generatedBugPager;
  167. $this->view->bugs = $this->build->getBugList($build->allBugs, $type == 'bug' ? $sort : '', $bugPager);
  168. $generatedBugs = $this->loadModel('bug')->getExecutionBugs((int)$build->execution, $build->product, 'all', "$build->id,{$build->builds}", $type, (int)$param, $type == 'generatedBug' ? $sort : 'status_desc,id_desc', '', $generatedBugPager);
  169. $this->view->generatedBugs = $this->bug->processBuildForBugs($generatedBugs);
  170. if($this->app->getViewType() == 'json')
  171. {
  172. unset($this->view->generatedBugPager);
  173. unset($this->view->bugPager);
  174. }
  175. }
  176. /**
  177. * 设置版本详情页面的导航。
  178. * Set the navigation for the build view page.
  179. *
  180. * @param object $build
  181. * @access protected
  182. * @return void
  183. */
  184. protected function setMenuForView($build)
  185. {
  186. $this->session->set('storyList', $this->app->getURI(true), $this->app->tab);
  187. $this->session->project = $build->project;
  188. $objectType = 'execution';
  189. $objectID = $build->execution;
  190. if($this->app->tab == 'project')
  191. {
  192. $this->loadModel('project')->setMenu($build->project);
  193. $objectType = 'project';
  194. $objectID = $build->project;
  195. }
  196. elseif($this->app->tab == 'execution')
  197. {
  198. $this->loadModel('execution')->setMenu((int)$build->execution);
  199. }
  200. $executions = $this->loadModel('execution')->getPairs($this->session->project, 'all', 'empty');
  201. $this->view->title = "BUILD #$build->id $build->name" . (isset($executions[$build->execution]) ? " - " . $executions[$build->execution] : '');
  202. $this->view->executions = $executions;
  203. $this->view->buildPairs = $this->build->getBuildPairs(0, 'all', 'noempty,notrunk', (int)$objectID, $objectType);
  204. $this->view->builds = $this->build->getByList(array_keys($this->view->buildPairs));
  205. $this->view->objectID = $objectID;
  206. }
  207. /**
  208. * 为创建页面构建版本数据。
  209. * Build build data for create.
  210. *
  211. * @access public
  212. * @return object
  213. */
  214. public function buildBuildForCreate()
  215. {
  216. $newSystem = $this->post->newSystem;
  217. if($this->post->isIntegrated == 'yes') $this->config->build->create->requiredFields = str_replace(',execution,', ',', ',' . $this->config->build->create->requiredFields . ',');
  218. if(!$newSystem && !$this->post->system) $this->config->build->form->create['system']['required'] = true;
  219. if($newSystem && !$this->post->systemName)
  220. {
  221. $this->config->build->form->create['systemName'] = array('type' => 'string', 'required' => true, 'filter' => 'trim');
  222. $this->lang->build->systemName = $this->lang->build->system;
  223. }
  224. $formData = form::data($this->config->build->form->create)
  225. ->setDefault('createdBy', $this->app->user->account)
  226. ->get();
  227. if($newSystem && $this->post->systemName)
  228. {
  229. $system = new stdclass();
  230. $system->name = trim($this->post->systemName);
  231. $system->product = $this->post->product;
  232. $system->createdBy = $this->app->user->account;
  233. $system->createdDate = helper::now();
  234. $formData->system = $this->loadModel('system')->create($system);
  235. }
  236. return $formData;
  237. }
  238. /**
  239. * 为编辑页面构建版本数据。
  240. * Build build data for edit.
  241. *
  242. * @param int $buildID
  243. * @access public
  244. * @return object
  245. */
  246. public function buildBuildForEdit($buildID)
  247. {
  248. $build = $this->build->getById($buildID);
  249. if(empty($build->execution)) $this->config->build->edit->requiredFields = str_replace(',execution,', ',', ',' . $this->config->build->edit->requiredFields . ',');
  250. return form::data($this->config->build->form->edit, $buildID)->get();
  251. }
  252. /**
  253. * 获取版本不可关联的需求ID列表。
  254. * Get the story ID list that cannot be linked to the build.
  255. *
  256. * @param object $build
  257. * @access protected
  258. * @return array
  259. */
  260. public function getExcludeStoryIdList($build)
  261. {
  262. $parentIdList = $this->dao->select('id')->from(TABLE_STORY)
  263. ->where('product')->eq($build->product)
  264. ->andWhere('type')->eq('story')
  265. ->andWhere('isParent')->eq('1')
  266. ->fetchPairs();
  267. foreach(explode(',', $build->allStories) as $storyID)
  268. {
  269. if(!$storyID) continue;
  270. if(!isset($parentIdList[$storyID])) $parentIdList[$storyID] = $storyID;
  271. }
  272. return $parentIdList;
  273. }
  274. /**
  275. * 生成关联需求的搜索表单数据。
  276. * Generate the search form data for the build view page.
  277. *
  278. * @param object $build
  279. * @param int $queryID
  280. * @param string $productType
  281. * @access protected
  282. * @return void
  283. */
  284. protected function buildLinkStorySearchForm($build, $queryID, $productType)
  285. {
  286. unset($this->config->product->search['fields']['product']);
  287. unset($this->config->product->search['fields']['project']);
  288. $this->config->product->search['actionURL'] = $this->createLink($this->app->rawModule, 'view', "buildID={$build->id}&type=story&link=true&param=" . helper::safe64Encode("&browseType=bySearch&queryID=myQueryID"));
  289. $this->config->product->search['queryID'] = $queryID;
  290. $this->config->product->search['style'] = 'simple';
  291. $this->config->product->search['params']['plan']['values'] = $this->loadModel('productplan')->getPairs($build->product, $build->branch, '', true);
  292. $this->config->product->search['params']['module']['values'] = $this->loadModel('tree')->getOptionMenu($build->product, 'story', 0, $build->branch);
  293. $this->config->product->search['params']['status'] = array('operator' => '=', 'control' => 'select', 'values' => $this->lang->story->statusList);
  294. if($build->project)
  295. {
  296. $project = $this->loadModel('project')->getByID($build->project);
  297. if(!$project->hasProduct and $project->model != 'scrum')
  298. {
  299. unset($this->config->product->search['fields']['plan']);
  300. }
  301. elseif(!$project->hasProduct and !$project->multiple)
  302. {
  303. unset($this->config->product->search['fields']['plan']);
  304. }
  305. }
  306. if($productType == 'normal')
  307. {
  308. unset($this->config->product->search['fields']['branch']);
  309. unset($this->config->product->search['params']['branch']);
  310. }
  311. else
  312. {
  313. $branchPairs = $this->loadModel('branch')->getPairs($build->product, 'noempty');
  314. $branchAll = sprintf($this->lang->build->branchAll, $this->lang->product->branchName[$productType]);
  315. $branches = array('' => $branchAll) + array(BRANCH_MAIN => $this->lang->branch->main);
  316. if($build->branch)
  317. {
  318. foreach(explode(',', $build->branch) as $branchID)
  319. {
  320. if($branchID == '0') continue;
  321. $branches += array($branchID => $branchPairs[$branchID]);
  322. }
  323. }
  324. $this->config->product->search['fields']['branch'] = sprintf($this->lang->product->branch, $this->lang->product->branchName[$productType]);
  325. $this->config->product->search['params']['branch']['values'] = $branches;
  326. }
  327. unset($this->config->product->search['fields']['grade']);
  328. unset($this->config->product->search['params']['grade']);
  329. $this->loadModel('search')->setSearchParams($this->config->product->search);
  330. }
  331. /**
  332. * 生成关联Bug的搜索表单数据。
  333. * Generate the search form data for the build view page.
  334. *
  335. * @param object $build
  336. * @param int $queryID
  337. * @param string $productType
  338. * @access protected
  339. * @return void
  340. */
  341. protected function buildLinkBugSearchForm($build, $queryID, $productType)
  342. {
  343. $this->loadModel('bug');
  344. $this->config->bug->search['actionURL'] = $this->createLink($this->app->rawModule, 'view', "buildID={$build->id}&type=bug&link=true&param=" . helper::safe64Encode("&browseType=bySearch&queryID=myQueryID"));
  345. $this->config->bug->search['queryID'] = $queryID;
  346. $this->config->bug->search['style'] = 'simple';
  347. $this->config->bug->search['params']['plan']['values'] = $this->loadModel('productplan')->getPairs($build->product, $build->branch, '', true);
  348. $this->config->bug->search['params']['module']['values'] = $this->loadModel('tree')->getOptionMenu($build->product, 'bug', 0, $build->branch);
  349. $this->config->bug->search['params']['execution']['values'] = $this->loadModel('product')->getExecutionPairsByProduct($build->product, $build->branch, (int)$this->session->project);
  350. $this->config->bug->search['params']['openedBuild']['values'] = $this->build->getBuildPairs(array($build->product), 'all', 'releasetag');
  351. $this->config->bug->search['params']['resolvedBuild']['values'] = $this->config->bug->search['params']['openedBuild']['values'];
  352. unset($this->config->bug->search['fields']['product']);
  353. unset($this->config->bug->search['params']['product']);
  354. unset($this->config->bug->search['fields']['project']);
  355. unset($this->config->bug->search['params']['project']);
  356. if($build->project)
  357. {
  358. $project = $this->loadModel('project')->getByID($build->project);
  359. if(!$project->hasProduct && $project->model != 'scrum')
  360. {
  361. unset($this->config->bug->search['fields']['plan']);
  362. }
  363. elseif(!$project->hasProduct && !$project->multiple)
  364. {
  365. unset($this->config->bug->search['fields']['plan']);
  366. }
  367. }
  368. if($productType == 'normal')
  369. {
  370. unset($this->config->bug->search['fields']['branch']);
  371. unset($this->config->bug->search['params']['branch']);
  372. }
  373. else
  374. {
  375. $buildBranch = array();
  376. $branchList = $this->loadModel('branch')->getPairs($build->product, '', $build->execution);
  377. $branchAll = sprintf($this->lang->build->branchAll, $this->lang->product->branchName[$productType]);
  378. $branches = array('' => $branchAll, BRANCH_MAIN => $this->lang->branch->main);
  379. if(strpos($build->branch, ',') !== false) $buildBranch = explode(',', $build->branch);
  380. foreach($buildBranch as $buildKey) $branches += array($buildKey => zget($branchList, $buildKey));
  381. $this->config->bug->search['fields']['branch'] = sprintf($this->lang->product->branch, $this->lang->product->branchName[$productType]);
  382. $this->config->bug->search['params']['branch']['values'] = $branches;
  383. }
  384. $this->loadModel('search')->setSearchParams($this->config->bug->search);
  385. }
  386. }