From 56c2cdcb218498dad4ac61b9765d26ac0c2eff51 Mon Sep 17 00:00:00 2001 From: hufangzhou Date: Tue, 14 Feb 2023 02:46:34 +0000 Subject: [PATCH] * Finish task #83954. --- config/zentaopms.php | 1 + module/action/control.php | 75 ++++++++++++++++++++++++++++++++++++ module/action/lang/de.php | 4 ++ module/action/lang/en.php | 4 ++ module/action/lang/fr.php | 4 ++ module/action/lang/zh-cn.php | 4 ++ module/action/model.php | 27 ++++++++++++- module/programplan/model.php | 10 +++-- 8 files changed, 125 insertions(+), 4 deletions(-) diff --git a/config/zentaopms.php b/config/zentaopms.php index 78d50b8e00..15a09f2e08 100644 --- a/config/zentaopms.php +++ b/config/zentaopms.php @@ -228,6 +228,7 @@ $config->openMethods[] = 'project.createguide'; $config->openMethods[] = 'task.editteam'; $config->openMethods[] = 'feedback.mergeproductmodule'; $config->openMethods[] = 'zanode.nodeList'; +$config->openMethods[] = 'action.restoreStages'; $config->openModules = array(); $config->openModules[] = 'install'; diff --git a/module/action/control.php b/module/action/control.php index fb83740280..fa74eb95cf 100755 --- a/module/action/control.php +++ b/module/action/control.php @@ -246,6 +246,12 @@ class action extends control if($confirmChange == 'yes') $this->dao->update($table)->set('code')->eq($replaceCode)->where('id')->eq($oldAction->objectID)->exec(); } } + + if($oldAction->objectType == 'execution') + { + $confirmLang = $this->restoreStages($oldAction, $browseType, $confirmChange); + if($confirmLang !== true) return print(js::confirm($confirmLang, $this->createLink('action', 'undelete', "action={$actionID}&browseType={$browseType}&confirmChange=yes"))); + } } $this->action->undelete($actionID); @@ -351,4 +357,73 @@ class action extends control } return $this->send(array('result' => 'success', 'locate' => 'reload')); } + + /** + * Restore stages. + * + * @param object $action + * @param string $browseType + * @param string $confirmChange + * @access public + * @return bool|string + */ + public function restoreStages($action, $browseType, $confirmChange) + { + /* Check parent stage isCreateTask. */ + $execution = $this->dao->select('*')->from(TABLE_EXECUTION)->where('id')->eq($action->objectID)->fetch(); + $hasCreatedTask = $this->loadModel('programplan')->isCreateTask($execution->parent); + if(!$hasCreatedTask) return print(js::alert($this->lang->action->hasCreatedTask)); + + /* If parent stage is not exists, you should recover its parent stages, refresh status. */ + $stagePathList = explode(',', trim($execution->path, ',')); + $deletedStageList = $this->dao->select('*')->from(TABLE_EXECUTION)->where('id')->in($stagePathList)->andWhere('deleted')->eq(1)->andWhere('type')->eq('stage')->orderBy('id_asc')->fetchAll('id'); + $deletedParents = $deletedStageList; + array_pop($deletedParents); + + $deletedTitle = ''; + foreach($deletedParents as $deletedParent) $deletedTitle .= "'{$deletedParent->name}',"; + + /* If parent stage's attribute has changed, sub-stage's attribute need change. */ + $deletedTopParent = current($deletedStageList); + $checkTopStage = $this->loadModel('programplan')->checkTopStage($deletedTopParent->id); + $parentAttr = $deletedTopParent->attribute; + if(!$checkTopStage) $parentAttr = $this->dao->select('attribute')->from(TABLE_EXECUTION)->where('id')->eq($deletedTopParent->parent)->fetch('attribute'); + + $needChangeAttr = false; + $startChangedStage = $execution; + foreach($deletedStageList as $deletedStage) + { + if($parentAttr != 'mix' and $parentAttr != $deletedStage->attribute) + { + $startChangedStage = $deletedStage; + $needChangeAttr = true; + break; + } + $parentAttr = $deletedStage->attribute; + } + + /* Confirm. */ + if(!empty($deletedTitle) or $needChangeAttr) + { + $this->app->loadLang('stage'); + + $confirmLang = sprintf($this->lang->action->hasDeletedParent, trim($deletedTitle, ',')) . $this->lang->action->whetherToRestore; + if($needChangeAttr) $confirmLang = sprintf($this->lang->action->hasChangedAttr, zget($this->lang->stage->typeList, $parentAttr)) . $this->lang->action->whetherToRestore; + if(!empty($deletedTitle) and $needChangeAttr) $confirmLang = sprintf($this->lang->action->hasDeletedParent, $deletedTitle) . sprintf($this->lang->action->hasChangedAttr, zget($this->lang->stage->typeList, $parentAttr)) . $this->lang->action->whetherToRestore; + + if($confirmChange == 'no') + { + return $confirmLang; + } + else + { + if(!empty($deletedTitle)) $this->action->restoreStages($deletedParents); + if($needChangeAttr) $this->programplan->updateSubStageAttr($startChangedStage->parent, $parentAttr, true); + } + } + + $this->programplan->computeProgress($startChangedStage->parent); + + return true; + } } diff --git a/module/action/lang/de.php b/module/action/lang/de.php index e29603c2f1..37e0d209a5 100644 --- a/module/action/lang/de.php +++ b/module/action/lang/de.php @@ -58,6 +58,10 @@ $lang->action->noDynamic = 'Kein Verlauf. '; $lang->action->undeletedTips = 'This data did not participate in the merging process during the version upgrade process, so restore is not supported.'; $lang->action->executionNoProject = 'The execution does not belong to a project,please restore the project first'; $lang->action->repoNoServer = 'The repo does not belong to a server,please restore the server first'; +$lang->action->hasCreatedTask = 'Tasks have been created in this parent phase and cannot be restored!'; +$lang->action->hasDeletedParent = 'Restoring this phase requires restoring the deleted parent phase %s at the same time.'; +$lang->action->hasChangedAttr = "After recovery, the phase type will be adjusted to '%s' according to the parent phase type."; +$lang->action->whetherToRestore = 'Confirm to restore?'; $lang->action->repeatChange = '%s with the same name and code already exists in the system, After recovery, the name are \"%s\",the code are \"%s\".'; $lang->action->nameRepeatChange = '%s with the same name already exists in the system, After recovery, the name are \"%s\".'; diff --git a/module/action/lang/en.php b/module/action/lang/en.php index 64223a9966..4b6a9032eb 100755 --- a/module/action/lang/en.php +++ b/module/action/lang/en.php @@ -58,6 +58,10 @@ $lang->action->noDynamic = 'No dynamics. '; $lang->action->undeletedTips = 'This data did not participate in the merging process during the version upgrade process, so restore is not supported.'; $lang->action->executionNoProject = 'The execution does not belong to a project,please restore the project first'; $lang->action->repoNoServer = 'The repo does not belong to a server,please restore the server first'; +$lang->action->hasCreatedTask = 'Tasks have been created in this parent phase and cannot be restored!'; +$lang->action->hasDeletedParent = 'Restoring this phase requires restoring the deleted parent phase %s at the same time.'; +$lang->action->hasChangedAttr = "After recovery, the phase type will be adjusted to '%s' according to the parent phase type."; +$lang->action->whetherToRestore = 'Confirm to restore?'; $lang->action->repeatChange = '%s with the same name and code already exists in the system, After recovery, the name are \"%s\",the code are \"%s\".'; $lang->action->nameRepeatChange = '%s with the same name already exists in the system, After recovery, the name are \"%s\".'; diff --git a/module/action/lang/fr.php b/module/action/lang/fr.php index b35dfacfe1..01fa888374 100644 --- a/module/action/lang/fr.php +++ b/module/action/lang/fr.php @@ -58,6 +58,10 @@ $lang->action->noDynamic = "Pas d'historique."; $lang->action->undeletedTips = 'This data did not participate in the merging process during the version upgrade process, so restore is not supported.'; $lang->action->executionNoProject = 'The execution does not belong to a project,please restore the project first'; $lang->action->repoNoServer = 'The repo does not belong to a server,please restore the server first'; +$lang->action->hasCreatedTask = 'Tasks have been created in this parent phase and cannot be restored!'; +$lang->action->hasDeletedParent = 'Restoring this phase requires restoring the deleted parent phase %s at the same time.'; +$lang->action->hasChangedAttr = "After recovery, the phase type will be adjusted to '%s' according to the parent phase type."; +$lang->action->whetherToRestore = 'Confirm to restore?'; $lang->action->repeatChange = '%s with the same name and code already exists in the system, After recovery, the name are \"%s\",the code are \"%s\".'; $lang->action->nameRepeatChange = '%s with the same name already exists in the system, After recovery, the name are \"%s\".'; diff --git a/module/action/lang/zh-cn.php b/module/action/lang/zh-cn.php index 8af5daae98..7680a7488a 100755 --- a/module/action/lang/zh-cn.php +++ b/module/action/lang/zh-cn.php @@ -58,6 +58,10 @@ $lang->action->noDynamic = '暂时没有动态。'; $lang->action->undeletedTips = '该数据在版本升级过程中未参与数据归并流程,不支持还原。'; $lang->action->executionNoProject = '该执行没有所属的项目,请先还原项目再还原执行'; $lang->action->repoNoServer = '该代码库没有所属的服务器,请先还原服务器再还原代码库'; +$lang->action->hasCreatedTask = '该父阶段已创建任务,无法恢复!'; +$lang->action->hasDeletedParent = '恢复该阶段需要同时恢复已删除的父阶段%s,'; +$lang->action->hasChangedAttr = '恢复后阶段类型将根据父阶段类型均调整为“%s”,'; +$lang->action->whetherToRestore = '是否恢复?'; $lang->action->repeatChange = '系统内已有同名、同代号的%s,恢复后名称为\"%s\"、代号为\"%s\"。'; $lang->action->nameRepeatChange = '系统内已有同名的%s,恢复后名称为\"%s\"。'; diff --git a/module/action/model.php b/module/action/model.php index be95cededf..e869003901 100755 --- a/module/action/model.php +++ b/module/action/model.php @@ -1887,7 +1887,7 @@ class actionModel extends model if($action->objectType == 'execution') { - $execution = $this->dao->select('id, project, grade, parent, status, deleted')->from(TABLE_EXECUTION)->where('id')->eq($action->objectID)->fetch(); + $execution = $this->dao->select('id, type, project, grade, parent, status, deleted')->from(TABLE_EXECUTION)->where('id')->eq($action->objectID)->fetch(); $this->loadModel('common')->syncExecutionByChild($execution); } } @@ -2221,4 +2221,29 @@ class actionModel extends model $this->loadModel('search')->setSearchParams($this->config->trash->search); } + + /** + * Restore stages. + * + * @param array $stageList + * @access public + * @return void + */ + public function restoreStages($stageList) + { + $deletedActions = $this->dao->select('*')->from(TABLE_ACTION) + ->where('objectID')->in(array_keys($stageList)) + ->andWhere('objectType')->eq('execution') + ->andWhere('action')->eq('deleted') + ->orderBy('id_desc') + ->fetchGroup('objectID'); + + foreach($stageList as $stageID => $stage) + { + $deletedAction = $deletedActions[$stageID][0]; + $this->dao->update(TABLE_EXECUTION)->set('deleted')->eq('0')->where('id')->eq($stageID)->exec(); + $this->dao->update(TABLE_ACTION)->set('extra')->eq(ACTIONMODEL::BE_UNDELETED)->where('id')->eq($deletedAction->id)->exec(); + $this->create($deletedAction->objectType, $deletedAction->objectID, 'undeleted'); + } + } } diff --git a/module/programplan/model.php b/module/programplan/model.php index f46c09526e..65485e133d 100755 --- a/module/programplan/model.php +++ b/module/programplan/model.php @@ -1571,19 +1571,23 @@ class programplanModel extends model * * @param int $planID * @param string $attribute + * @param bool $withDeleted * @access public * @return bool */ - public function updateSubStageAttr($planID, $attribute) + public function updateSubStageAttr($planID, $attribute, $withDeleted = false) { if($attribute == 'mix') return true; - $subStageList = $this->dao->select('id')->from(TABLE_EXECUTION)->where('parent')->eq($planID)->andWhere('deleted')->eq(0)->fetchAll('id'); + $subStageList = $this->dao->select('id')->from(TABLE_EXECUTION) + ->where('parent')->eq($planID) + ->beginIF(!$withDeleted)->andWhere('deleted')->eq(0)->fi() + ->fetchAll('id'); $this->dao->update(TABLE_EXECUTION)->set('attribute')->eq($attribute)->where('id')->in(array_keys($subStageList))->exec(); foreach($subStageList as $childID => $subStage) { - $this->updateSubStageAttr($childID, $attribute); + $this->updateSubStageAttr($childID, $attribute, $withDeleted); } } }