zen.php 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349
  1. <?php
  2. class actionZen extends action
  3. {
  4. /**
  5. * 获取回收站的导航栏。
  6. * Get the navigation bar of the trashes.
  7. *
  8. * @param array $objectTypeList
  9. * @access public
  10. * @return array
  11. */
  12. public function getTrashesHeaderNavigation($objectTypeList)
  13. {
  14. $preferredType = array();
  15. $moreType = array();
  16. $preferredTypeConfig = $this->config->action->preferredType->ALM;
  17. $preferredTypeConfig = $this->config->systemMode == 'light' ? $this->config->action->preferredType->light : $this->config->action->preferredType->ALM;
  18. foreach($objectTypeList as $objectType)
  19. {
  20. if(!isset($this->config->objectTables[$objectType])) continue;
  21. in_array($objectType, $preferredTypeConfig) ? $preferredType[$objectType] = $objectType : $moreType[$objectType] = $objectType;
  22. }
  23. if(count($preferredType) < $this->config->action->preferredTypeNum)
  24. {
  25. $toPreferredType = array_splice($moreType, 0, $this->config->action->preferredTypeNum - count($preferredType));
  26. $preferredType = $preferredType + $toPreferredType; //填充至设定的展示数量。
  27. }
  28. $this->view->moreType = $moreType;
  29. $this->view->preferredTypeConfig = $preferredTypeConfig;
  30. return $preferredType;
  31. }
  32. /**
  33. * 保存当前页面的URL到Session中。
  34. * Save the current page URL to the session.
  35. *
  36. * @access public
  37. * @return void
  38. */
  39. public function saveUrlIntoSession()
  40. {
  41. $uri = $this->app->getURI(true);
  42. $this->session->set('productList', $uri, 'product');
  43. $this->session->set('productPlanList', $uri, 'product');
  44. $this->session->set('releaseList', $uri, 'product');
  45. $this->session->set('programList', $uri, 'program');
  46. $this->session->set('projectList', $uri, 'project');
  47. $this->session->set('executionList', $uri, 'execution');
  48. $this->session->set('taskList', $uri, 'execution');
  49. $this->session->set('buildList', $uri, 'execution');
  50. $this->session->set('bugList', $uri, 'qa');
  51. $this->session->set('caseList', $uri, 'qa');
  52. $this->session->set('testtaskList', $uri, 'qa');
  53. $this->session->set('docList', $uri, 'doc');
  54. $this->session->set('opportunityList', $uri, 'project');
  55. $this->session->set('riskList', $uri, 'project');
  56. $this->session->set('trainplanList', $uri, 'project');
  57. $this->session->set('roomList', $uri, 'admin');
  58. $this->session->set('researchplanList', $uri, 'project');
  59. $this->session->set('researchreportList', $uri, 'project');
  60. $this->session->set('meetingList', $uri, 'project');
  61. $this->session->set('designList', $uri, 'project');
  62. $this->session->set('storyLibList', $uri, 'assetlib');
  63. $this->session->set('issueLibList', $uri, 'assetlib');
  64. $this->session->set('riskLibList', $uri, 'assetlib');
  65. $this->session->set('opportunityLibList', $uri, 'assetlib');
  66. $this->session->set('practiceLibList', $uri, 'assetlib');
  67. $this->session->set('componentLibList', $uri, 'assetlib');
  68. }
  69. /*
  70. * 构建回收站内容的属性。
  71. * Build the attributes of the trashes.
  72. *
  73. * @param object $trash
  74. * @param array $projectList
  75. * @param array $productList
  76. * @param array $executionList
  77. * @access public
  78. * @return void
  79. */
  80. /**
  81. * @param object $trash
  82. * @param mixed[] $projectList
  83. * @param mixed[] $productList
  84. * @param mixed[] $executionList
  85. */
  86. public function processTrash($trash, $projectList, $productList, $executionList)
  87. {
  88. if($trash->objectType == 'pivot')
  89. {
  90. $pivotNames = json_decode($trash->objectName, true);
  91. $pivotNames = empty($pivotNames) ? array() : $pivotNames;
  92. $trash->objectName = zget($pivotNames, $this->app->getClientLang(), '') ? : reset(array_filter($pivotNames));
  93. }
  94. else
  95. {
  96. $module = $trash->objectType == 'case' ? 'testcase' : $trash->objectType;
  97. $module = $trash->objectType == 'doctemplate' ? 'doc' : $module;
  98. $params = $trash->objectType == 'user' ? "account={$trash->objectName}" : "id={$trash->objectID}";
  99. $methodName = 'view';
  100. if($module == 'basicmeas')
  101. {
  102. $module = 'measurement';
  103. $methodName = 'setSQL';
  104. $params = "id={$trash->objectID}";
  105. }
  106. if($module == 'deploystep')
  107. {
  108. $module = 'deploy';
  109. $methodName = 'viewStep';
  110. }
  111. if($trash->objectType == 'api')
  112. {
  113. $params = "libID=0&moduelID=0&apiID={$trash->objectID}";
  114. $methodName = 'index';
  115. }
  116. if(in_array($module, array('traincourse','traincontents')))
  117. {
  118. $methodName = $module == 'traincourse' ? 'viewcourse' : 'viewchapter';
  119. $module = 'traincourse';
  120. }
  121. if(isset($this->config->action->customFlows[$trash->objectType]))
  122. {
  123. $flow = $this->config->action->customFlows[$trash->objectType];
  124. $module = $flow->module;
  125. }
  126. if(strpos($this->config->action->noLinkModules, ",{$module},") === false)
  127. {
  128. $tab = '';
  129. $canView = common::hasPriv($module, $methodName);
  130. if($trash->objectType == 'meeting') $tab = $trash->project ? "data-app='project'" : "data-app='my'";
  131. $trash->objectName = $canView ? html::a($this->createLink($module, $methodName, $params), $trash->objectName, '_self', "title='{$trash->objectName}' $tab") : "<span title='$trash->objectName'>$trash->objectName</span>";
  132. }
  133. }
  134. if(!empty($projectList[$trash->project])) $trash->project = $projectList[$trash->project]->name . ($projectList[$trash->project]->deleted ? "<span class='label danger ml-2'>{$this->lang->project->deleted}</span>" : '');
  135. if(!empty($productList[$trash->objectID])) $trash->product = $productList[$trash->objectID]->productTitle . ($productList[$trash->objectID]->productDeleted ? "<span class='label danger ml-2'>{$this->lang->story->deleted}</span>" : '');
  136. if(!empty($executionList[$trash->execution])) $trash->execution = $executionList[$trash->execution]->name . ($executionList[$trash->execution]->deleted ? "<span class='label danger ml-2'>{$this->lang->execution->deleted}</span>" : '');
  137. }
  138. /**
  139. * 获取重复的名称和代号。
  140. * Get the repeated name and code.
  141. *
  142. * @param object $repeatObject
  143. * @param object $object
  144. * @param string $table
  145. * @access public
  146. * @return array
  147. */
  148. public function getReplaceNameAndCode($repeatObject, $object, $table)
  149. {
  150. $replaceName = '';
  151. $existNames = $this->action->getLikeObject($table, 'name', 'name', $repeatObject->name . '_%');
  152. for($i = 1; $i < 10000; $i ++)
  153. {
  154. $replaceName = $repeatObject->name . '_' . $i;
  155. if(!in_array($replaceName, $existNames)) break;
  156. }
  157. $replaceCode = '';
  158. if(isset($object->code))
  159. {
  160. $existCodes = $this->action->getLikeObject($table, 'code', 'code', $repeatObject->code . '_%');
  161. for($i = 1; $i < 10000; $i ++)
  162. {
  163. $replaceCode = $repeatObject->code . '_' . $i;
  164. if(!in_array($replaceCode, $existCodes)) break;
  165. }
  166. }
  167. return array($replaceName, $replaceCode);
  168. }
  169. /**
  170. * 检查操作记录是否存在。
  171. * Check if the action record exists.
  172. *
  173. * @param int $actionID
  174. * @access public
  175. * @return array|object
  176. */
  177. public function checkActionExist($actionID)
  178. {
  179. if($actionID <= 0) return ['result' => 'fail', 'message' => $this->lang->notFound];
  180. $action = $this->action->getById($actionID);
  181. if(!$action) return ['result' => 'fail', 'message' => $this->lang->notFound];
  182. return $action;
  183. }
  184. /**
  185. * 获取需要确认为否状态下的信息。
  186. * Get the information that needs to be confirmed as no.
  187. *
  188. * @param object $object
  189. * @param object $repeatObject
  190. * @access public
  191. * @return string
  192. * @param object $oldAction
  193. * @param string $replaceName
  194. * @param string $replaceCode
  195. */
  196. public function getConfirmNoMessage($repeatObject, $object, $oldAction, $replaceName, $replaceCode)
  197. {
  198. $message = '';
  199. if($repeatObject->name == $object->name && !empty($repeatObject->code) && $repeatObject->code == $object->code)
  200. {
  201. $message = sprintf($this->lang->action->repeatChange, $this->lang->{$oldAction->objectType}->common, $replaceName, $replaceCode);
  202. }
  203. elseif($repeatObject->name == $object->name)
  204. {
  205. $message = sprintf($this->lang->action->nameRepeatChange, $this->lang->{$oldAction->objectType}->common, $replaceName);
  206. }
  207. elseif(!empty($repeatObject->code) && $repeatObject->code == $object->code)
  208. {
  209. $message = sprintf($this->lang->action->codeRepeatChange, $this->lang->{$oldAction->objectType}->common, $replaceCode);
  210. }
  211. return $message;
  212. }
  213. /**
  214. * 恢复对象。
  215. * Recover the object.
  216. *
  217. * @param object $repeatObject
  218. * @param object $object
  219. * @param string $replaceName
  220. * @param string $replaceCode
  221. * @param string $table
  222. * @param object $oldAction
  223. * @access public
  224. * @return void
  225. */
  226. public function recoverObject($repeatObject, $object, $replaceName, $replaceCode, $table, $oldAction)
  227. {
  228. $recoverData = array();
  229. if($repeatObject->name == $object->name && !empty($repeatObject->code) && $repeatObject->code == $object->code)
  230. {
  231. $recoverData = array('code' => $replaceCode, 'name' => $replaceName);
  232. }
  233. elseif($repeatObject->name == $object->name)
  234. {
  235. $recoverData = array('name' => $replaceName);
  236. }
  237. elseif(!empty($repeatObject->code) && $repeatObject->code == $object->code)
  238. {
  239. $recoverData = array('code' => $replaceCode);
  240. }
  241. if(!empty($recoverData)) $this->action->updateObjectByID($table, $oldAction->objectID, $recoverData);
  242. }
  243. /**
  244. * 恢复阶段。
  245. * Restore stages.
  246. *
  247. * @param object $action
  248. * @param string $confirmChange
  249. * @access public
  250. * @return bool|string
  251. */
  252. public function restoreStages($action, $confirmChange = 'no')
  253. {
  254. /* 检查父阶段是否创建过任务。 */
  255. /* Check parent stage isCreateTask. */
  256. $execution = $this->loadModel('execution')->getByID($action->objectID);
  257. $hasCreatedTask = $this->loadModel('programplan')->isCreateTask($execution->parent);
  258. if(!$hasCreatedTask) return $this->lang->action->hasCreatedTask;
  259. /* 检查同级执行的类型。 */
  260. /* Check type of siblings. */
  261. $siblings = $this->execution->getSiblingsTypeByParentID($execution->parent);
  262. if($execution->type == 'stage' && (isset($siblings['sprint']) || isset($siblings['kanban']))) return $this->lang->action->hasOtherType[$execution->type];
  263. if(($execution->type == 'sprint' || $execution->type == 'kanban') && isset($siblings['stage'])) return $this->lang->action->hasOtherType[$execution->type];
  264. /* 如果父阶段不存在,你应该恢复父级阶段,并且刷新状态。 */
  265. /* If parent stage is not exists, you should recover its parent stages, refresh status. */
  266. $stagePathList = explode(',', trim($execution->path, ','));
  267. $deletedStageList = $this->action->getDeletedStagedByList($stagePathList);
  268. $deletedParents = $deletedStageList;
  269. array_pop($deletedParents);
  270. $needChangeAttr = false; //是否需要修改attribute值
  271. $deletedTitle = ''; //被删除的标题
  272. $startChangedStage = $execution;
  273. if(!empty($deletedParents))
  274. {
  275. foreach($deletedParents as $deletedParent) $deletedTitle .= "'{$deletedParent->name}',";
  276. /* 如果父阶段的状态已经被改变,子阶段的的状态也要改变。 */
  277. /* If parent stage's attribute has changed, sub-stage's attribute need change. */
  278. $deletedTopParent = current($deletedStageList);
  279. $isTopStage = $this->loadModel('programplan')->isTopStage($deletedTopParent->id);
  280. $parentAttr = $deletedTopParent->attribute;
  281. if(!$isTopStage) $parentAttr = $this->action->getAttributeByExecutionID();
  282. /* 从父阶段开始逐级下查,如果发现有跟父阶段不一样的attribute,对后面所有的attrubite值进行修改。 */
  283. /* Check down step by step from the parent stage, if you find that there is an attribute different from the parent stage, modify all the later attrubite values*. */
  284. $startChangedStage = $execution;
  285. foreach($deletedStageList as $deletedStage)
  286. {
  287. if($parentAttr != 'mix' && $parentAttr != $deletedStage->attribute)
  288. {
  289. $startChangedStage = $deletedStage;
  290. $needChangeAttr = true;
  291. break;
  292. }
  293. $parentAttr = $deletedStage->attribute;
  294. }
  295. }
  296. /* 确认是否要恢复父阶段并且修改不一样的attribute值。 */
  297. /* Confirm whether you want to restore the parent stage and modify the different attribute value. */
  298. if(!empty($deletedTitle) || $needChangeAttr)
  299. {
  300. $this->app->loadLang('stage');
  301. $confirmLang = sprintf($this->lang->action->hasDeletedParent, trim($deletedTitle, ',')) . $this->lang->action->whetherToRestore;
  302. if($needChangeAttr) $confirmLang = sprintf($this->lang->action->hasChangedAttr, zget($this->lang->stage->typeList, $parentAttr)) . $this->lang->action->whetherToRestore;
  303. if(!empty($deletedTitle) && $needChangeAttr) $confirmLang = sprintf($this->lang->action->hasDeletedParent, $deletedTitle) . sprintf($this->lang->action->hasChangedAttr, zget($this->lang->stage->typeList, $parentAttr)) . $this->lang->action->whetherToRestore;
  304. if($confirmChange == 'no') return $confirmLang;
  305. /* 如果被删除的标题集合不为空,则更新所有的阶段。 */
  306. /* If the collection of titles being deleted is not empty, all stages are updated. */
  307. if(!empty($deletedTitle)) $this->action->restoreStages($deletedParents);
  308. /* 如果需要更新attribute的值,则恢复路径上所有的父节点以及更新attrubute值。 */
  309. /* If the attribute value needs to be updated, restore all parent nodes on the path and update the attribute value. */
  310. if($needChangeAttr)
  311. {
  312. $needChangedStages = substr($execution->path, strpos($execution->path, ",{$startChangedStage->id},"));
  313. $needChangedStages = explode(',', trim($needChangedStages, ','));
  314. $this->action->updateStageAttribute($parentAttr, $needChangedStages);
  315. }
  316. }
  317. $this->programplan->computeProgress($startChangedStage->parent);
  318. return true;
  319. }
  320. }