| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704 |
- <?php
- /**
- * The model 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: model.php 5149 2013-07-16 01:47:01Z zhujinyonging@gmail.com $
- * @link https://www.zentao.net
- */
- class treeModel extends model
- {
- /**
- * 通过ID获取模块信息。
- * Get module by ID.
- *
- * @param int $moduleID
- * @access public
- * @return object
- */
- public function getByID($moduleID)
- {
- return $this->dao->findById((int)$moduleID)->from(TABLE_MODULE)->fetch();
- }
- /**
- * 获取模块列表(全路径名称)
- * Get all module pairs with path.
- *
- * @access public
- * @return object
- * @param string $type
- */
- public function getAllModulePairs($type = 'task')
- {
- $modules = $this->dao->select('*')->from(TABLE_MODULE)
- ->where('(type')->eq('story')
- ->beginIF($type == 'task')->orWhere('type')->eq('task')->fi()
- ->beginIF($type == 'bug')->orWhere('type')->eq('bug')->fi()
- ->beginIF($type == 'case')->orWhere('type')->eq('case')->fi()
- ->beginIF($type == 'ticket')->orWhere('type')->eq('ticket')->fi()
- ->beginIF($type == 'feedback')->orWhere('type')->eq('feedback')->fi()
- ->markRight(1)
- ->andWhere('deleted')->eq('0')
- ->orderBy('grade asc')
- ->fetchAll();
- $pairs = array();
- $pairs[0] = '/';
- foreach($modules as $module)
- {
- if($module->grade == 1)
- {
- $pairs[$module->id] = '/' . $module->name;
- continue;
- }
- $moduleName = '/' . $module->name;
- $pairs[$module->id] = isset($pairs[$module->parent]) ? $pairs[$module->parent] . $moduleName : $moduleName;
- }
- return $pairs;
- }
- /**
- * 构建SQL查询语句。
- * Build the sql query.
- *
- * @param int $rootID
- * @param string $type
- * @param int $startModule
- * @param string $branch
- * @param string $param
- * @param int $grade
- * @access public
- * @return string
- */
- public function buildMenuQuery($rootID, $type, $startModule = 0, $branch = 'all', $param = 'nodeleted', $grade = 0)
- {
- /* Set the start module. */
- $startModulePath = '';
- if($startModule > 0)
- {
- $startModule = $this->getById($startModule);
- if($startModule) $startModulePath = $startModule->path . '%';
- }
- if($this->isMergeModule($rootID, $type))
- {
- return $this->dao->select('id, name, root, branch, grade, path, parent, owner, type, extra')->from(TABLE_MODULE)
- ->where('root')->eq((int)$rootID)
- ->beginIF($type == 'task')->andWhere('type')->eq('task')->fi()
- ->beginIF($type != 'task')->andWhere('type')->in("story,$type")->fi()
- ->beginIF($startModulePath)->andWhere('path')->like($startModulePath)->fi()
- ->beginIF($branch !== 'all' && $branch !== '' && strpos($param, 'noMainBranch') === false)
- ->andWhere("(branch")->eq(0)
- ->orWhere('branch')->in($branch)
- ->markRight(1)
- ->fi()
- ->beginIF($branch !== 'all' && $branch !== '' && strpos($param, 'noMainBranch') !== false)
- ->andWhere('branch')->eq($branch)
- ->fi()
- ->beginIF(strpos($param, 'nodeleted') !== false)->andWhere('deleted')->eq(0)->fi()
- ->orderBy('grade desc, `order`, type desc')
- ->get();
- }
- /* If feedback module is merge add story module.*/
- $syncConfig = $this->getSyncConfig($type);
- $storyCondition = array();
- if(($type == 'feedback' || $type == 'ticket') && strpos($param, 'noproduct') === false && !empty($syncConfig))
- {
- if(isset($syncConfig[$rootID]))
- {
- $storyCondition[] = "`type` = 'story' AND `grade` <= " . (int)zget($syncConfig, $rootID, 0);
- }
- elseif(empty($rootID))
- {
- foreach($syncConfig as $productID => $storyGrade) $storyCondition[] = "(`type` = 'story' AND `root` = '$productID' AND `grade` <= '$storyGrade')";
- }
- }
- $storyCondition = implode(' OR ', array_unique($storyCondition));
- /* $createdVersion < 4.1 or $type == 'story'. */
- return $this->dao->select('*')->from(TABLE_MODULE)
- ->where('1=1')
- ->beginIF($type != 'feedback' || !empty($rootID))->andwhere('root')->eq((int)$rootID)->fi()
- ->andWhere('type', true)->in($type)
- ->beginIF($storyCondition)->orWhere('(' . $storyCondition . ')')->fi()
- ->markRight(1)
- ->beginIF($grade)->andWhere('grade')->le($grade)->fi()
- ->beginIF($startModulePath)->andWhere('path')->like($startModulePath)->fi()
- ->beginIF($branch !== 'all' && $branch !== '' && strpos($param, 'noMainBranch') === false)
- ->andWhere('(branch')->eq(0)
- ->orWhere('branch')->eq($branch)
- ->markRight(1)
- ->fi()
- ->beginIF($branch !== 'all' && $branch !== '' && strpos($param, 'noMainBranch') !== false)
- ->andWhere('branch')->eq($branch)
- ->fi()
- ->beginIF(strpos($param, 'nodeleted') !== false)->andWhere('deleted')->eq(0)->fi()
- ->orderBy('root, grade desc, `order`')
- ->get();
- }
- /**
- * 获取某个分支模块的下拉菜单。
- * Get option menu by branch.
- *
- * @param int $rootID
- * @param string $type
- * @param int $startModule
- * @param string $branch
- * @param string $param
- * @param string $grade
- * @param string $divide /|>
- * @access public
- * @return array
- */
- protected function getOptionMenuByBranch($rootID, $type = 'story', $startModule = 0, $branch = 'all', $param = 'nodeleted', $grade = 'all', $divide = '/')
- {
- $branches = array($branch => '');
- if($branch != 'all' && strpos('story|bug|case', $type) !== false)
- {
- $product = $this->loadModel('product')->getById($rootID);
- if($product && $product->type == 'normal') $branches = array('0' => '');
- if($product && $product->type != 'normal')
- {
- $branchPairs = $this->loadModel('branch')->getPairs($rootID, 'all');
- foreach(explode(',', (string)$branch) as $branchID)
- {
- $branchID = (int)$branchID;
- $branches[$branchID] = $branchPairs[$branchID];
- }
- }
- }
- $syncConfig = $this->getSyncConfig($type); // If feedback or ticket module is merge add story module.
- $treeMenu = array();
- foreach($branches as $branchID => $branch)
- {
- $stmt = $this->app->dbQuery($this->buildMenuQuery($rootID, $type, $startModule, (string)$branchID, $param));
- $modules = array();
- while($module = $stmt->fetch())
- {
- if(($type == 'feedback' || $type == 'ticket') && $module->type == 'story') // If is feedback or ticket filter story module by grade.
- {
- if(isset($syncConfig[$module->root]) && $module->grade > $syncConfig[$module->root]) continue;
- }
- if($grade != 'all' && $module->grade > $grade) continue;
- $modules[$module->id] = $module;
- }
- foreach($modules as $module)
- {
- $branchName = (isset($product) && $product->type != 'normal' && (string)$module->branch === BRANCH_MAIN) ? $this->lang->branch->main : $branch;
- $this->buildTreeArray($treeMenu, $modules, $module, (empty($branchName)) ? '/' : "/$branchName/", $divide);
- }
- }
- ksort($treeMenu);
- $topMenu = explode("\n", trim((string)array_shift($treeMenu)));
- $lastMenu = array(0 => '/');
- foreach($topMenu as $menu)
- {
- if(!strpos($menu, '|')) continue;
- list($label, $moduleID) = explode('|', $menu);
- $lastMenu[$moduleID] = $label;
- }
- return $lastMenu;
- }
- /**
- * 获取模块的下拉菜单。
- * Get option menu.
- *
- * @param int $rootID
- * @param string $type
- * @param int $startModule
- * @param string|array $branch
- * @param string $param
- * @param string $grade
- * @param string $divide /|>
- * @access public
- * @return array
- */
- public function getOptionMenu($rootID, $type = 'story', $startModule = 0, $branch = 'all', $param = 'nodeleted', $grade = 'all', $divide = '/')
- {
- /* 新手引导。 Tutorial. */
- if(commonModel::isTutorialMode())
- {
- $modulePairs = $this->loadModel('tutorial')->getModulePairs();
- if(!is_array($branch)) return $modulePairs;
- $modules = array();
- foreach($branch as $branchID) $modules[$branchID] = $modulePairs;
- return $modules;
- }
- if($type == 'line') $rootID = 0;
- if(is_array($branch))
- {
- $modules = array();
- foreach($branch as $branchID) $modules[$branchID] = $this->getOptionMenuByBranch($rootID, $type, $startModule, (string)$branchID, $param, $grade, $divide);
- return $modules;
- }
- return $this->getOptionMenuByBranch($rootID, $type, $startModule, $branch, $param, $grade, $divide);
- }
- /**
- * 获取模块对列表。
- * Get module pairs.
- *
- * @param int|array $rootID
- * @param string $viewType
- * @param string $showModule
- * @access public
- * @return array
- * @param string $extra
- */
- public function getModulePairs($rootID, $viewType = 'story', $showModule = 'end', $extra = '')
- {
- if(common::isTutorialMode()) $modulePairs = $this->loadModel('tutorial')->getModulePairs();
- if($viewType == 'task')
- {
- $products = array_keys($this->loadModel('product')->getProductPairsByProject($rootID));
- if(!$this->isMergeModule($rootID, $viewType) || !$products)
- {
- $modules = $this->dao->select('id,name,path,short')->from(TABLE_MODULE)->where('root')->in($rootID)->andWhere('type')->in($viewType)->andWhere('deleted')->eq(0)->fetchAll('id');
- }
- else
- {
- $modules = $this->dao->select('id,name,path,short')->from(TABLE_MODULE)
- ->where("((root = '" . (int)$rootID . "' AND type = 'task')")
- ->orWhere('(root')->in($products)->andWhere('type')->eq('story')
- ->markRight(2)
- ->andWhere('deleted')->eq(0)
- ->fetchAll('id');
- }
- }
- else
- {
- /* When case with libIdList then append lib modules. */
- $modules = array();
- if($this->isMergeModule($rootID, $viewType) || !$rootID) $viewType .= ',story';
- $modules += $this->dao->select('id,name,path,short')->from(TABLE_MODULE)
- ->where('type')->in($viewType)
- ->beginIF($rootID)->andWhere('root')->in($rootID)->fi()
- ->andWhere('deleted')->eq(0)
- ->fetchAll('id');
- }
- $modulePairs = array();
- foreach($modules as $moduleID => $module)
- {
- list($baseModule) = explode(',', trim($module->path, ','));
- if($showModule == 'base' && isset($modules[$baseModule])) $module = $modules[$baseModule];
- $modulePairs[$moduleID] = $module->short ? $module->short : $module->name;
- }
- return $modulePairs;
- }
- /**
- * 获取项目的模块下拉菜单。
- * Get an option menu of task in html.
- *
- * @param int $rootID
- * @param int $startModule
- * @param string $extra
- * @access public
- * @return array
- */
- public function getTaskOptionMenu($rootID, $startModule = 0, $extra = '')
- {
- /* If createdVersion <= 4.1, go to getOptionMenu(). */
- $products = $this->loadModel('product')->getProductPairsByProject($rootID);
- $branchGroups = $this->loadModel('branch')->getByProducts(array_keys($products), 'noclosed');
- if(!$this->isMergeModule($rootID, 'task') || !$products) return $this->getOptionMenu($rootID, 'task', $startModule);
- /* createdVersion > 4.1. */
- $startModulePath = '';
- if($startModule > 0)
- {
- $startModule = $this->getById($startModule);
- if($startModule) $startModulePath = $startModule->path . '%';
- }
- $treeMenu = array();
- $lastMenu[] = '/';
- $executionModules = $this->getTaskTreeModules($rootID, true);
- $noProductModules = $this->dao->select('*')->from(TABLE_MODULE)->where('root')->eq($rootID)->andWhere('type')->eq('task')->andWhere('parent')->eq(0)->andWhere('deleted')->eq(0)->orderBy('grade desc, branch, `order`, type')->fetchPairs('id', 'name');
- /* Fix for not in product modules. */
- $productNum = count($products);
- foreach(array('product' => $products, 'noProduct' => $noProductModules) as $type => $rootModules)
- {
- foreach($rootModules as $id => $rootModule)
- {
- $activeBranch = isset($branchGroups[$id]) ? array_keys($branchGroups[$id]) : array();
- if($type == 'product')
- {
- $modules = $this->dao->select('*')->from(TABLE_MODULE)->where("((root = '" . (int)$rootID . "' AND type = 'task' AND parent != 0) OR (root = $id AND type = 'story'))")
- ->beginIF($startModulePath)->andWhere('path')->like($startModulePath)->fi()
- ->beginIF($activeBranch)->andWhere('branch')->in($activeBranch)->fi()
- ->andWhere('deleted')->eq(0)
- ->orderBy('grade desc, branch, `order`, type')
- ->fetchAll('id');
- }
- else
- {
- $modules = $this->dao->select('*')->from(TABLE_MODULE)->where('root')->eq((int)$rootID)
- ->andWhere('type')->eq('task')
- ->andWhere('path')->like("%,$id,%")
- ->beginIF($startModulePath)->andWhere('path')->like($startModulePath)->fi()
- ->andWhere('deleted')->eq(0)
- ->orderBy('grade desc, `order`, type')
- ->fetchAll('id');
- }
- foreach($modules as $module)
- {
- $parentModules = explode(',', trim($module->path, ','));
- if($type == 'product' && isset($noProductModules[$parentModules[0]])) continue;
- /* Fix bug #2007. */
- if($type == 'product' && $module->type == 'task' && !isset($modules[$parentModules[0]])) continue;
- $rootName = ($productNum > 1 && $type == 'product') ? "/$rootModule/" : '/';
- if($type == 'product' && $module->branch && isset($branchGroups[$id][$module->branch])) $rootName .= $branchGroups[$id][$module->branch] . '/';
- $this->buildTreeArray($treeMenu, $modules, $module, $rootName);
- }
- ksort($treeMenu);
- $topMenu = array_shift($treeMenu);
- $topMenu = explode("\n", trim((string)$topMenu));
- foreach($topMenu as $menu)
- {
- if(!strpos($menu, '|')) continue;
- list($label, $moduleID) = explode('|', $menu);
- if(isset($executionModules[$moduleID]) || strpos($extra, 'allModule') !== false) $lastMenu[$moduleID] = $label;
- }
- foreach($topMenu as $moduleID => $moduleName)
- {
- if(!isset($executionModules[$moduleID])) unset($treeMenu[$moduleID]);
- }
- }
- }
- return $lastMenu;
- }
- /**
- * 构建模块树数组。
- * Build tree array.
- *
- * @param array $&treeMenu
- * @param array $modules
- * @param object $module
- * @param string $moduleName
- * @param string $divide
- * @access protected
- * @return void
- */
- protected function buildTreeArray(& $treeMenu, $modules, $module, $moduleName = '/', $divide = '/')
- {
- $parentModules = array_filter(explode(',', $module->path));
- foreach($parentModules as $parentModuleID)
- {
- if(empty($parentModuleID)) continue;
- if(empty($modules[$parentModuleID])) continue;
- $moduleName .= $modules[$parentModuleID]->name . $divide;
- }
- $moduleName = rtrim($moduleName, $divide);
- $moduleName .= "|$module->id\n";
- if(isset($treeMenu[$module->id]) && !empty($treeMenu[$module->id]))
- {
- if(isset($treeMenu[$module->parent]))
- {
- $treeMenu[$module->parent] .= $moduleName;
- }
- else
- {
- $treeMenu[$module->parent] = $moduleName;
- }
- $treeMenu[$module->parent] .= $treeMenu[$module->id];
- }
- else
- {
- if(isset($treeMenu[$module->parent]) && !empty($treeMenu[$module->parent]))
- {
- $treeMenu[$module->parent] .= $moduleName;
- }
- else
- {
- $treeMenu[$module->parent] = $moduleName;
- }
- }
- }
- /**
- * 获取模块树菜单。
- * Get the tree menu.
- *
- * @param int $rootID
- * @param string $type
- * @param int $startModule
- * @param array $userFunc the function used to create link
- * @param array $extra extra params
- * @param string $branch product branch
- * @access public
- * @return array
- */
- public function getTreeMenu($rootID, $type = 'root', $startModule = 0, $userFunc = array(), $extra = array(), $branch = 'all')
- {
- if($type == 'line') $rootID = 0;
- $this->loadModel('branch');
- $projectID = zget($extra, 'projectID', 0);
- $branches = array($branch => '');
- $executionModules = array();
- if($branch && empty($projectID))
- {
- $branchName = $this->branch->getByID($branch);
- $branches = array($branch => $branchName);
- $extra = $userFunc[1] == 'createTestTaskLink' ? $extra : array('rootID' => $rootID, 'branch' => $branch);
- }
- $product = $this->loadModel('product')->getByID($rootID);
- $onlyGetLinked = ($projectID && $this->config->vision != 'lite');
- if(strpos('story|bug|case', $type) !== false && $branch === 'all' && empty($projectID))
- {
- if($product->type != 'normal') $branches = array(BRANCH_MAIN => $this->lang->branch->main) + $this->loadModel('branch')->getPairs($rootID, 'noempty');
- }
- elseif(strpos(',case,bug,', ",$type,") !== false && $this->app->tab == 'execution')
- {
- if($product->type != 'normal' && $projectID) $branches += $this->branch->getPairs($product->id, 'noempty', $projectID);
- if($onlyGetLinked) $executionModules = $this->getTaskTreeModules($projectID, true, $type, array('branchID' => $branch));
- }
- elseif(($type == 'story' && $this->app->rawModule == 'projectstory') || (strpos(',case,bug,', ",$type,") !== false && $this->app->tab == 'project'))
- {
- if($product->type != 'normal' && $projectID) $branches += $this->branch->getPairs((int)$product->id, 'noempty', $projectID);
- if($onlyGetLinked) $executionModules = $this->getTaskTreeModules($projectID, true, $type, $type == 'story' ? array() : array('branchID' => $branch));
- }
- /* Add for task #1945. check the module has case or no. */
- if($type == 'case' && !empty($extra)) $this->loadModel('testtask');
- $modules = array();
- $stmt = $this->app->dbQuery($this->buildMenuQuery($rootID, $type, $startModule, $branch));
- while($module = $stmt->fetch())
- {
- if($onlyGetLinked && !isset($executionModules[$module->id]) && empty($product->shadow)) continue;
- $data = $this->buildTree($module, $type, '0', $userFunc, $extra, $branch);
- if($data) $modules[] = $data;
- }
- return $modules;
- }
- /**
- * 获取任务模块树菜单。
- * Get the tree menu of task.
- *
- * @param int $rootID
- * @param int $productID
- * @param int $startModule
- * @param array $userFunc
- * @param string $extra
- * @access public
- * @return array
- */
- public function getTaskTreeMenu($rootID, $productID = 0, $startModule = 0, $userFunc = array(), $extra = '')
- {
- $extra = array('tip' => true, 'extra' => $extra, 'executionID' => $rootID, 'productID' => $productID);
- /* If createdVersion <= 4.1, go to getTreeMenu(). */
- $products = $this->loadModel('product')->getProductPairsByProject($rootID);
- $branchGroups = $this->loadModel('branch')->getByProducts(array_keys($products));
- if(!$this->isMergeModule($rootID, 'task') || !$products)
- {
- $extra['tip'] = false;
- return (array)$this->getTreeMenu($rootID, 'task', $startModule, $userFunc, $extra);
- }
- /* createdVersion > 4.1. */
- $menu = array();
- /* Set the start module. */
- $startModulePath = '';
- if($startModule > 0)
- {
- $startModule = $this->getById($startModule);
- if($startModule) $startModulePath = $startModule->path . '%';
- }
- $executionModules = $this->getTaskTreeModules($rootID, true);
- /* Get module according to product. */
- $productNum = count($products);
- foreach($products as $id => $product)
- {
- /* 产品名也要放在树状菜单上。Show the product in tree menu. */
- $menuItem = new stdclass();
- $menuItem->id = "product-$id";
- $menuItem->name = $product;
- $menuItem->parent = 0;
- $menuItem->url = helper::createLink('execution', 'task', "executionID=$rootID&status=byProduct&praram=$id");
- $menu["product-$id"] = $menuItem;
- /* tree menu. */
- if(empty($branchGroups[$id])) $branchGroups[$id]['0'] = '';
- foreach($branchGroups[$id] as $branch => $branchName)
- {
- $query = $this->dao->select('*')->from(TABLE_MODULE)->where("((root = '" . (int)$rootID . "' AND type = 'task' AND parent != 0) OR (root = $id AND type = 'story' AND branch ='$branch'))")
- ->beginIF($startModulePath)->andWhere('path')->like($startModulePath)->fi()
- ->andWhere('deleted')->eq(0)
- ->orderBy('grade desc, `order`, type')
- ->get();
- $stmt = $this->app->dbQuery($query);
- while($module = $stmt->fetch())
- {
- if(!isset($executionModules[$module->id]) && strpos($extra['extra'], 'allModule') === false) continue;
- if($module->type == 'story' && $module->root > 0 && $module->parent == 0) $module->parent = "product-{$module->root}";
- $module->url = helper::createLink('execution', 'task', "executionID={$rootID}&type=byModule¶m={$module->id}");
- $menu[$module->id] = $module;
- }
- }
- }
- /* Get execution module. */
- if($startModule == 0)
- {
- $query = $this->dao->select('*')->from(TABLE_MODULE)
- ->where('root')->eq((int)$rootID)
- ->andWhere('type')->eq('task')
- ->andWhere('deleted')->eq(0)
- ->orderBy('grade desc, `order`, type')
- ->get();
- $stmt = $this->app->dbQuery($query);
- while($module = $stmt->fetch())
- {
- $module->url = helper::createLink('execution', 'task', "executionID={$rootID}&type=byModule¶m={$module->id}");
- $menu[$module->id] = $module;
- }
- }
- return $menu;
- }
- /**
- * 获取 bug 的模块。
- * Get the modules of bug.
- *
- * @param int $rootID
- * @param int $productID
- * @param int $startModule
- * @param array $userFunc
- * @param array $extra
- * @access public
- * @return void
- */
- public function getBugTreeMenu($rootID, $productID = 0, $startModule = 0, $userFunc = array(), $extra = array())
- {
- $extra += array('executionID' => $rootID, 'projectID' => $rootID, 'productID' => $productID, 'tip' => true);
- $tab = $this->app->tab;
- /* If createdVersion <= 4.1, go to getTreeMenu(). */
- $products = $tab == 'execution' ? $this->loadModel('product')->getProducts($rootID) : $this->loadModel('product')->getProductPairsByProject($rootID);
- $branchGroups = $this->loadModel('branch')->getByProducts(array_keys($products));
- /* Set the start module. */
- $startModulePath = '';
- if($startModule > 0)
- {
- $startModule = $this->getByID($startModule);
- if($startModule) $startModulePath = $startModule->path . '%';
- }
- $executionModules = $this->getTaskTreeModules($rootID, true, 'bug');
- /* Get module according to product. */
- $moduleName = strpos(',project,execution,', ",$tab,") !== false ? $this->app->tab : 'bug';
- $methodName = strpos(',project,execution,', ",$tab,") !== false ? 'bug' : 'browse';
- $param = strpos(',project,execution,', ",$tab,") !== false ? "{$tab}ID={$rootID}&" : '';
- $modules = array();
- foreach($products as $productID => $product)
- {
- $data = new stdclass();
- $data->id = uniqid();
- $data->parent = '0';
- $data->name = is_object($product) ? $product->name : $product;
- $data->url = helper::createLink($moduleName, $methodName, "{$param}productID=$productID");
- $modules[] = $data;
- if(empty($branchGroups[$productID])) $branchGroups[$productID]['0'] = '';
- foreach($branchGroups[$productID] as $branch => $branchName)
- {
- $query = $this->dao->select('*')->from(TABLE_MODULE)->where("((root = $productID AND type = 'bug' AND branch = '$branch') OR (root = $productID AND type = 'story' AND branch = '$branch'))")
- ->beginIF($startModulePath)->andWhere('path')->like($startModulePath)->fi()
- ->andWhere('deleted')->eq(0)
- ->orderBy('grade desc, `order`, type')
- ->get();
- $stmt = $this->app->dbQuery($query);
- while($module = $stmt->fetch())
- {
- if(isset($executionModules[$module->id])) $modules[] = $this->buildTree($module, 'bug', $data->id, $userFunc, $extra, (string)$branch);
- }
- }
- }
- return $modules;
- }
- /**
- * 获取用例模块树菜单。
- * Get the tree menu of case in html.
- *
- * @param int $rootID
- * @param int $productID
- * @param int $startModule
- * @param array $userFunc
- * @param string $extra
- * @access public
- * @return array
- */
- public function getCaseTreeMenu($rootID, $productID = 0, $startModule = 0, $userFunc = array(), $extra = '')
- {
- $extra = array('projectID' => $rootID, 'executionID' => $rootID, 'productID' => $productID, 'tip' => true, 'extra' => $extra);
- /* If createdVersion <= 4.1, go to getTreeMenu(). */
- $products = $this->app->tab != 'execution' ? $this->loadModel('product')->getProductPairsByProject($rootID) : $this->loadModel('product')->getProducts($rootID);
- $branchGroups = $this->dao->select('t1.product as product,branch,t3.name')->from(TABLE_PROJECTPRODUCT)->alias('t1')
- ->leftJoin(TABLE_PRODUCT)->alias('t2')->on('t1.product=t2.id')
- ->leftJoin(TABLE_BRANCH)->alias('t3')->on('t1.branch=t3.id')
- ->where('t1.project')->eq($rootID)
- ->andWhere('t2.type')->ne('normal')
- ->andWhere('t1.product')->in(array_keys($products))
- ->andWhere('t2.deleted')->eq('0')
- ->fetchGroup('product', 'branch');
- $this->app->loadLang('branch');
- foreach($branchGroups as $productID => $branches)
- {
- $branchGroups[$productID][0] = $this->lang->branch->main;
- foreach($branches as $branchID => $branchInfo)
- {
- $branchGroups[$productID][$branchID] = $branchID == BRANCH_MAIN ? $this->lang->branch->main : $branchInfo->name;
- }
- }
- /* Set the start module. */
- $startModulePath = '';
- if($startModule > 0)
- {
- $startModule = $this->getById($startModule);
- if($startModule) $startModulePath = $startModule->path . '%';
- }
- $executionModules = $this->getTaskTreeModules($rootID, true, 'case');
- /* Get module according to product. */
- $productNum = count($products);
- $moduleName = strpos(',project,execution,', ",{$this->app->tab},") !== false ? $this->app->tab : 'testcase';
- $methodName = strpos(',project,execution,', ",{$this->app->tab},") !== false ? 'testcase' : 'browse';
- $param = $this->app->tab == 'project' ? "projectID={$this->session->project}&" : '';
- $param = $this->app->tab == 'execution' ? "executionID={$rootID}&" : $param;
- $modules = array();
- foreach($products as $productID => $product)
- {
- $extra['productID'] = $productID;
- $data = new stdclass();
- $data->id = uniqid();
- $data->parent = 0;
- $data->name = is_object($product) ? $product->name : $product;
- $data->url = helper::createLink($moduleName, $methodName, $param . "productID=$productID");
- $modules[] = $data;
- if(empty($branchGroups[$productID])) $branchGroups[$productID]['0'] = '';
- foreach($branchGroups[$productID] as $branch => $branchName)
- {
- $query = $this->dao->select('*')->from(TABLE_MODULE)->where("((root = $productID AND type = 'case' AND branch = '$branch') OR (root = $productID AND type = 'story' AND branch = '$branch'))")
- ->beginIF($startModulePath)->andWhere('path')->like($startModulePath)->fi()
- ->andWhere('deleted')->eq(0)
- ->orderBy('grade desc, `order`, type')
- ->get();
- $stmt = $this->app->dbQuery($query);
- while($module = $stmt->fetch())
- {
- if(isset($executionModules[$module->id])) $modules[] = $this->buildTree($module, 'case', $data->id, $userFunc, $extra, (string)$branch);
- }
- }
- }
- return $modules;
- }
- /**
- * 获取项目关联的story。
- * Get project story tree menu.
- *
- * @param int $rootID
- * @param int $startModule
- * @param string|array $userFunc
- * @param array $extra
- * @access public
- * @return array
- */
- public function getProjectStoryTreeMenu($rootID, $startModule = 0, $userFunc = '', $extra = array())
- {
- $this->app->loadLang('branch');
- $menu = array();
- if($this->app->rawModule == 'projectstory') $extra['projectID'] = $rootID;
- if($this->app->rawModule == 'execution') $extra['executionID'] = $rootID;
- $startModulePath = '';
- if($startModule > 0)
- {
- $startModule = $this->getById($startModule);
- if($startModule) $startModulePath = $startModule->path . '%';
- }
- $executionModules = $this->getTaskTreeModules($rootID, true);
- /* Get module according to product. */
- $products = $this->loadModel('product')->getProductPairsByProject($rootID);
- $branchGroups = $this->loadModel('execution')->getBranchByProduct(array_keys($products), $rootID);
- $productNum = count($products);
- $storyType = zget($extra, 'storyType', 'story');
- foreach($products as $id => $product)
- {
- $extra['productID'] = $id;
- $projectProductLink = helper::createLink('projectstory', 'story', "projectID=$rootID&productID=$id&branch=all&browseType=¶m=0&storyType={$storyType}");
- $executionProductLink = helper::createLink('execution', 'story', "executionID=$rootID&storyType={$storyType}&orderBy=&type=byProduct&praram=$id");
- $link = $this->app->rawModule == 'projectstory' ? $projectProductLink : $executionProductLink;
- if($productNum > 1)
- {
- $data = new stdclass();
- $data->id = "p_{$id}";
- $data->parent = '0';
- $data->name = $product;
- $data->url = $link;
- $menu[] = $data;
- }
- /* tree menu. */
- $branchGroups[$id][BRANCH_MAIN] = empty($branchGroups[$id]) ? '' : $this->lang->branch->main;
- foreach($branchGroups[$id] as $branch => $branchName)
- {
- $treeMenu = array();
- $query = $this->dao->select('*')->from(TABLE_MODULE)
- ->where('root')->eq((int)$id)
- ->andWhere('type')->eq('story')
- ->beginIF(count($branchGroups[$id]) > 1)->andWhere('branch')->eq($branch)->fi()
- ->beginIF($startModulePath)->andWhere('path')->like($startModulePath)->fi()
- ->andWhere('deleted')->eq(0)
- ->orderBy('grade desc, branch, `order`, type')
- ->get();
- $stmt = $this->app->dbQuery($query);
- while($module = $stmt->fetch())
- {
- /* Ignore unused modules. */
- if(!isset($executionModules[$module->id]) && $this->config->vision != 'lite') continue;
- $treeMenu = $this->buildTree($module, 'story', '0', $userFunc, $extra);
- if($productNum > 1 && $module->parent == 0) $treeMenu->parent = "p_{$module->root}";
- $menu[] = $treeMenu;
- }
- }
- }
- return $menu;
- }
- /**
- * 获取主机模块树菜单。
- * Get host tree menu.
- *
- * @access public
- * @return array
- */
- public function getHostTreeMenu()
- {
- $menu = array();
- /* tree menu. */
- $treeMenu = array();
- $stmt = $this->dao->select('*')->from(TABLE_MODULE)
- ->where('type')->eq('host')
- ->andWhere('deleted')->eq(0)
- ->orderBy('grade_desc,id_asc')
- ->query();
- while($module = $stmt->fetch())
- {
- $treeMenu = $this->buildTree($module, '', '0', array('treeModel', 'createHostLink'));
- if($module->parent == 0) $treeMenu->parent = $module->root;
- $menu[] = $treeMenu;
- }
- return $menu;
- }
- /**
- * 获取模块树。
- * Get tree structure.
- *
- * @param int $rootID
- * @param string $type
- * @access public
- * @return array
- */
- public function getTreeStructure($rootID, $type)
- {
- $stmt = $this->app->dbQuery($this->buildMenuQuery($rootID, $type, $startModule = 0));
- return $this->getDataStructure($stmt, $type, $rootID);
- }
- /**
- * 获取某个项目的所有任务模块树。
- * Get full task tree
- * @param int $executionID, common value is execution id
- * @param int $productID
- * @access public
- * @return array
- * @param int $rootID
- */
- public function getTaskStructure($rootID, $productID = 0)
- {
- $extra = array('executionID' => $rootID, 'productID' => $productID, 'tip' => true);
- /* If createdVersion <= 4.1, go to getTreeMenu(). */
- $products = $this->loadModel('product')->getProductPairsByProject($rootID);
- $branchGroups = $this->loadModel('branch')->getByProducts(array_keys($products));
- if(!$this->isMergeModule($rootID, 'task') || !$products)
- {
- $extra['tip'] = false;
- $stmt = $this->app->dbQuery($this->buildMenuQuery($rootID, 'task', $startModule = 0));
- if(empty($products))
- {
- $this->app->loadConfig('execution');
- $this->config->execution->task->allModule = 1;
- }
- return $this->getDataStructure($stmt, 'task', $rootID);
- }
- /* only get linked modules && ignore others. */
- $executionModules = $this->getTaskTreeModules($rootID, true);
- /* Get module according to product. */
- $fullTrees = array();
- foreach($products as $id => $product)
- {
- $productInfo = $this->product->getById($id);
- /* tree menu. */
- $productTree = array();
- $branchTrees = array();
- if(empty($branchGroups[$id])) $branchGroups[$id]['0'] = '';
- foreach($branchGroups[$id] as $branch => $branchName)
- {
- $query = $this->dao->select('id, name, type, grade, path, parent, root')->from(TABLE_MODULE)->where("((root = '" . (int)$rootID . "' AND type = 'task' AND parent != 0) OR (root = $id AND type = 'story' AND branch ='$branch'))")
- ->andWhere('deleted')->eq(0)
- ->orderBy('grade desc, `order`, type')
- ->get();
- $stmt = $this->app->dbQuery($query);
- if($branch == 0) $productTree = $this->getDataStructure($stmt, 'task', $rootID, $executionModules);
- if($branch != 0)
- {
- $children = $this->getDataStructure($stmt, 'task', $rootID, $executionModules);
- if($children) $branchTrees[] = array('name' => $branchName, 'root' => $id, 'type' => 'branch', 'actions' => false, 'children' => $children);
- }
- }
- if($branchTrees) $productTree[] = array('name' => $this->lang->product->branchName[$productInfo->type], 'root' => $id, 'type' => 'branch', 'actions' => false, 'children' => $branchTrees);
- $fullTrees[] = array('name' => $productInfo->name, 'root' => $id, 'type' => 'product', 'actions' => false, 'children' => $productTree);
- }
- /* Get execution module. */
- $query = $this->dao->select('id,name,type,grade,path,parent')->from(TABLE_MODULE)
- ->where('root')->eq((int)$rootID)
- ->andWhere('type')->eq('task')
- ->andWhere('deleted')->eq(0)
- ->orderBy('grade desc, `order`, type')
- ->get();
- $stmt = $this->app->dbQuery($query);
- $taskTrees = $this->getDataStructure($stmt, 'task', $rootID, $executionModules);
- foreach($taskTrees as $taskModule) $fullTrees[] = $taskModule;
- return $fullTrees;
- }
- /**
- * 构造模块树。
- * Build tree.
- *
- * @param object $module
- * @param string $type
- * @param string $parent
- * @param array $userFunc
- * @param array $extra
- * @param string $branch
- * @access protected
- * @return object|false
- */
- protected function buildTree($module, $type, $parent = '0', $userFunc = array(), $extra = array(), $branch = 'all')
- {
- /* Add for task #1945. check the module has case or no. */
- if((isset($extra['rootID']) && isset($extra['branch']) && $branch === 'null') || ($type == 'case' && is_numeric($extra)))
- {
- static $objects = array();
- if(empty($objects))
- {
- if(is_array($extra))
- {
- $table = $this->config->objectTables[$type];
- $objects = $this->dao->select('module')->from($table)->where('product')->eq((int)$extra['rootID'])->andWhere('branch')->eq($extra['branch'])->fetchAll('module');
- }
- else
- {
- $objects = $this->dao->select('t1.*,t2.module')->from(TABLE_TESTRUN)->alias('t1')
- ->leftJoin(TABLE_CASE)->alias('t2')->on('t1.case = t2.id')
- ->where('t1.task')->eq((int)$extra)
- ->fetchAll('module');
- }
- }
- static $modules = array();
- if(empty($modules))
- {
- $typeCondition = "type='story'";
- if($type != 'story') $typeCondition .= " OR type='{$type}'";
- $modules = $this->dao->select('id,path')->from(TABLE_MODULE)->where('root')->eq($module->root)->andWhere("({$typeCondition})")->fetchPairs('id', 'path');
- }
- $childModules = array();
- foreach($modules as $moduleID => $modulePath)
- {
- if(strpos($modulePath, $module->path) === 0) $childModules[$moduleID] = $moduleID;
- }
- $hasObjects = false;
- foreach($childModules as $moduleID)
- {
- if(isset($objects[$moduleID]))
- {
- $hasObjects = true;
- break;
- }
- }
- if(!$hasObjects) return false;
- }
- if(is_array($extra)) $extra['branchID'] = $branch;
- if(empty($extra))
- {
- $extra = array();
- $extra['branchID'] = $branch;
- }
- return call_user_func($userFunc, $type, $module, $parent, $extra);
- }
- /**
- * 获取执行的模块。
- * Get execution modules.
- *
- * @param int $executionID
- * @param bool $parent
- * @param string $linkObject
- * @param array $extra
- * @access public
- * @return array
- */
- public function getTaskTreeModules($executionID, $parent = false, $linkObject = 'story', $extra = array())
- {
- $field = $parent ? 'path' : 'id';
- $paths = array();
- if($linkObject)
- {
- $branch = zget($extra, 'branchID', 0);
- /* 获取执行下关联Bug、Story、Case的模块。 Get object paths of this execution. */
- if($linkObject == 'story' || $linkObject == 'case') // Get story or case from projectStory and projectCase, get bug from zt_bug
- {
- $table1 = TABLE_PROJECTSTORY;
- $table2 = TABLE_STORY;
- if($linkObject == 'case')
- {
- $table1 = TABLE_PROJECTCASE;
- $table2 = TABLE_CASE;
- }
- $paths = $this->dao->select("t4.{$field}")->from(TABLE_PROJECT)->alias('t1')
- ->leftJoin($table1)->alias('t2')->on('t1.id=t2.project')
- ->leftJoin($table2)->alias('t3')->on("t2.{$linkObject}=t3.id")
- ->leftJoin(TABLE_MODULE)->alias('t4')->on('t3.module=t4.id')
- ->where('t3.deleted')->eq(0)
- ->andWhere('t4.deleted')->eq(0)
- ->andWhere('t1.project', true)->eq($executionID)->orWhere('t2.project')->eq($executionID)->markRight(1)
- ->beginIF(isset($extra['branchID']) && $branch !== 'all')->andWhere('t3.branch')->eq($branch)->fi()
- ->fetchPairs();
- }
- elseif($linkObject == 'bug' && strpos(',project,execution,', ",{$this->app->tab},") !== false)
- {
- $paths = $this->dao->select("t2.{$field}")->from(TABLE_BUG)->alias('t1')
- ->leftJoin(TABLE_MODULE)->alias('t2')->on('t1.module = t2.id')
- ->where('t1.deleted')->eq(0)
- ->andWhere('t2.deleted')->eq(0)
- ->beginIF(isset($extra['branchID']) && $branch !== 'all')->andWhere('t1.branch')->eq($branch)->fi()
- ->andWhere("t1.{$this->app->tab}")->eq($executionID)
- ->fetchPairs();
- }
- else
- {
- return $paths;
- }
- }
- else
- {
- $productGroups = $this->dao->select('product,branch')->from(TABLE_PROJECTPRODUCT)->where('project')->eq($executionID)->fetchGroup('product', 'branch');
- $modules = $this->dao->select('id,root,branch')->from(TABLE_MODULE)->where('root')->in(array_keys($productGroups))->andWhere('type')->eq('story')->andWhere('deleted')->eq(0)->fetchAll();
- foreach($modules as $module)
- {
- if(empty($module->branch)) $paths[$module->id] = $module->id;
- if(isset($productGroups[$module->root][0]) || isset($productGroups[$module->root][$module->branch])) $paths[$module->id] = $module->id;
- }
- }
- if(strpos(',case,bug,', ",$linkObject,") === false)
- {
- /* Add task paths of this execution.*/
- $paths += $this->dao->select($field)->from(TABLE_MODULE)->where('root')->eq($executionID)->andWhere('type')->eq('task')->andWhere('deleted')->eq(0)->fetchPairs($field, $field);
- /* Add task paths of this execution for has existed. */
- $paths += $this->dao->select("t1.{$field}")->from(TABLE_MODULE)->alias('t1')
- ->leftJoin(TABLE_TASK)->alias('t2')->on('t1.id=t2.module')
- ->where('t2.module')->ne(0)
- ->andWhere('t2.execution')->eq($executionID)
- ->andWhere('t2.deleted')->eq(0)
- ->andWhere('t1.type')->eq('story')
- ->andWhere('t1.deleted')->eq(0)
- ->fetchPairs($field, $field);
- }
- /* Get all modules from paths. */
- $executionModules = array();
- foreach($paths as $path)
- {
- foreach(explode(',', (string)$path) as $module) $executionModules[$module] = $module;
- }
- return array_filter($executionModules);
- }
- /**
- * 生成需求链接。
- * Create link of a story.
- *
- * @param string $type
- * @param object $module
- * @param string $parent
- * @param array $extra
- * @access public
- * @return object
- */
- public function createStoryLink($type, $module, $parent = '0', $extra = array())
- {
- $data = new stdclass();
- $data->id = $parent ? uniqid() : (string)$module->id;
- $data->parent = $parent ? $parent : (string)$module->parent;
- $data->name = $module->name;
- if(isset($extra['projectID']) && !empty($extra['projectID']))
- {
- $productID = zget($extra, 'productID', 0);
- $projectID = $extra['projectID'];
- $data->url = helper::createLink('projectstory', 'story', "projectID=$projectID&productID=$productID&branch=&browseType=byModule¶m={$module->id}&storyType=story");
- }
- elseif(isset($extra['executionID']) && !empty($extra['executionID']))
- {
- $executionID = $extra['executionID'];
- $data->url = helper::createLink('execution', 'story', "executionID=$executionID&storyType=story&orderBy=order_desc&type=byModule¶m={$module->id}");
- }
- else
- {
- $data->url = helper::createLink('product', 'browse', "root={$module->root}&branch={$extra['branchID']}&type=byModule¶m={$module->id}&storyType=story");
- }
- return $data;
- }
- /**
- * 生成用户需求链接。
- * Create link of requirement for waterfall.
- *
- * @param string $type
- * @param object $module
- * @param string $parent
- * @param array $extra
- * @access public
- * @return object
- */
- public function createRequirementLink($type, $module, $parent = '0', $extra = array())
- {
- $data = new stdclass();
- $data->id = $parent ? uniqid() : (string)$module->id;
- $data->parent = $parent ? $parent : (string)$module->parent;
- $data->name = $module->name;
- if(isset($extra['projectID']) && !empty($extra['projectID']))
- {
- $productID = zget($extra, 'productID', 0);
- $projectID = $extra['projectID'];
- $data->url = helper::createLink('projectstory', 'story', "projectID=$projectID&productID=$productID&branch=&browseType=byModule¶m={$module->id}&storyType=requirement");
- }
- elseif(isset($extra['executionID']) && !empty($extra['executionID']))
- {
- $executionID = $extra['executionID'];
- $data->url = helper::createLink('execution', 'story', "executionID=$executionID&storyType=requirement&orderBy=order_desc&type=byModule¶m={$module->id}");
- }
- else
- {
- $branch = isset($extra['branchID']) ? $extra['branchID'] : 'all';
- $data->url = helper::createLink('product', 'browse', "root={$module->root}&branch=$branch&type=byModule¶m={$module->id}&storyType=requirement");
- }
- return $data;
- }
- /**
- * 生成业务需求链接。
- * Create link of epic for waterfall.
- *
- * @param string $type
- * @param object $module
- * @param string $parent
- * @param array $extra
- * @access public
- * @return object
- */
- public function createEpicLink($type, $module, $parent = '0', $extra = array())
- {
- $data = new stdclass();
- $data->id = $parent ? uniqid() : (string)$module->id;
- $data->parent = $parent ? $parent : (string)$module->parent;
- $data->name = $module->name;
- if(isset($extra['projectID']) && !empty($extra['projectID']))
- {
- $productID = zget($extra, 'productID', 0);
- $projectID = $extra['projectID'];
- $data->url = helper::createLink('projectstory', 'story', "projectID=$projectID&productID=$productID&branch=&browseType=byModule¶m={$module->id}&storyType=epic");
- }
- elseif(isset($extra['executionID']) && !empty($extra['executionID']))
- {
- $executionID = $extra['executionID'];
- $data->url = helper::createLink('execution', 'story', "executionID=$executionID&storyType=epic&orderBy=order_desc&type=byModule¶m={$module->id}");
- }
- else
- {
- $branch = isset($extra['branchID']) ? $extra['branchID'] : 'all';
- $data->url = helper::createLink('product', 'browse', "root={$module->root}&branch=$branch&type=byModule¶m={$module->id}&storyType=epic");
- }
- return $data;
- }
- /**
- * 生成任务链接。
- * Create link of a task.
- *
- * @param string $type
- * @param object $module
- * @access public
- * @return object
- */
- public function createTaskLink($type, $module)
- {
- $data = new stdclass();
- $data->id = (string)$module->id;
- $data->parent = (string)$module->parent;
- $data->name = $module->name;
- $data->url = helper::createLink('execution', 'task', "executionID={$module->root}&type=byModule¶m={$module->id}");
- return $data;
- }
- /**
- * 生成交付物链接。
- * Create link of a deliverable.
- *
- * @param string $type
- * @param object $module
- * @param string $parent
- * @param string $extra
- * @access public
- * @return object
- */
- public function createDeliverableLink($type, $module, $parent, $extra = '')
- {
- if(!$extra) $extra = 'all';
- $data = new stdclass();
- $data->id = (string)$module->id;
- $data->parent = (string)$module->parent;
- $data->name = $module->name;
- $data->url = helper::createLink('deliverable', 'browse', "groupID={$module->root}&browseType={$extra}¶m={$module->id}");
- $data->extra = $module->extra;
- return $data;
- }
- /**
- * 生成项目交付物链接。
- * Create link of a project deliverable.
- *
- * @param string $type
- * @param object $module
- * @param string $parent
- * @param string $extra
- * @access public
- * @return object
- */
- public function createProjectDeliverableLink($type, $module, $parent, $extra = '')
- {
- $data = new stdclass();
- $data->id = (string)$module->id;
- $data->parent = (string)$module->parent;
- $data->name = $module->name;
- $data->url = helper::createLink('project', 'deliverable', "projectID={$extra}&browseType=bymodule¶m={$module->id}");
- return $data;
- }
- /**
- * 生成文档链接。
- * Create link of a doc.
- *
- * @param string $type
- * @param object $module
- * @access public
- * @return object
- */
- public function createDocLink($type, $module)
- {
- $data = new stdclass();
- $data->id = $parent ? uniqid() : (string)$module->id;
- $data->parent = $parent ? $parent : (string)$module->parent;
- $data->name = $module->name;
- $data->url = helper::createLink('doc', 'browse', "libID={$module->root}&browseType=byModule¶m={$module->id}");
- return $data;
- }
- /**
- * Create the manage link of a module.
- *
- * @param string $type
- * @param object $module
- * @access public
- * @return object
- */
- public function createManageLink($type, $module)
- {
- static $users;
- if(empty($users)) $users = $this->loadModel('user')->getPairs('noletter');
- $name = $module->name;
- if(strpos('bug,case', $type) !== false) $name .= '[' . strtoupper(substr($type, 0, 1)) . ']';
- if($type == 'bug' && $module->owner) $name .= '[' . $users[$module->owner] . ']';
- $data = new stdclass();
- $data->id = (string)$module->id;
- $data->parent = (string)$module->parent;
- $data->name = $name;
- $data->url = helper::createLink('subject', 'browse', "currentModuleID={$module->id}");
- return $data;
- }
- /**
- * 设置Bug模块树的点击链接。
- * Click link to set Bug module tree.
- *
- * @param string $type
- * @param object $module
- * @param string $parent
- * @param array $extra
- * @access public
- * @return object
- */
- public function createBugLink($type, $module, $parent, $extra = array())
- {
- $moduleName = strpos(',project,execution,', ",{$this->app->tab},") !== false ? $this->app->tab : 'bug';
- $methodName = strpos(',project,execution,', ",{$this->app->tab},") !== false ? 'bug' : 'browse';
- $param = "root={$module->root}&branch=&type=byModule¶m={$module->id}";
- $extraType = (isset($extra['type']) && $extra['type'] != 'bysearch') ? $extra['type'] : 'all';
- $projectID = zget($extra, 'projectID', 0);
- $branchID = zget($extra, 'branchID', 0);
- $orderBy = zget($extra, 'orderBy', '');
- $build = zget($extra, 'build', 0);
- if($this->app->tab == 'execution') $param = "executionID={$projectID}&productID={$module->root}&branch={$branchID}&orderBy={$orderBy}&build={$build}&type={$extraType}¶m={$module->id}";
- if($this->app->tab == 'project') $param = "projectID={$projectID}&productID={$module->root}&branch={$branchID}&orderBy={$orderBy}&build={$build}&type={$extraType}¶m={$module->id}";
- $data = new stdclass();
- $data->id = (string)$module->id;
- $data->parent = $parent && empty($module->parent) ? $parent : (string)$module->parent;
- $data->name = $module->name;
- $data->url = helper::createLink($moduleName, $methodName, $param);
- return $data;
- }
- /**
- * 生成测试用例的链接。
- * Create module of a test case.
- *
- * @param string $type
- * @param object $module
- * @param string $parent
- * @param array|string $extra
- * @access public
- * @return object
- */
- public function createCaseLink($type, $module, $parent, $extra = array())
- {
- $moduleName = strpos(',project,execution,', ",{$this->app->tab},") !== false ? $this->app->tab : 'testcase';
- $methodName = strpos(',project,execution,', ",{$this->app->tab},") !== false ? 'testcase' : 'browse';
- $param = $this->app->tab == 'project' ? "projectID={$this->session->project}&" : "";
- $param = $this->app->tab == 'execution' ? "executionID={$extra['projectID']}&" : $param;
- $branch = isset($extra['branchID']) ? $extra['branchID'] : 'all';
- $moduleParam = $this->app->tab == 'execution' ? "¶m=0&moduleID={$module->id}" : "¶m={$module->id}";
- $data = new stdclass();
- $data->id = (string)$module->id;
- $data->parent = $parent && empty($module->parent) ? $parent : (string)$module->parent;
- $data->name = $module->name;
- $data->url = helper::createLink($moduleName, $methodName, $param . "productID={$module->root}&branch=$branch&browseType=byModule" . $moduleParam);
- return $data;
- }
- /**
- * 生成测试场景的链接。
- * Create module of a scene.
- *
- * @param string $type
- * @param object $module
- * @param string $parent
- * @param array|string $extra
- * @access public
- * @return object
- */
- public function createSceneLink($type, $module, $parent, $extra = array())
- {
- $branch = $extra['branchID'] ?? '';
- $orderBy = $extra['orderBy'] ?? 'id_desc';
- $data = new stdclass();
- $data->id = (string)$module->id;
- $data->parent = $parent && empty($module->parent) ? $parent : (string)$module->parent;
- $data->name = $module->name;
- $data->url = helper::createLink('testcase', 'browseScene', "productID={$module->root}&branch=$branch&moduleID={$module->id}&orderBy=$orderBy");
- return $data;
- }
- /**
- * 生成测试任务的链接。
- * Create link of a test task.
- *
- * @param string $type
- * @param object $module
- * @param string $parent
- * @param array|string $extra
- * @access public
- * @return object
- */
- public function createTestTaskLink($type, $module, $parent, $extra = array())
- {
- $data = new stdclass();
- $data->id = $parent ? uniqid() : (string)$module->id;
- $data->parent = $parent ? $parent : (string)$module->parent;
- $data->name = $module->name;
- $data->url = helper::createLink('testtask', 'cases', "taskID=$extra&type=byModule&module={$module->id}");
- return $data;
- }
- /**
- * 生成用例库的链接。
- * Create case lib link.
- *
- * @param string $type
- * @param object $module
- * @access public
- * @return object
- */
- public function createCaseLibLink($type, $module)
- {
- $data = new stdclass();
- $data->id = $module->id;
- $data->parent = $module->parent;
- $data->name = $module->name;
- $data->url = helper::createLink('caselib', 'browse', "root={$module->root}&type=byModule¶m={$module->id}");
- return $data;
- }
- /**
- * 生成分支的链接。
- * Create branch link
- *
- * @param string $type
- * @param int $rootID
- * @param int $branchID
- * @param string $branch
- * @access public
- * @return string
- */
- public function createBranchLink($type, $rootID, $branchID, $branch)
- {
- if($type == 'story') return html::a(helper::createLink('product', 'browse', "productID={$rootID}&branch=$branchID"), $branch, '_self', "id='branch{$branchID}'");
- if($type == 'bug') return html::a(helper::createLink('bug', 'browse', "productID={$rootID}&branch=$branchID"), $branch, '_self', "id='branch{$branchID}'");
- if($type == 'case') return html::a(helper::createLink('testcase', 'browse', "productID={$rootID}&branch=$branchID"), $branch, '_self', "id='branch{$branchID}'");
- return '';
- }
- /**
- * 生成反馈的链接。
- * Create link of feedback.
- *
- * @param string $type
- * @param object $module
- * @access public
- * @return object
- */
- public function createFeedbackLink($type, $module)
- {
- $data = new stdclass();
- $data->id = $module->id;
- $data->parent = $module->parent;
- $data->name = $module->name;
- $data->url = helper::createLink('feedback', $this->app->methodName, "type=byModule¶m={$module->id}");
- return $data;
- }
- /**
- * 生成工单的链接。
- * Create link of ticket.
- *
- * @param string $type
- * @param object $module
- * @access public
- * @return object
- */
- public function createTicketLink($type, $module)
- {
- $data = new stdclass();
- $data->id = $module->id;
- $data->parent = $module->parent;
- $data->name = $module->name;
- $data->url = helper::createLink('ticket', $this->app->methodName, "type=byModule¶m={$module->id}");
- return $data;
- }
- /**
- * Create link of practice.
- *
- * @param string $type
- * @param object $module
- * @access public
- * @return string
- */
- public function createPracticeLink($type, $module)
- {
- return html::a(helper::createLink('traincourse', 'practicebrowse', "moduleID={$module->id}"), $module->name, '_self', "id='module{$module->id}' title='{$module->name}'");
- }
- /**
- * 生成培训技能的链接。
- * Create link of trainskill.
- *
- * @param string $type
- * @param object $module
- * @param string $extra
- * @access public
- * @return string
- */
- public function createTrainSkillLink($type, $module, $extra = '')
- {
- return html::a(helper::createLink('trainskill', 'browse', "type=byModule¶m={$module->id}"), $module->name, '', "id='module{$module->id}' title='{$module->name}'");
- }
- /**
- * 生成培训课程的链接。
- * Create link of traincourse.
- *
- * @param string $type
- * @param object $module
- * @param string $extra
- * @access public
- * @return string
- */
- public function createTrainCourseLink($type, $module, $extra = '')
- {
- return html::a(helper::createLink('traincourse', 'browse', "type=byModule¶m={$module->id}"), $module->name, '', "id='module{$module->id}' title='{$module->name}'");
- }
- /**
- * 生成培训评论的链接。
- * Create link of trainpost.
- *
- * @param string $type
- * @param object $module
- * @param string $extra
- * @access public
- * @return string
- */
- public function createTrainPostLink($type, $module, $extra = '')
- {
- return html::a(helper::createLink('trainpost', 'browse', "type=byModule¶m={$module->id}"), $module->name, '', "id='module{$module->id}' title='{$module->name}'");
- }
- /**
- * 生成报告的链接。
- * Create report link.
- *
- * @param string $type
- * @param object $module
- * @param string $extra
- * @access public
- * @return string
- */
- public function createReportLink($type, $module, $extra)
- {
- $dimension = zget($extra, 'dimension', 0);
- return html::a(helper::createLink('report', 'browsereport', "dimension={$dimension}&module={$module->id}"), $module->name, '', "id='module{$module->id}' title='{$module->name}'");
- }
- /**
- * 生成主机的链接。
- * Create link of a host.
- *
- * @param string $type
- * @param object $module
- * @param string $parent
- * @param array $extra
- * @access public
- * @return object
- */
- public function createHostLink($type, $module, $parent = '0', $extra = array())
- {
- $data = new stdclass();
- $data->id = $parent ? uniqid() : (string)$module->id;
- $data->parent = $parent ? $parent : (string)$module->parent;
- $data->name = $module->name;
- $data->url = helper::createLink('host', 'browse', "browseType=bymodule¶m={$module->id}");
- return $data;
- }
- /**
- * 获取一个模块的子模块。
- * Get sons of a module.
- *
- * @param int $rootID
- * @param int $moduleID
- * @param string $type
- * @param string $branch
- * @access public
- * @return array
- */
- public function getSons($rootID, $moduleID, $type = 'root', $branch = '0')
- {
- if(common::isTutorialMode()) return array();
- $syncConfig = $this->getSyncConfig($type);
- if($type == 'line') $rootID = 0;
- /* if createVersion <= 4.1 or type == 'story', only get modules of its type. */
- if(!$this->isMergeModule($rootID, $type) || $type == 'story')
- {
- return $this->dao->select('*')->from(TABLE_MODULE)
- ->where('root')->eq((int)$rootID)
- ->andWhere('parent')->eq((int)$moduleID)
- ->andWhere('type')->in($type)
- ->beginIF($branch !== 'all')
- ->andWhere("(branch")->eq(0)
- ->orWhere("branch")->eq((int)$branch)
- ->markRight(1)
- ->fi()
- ->andWhere('deleted')->eq(0)
- ->orderBy('`order`')
- ->fetchAll();
- }
- /* else get modules of its type && story type. */
- if(strpos('task|case|bug', $type) !== false) $type = "$type,story";
- return $this->dao->select('*')->from(TABLE_MODULE)
- ->where('root')->eq((int)$rootID)
- ->andWhere('parent')->eq((int)$moduleID)
- ->andWhere('type', true)->in($type)
- ->beginIF(($type == 'feedback' || $type == 'ticket') && isset($syncConfig[$rootID]))
- ->orWhere('(type')->eq('story')->andWhere('grade')->le(zget($syncConfig, $rootID, 0))->markRight(1)
- ->fi()
- ->markRight(1)
- ->beginIF($branch !== 'all')
- ->andWhere("(branch")->eq(0)
- ->orWhere("branch")->eq((int)$branch)
- ->markRight(1)
- ->fi()
- ->andWhere('deleted')->eq(0)
- ->orderBy('`order`, type desc')
- ->fetchAll();
- }
- /**
- * 获取一个任务模块的子模块。
- * Get sons of a task module.
- *
- * @param int $rootID
- * @param int $productID
- * @param int $moduleID
- * @access public
- * @return array
- */
- public function getTaskSons($rootID, $productID, $moduleID)
- {
- if($moduleID)
- {
- return $this->dao->select('*')->from(TABLE_MODULE)
- ->where('root')->eq((int)$rootID)
- ->andWhere('parent')->eq((int)$moduleID)
- ->andWhere('type')->in("task,story")
- ->andWhere('deleted')->eq(0)
- ->orderBy('`order`, type')
- ->fetchAll();
- }
- else
- {
- return $this->dao->select('*')->from(TABLE_MODULE)
- ->where('parent')->eq(0)
- ->andWhere('deleted')->eq(0)
- ->andWhere("(root = '" . (int)$rootID . "' AND type = 'task'")
- ->orWhere("root = '" . (int)$productID . "' AND type = 'story')")
- ->orderBy('`order`, type')
- ->fetchAll();
- }
- }
- /**
- * 获取所有子模块的ID列表。
- * Get id list of a module's children.
- *
- * @param int $moduleID
- * @access public
- * @return array
- */
- public function getAllChildId($moduleID)
- {
- if($moduleID == 0) return array();
- $module = $this->getById((int)$moduleID);
- if(empty($module)) return array();
- return $this->dao->select('id')->from(TABLE_MODULE)->where("CONCAT(',', path, ',')")->like("%$module->path%")->andWhere('deleted')->eq(0)->fetchPairs();
- }
- /**
- * 获取一个模块的所有父模块。
- * Get parents of a module.
- *
- * @param int $moduleID
- * @param bool $queryAll
- * @access public
- * @return array
- */
- public function getParents($moduleID, $queryAll = false)
- {
- if($moduleID == 0 || common::isTutorialMode()) return array();
- $path = $this->dao->select('path')->from(TABLE_MODULE)->where('id')->eq((int)$moduleID)->fetch('path');
- $path = trim($path, ',');
- if(!$path) return array();
- return $this->dao->select('*')->from(TABLE_MODULE)
- ->where('id')->in($path)
- ->beginIF(!$queryAll)->andWhere('deleted')->eq(0)->fi()
- ->orderBy('grade')
- ->fetchAll();
- }
- /**
- * 获取一个模块所属的产品。
- * Get product by moduleID.
- *
- * @param int $moduleID
- * @access public
- * @return object|false
- */
- public function getProduct($moduleID)
- {
- if($moduleID == 0) return false;
- $path = $this->dao->select('path')->from(TABLE_MODULE)->where('id')->eq($moduleID)->fetch('path');
- $paths = explode(',', trim($path, ','));
- if(!$path) return false;
- $moduleID = $paths[0];
- $module = $this->dao->select('*')->from(TABLE_MODULE)->where('id')->eq($moduleID)->fetch();
- if($module->type != 'story' || !$module->root) return false;
- return $this->dao->select('id,name')->from(TABLE_PRODUCT)->where('id')->eq($module->root)->fetch();
- }
- /**
- * 获取一个需求模块。
- * Get the module that its type == 'story'.
- *
- * @param int $moduleID
- * @access public
- * @return int
- */
- public function getStoryModule($moduleID)
- {
- $module = $this->dao->select('id,type,parent')->from(TABLE_MODULE)->where('id')->eq((int)$moduleID)->fetch();
- if(empty($module)) return 0;
- while(!empty($module) && $module->id && $module->type != 'story')
- {
- $module = $this->dao->select('id,type,parent')->from(TABLE_MODULE)->where('id')->eq($module->parent)->fetch();
- }
- return empty($module) ? 0 : $module->id;
- }
- /**
- * 获取一些模块的名称。
- * Get modules name.
- *
- * @param array $moduleIdList
- * @param bool $allPath
- * @param bool $branchPath
- * @access public
- * @return array
- */
- public function getModulesName($moduleIdList, $allPath = true, $branchPath = false)
- {
- if(!$allPath) return $this->dao->select('id, name')->from(TABLE_MODULE)->where('id')->in($moduleIdList)->andWhere('deleted')->eq(0)->fetchPairs('id', 'name');
- /* Get modules && submodules through id list. */
- $modules = $this->dao->select('id, name, path, branch')->from(TABLE_MODULE)->where('id')->in($moduleIdList)->andWhere('deleted')->eq(0)->fetchAll('path');
- $allModules = $this->dao->select('id, name')->from(TABLE_MODULE)->where('id')->in(join(array_keys($modules)))->andWhere('deleted')->eq(0)->fetchPairs('id', 'name');
- /* Constructs a key-value pair for the module name:id. */
- $branchIDList = array();
- $modulePairs = array();
- foreach($modules as $module)
- {
- $paths = explode(',', trim($module->path, ','));
- $moduleName = '';
- foreach($paths as $path) $moduleName .= '/' . zget($allModules, $path);
- $modulePairs[$module->id] = $moduleName;
- if($module->branch) $branchIDList[$module->branch] = $module->branch;
- }
- if(!$branchPath) return $modulePairs;
- /* Prefixes the module name with the branch name. */
- $branchs = $this->dao->select('id, name')->from(TABLE_BRANCH)->where('id')->in($branchIDList)->andWhere('deleted')->eq(0)->fetchALL('id');
- foreach($modules as $module)
- {
- if(!isset($modulePairs[$module->id])) continue;
- $branchName = isset($branchs[$module->branch]) ? '/' . $branchs[$module->branch]->name : '';
- $modulePairs[$module->id] = $branchName . $modulePairs[$module->id];
- }
- return $modulePairs;
- }
- /**
- * 更新模块排序。
- * Update modules' order.
- *
- * @param array $orders
- * @access public
- * @return void
- */
- public function updateOrder($orders)
- {
- asort($orders);
- $orderInfo = $this->dao->select('*')->from(TABLE_MODULE)->where('id')->in(array_keys($orders))->andWhere('deleted')->eq(0)->fetchAll('id');
- $newOrders = array();
- foreach(array_keys($orders) as $moduleID)
- {
- $parent = $orderInfo[$moduleID]->parent;
- $grade = $orderInfo[$moduleID]->grade;
- $branch = $orderInfo[$moduleID]->branch;
- if(!isset($newOrders[$parent][$grade][$branch]))
- {
- $newOrders[$parent][$grade][$branch] = 1;
- }
- else
- {
- $newOrders[$parent][$grade][$branch] ++;
- }
- $newOrder = $newOrders[$parent][$grade][$branch] * 10;
- $this->dao->update(TABLE_MODULE)->set('`order`')->eq($newOrder)->where('id')->eq((int)$moduleID)->exec();
- }
- }
- /**
- * 修改模块的所有子模块。
- * Manage childs of a module.
- *
- * @param int $rootID
- * @param string $type
- * @access public
- * @return array|false
- */
- public function manageChild($rootID, $type)
- {
- if($type == 'line') $rootID = 0;
- $data = fixer::input('post')->get();
- $childs = $data->modules;
- $parentModuleID = (int)$data->parentModuleID;
- foreach($childs as $moduleID => $moduleName)
- {
- if(preg_match('/(^\s+$)/', $moduleName))
- {
- dao::$errors['root'] = $this->lang->tree->shouldNotBlank;
- return false;
- }
- }
- $module = new stdClass();
- $module->root = $rootID;
- $module->type = $type;
- $module->parent = $parentModuleID;
- $repeatName = $this->checkUnique($module, $childs);
- if($repeatName)
- {
- dao::$errors['name'] = sprintf($this->lang->tree->repeatName, $repeatName);
- return false;
- }
- $parentModule = $this->getByID($parentModuleID);
- $branches = isset($data->branch) ? $data->branch : array();
- $orders = isset($data->order) ? $data->order : array();
- $shorts = $data->shorts;
- if($parentModule)
- {
- $grade = $parentModule->grade + 1;
- $parentPath = $parentModule->path;
- }
- else
- {
- $grade = 1;
- $parentPath = ',';
- }
- $this->setModuleLang();
- $i = 1;
- $oldModules = $this->getOptionMenu($rootID, 'story', 0, 'all');
- $createIdList = array();
- $editIdList = array();
- foreach($childs as $moduleID => $moduleName)
- {
- if(empty($moduleName)) continue;
- /* The new modules. */
- if(is_numeric($moduleID))
- {
- if(isset($orders[$moduleID]) && !empty($orders[$moduleID]))
- {
- $order = $orders[$moduleID];
- }
- else
- {
- $order = (int)$this->post->maxOrder + $i * 10;
- $i ++;
- }
- $module = new stdClass();
- $module->root = $rootID;
- $module->name = strip_tags(trim($moduleName));
- $module->parent = $parentModuleID;
- $module->branch = isset($branches[$moduleID]) ? $branches[$moduleID] : 0;
- $module->short = $shorts[$moduleID];
- $module->grade = $grade;
- $module->type = $type;
- $module->order = $order;
- $this->dao->insert(TABLE_MODULE)->data($module)->autoCheck()->exec();
- if(dao::isError()) return false;
- $moduleID = $this->dao->lastInsertID();
- $createIdList[] = $moduleID;
- $childPath = $parentPath . "$moduleID,";
- $this->dao->update(TABLE_MODULE)->set('path')->eq($childPath)->where('id')->eq($moduleID)->exec();
- if(dao::isError()) return false;
- }
- else
- {
- $originID = $moduleID;
- $short = $shorts[$moduleID];
- $order = $orders[$moduleID];
- $moduleID = (int)str_replace('id', '', $moduleID);
- $oldModule = $this->getByID($moduleID);
- $data = new stdClass();
- $data->name = strip_tags(trim($moduleName));
- $data->short = $short;
- $data->order = $order;
- $data->branch = isset($branches[$originID]) ? $branches[$originID] : 0;
- $this->dao->update(TABLE_MODULE)->data($data)->autoCheck()->where('id')->eq($moduleID)->exec();
- if(dao::isError()) return false;
- $newModule = $this->getByID($moduleID);
- if(common::createChanges($oldModule, $newModule))
- {
- $editIdList[] = $moduleID;
- $moduleChanges[$moduleID] = common::createChanges($oldModule, $newModule);
- }
- }
- }
- if($type == 'story' || strpos($this->config->tree->groupTypes, ",$type,") !== false)
- {
- $objectType = $type == 'story' ? 'module' : 'chartgroup';
- $this->loadModel('action');
- if(!empty($createIdList)) $actionID = $this->action->create($objectType, $rootID, 'created', '', implode(',', $createIdList));
- if(!empty($editIdList))
- {
- $changes = array();
- $newModules = $this->getOptionMenu($rootID, 'story', 0, 'all');
- foreach($moduleChanges as $moduleID => $moduleChange)
- {
- foreach($moduleChange as $change)
- {
- if($change['field'] == 'name')
- {
- $change['old'] = zget($oldModules, $moduleID);
- $change['new'] = zget($newModules, $moduleID);
- $change['diff'] = '';
- }
- $changes[] = $change;
- }
- }
- $actionID = $this->action->create($objectType, $rootID, 'edited', '', implode(',', $editIdList));
- if(!empty($changes)) $this->action->logHistory($actionID, $changes);
- }
- }
- return $createIdList;
- }
- /**
- * 更新模块信息。
- * Update a module.
- *
- * @param int $moduleID
- * @param string $type
- * @access public
- * @return bool
- */
- public function update($moduleID, $type = '')
- {
- $module = fixer::input('post')->cleanInt('branch')->setDefault('parent', 0)->get();
- $self = $this->getById($moduleID);
- $changes = common::createChanges($self, $module);
- if(!isset($_POST['branch'])) $module->branch = $self->branch;
- if($self)
- {
- if($type == 'ticket' || $type == 'feedback') $module->root = $self->root;
- if($type == 'host' || !isset($module->root)) $module->root = 0;
- if(strpos($this->config->tree->groupTypes, ",$type,") !== false) $module->root = $self->root;
- if($self->root && !$module->root) $module->root = $self->root;
- if($self->parent != $module->parent || $self->root != $module->root)
- {
- $maxOrder = $this->dao->select('MAX(`order`) AS `order`')->from(TABLE_MODULE)->where('parent')->eq($module->parent)->andWhere('root')->eq($module->root)->fetch('order');
- $module->order = $maxOrder ? ++ $maxOrder : $self->order;
- }
- if($module->parent) $self->parent = $module->parent;
- }
- $repeatName = $this->checkUnique($self, array("id{$self->id}" => $module->name), array("id{$self->id}" => $module->branch));
- if($repeatName)
- {
- $tips = in_array($self->type, array('doc', 'api')) ? $this->lang->tree->repeatDirName : $this->lang->tree->repeatName;
- dao::$errors['name'] = sprintf($tips, $repeatName);
- return false;
- }
- if((empty($module->root) || empty($module->name)) && in_array($self->type, array('doc', 'api')))
- {
- $this->app->loadLang('doc');
- if(empty($module->root))
- {
- dao::$errors['root'] = sprintf($this->lang->error->notempty, $this->lang->doc->lib);
- return false;
- }
- if(empty($module->name))
- {
- dao::$errors['name'] = sprintf($this->lang->error->notempty, $this->lang->doc->catalogName);
- return false;
- }
- }
- $module->name = strip_tags(trim($module->name));
- if(empty($module->name))
- {
- dao::$errors['name'] = sprintf($this->lang->error->notempty, $this->lang->tree->name);
- return false;
- }
- $this->setModuleLang();
- $modules = $self->type == 'story' ? $this->getOptionMenu($self->root, 'story', 0, 'all') : array();
- $parent = $this->getById((int)$this->post->parent);
- $childs = $this->getAllChildId($moduleID);
- $module->grade = $parent ? $parent->grade + 1 : 1;
- $module->path = $parent ? $parent->path . $moduleID . ',' : ',' . $moduleID . ',';
- $this->dao->update(TABLE_MODULE)->data($module)->autoCheck()->check('name', 'notempty')->where('id')->eq($moduleID)->exec();
- if(dao::isError()) return false;
- $this->dao->update(TABLE_MODULE)->set('grade = grade + 1')->where('id')->in($childs)->andWhere('id')->ne($moduleID)->exec();
- $this->dao->update(TABLE_MODULE)->set('owner')->eq($this->post->owner)->where('id')->in($childs)->andWhere('owner')->eq('')->exec();
- $this->dao->update(TABLE_MODULE)->set('owner')->eq($this->post->owner)->where('id')->in($childs)->andWhere('owner')->eq($self->owner)->exec();
- if($self->type == 'story' || strpos($this->config->tree->groupTypes, ",$self->type,") !== false)
- {
- $objectType = $self->type == 'story' ? 'module' : 'chartgroup';
- $rootID = isset($module->root) ? (int)$module->root : $self->root;
- $newModules = $this->getOptionMenu($rootID, 'story', 0, 'all');
- foreach($changes as $id => $change)
- {
- if($change['field'] == 'name')
- {
- $changes[$id]['old'] = zget($modules, $moduleID);
- $changes[$id]['new'] = zget($newModules, $moduleID);
- $changes[$id]['diff'] = '';
- break;
- }
- }
- $actionID = $this->loadModel('action')->create($objectType, $self->root, 'edited', '', $moduleID);
- if(!empty($changes)) $this->action->logHistory($actionID, $changes);
- if(isset($module->root) && $module->root != $self->root)
- {
- $actionID = $this->action->create($objectType, $rootID, 'edited', '', $moduleID);
- if(!empty($changes)) $this->action->logHistory($actionID, $changes);
- }
- }
- if(isset($module->root) && $module->root != $self->root)
- {
- $this->dao->update(TABLE_MODULE)->set('root')->eq($module->root)->where('id')->in($childs)->exec();
- $this->dao->update(TABLE_MODULE)->set('branch')->eq($module->branch)->where('id')->in($childs)->exec();
- if($self->type == 'doc')
- {
- $this->dao->update(TABLE_DOC)->set('`lib`')->eq($module->root)
- ->where('module')->eq($moduleID)
- ->orWhere('module')->in($childs)
- ->exec();
- }
- }
- $this->fixModulePath(isset($module->root) ? (int)$module->root : $self->root, $self->type);
- if(isset($module->root) && $module->root != $self->root) $this->changeRoot($moduleID, $self->root, (int)$module->root, $self->type);
- return true;
- }
- /**
- * 修改模块下关联事项的root,注意: 修改module本身的root不在该逻辑中。
- * Change root of items in the module.
- *
- * @param int $moduleID
- * @param int $oldRoot
- * @param int $newRoot
- * @param string $type
- * @access public
- * @return void
- */
- public function changeRoot($moduleID, $oldRoot, $newRoot, $type)
- {
- /* Get all children id list. */
- $childIdList = $this->dao->select('id')->from(TABLE_MODULE)->where('path')->like("%,$moduleID,%")->andWhere('deleted')->eq(0)->fetchPairs('id');
- /* Update product field for stories, bugs, cases under this module. */
- $this->dao->update(TABLE_STORY)->set('product')->eq($newRoot)->where('module')->in($childIdList)->exec();
- $this->dao->update(TABLE_BUG)->set('product')->eq($newRoot)->where('module')->in($childIdList)->exec();
- $this->dao->update(TABLE_CASE)->set('product')->eq($newRoot)->where('module')->in($childIdList)->exec();
- $this->dao->update(TABLE_DOC)->set('lib')->eq($newRoot)->where('module')->in($childIdList)->exec();
- if($type != 'story') return;
- /* If the type if story, check it's releated projects. */
- $projectStories = $this->dao->select('DISTINCT t1.id,t1.version,t2.project')
- ->from(TABLE_STORY)->alias('t1')
- ->leftJoin(TABLE_PROJECTSTORY)->alias('t2')->on('t1.id=t2.story')
- ->where('t1.module')->in($childIdList)
- ->andWhere('t2.product')->eq($oldRoot)
- ->fetchAll('id');
- $executions = array();
- foreach($projectStories as $story)
- {
- $this->dao->update(TABLE_PROJECTSTORY)
- ->set('product')->eq($newRoot)
- ->where('project')->eq($story->project)
- ->andWhere('story')->eq($story->id)
- ->andWhere('version')->eq($story->version)
- ->exec();
- $executions[$story->project] = $story->project;
- }
- if($executions)
- {
- $projectProduct = $this->dao->select('*')->from(TABLE_PROJECTPRODUCT)->where('project')->in($executions)->fetchGroup('project', 'product');
- $linkedProduct = $this->dao->select('DISTINCT project,product')->from(TABLE_PROJECTSTORY)->where('project')->in($executions)->fetchGroup('project', 'product');
- foreach($executions as $executionID)
- {
- if(!isset($projectProduct[$executionID]) || !in_array($newRoot, array_keys($projectProduct[$executionID]))) $this->dao->insert(TABLE_PROJECTPRODUCT)->set('project')->eq($executionID)->set('product')->eq($newRoot)->exec();
- if(isset($linkedProduct[$executionID]) && !in_array($oldRoot, array_keys($linkedProduct[$executionID])))
- {
- $this->dao->delete()->from(TABLE_PROJECTPRODUCT)->where('project')->eq($project)->andWhere('product')->eq($oldRoot)->exec();
- $this->dao->update(TABLE_BUILD)->set('product')->eq($newRoot)->where('product')->eq($oldRoot)->andWhere('execution')->eq($executionID)->exec();
- }
- }
- }
- }
- /**
- * 删除一个模块。
- * Delete a module.
- *
- * @param int $moduleID
- * @access public
- * @return bool
- */
- public function remove($moduleID)
- {
- $module = $this->getById($moduleID);
- if(empty($module)) return false;
- if($module->type == 'doc')
- {
- $childs = array();
- }
- else
- {
- $childs = $this->getAllChildId($moduleID);
- }
- $childs[$moduleID] = $moduleID;
- $objectType = (!empty($module->type) && strpos($this->config->tree->groupTypes, ",$module->type,") !== false) ? 'chartgroup' : 'module';
- /* Mark deletion when delete a module. */
- $this->dao->update(TABLE_MODULE)->set('deleted')->eq(1)->where('id')->in($childs)->exec();
- if($module->type != 'deliverable')
- {
- foreach($childs as $childID) $this->loadModel('action')->create($objectType, $childID, 'deleted', '', actionModel::CAN_UNDELETED);
- }
- $this->fixModulePath($module->root, $module->type);
- $cookieName = '';
- switch ($module->type)
- {
- case 'line':
- $this->dao->update(TABLE_PRODUCT)->set('line')->eq('0')->where('line')->eq($moduleID)->exec();
- break;
- case 'task':
- $this->dao->update(TABLE_TASK)->set('module')->eq($module->parent)->where('module')->in($childs)->exec();
- $cookieName = 'moduleBrowseParam';
- break;
- case 'bug':
- $this->dao->update(TABLE_BUG)->set('module')->eq($module->parent)->where('module')->in($childs)->exec();
- $cookieName = 'bugModule';
- break;
- case 'case':
- $this->dao->update(TABLE_CASE)->set('module')->eq($module->parent)->where('module')->in($childs)->exec();
- $cookieName = 'caseModule';
- break;
- case 'story':
- $this->dao->update(TABLE_STORY)->set('module')->eq($module->parent)->where('module')->in($childs)->exec();
- $this->dao->update(TABLE_TASK)->set('module')->eq($module->parent)->where('module')->in($childs)->exec();
- $this->dao->update(TABLE_BUG)->set('module')->eq($module->parent)->where('module')->in($childs)->exec();
- $this->dao->update(TABLE_CASE)->set('module')->eq($module->parent)->where('module')->in($childs)->exec();
- $this->dao->update(TABLE_FEEDBACK)->set('module')->eq($module->parent)->where('module')->in($childs)->exec();
- $this->dao->update(TABLE_TICKET)->set('module')->eq($module->parent)->where('module')->in($childs)->exec();
- $cookieName = 'storyModule';
- break;
- case 'chart':
- $this->dao->update(TABLE_CHART)->set('`group`')->eq($module->parent)->where('`group`')->in($childs)->exec();
- break;
- case 'report':
- $this->dao->update(TABLE_REPORT)->set('`module`')->eq($module->parent)->where('`module`')->in($childs)->exec();
- break;
- case 'dataview':
- $this->dao->update(TABLE_DATAVIEW)->set('`group`')->eq($module->parent)->where('`group`')->in($childs)->exec();
- break;
- case 'feedback':
- $this->dao->update(TABLE_FEEDBACK)->set('module')->eq($module->parent)->where('module')->in($childs)->exec();
- $cookieName = 'feedbackModule';
- break;
- case 'ticket':
- $this->dao->update(TABLE_TICKET)->set('module')->eq($module->parent)->where('module')->in($childs)->exec();
- $cookieName = 'ticketModule';
- break;
- }
- $sessionValue = $this->session->{$module->type . 'List'};
- if($sessionValue && strpos($sessionValue, 'param=' . $moduleID)) $this->session->set($module->type . 'List', str_replace('param=' . $moduleID, 'param=0', $sessionValue));
- if($cookieName) helper::setcookie($cookieName, 0, time() - 3600, $this->config->webRoot, '', $this->config->cookieSecure, true);
- return true;
- }
- /**
- * 修复模块的Path和Grade。
- * Fix the path, grade fields according to the id && parent fields.
- *
- * @param int $rootID
- * @param string $type
- * @access public
- * @return void
- */
- public function fixModulePath($rootID, $type)
- {
- /* Get all modules grouped by parent. */
- if($type == 'bug' || $type == 'case') $type = 'story,' . $type;
- $groupModules = $this->dao->select('id, parent, branch')->from(TABLE_MODULE)->where('root')->eq($rootID)->andWhere('type')->in($type)->andWhere('deleted')->eq(0)->fetchGroup('parent', 'id');
- $modules = array();
- /* Cycle the groupModules until it has no item any more. */
- while(count($groupModules) > 0)
- {
- $oldCounts = count($groupModules); // Record the counts before processing.
- foreach($groupModules as $parentModuleID => $childModules)
- {
- /* If the parentModule doesn't exsit in the modules, skip it. If exists, compute it's child modules. */
- if(!isset($modules[$parentModuleID]) && $parentModuleID != 0) continue;
- if($parentModuleID == 0)
- {
- $parentModule = new stdclass();
- $parentModule->grade = 0;
- $parentModule->path = ',';
- }
- else
- {
- $parentModule = $modules[$parentModuleID];
- }
- /* Compute it's child modules. */
- foreach($childModules as $childModuleID => $childModule)
- {
- $childModule->grade = $parentModule->grade + 1;
- $childModule->path = $parentModule->path . $childModule->id . ',';
- if(isset($parentModule->branch))$childModule->branch = $parentModule->branch;
- $modules[$childModuleID] = $childModule; // Save child module to modules, thus the child of child can compute it's grade && path.
- }
- unset($groupModules[$parentModuleID]); // Remove it from the groupModules.
- }
- if(count($groupModules) == $oldCounts) break; // If after processing, no module processed, break the cycle.
- }
- /* Save modules to database. */
- foreach($modules as $module) $this->dao->update(TABLE_MODULE)->data($module)->where('id')->eq($module->id)->exec();
- }
- /**
- * 检查模块是否重名。
- * Check unique module name.
- *
- * @param object $module 检查范围,包括root,type,parent
- * @param array $modules
- * @param array $branches 检查范围
- * @access public
- * @return string|false
- */
- public function checkUnique($module, $modules = array(), $branches = array())
- {
- if(empty($branches)) $branches = $this->post->branch;
- if(empty($branches) && isset($module->branch)) $branches = array($module->branch);
- if(empty($branches)) $branches = array(0);
- /* If no modules to check, check the name of module. */
- if(empty($modules) && isset($module->name)) $modules = array($module->name);
- $branches = array_unique($branches);
- $rootID = $module->root;
- $viewType = $module->type;
- $parentModuleID = $module->parent;
- if($this->isMergeModule($rootID, $viewType) && $viewType != 'task') $viewType .= ',story';
- $existsModules = $this->dao->select('id,branch,name')->from(TABLE_MODULE)->where('root')->eq($rootID)->andWhere('type')->in($viewType)->andWhere('parent')->eq($parentModuleID)->andWhere('branch')->in($branches)->andWhere('deleted')->eq(0)->fetchAll();
- $checkedModules = ',';
- $repeatName = '';
- foreach($modules as $id => $name)
- {
- $existed = false;
- if(!is_numeric($id) && strpos($id, 'id') === 0)
- {
- $existed = true;
- $moduleID = substr($id, 2);
- }
- if(strpos($checkedModules, ",$name,") !== false) return $name;
- foreach($existsModules as $existsModule)
- {
- if($name == $existsModule->name && (!$existed || $moduleID != $existsModule->id) && (!isset($branches[$id]) || $branches[$id] == $existsModule->branch)) return $name;
- }
- $checkedModules .= "$name,";
- }
- return false;
- }
- /**
- * 检查是否是已合并模块。4.1后task,case,bug也会使用story的模块。
- * Check merge module version.
- *
- * @param int|array $rootID
- * @param string $viewType
- * @access public
- * @return bool
- */
- public function isMergeModule($rootID, $viewType)
- {
- if(!in_array($viewType, array('bug', 'case', 'task'))) return false;
- /* Get createdVersion. */
- $table = $viewType == 'task' ? TABLE_PROJECT : TABLE_PRODUCT;
- $versionField = $viewType == 'task' ? 'openedVersion' : 'createdVersion';
- $createdVersion = $this->dao->select($versionField)->from($table)->where('id')->in($rootID)->fetch($versionField);
- if(!$createdVersion) return true;
- if(is_numeric($createdVersion[0]) && version_compare($createdVersion, '4.1', '<=')) return false;
- return true;
- }
- /**
- * 获取产品的模块树。
- * Get full trees.
- *
- * @param int $rootID
- * @param string $viewType
- * @param string $branchID
- * @param int $currentModuleID
- * @access public
- * @return array
- */
- public function getProductStructure($rootID, $viewType, $branchID = 'all', $currentModuleID = 0)
- {
- if(common::isTutorialMode()) return array();
- if($viewType == 'line') $rootID = 0;
- $stmt = $this->app->dbQuery($this->buildMenuQuery($rootID, $viewType, $currentModuleID, $branchID));
- $trees = $this->getDataStructure($stmt, $viewType, $rootID, array(), $branchID);
- return $trees;
- }
- /**
- * 获取模块树。
- * Get full modules tree.
- *
- * @param object $stmt
- * @param string $viewType
- * @param int $rootID
- * @param array $keepModules
- * @param string $branch
- * @access public
- * @return array
- */
- public function getDataStructure($stmt, $viewType, $rootID, $keepModules = array(), $branch = 'all')
- {
- $parent = array();
- /* If feedback || ticket module is merge add story module.*/
- $syncConfig = $this->getSyncConfig($viewType);
- while($module = $stmt->fetch())
- {
- /* If is feedback || ticket filter story module by grade.*/
- if(($viewType == 'feedback' || $viewType == 'ticket') && $module->type == 'story')
- {
- if(isset($syncConfig[$module->root]) && $module->grade > $syncConfig[$module->root]) continue;
- }
- /* Ignore useless module for task. */
- $allModule = (isset($this->config->execution->task->allModule) && ($this->config->execution->task->allModule == 1));
- if($keepModules && !isset($keepModules[$module->id]) && !$allModule) continue;
- if($viewType == 'task' && empty($keepModules) && !$allModule) continue;
- if(isset($parent[$module->id]))
- {
- $module->children = $parent[$module->id]->children;
- unset($parent[$module->id]);
- }
- if(!isset($parent[$module->parent])) $parent[$module->parent] = new stdclass();
- if($viewType == 'task')
- {
- $module->url = helper::createLink('tree', 'browsetask', "rootID=$rootID&productID=0&moduleID=$module->id");
- }
- else if(in_array($viewType, array('pivot', 'chart')))
- {
- $module->url = helper::createLink('tree', 'browsegroup', "dimensionID=$rootID&groupID=$module->id&type=$viewType");
- }
- else
- {
- $module->url = helper::createLink('tree', 'browse', "rootID=$rootID&view=$viewType¤tModuleID=$module->id&branchID=$branch");
- }
- $parent[$module->parent]->children[] = $module;
- }
- if($viewType == 'task') $parentTypePairs = $this->dao->select('id,type')->from(TABLE_MODULE)->where('id')->in(array_keys($parent))->andWhere('deleted')->eq(0)->fetchPairs('id', 'type');
- $tree = array();
- foreach($parent as $module)
- {
- foreach($module->children as $item)
- {
- if($viewType == 'task' && isset($parentTypePairs[$item->parent]) && $parentTypePairs[$item->parent] != 'task') continue;
- if($item->parent != 0) continue; // Filter project children modules.
- $tree[] = $item;
- }
- }
- return $tree;
- }
- /**
- * 获取文档模块树。
- * Get all doc structure.
- *
- * @access public
- * @return array
- */
- public function getDocStructure()
- {
- $stmt = $this->app->dbQuery($this->dao->select('*')->from(TABLE_MODULE)->where('type')->eq('doc')->andWhere('deleted')->eq(0)->orderBy('`grade`_desc, `order`')->get());
- $parent = array();
- while($module = $stmt->fetch())
- {
- if(!isset($parent[$module->root])) $parent[$module->root] = array();
- if(isset($parent[$module->root][$module->id]))
- {
- $module->children = $parent[$module->root][$module->id]->children;
- unset($parent[$module->root][$module->id]);
- }
- if(!isset($parent[$module->root][$module->parent])) $parent[$module->root][$module->parent] = new stdclass();
- $parent[$module->root][$module->parent]->children[] = $module;
- }
- $tree = array();
- foreach($parent as $root => $modules)
- {
- foreach($modules as $module)
- {
- foreach($module->children as $children)
- {
- if($children->parent != 0 && !empty($tree[$root]))
- {
- foreach($tree[$root] as $firstChildren)
- {
- if($firstChildren->id == $children->parent) $firstChildren->children[] = $children;
- }
- }
- $tree[$root][] = $children;
- }
- }
- }
- return $tree;
- }
- /**
- * 获取反馈和工单是否已跟产品同步的信息。
- * Get syncProduct module config.
- *
- * @param string $type feedback|ticket
- * @access public
- * @return array
- */
- public function getSyncConfig($type = '')
- {
- if(!isset($this->config->global->syncProduct)) return array();
- /* If feedback or ticket module is merge add story module.*/
- $syncConfig = json_decode($this->config->global->syncProduct, true);
- $syncConfig = isset($syncConfig[$type]) ? $syncConfig[$type] : array();
- return $syncConfig;
- }
- /**
- * 加载模块的语言项。
- * Load module language.
- *
- * @access public
- * @return void
- */
- public function setModuleLang()
- {
- $this->lang->module = new stdclass();
- $this->lang->module->name = $this->lang->tree->wordName;
- $this->lang->module->short = $this->lang->tree->short;
- }
- /**
- * 创建模块。
- * Create module.
- *
- * @access public
- * @return object|false
- */
- public function createModule()
- {
- $data = fixer::input('post')
- ->setDefault('name', '')
- ->setDefault('createType', 'child')
- ->setDefault('objectID', 0)
- ->setDefault('order', 10)
- ->cleanInt('libID,parentID,objectID')
- ->get();
- $module = new stdClass();
- $module->root = zget($data, 'libID', 0);
- $module->type = zget($data, 'moduleType', 'doc');
- $module->parent = zget($data, 'parentID', 0);
- $module->name = strip_tags(trim($data->name));
- $module->branch = 0;
- $module->short = '';
- $module->order = $data->order;
- if(empty($module->name))
- {
- dao::$errors[] = sprintf($this->lang->error->notempty, $this->lang->tree->dir);
- return false;
- }
- if($data->createType == 'same')
- {
- $baseModule = $this->getByID($data->objectID);
- if(!empty($baseModule))
- {
- $module->parent = $baseModule->parent;
- $module->order = $baseModule->order;
- }
- }
- elseif($data->createType == 'child')
- {
- $maxOrder = $this->dao->select('`order`')->from(TABLE_MODULE)
- ->where('root')->eq($module->root)
- ->andWhere('parent')->eq($module->parent)
- ->andWhere('type')->eq($module->type)
- ->orderBy('order_desc')
- ->limit(1)
- ->fetch('order');
- $module->order = (int)$maxOrder + 10;
- }
- $repeatName = $this->checkUnique($module);
- if($repeatName)
- {
- dao::$errors[] = sprintf($this->lang->tree->repeatDirName, $repeatName);
- return false;
- }
- $parent = $this->getByID($module->parent);
- $module->grade = $module->parent ? $parent->grade + 1 : 1;
- $this->dao->insert(TABLE_MODULE)->data($module)->exec();
- $moduleID = $this->dao->lastInsertID();
- if($data->createType == 'same')
- {
- $this->dao->update(TABLE_MODULE)
- ->set('`order` = `order` + 10')
- ->where('`root`')->eq($module->root)
- ->andWhere('`parent`')->eq($module->parent)
- ->andWhere('`type`')->eq($module->type)
- ->andWhere('`order`')->gt($module->order)
- ->exec();
- $module->order += 10;
- }
- $modulePath = "$moduleID,";
- if($module->parent) $modulePath = $parent->path . $modulePath;
- $this->dao->update(TABLE_MODULE)->set('`path`')->eq($modulePath)->set('`order`')->eq($module->order)->where('id')->eq($moduleID)->exec();
- return $this->getByID($moduleID);
- }
- /**
- * 获取分组模块对列表。
- * Get group pairs.
- *
- * @param int $dimensionID
- * @param int $parentGroup
- * @param int $grade
- * @param string $type
- * @access public
- * @return array
- */
- public function getGroupPairs($dimensionID = 0, $parentGroup = 0, $grade = 2, $type = 'chart')
- {
- $groups = $this->dao->select('id,name,grade,parent')->from(TABLE_MODULE)
- ->where('root')->eq($dimensionID)
- ->beginIF(!empty($parentGroup))->andWhere('root')->eq($dimensionID)->fi()
- ->andWhere('type')->eq($type)
- ->andWhere('deleted')->eq(0)
- ->orderBy('order')
- ->fetchGroup('grade', 'id');
- $groupPairs = array();
- if(!empty($groups[1]))
- {
- foreach($groups[1] as $parentGroup)
- {
- if($grade == 1) $groupPairs[$parentGroup->id] = $parentGroup->name;
- if($grade == 2 && !empty($groups[2]))
- {
- foreach($groups[2] as $childGroup)
- {
- if($parentGroup->id == $childGroup->parent) $groupPairs[$childGroup->id] = '/' . $parentGroup->name . '/' . $childGroup->name;
- }
- }
- }
- }
- return $groupPairs;
- }
- }
|