| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575 |
- <?php
- /**
- * The control file of tree 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 tree
- * @version $Id: control.php 5002 2013-07-03 08:25:39Z chencongzhi520@gmail.com $
- * @link https://www.zentao.net
- */
- class tree extends control
- {
- const NEW_CHILD_COUNT = 5;
- /**
- * 模块维护。
- * Module browse.
- *
- * @param int $rootID
- * @param string $viewType story|bug|case|doc
- * @param int $currentModuleID
- * @param string $branch
- * @param string $from
- * @access public
- * @return void
- */
- public function browse($rootID, $viewType, $currentModuleID = 0, $branch = 'all', $from = '')
- {
- $this->updateBrowseLang($viewType);
- $this->updateRawModule($rootID, $viewType);
- /* 可以维护模块的类型:story, bug, case, feedback, caselib, ticket, line, 另外 doc, api在列表页面维护。*/
- $this->app->loadLang('host');
- $root = $this->treeZen->setRoot($rootID, $viewType, $branch);
- if($viewType == 'story')
- {
- $products = $this->loadModel('product')->getPairs('', 0, '', 'all');
- $this->session->set('product', $rootID, $this->app->tab);
- $this->lang->modulePageNav = '';
- unset($products[$rootID]);
- $currentProduct = (int)key($products);
- $this->view->allProduct = $products;
- $this->view->currentProduct = $currentProduct;
- $this->view->productModules = $this->tree->getOptionMenu($currentProduct, 'story');
- }
- /* 无产品项目也可以维护模块。 */
- if($this->app->tab == 'project')
- {
- $this->loadModel('project')->setMenu($this->session->project);
- $this->view->projectID = $this->session->project;
- }
- /* 无产品迭代也可以维护模块。 */
- if($this->app->tab == 'execution')
- {
- $this->loadModel('execution')->setMenu($this->session->execution);
- $menuType = $viewType == 'case' ? 'testcase' : $viewType;
- if(isset($this->lang->execution->menu->qa['subMenu']->{$menuType})) $this->lang->execution->menu->qa['subMenu']->{$menuType}['subModule'] = 'tree';
- if($menuType == 'story' && isset($this->lang->execution->menu->story)) $this->lang->execution->menu->story['subModule'] = 'tree';
- $this->view->executionID = $this->session->execution;
- }
- if($viewType == 'feedback' or $viewType == 'ticket')
- {
- $syncConfig = json_decode($this->config->global->syncProduct, true);
- $this->view->syncConfig = isset($syncConfig[$viewType]) ? $syncConfig[$viewType] : array();
- $this->view->productID = $rootID;
- }
- /* 获取产品的分支。 Get branches of product. */
- $branches = ($root->rootType == 'product' && $root->type != 'normal') ? $this->loadModel('branch')->getPairs($root->id, 'withClosed') : array();
- $isFlowModule = false;
- if($this->config->edition != 'open')
- {
- $flow = $this->loadModel('workflow')->getByModule($from);
- $isFlowModule = !empty($flow);
- }
- if($isFlowModule) $this->config->excludeDropmenuList[] = "{$from}-browse";
- $this->view->title = $viewType == 'host' ? $this->lang->host->groupMaintenance : $this->lang->tree->manage;
- $this->view->rootID = $root->id;
- $this->view->root = $root;
- $this->view->productID = $root->rootType == 'product' ? $root->id : 0;
- $this->view->branches = $branches;
- $this->view->libID = $root->rootType == 'caselib' || $root->rootType == 'lib' ? $root->id : 0;
- $this->view->viewType = $viewType;
- $this->view->placeholder = $viewType == 'host' ? $this->lang->tree->groupName : $this->lang->tree->name;
- $this->view->sons = $this->tree->getSons($rootID, $currentModuleID, $viewType, $branch);
- $this->view->currentModuleID = $currentModuleID;
- $this->view->parentModules = $this->tree->getParents($currentModuleID);
- $this->view->branch = $branch;
- $this->view->from = $from;
- $this->view->tree = $this->tree->getProductStructure($rootID, $viewType, $branch);
- $this->view->canBeChanged = common::canModify($root->rootType, $root);
- $this->view->isFlowModule = $isFlowModule;
- $this->display();
- }
- /**
- * 任务模块维护。
- * Browse task module.
- *
- * @param int $rootID
- * @param int $productID
- * @param int $currentModuleID
- * @access public
- * @return void
- */
- public function browseTask($rootID, $productID = 0, $currentModuleID = 0)
- {
- $this->lang->navGroup->tree = 'execution';
- /* Get execution. */
- $execution = $this->loadModel('execution')->getById($rootID);
- $this->view->root = $execution;
- /* Get all associated products. */
- $products = $this->loadModel('product')->getProducts($rootID);
- $this->view->products = $products;
- $executions = $this->execution->getPairs((int)$this->session->project);
- /* Set menu. */
- $this->execution->setMenu($rootID);
- $this->lang->tree->menu = $this->lang->execution->menu;
- $this->lang->tree->menuOrder = $this->lang->execution->menuOrder;
- if($this->app->tab == 'project') $this->view->projectID = $rootID;
- unset($executions[$rootID]);
- $parentModules = $this->tree->getParents($currentModuleID);
- $newModule = (version_compare($execution->openedVersion, '4.1', '>') and $products) ? true : false;
- $title = $execution->multiple ? $this->lang->tree->manageExecution : $this->lang->tree->manageProject;
- $this->view->title = $title;
- $this->view->rootID = $rootID;
- $this->view->productID = $productID;
- $this->view->execution = $execution;
- $this->view->allProject = $executions;
- $this->view->newModule = $newModule;
- $this->view->sons = $this->tree->getTaskSons($rootID, $productID, $currentModuleID);
- $this->view->parentModules = $parentModules;
- $this->view->currentModuleID = $currentModuleID;
- $this->view->tree = $this->tree->getTaskStructure($rootID, $productID);
- $this->view->canBeChanged = common::canModify('execution', $execution); // Determines whether an object is editable.
- $this->display();
- }
- /**
- * 编辑模块。
- * Edit a module.
- *
- * @param int $moduleID
- * @param string $type
- * @param string $branch
- * @access public
- * @return void
- */
- public function edit($moduleID, $type, $branch = '0')
- {
- $this->app->loadLang('task');
- if(!empty($_POST))
- {
- if($type == 'docTemplate') $this->lang->tree->name = $this->lang->docTemplate->typeName;
- $this->tree->update($moduleID, $type);
- if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
- return $this->sendSuccess(array('closeModal' => true, 'load' => true, 'docApp' => array('load', null, null, null, array('noLoading' => true, 'picks' => 'module'))));
- }
- $module = $this->tree->getById($moduleID);
- if($type == 'task')
- {
- $this->view->optionMenu = $this->tree->getTaskOptionMenu($module->root);
- }
- elseif($type != 'chart')
- {
- $this->view->optionMenu = $this->tree->getOptionMenu($module->root, $module->type, 0, (string)$module->branch, 'noMainBranch|nodeleted', $type == 'docTemplate' ? '1' : 'all');
- }
- if($type == 'doc')
- {
- $docLib = $this->loadModel('doc')->getLibById((int)$module->root);
- $objectID = isset($docLib->{$docLib->type}) ? $docLib->{$docLib->type} : 0;
- $this->view->libs = $this->doc->getLibs($docLib->type, '', '', $objectID, 'book');
- }
- if($type == 'docTemplate')
- {
- $name = $this->lang->docTemplate->typeName;
- $title = $this->lang->docTemplate->editTemplateType;
- $parentLabel = $this->lang->docTemplate->parentModule;
- $scopes = array();
- $scopeList = $this->loadModel('doc')->getTemplateScopes();
- foreach($scopeList as $scope) $scopes[$scope->id] = $scope->name;
- $this->view->scopes = $scopes;
- }
- elseif($type == 'doc' || $type == 'api')
- {
- $name = $this->lang->tree->dir;
- $title = $this->lang->tree->editDir;
- $parentLabel = $this->lang->tree->parentCate;
- }
- elseif($type == 'line')
- {
- $name = $this->lang->tree->line;
- $title = $this->lang->tree->manageLine;
- $parentLabel = $this->lang->tree->parent;
- }
- else
- {
- $name = $this->lang->tree->name;
- $title = $this->lang->tree->edit;
- $parentLabel = $this->lang->tree->parent;
- }
- if($type == 'host') $this->app->loadLang('host');
- $this->view->name = $name;
- $this->view->title = $title;
- $this->view->title = $type == 'host' ? $this->lang->host->groupMaintenance : $title;
- $this->view->parentLabel = $parentLabel;
- $this->view->module = $module;
- $this->view->type = $type;
- $this->view->branch = $branch;
- $this->view->users = $this->loadModel('user')->getPairs('noclosed|nodeleted', $module->owner);
- $showProduct = strpos('story|bug|case', $type) !== false ? true : false;
- if($showProduct)
- {
- $product = $this->loadModel('product')->getById($module->root);
- $this->view->branches = $product->type != 'normal' ? $this->loadModel('branch')->getPairs($module->root, 'withClosed') : array(0);
- $this->view->product = $product;
- $this->view->products = $this->product->getPairs('', $product->program);
- if($product->shadow) $showProduct = false;
- }
- $this->view->showProduct = $showProduct;
- /* Remove self and childs from the $optionMenu. Because it's parent can't be self or childs. */
- $childs = $this->tree->getAllChildId($moduleID);
- foreach($childs as $childModuleID) unset($this->view->optionMenu[$childModuleID]);
- if($type == 'doc') $this->view->optionMenu = array_merge(array(0 => '/'), $this->doc->buildNestedDocs(array(), $this->view->optionMenu, false));
- $this->display();
- }
- /**
- * 修复模块的path和grade字段。
- * Fix path, grades.
- *
- * @param int $rootID
- * @param string $type
- * @access public
- * @return void
- */
- public function fix($rootID, $type)
- {
- $this->tree->fixModulePath($rootID, $type);
- echo js::alert($this->lang->tree->successFixed) . js::reload('parent');
- }
- /**
- * 更新模块排序。
- * Update modules' orders.
- *
- * @param int $root
- * @param string $viewType
- * @param int $moduleID
- *
- * @access public
- * @return void
- * @param int $rootID
- */
- public function updateOrder($rootID = 0, $viewType = '', $moduleID = 0)
- {
- if(!empty($_POST))
- {
- $this->tree->updateOrder($_POST['orders']);
- if($viewType == 'story' and !empty($rootID) and !empty($moduleID)) $this->loadModel('action')->create('module', $rootID, 'moved', '', $moduleID);
- }
- }
- /**
- * 管理子模块。
- * Manage child modules.
- *
- * @param int $rootID
- * @param string $viewType
- * @param string $oldPage yes|no
- * @access public
- * @return void
- */
- public function manageChild($rootID, $viewType, $oldPage = 'no')
- {
- if(!empty($_POST))
- {
- $moduleIDList = $this->tree->manageChild($rootID, $viewType);
- if(dao::isError()) return $this->sendError(dao::getError());
- if($this->viewType == 'json') return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'idList' => $moduleIDList));
- if(isInModal())
- {
- return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'closeModal' => true, 'callback' => "renderModulePicker($rootID, '$viewType');"));
- }
- if($oldPage == 'yes') return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => 'reload'));
- return $this->sendSuccess(array('load' => true));
- }
- }
- /**
- * 新增一个模块。
- * Create a module.
- *
- * @param int $rootID
- * @param string $viewType
- * @access public
- * @return void
- */
- public function create($rootID, $viewType)
- {
- if(!empty($_POST))
- {
- if(empty($_POST['name'])) return $this->sendError(array('name' => sprintf($this->lang->error->notempty, $this->lang->tree->name)));
- $count = $this->dao->select(`order`)->from(TABLE_MODULE)->where('type')->eq($viewType)->andWhere('root')->eq($rootID)->andWhere('parent')->eq('0')->count();
- $_POST['parentModuleID'] = 0;
- $_POST['modules'] = array($_POST['name']);
- $_POST['shorts'] = array($_POST['short']);
- $_POST['maxOrder'] = $count ? $count * 10 : 0;
- $this->tree->manageChild($rootID, $viewType);
- if(dao::isError()) return $this->sendError(dao::getError());
- return $this->sendSuccess(array('load' => true, 'closeModel' => true));
- }
- $this->view->title = $this->lang->tree->create;
- $this->display();
- }
- /**
- * 查看模块历史记录。
- * View module histories.
- *
- * @param int $productID
- * @access public
- * @return void
- */
- public function viewHistory($productID)
- {
- $this->view->productID = $productID;
- $this->view->actions = $this->loadModel('action')->getList('module', $productID);
- $this->view->users = $this->loadModel('user')->getPairs('noletter');
- $this->display();
- }
- /**
- * 删除模块。
- * Delete a module.
- *
- * @param int $moduleID
- * @param string $confirm yes|no
- * @access public
- * @return void
- */
- public function delete($moduleID, $confirm = 'no')
- {
- if($confirm == 'no')
- {
- $module = $this->tree->getByID($moduleID);
- $confirmLang = $this->lang->tree->confirmDelete;
- if($module->type == 'doc' or $module->type == 'api') $confirmLang = $this->lang->tree->confirmDeleteMenu;
- if($module->type == 'line') $confirmLang = $this->lang->tree->confirmDeleteLine;
- if($module->type == 'host') $confirmLang = $this->lang->tree->confirmDeleteHost;
- if(strpos($this->config->tree->groupTypes, ",$module->type,") !== false) $confirmLang = $this->lang->tree->confirmDeleteGroup;
- $confirmURL = $this->createLink($this->app->rawModule, $this->app->rawMethod, "moduleID=$moduleID&confirm=yes");
- return $this->send(array('result' => 'fail', 'callback' => "zui.Modal.confirm({message: '{$confirmLang}', icon: 'icon-exclamation-sign', iconClass: 'warning-pale rounded-full icon-2x'}).then((res) => {if(res) $.ajaxSubmit({url: '$confirmURL'});});"));
- }
- else
- {
- $result = $this->tree->remove($moduleID);
- if(!$result) return;
- return $this->send(array('result' => 'success', 'load' => true, 'closeModal' => true));
- }
- }
- /**
- * Ajax: 获取模块的下拉菜单。
- * Ajax: Get the option menu of modules.
- *
- * @param int $rootID
- * @param string $viewType
- * @param string $branch
- * @param int $rootModuleID
- * @param string $returnType
- * @param string $fieldID
- * @param string $extra
- * @param int $currentModuleID
- * @param string $grade
- * @access public
- * @return string the html select string.
- */
- public function ajaxGetOptionMenu($rootID, $viewType = 'story', $branch = 'all', $rootModuleID = 0, $returnType = 'html', $fieldID = '', $extra = 'nodeleted', $currentModuleID = 0, $grade = 'all')
- {
- if($viewType == 'task')
- {
- $optionMenu = $this->tree->getTaskOptionMenu($rootID, 0, $extra);
- }
- else
- {
- $optionMenu = $this->tree->getOptionMenu($rootID, $viewType, $rootModuleID, $branch, $extra, $grade);
- }
- if(strpos($extra, 'excludeModuleID') !== false)
- {
- list($excludeModule, $noMainBranch) = explode(',', $extra);
- parse_str($excludeModule, $output);
- $excludeModuleID = $output['excludeModuleID'];
- if(strpos($extra, 'excludeRelated') !== false)
- {
- $childs = $this->tree->getAllChildId((int)$excludeModuleID);
- foreach($childs as $childModuleID) unset($optionMenu[$childModuleID]);
- }
- else
- {
- if(isset($optionMenu[$excludeModuleID])) unset($optionMenu[$excludeModuleID]);
- }
- }
- if($returnType == 'items')
- {
- $this->printOptionMenuArray($optionMenu);
- }
- elseif($returnType == 'html')
- {
- $this->printOptionMenuHtml($optionMenu, $viewType, $fieldID, $currentModuleID);
- }
- elseif($returnType == 'mhtml')
- {
- $this->printOptionMenuMHtml($optionMenu, $viewType, $rootID);
- $changeFunc = '';
- if($viewType == 'bug' or $viewType == 'case') $changeFunc = "onchange='loadModuleRelated()'";
- if($viewType == 'task') $changeFunc = "onchange='setStories(this.value, $rootID)'";
- $field = $fieldID ? "modules[$fieldID]" : 'module';
- $output = html::select("$field", $optionMenu, '', "class='input' $changeFunc");
- return print($output);
- }
- elseif($returnType == 'json')
- {
- print(json_encode($optionMenu));
- }
- }
- /**
- * Ajax: 获取drop菜单。
- * Ajax: get drop menu.
- *
- * @param int $rootID
- * @param string $module
- * @param string $method
- * @param string $extra
- * @access public
- * @return void
- */
- public function ajaxGetDropMenu($rootID, $module, $method, $extra = '')
- {
- $this->view->productID = $rootID;
- $this->view->module = $module;
- $this->view->method = $method;
- $this->view->extra = $extra;
- $viewType = $module;
- if($module == 'bug') $viewType = 'bug';
- if($module == 'testcase') $viewType = 'case';
- $modules = $this->tree->getOptionMenu($rootID, $viewType);
- $modulesPinyin = common::convert2Pinyin($modules);
- $this->view->link = $viewType == 'caselib' ? helper::createLink($module, $method, "rootID=%s&type=byModule¶m=%s") : helper::createLink($module, $method, "rootID=%s&branch=&type=byModule¶m=%s");
- $this->view->viewType = $viewType;
- $this->view->modules = $modules;
- $this->view->modulesPinyin = $modulesPinyin;
- $this->display();
- }
- /**
- * Ajax: 获取模块列表。
- * Ajax: get modules.
- *
- * @param int $productID
- * @param string $viewType
- * @param string $branchID
- * @param int $number
- * @param int $currentModuleID
- * @param string $from showImport
- * @access public
- * @return string the html select string.
- */
- public function ajaxGetModules($productID, $viewType = 'story', $branchID = '0', $number = 0, $currentModuleID = 0, $from = '')
- {
- $currentModule = $this->tree->getById($currentModuleID);
- $currentModuleID = (isset($currentModule->branch) and $currentModule->branch == 0) ? $currentModuleID : 0;
- $modules = $this->tree->getOptionMenu($productID, $viewType, $startModuleID = 0, $branchID);
- $modules = empty($modules) ? array('' => '/') : $modules;
- if($viewType == 'bug' || $viewType == 'case')
- {
- $moduleList = array();
- foreach($modules as $moduleID => $moduleName) $moduleList[] = array('value' => $moduleID, 'text' => $moduleName);
- return $this->send(array('modules' => $moduleList, 'currentModuleID' => $currentModuleID));
- }
- if($this->viewType == 'json') return print(array('modules' => $modules, 'currentModuleID' => $currentModuleID));
- $moduleName = ($viewType == 'bug' and $from != 'showImport') ? "modules[$number]" : "module[$number]";
- echo html::select($moduleName, $modules, $currentModuleID, 'class=form-control');
- }
- /**
- * Ajax: 获取一个模块的子模块。
- * Ajax: get a module's son modules.
- *
- * @param int $moduleID
- * @param int $rootID
- * @param string $type
- * @access public
- * @return string json_encoded modules.
- */
- public function ajaxGetSonModules($moduleID, $rootID = 0, $type = 'story')
- {
- $modules = $this->dao->select('id,name,short')->from(TABLE_MODULE)
- ->where('root')->eq($rootID)
- ->andWhere('parent')->eq((int)$moduleID)
- ->andWhere('type')->eq($type)
- ->andWhere('deleted')->eq(0)
- ->fetchAll('id');
- echo json_encode($modules);
- }
- /**
- * Ajax: 创建模块。
- * Ajax: Create module.
- *
- * @access public
- * @return void
- */
- public function ajaxCreateModule()
- {
- if(!helper::isAjaxRequest()) return $this->send(array('result' => 'fail', 'message' => ''));;
- $module = $this->tree->createModule();
- if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => implode('\n', dao::getError())));
- return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'load' => true, 'module' => $module));
- }
- }
|