diff --git a/config/config.php b/config/config.php index f8a7993985..fef6e3bc31 100644 --- a/config/config.php +++ b/config/config.php @@ -130,6 +130,7 @@ define('TABLE_TESTRESULT', '`' . $config->db->prefix . 'testresult`'); define('TABLE_USERTPL', '`' . $config->db->prefix . 'usertpl`'); define('TABLE_PRODUCT', '`' . $config->db->prefix . 'product`'); +define('TABLE_BRANCH', '`' . $config->db->prefix . 'branch`'); define('TABLE_STORY', '`' . $config->db->prefix . 'story`'); define('TABLE_STORYSPEC', '`' . $config->db->prefix . 'storyspec`'); define('TABLE_PRODUCTPLAN', '`' . $config->db->prefix . 'productplan`'); diff --git a/db/update7.3.sql b/db/update7.3.sql index e99585ea65..9c80ac0ff4 100644 --- a/db/update7.3.sql +++ b/db/update7.3.sql @@ -1,3 +1,20 @@ ALTER TABLE `zt_action` CHANGE `extra` `extra` text COLLATE 'utf8_general_ci' NOT NULL AFTER `comment`; ALTER TABLE `zt_release` ADD `leftBugs` text COLLATE 'utf8_general_ci' NOT NULL AFTER `bugs`; ALTER TABLE `zt_release` ADD `status` varchar(20) COLLATE 'utf8_general_ci' NOT NULL DEFAULT 'normal' AFTER `desc`; +ALTER TABLE `zt_product` ADD `type` varchar(30) COLLATE 'utf8_general_ci' NOT NULL DEFAULT 'normal' AFTER `code`; + +ALTER TABLE `zt_projectproduct` ADD `branch` mediumint(8) unsigned NOT NULL; +ALTER TABLE `zt_productplan` ADD `branch` mediumint(8) unsigned NOT NULL AFTER `product`; +ALTER TABLE `zt_build` ADD `branch` mediumint(8) unsigned NOT NULL AFTER `product`; +ALTER TABLE `zt_release` ADD `branch` mediumint(8) unsigned NOT NULL AFTER `product`; +ALTER TABLE `zt_bug` ADD `branch` mediumint(8) unsigned NOT NULL AFTER `product`; +ALTER TABLE `zt_case` ADD `branch` mediumint(8) unsigned NOT NULL AFTER `product`; +ALTER TABLE `zt_module` ADD `branch` varchar(50) COLLATE 'utf8_general_ci' unsigned NOT NULL AFTER `root`; +ALTER TABLE `zt_story` ADD `branch` varchar(50) COLLATE 'utf8_general_ci' NOT NULL AFTER `product`; + +CREATE TABLE `zt_branch` ( + `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT PRIMARY KEY, + `product` mediumint unsigned NOT NULL, + `name` varchar(255) COLLATE 'utf8_general_ci' NOT NULL, + `deleted` enum('0','1') COLLATE 'utf8_general_ci' NOT NULL DEFAULT '0' +); diff --git a/module/branch/control.php b/module/branch/control.php new file mode 100644 index 0000000000..1e105daac2 --- /dev/null +++ b/module/branch/control.php @@ -0,0 +1,60 @@ + + * @package branch + * @version $Id$ + * @link http://www.zentao.net + */ +class branch extends control +{ + public function manage($productID) + { + if($_POST) + { + $this->branch->manage($productID); + die(js::reload('parent')); + } + $this->view->title = $this->lang->branch->manage; + $this->view->position[] = $this->lang->branch->manage; + + $this->loadModel('product')->setMenu($this->product->getPairs('nocode'), $productID); + + $this->view->product = $this->product->getById($productID); + $this->view->branches = $this->branch->getPairs($productID, 'noempty'); + $this->display(); + } + + public function ajaxGetDropMenu($productID, $module, $method, $extra) + { + $this->view->link = $this->loadModel('product')->getProductLink($module, $method, $extra, true); + $this->view->productID = $productID; + $this->view->module = $module; + $this->view->method = $method; + $this->view->extra = $extra; + $this->view->branches = $this->branch->getPairs($productID); + $this->display(); + } + + public function ajaxGetMatchedItems($keywords, $module, $method, $extra, $objectID) + { + $this->view->link = $this->loadModel('product')->getProductLink($module, $method, $extra, true); + $this->view->branches = $this->dao->select('*')->from(TABLE_BRANCH)->where('deleted')->eq(0)->andWhere('product')->eq($objectID)->andWhere('name')->like("%$keywords%")->orderBy('id desc')->fetchPairs('id', 'name'); + $this->view->productID = $objectID; + $this->view->keywords = $keywords; + $this->display(); + } + + public function ajaxGetBranches($productID) + { + $product = $this->loadModel('product')->getById($productID); + if($product->type == 'normal') die(); + + $branches = $this->branch->getPairs($productID); + die(html::select('branch[]', $branches, '', "class='form-control'")); + } +} + diff --git a/module/branch/lang/zh-cn.php b/module/branch/lang/zh-cn.php new file mode 100644 index 0000000000..180dd612a0 --- /dev/null +++ b/module/branch/lang/zh-cn.php @@ -0,0 +1,4 @@ +branch->manage = '分支管理'; + +$lang->branch->all = '所有'; diff --git a/module/branch/model.php b/module/branch/model.php new file mode 100644 index 0000000000..08d6c74f04 --- /dev/null +++ b/module/branch/model.php @@ -0,0 +1,41 @@ + + * @package branch + * @version $Id$ + * @link http://www.zentao.net + */ +class branchModel extends model +{ + public function getPairs($productID, $params = '') + { + $branches = $this->dao->select('*')->from(TABLE_BRANCH)->where('product')->eq($productID)->andWhere('deleted')->eq(0)->orderBy('id_desc')->fetchPairs('id', 'name'); + if(strpos($params, 'noempty') === false) $branches = array('0' => $this->lang->branch->all) + $branches; + return $branches; + } + + public function manage($productID) + { + $oldBranches = $this->getPairs($productID, 'noempty'); + $data = fixer::input('post')->get(); + if(isset($data->branch)) + { + foreach($data->branch as $branchID => $branch) + { + if($oldBranches[$branchID] != $branch) $this->dao->update(TABLE_BRANCH)->set('name')->eq($branch)->where('id')->eq($branchID)->exec(); + } + } + foreach($data->newbranch as $branch) + { + if(empty($branch)) continue; + $this->dao->insert(TABLE_BRANCH)->set('name')->eq($branch)->set('product')->eq($productID)->exec(); + } + + return dao::isError(); + } +} + diff --git a/module/branch/view/ajaxgetdropmenu.html.php b/module/branch/view/ajaxgetdropmenu.html.php new file mode 100644 index 0000000000..8a270cd345 --- /dev/null +++ b/module/branch/view/ajaxgetdropmenu.html.php @@ -0,0 +1,17 @@ + + + + +search->common;?>'/> +
2、如果文件名可以开头含有 数字+下划线,以方便排序,程序会将他们忽略。
diff --git a/module/file/model.php b/module/file/model.php index 5956bb2460..3cb1d13679 100644 --- a/module/file/model.php +++ b/module/file/model.php @@ -403,8 +403,14 @@ class fileModel extends model if(is_dir($filePath)) $classFile->removeDir($filePath); $this->app->loadClass('pclzip', true); - $zip = new pclzip($zipFile); + $zip = new pclzip($zipFile); $files = $zip->listContent(); + foreach($files as $uploadFile) + { + $extension = substr(strrchr($uploadFile['filename'], '.'), 1); + if(empty($extension) or strpos($this->config->file->dangers, $extension) !== false) return false; + } + if($zip->extract(PCLZIP_OPT_PATH, $filePath) == 0) return false; return $filePath; } diff --git a/module/product/config.php b/module/product/config.php index 2c7c88ff47..75877e96da 100644 --- a/module/product/config.php +++ b/module/product/config.php @@ -13,6 +13,7 @@ $config->product->search['fields']['status'] = $lang->story->status; $config->product->search['fields']['pri'] = $lang->story->pri; $config->product->search['fields']['product'] = $lang->story->product; +$config->product->search['fields']['branch'] = $lang->story->branch; $config->product->search['fields']['module'] = $lang->story->module; $config->product->search['fields']['plan'] = $lang->story->plan; $config->product->search['fields']['estimate'] = $lang->story->estimate; @@ -44,6 +45,7 @@ $config->product->search['params']['stage'] = array('operator' => '=', $config->product->search['params']['pri'] = array('operator' => '=', 'control' => 'select', 'values' => $lang->story->priList); $config->product->search['params']['product'] = array('operator' => '=', 'control' => 'select', 'values' => ''); +$config->product->search['params']['branch'] = array('operator' => '=', 'control' => 'select', 'values' => ''); $config->product->search['params']['module'] = array('operator' => 'belong', 'control' => 'select', 'values' => ''); $config->product->search['params']['plan'] = array('operator' => '=', 'control' => 'select', 'values' => ''); $config->product->search['params']['estimate'] = array('operator' => '=', 'control' => 'input', 'values' => ''); diff --git a/module/product/control.php b/module/product/control.php index eddbee8c29..46633adb86 100644 --- a/module/product/control.php +++ b/module/product/control.php @@ -79,9 +79,9 @@ class product extends control * @access public * @return void */ - public function project($status = 'all', $productID = 0) + public function project($status = 'all', $productID = 0, $branch = 0) { - $this->product->setMenu($this->products, $productID); + $this->product->setMenu($this->products, $productID, $branch); $this->app->loadLang('my'); $this->view->projectStats = $this->loadModel('project')->getProjectStats($status, $productID); @@ -106,7 +106,7 @@ class product extends control * @access public * @return void */ - public function browse($productID = 0, $browseType = 'unclosed', $param = 0, $orderBy = '', $recTotal = 0, $recPerPage = 20, $pageID = 1) + public function browse($productID = 0, $branch = '', $browseType = 'unclosed', $param = 0, $orderBy = '', $recTotal = 0, $recPerPage = 20, $pageID = 1) { /* Lower browse type. */ $browseType = strtolower($browseType); @@ -117,11 +117,13 @@ class product extends control /* Set product, module and query. */ $productID = $this->product->saveState($productID, $this->products); + $product = $this->product->getById($productID); + if($branch === '') $branch = $this->session->branch; $moduleID = ($browseType == 'bymodule') ? (int)$param : 0; $queryID = ($browseType == 'bysearch') ? (int)$param : 0; /* Set menu. */ - $this->product->setMenu($this->products, $productID); + $this->product->setMenu($this->products, $productID, $branch); /* Process the order by field. */ if(!$orderBy) $orderBy = $this->cookie->productStoryOrder ? $this->cookie->productStoryOrder : 'id_desc'; @@ -146,37 +148,46 @@ class product extends control { $unclosedStatus = $this->lang->story->statusList; unset($unclosedStatus['closed']); - $stories = $this->story->getProductStories($productID, 0, array_keys($unclosedStatus), $sort, $pager); + $stories = $this->story->getProductStories($productID, $branch, 0, array_keys($unclosedStatus), $sort, $pager); } - if($browseType == 'allstory') $stories = $this->story->getProductStories($productID, 0, 'all', $sort, $pager); - if($browseType == 'bymodule') $stories = $this->story->getProductStories($productID, $this->tree->getAllChildID($moduleID), 'all', $sort, $pager); + if($browseType == 'allstory') $stories = $this->story->getProductStories($productID, $branch, 0, 'all', $sort, $pager); + if($browseType == 'bymodule') $stories = $this->story->getProductStories($productID, $branch, $this->tree->getAllChildID($moduleID), 'all', $sort, $pager); if($browseType == 'bysearch') $stories = $this->story->getBySearch($productID, $queryID, $sort, $pager); - if($browseType == 'assignedtome')$stories = $this->story->getByAssignedTo($productID, $this->app->user->account, $sort, $pager); - if($browseType == 'openedbyme') $stories = $this->story->getByOpenedBy($productID, $this->app->user->account, $sort, $pager); - if($browseType == 'reviewedbyme')$stories = $this->story->getByReviewedBy($productID, $this->app->user->account, $sort, $pager); - if($browseType == 'closedbyme') $stories = $this->story->getByClosedBy($productID, $this->app->user->account, $sort, $pager); - if($browseType == 'draftstory') $stories = $this->story->getByStatus($productID, 'draft', $sort, $pager); - if($browseType == 'activestory') $stories = $this->story->getByStatus($productID, 'active', $sort, $pager); - if($browseType == 'changedstory')$stories = $this->story->getByStatus($productID, 'changed', $sort, $pager); - if($browseType == 'willclose') $stories = $this->story->getWillClose($productID, $sort, $pager); - if($browseType == 'closedstory') $stories = $this->story->getByStatus($productID, 'closed', $sort, $pager); + if($browseType == 'assignedtome')$stories = $this->story->getByAssignedTo($productID, $branch, $this->app->user->account, $sort, $pager); + if($browseType == 'openedbyme') $stories = $this->story->getByOpenedBy($productID, $branch, $this->app->user->account, $sort, $pager); + if($browseType == 'reviewedbyme')$stories = $this->story->getByReviewedBy($productID, $branch, $this->app->user->account, $sort, $pager); + if($browseType == 'closedbyme') $stories = $this->story->getByClosedBy($productID, $branch, $this->app->user->account, $sort, $pager); + if($browseType == 'draftstory') $stories = $this->story->getByStatus($productID, $branch, 'draft', $sort, $pager); + if($browseType == 'activestory') $stories = $this->story->getByStatus($productID, $branch, 'active', $sort, $pager); + if($browseType == 'changedstory')$stories = $this->story->getByStatus($productID, $branch, 'changed', $sort, $pager); + if($browseType == 'willclose') $stories = $this->story->getWillClose($productID, $branch, $sort, $pager); + if($browseType == 'closedstory') $stories = $this->story->getByStatus($productID, $branch, 'closed', $sort, $pager); /* Process the sql, get the conditon partion, save it to session. */ $this->loadModel('common')->saveQueryCondition($this->dao->get(), 'story'); /* Build search form. */ - $this->config->product->search['actionURL'] = $this->createLink('product', 'browse', "productID=$productID&browseType=bySearch&queryID=myQueryID"); + $this->config->product->search['actionURL'] = $this->createLink('product', 'browse', "productID=$productID&branch=$branch&browseType=bySearch&queryID=myQueryID"); $this->config->product->search['queryID'] = $queryID; $this->config->product->search['params']['plan']['values'] = $this->loadModel('productplan')->getPairs($productID); $this->config->product->search['params']['product']['values'] = array($productID => $this->products[$productID], 'all' => $this->lang->product->allProduct); $this->config->product->search['params']['module']['values'] = $this->tree->getOptionMenu($productID, $viewType = 'story', $startModuleID = 0); + if($product->type == 'normal') + { + unset($this->config->product->search['fields']['branch']); + unset($this->config->product->search['params']['branch']); + } + else + { + $this->config->product->search['params']['branch']['values'] = array('' => '') + $this->loadModel('branch')->getPairs($productID, 'noempty'); + } $this->loadModel('search')->setSearchParams($this->config->product->search); $this->view->productID = $productID; $this->view->productName = $this->products[$productID]; $this->view->moduleID = $moduleID; $this->view->stories = $stories; - $this->view->plans = $this->loadModel('productplan')->getPairs($productID); + $this->view->plans = $this->loadModel('productplan')->getPairs($productID, $branch); $this->view->summary = $this->product->summary($stories); $this->view->moduleTree = $this->tree->getTreeMenu($productID, $viewType = 'story', $startModuleID = 0, array('treeModel', 'createStoryLink')); $this->view->parentModules = $this->tree->getParents($moduleID); @@ -185,6 +196,7 @@ class product extends control $this->view->orderBy = $orderBy; $this->view->browseType = $browseType; $this->view->moduleID = $moduleID; + $this->view->branch = $branch; $this->display(); } @@ -505,14 +517,14 @@ class product extends control * @access public * @return void */ - public function ajaxGetPlans($productID, $planID = 0, $needCreate = false) + public function ajaxGetPlans($productID, $branch = 0, $planID = 0, $needCreate = false) { - $plans = $this->loadModel('productplan')->getPairs($productID); + $plans = $this->loadModel('productplan')->getPairs($productID, $branch); $output = html::select('plan', $plans, $planID, "class='form-control chosen'"); if(count($plans) == 1 and $needCreate) { $output .= ""; - $output .= html::a($this->createLink('productplan', 'create', "productID=$productID"), $this->lang->productplan->create, '_blank'); + $output .= html::a($this->createLink('productplan', 'create', "productID=$productID&branch=$branch"), $this->lang->productplan->create, '_blank'); $output .= ' '; $output .= html::a("javascript:loadProductPlans($productID)", $this->lang->refresh); $output .= ''; diff --git a/module/product/lang/zh-cn.php b/module/product/lang/zh-cn.php index 2e93bad680..82a375b6c3 100644 --- a/module/product/lang/zh-cn.php +++ b/module/product/lang/zh-cn.php @@ -58,6 +58,7 @@ $lang->product->company = '所属公司'; $lang->product->name = "{$lang->productCommon}名称"; $lang->product->code = "{$lang->productCommon}代号"; $lang->product->order = '排序'; +$lang->product->type = "{$lang->productCommon}类型"; $lang->product->status = '状态'; $lang->product->desc = "{$lang->productCommon}描述"; $lang->product->PO = "{$lang->productCommon}负责人"; @@ -83,6 +84,11 @@ $lang->product->allStory = '全部需求'; $lang->product->allProduct = '全部' . $lang->productCommon; $lang->product->allProductsOfProject = '全部关联' . $lang->productCommon; +$lang->product->typeList[''] = ''; +$lang->product->typeList['normal'] = '正常'; +$lang->product->typeList['branch'] = '多分支'; +$lang->product->typeList['platform'] = '多平台'; + $lang->product->statusList[''] = ''; $lang->product->statusList['normal'] = '正常'; $lang->product->statusList['closed'] = '结束'; diff --git a/module/product/model.php b/module/product/model.php index 9b6572ad90..23b91a6812 100644 --- a/module/product/model.php +++ b/module/product/model.php @@ -22,7 +22,7 @@ class productModel extends model * @access public * @return void */ - public function setMenu($products, $productID, $extra = '') + public function setMenu($products, $productID, $branch = 0, $extra = '') { /* Has access privilege?. */ if($products and !isset($products[$productID]) and !$this->checkPriv($this->getById($productID))) @@ -38,7 +38,7 @@ class productModel extends model if($currentModule == 'story' and $currentMethod != 'create' and $currentMethod != 'batchcreate') $currentModule = 'product'; if($currentMethod == 'report') $currentMethod = 'browse'; - $selectHtml = $this->select($products, $productID, $currentModule, $currentMethod, $extra); + $selectHtml = $this->select($products, $productID, $currentModule, $currentMethod, $extra, $branch); foreach($this->lang->product->menu as $key => $menu) { $replace = $key == 'list' ? $selectHtml : $productID; @@ -57,13 +57,21 @@ class productModel extends model * @access public * @return string */ - public function select($products, $productID, $currentModule, $currentMethod, $extra = '') + public function select($products, $productID, $currentModule, $currentMethod, $extra = '', $branch = 0) { if(!$productID) return; setCookie("lastProduct", $productID, $this->config->cookieLife, $this->config->webRoot); + setCookie("lastBranch", "$productID-$branch", $this->config->cookieLife, $this->config->webRoot); $currentProduct = $this->getById($productID); - $output = "{$currentProduct->name}| idAB);?> | priAB);?> | story->title);?> | @@ -130,7 +130,7 @@ createLink('story', 'batchEdit', "productID=$productID&projectID=0"); + $actionLink = $this->createLink('story', 'batchEdit', "productID=$productID&projectID=0&branch=$branch"); ?>product->RD;?> | ||
|---|---|---|---|---|---|
| product->type;?> | +product->typeList, 'normal', "class='form-control'");?> | + | |||
| product->desc;?> | diff --git a/module/product/view/edit.html.php b/module/product/view/edit.html.php index 201494a4bf..d665866660 100644 --- a/module/product/view/edit.html.php +++ b/module/product/view/edit.html.php @@ -42,6 +42,10 @@ | product->RD;?> | RD, "class='form-control chosen'");?> | ||
| product->type;?> | +product->typeList, $product->type, "class='form-control'");?> | + | |||
| product->status;?> | product->statusList, $product->status, "class='form-control'");?> | diff --git a/module/product/view/view.html.php b/module/product/view/view.html.php index ca66c7814c..21a25cfe5f 100644 --- a/module/product/view/view.html.php +++ b/module/product/view/view.html.php @@ -81,6 +81,10 @@ | product->RD;?> | RD];?> | |
| product->type;?> | +product->typeList[$product->type];?> | + | |||
| product->status;?> | product->statusList[$product->status];?> | diff --git a/module/productplan/control.php b/module/productplan/control.php index 1fe52294b5..63ba6c8dc4 100644 --- a/module/productplan/control.php +++ b/module/productplan/control.php @@ -18,12 +18,15 @@ class productplan extends control * @access public * @return void */ - public function commonAction($productID) + public function commonAction($productID, $branch = 0) { $this->loadModel('product'); - $this->view->product = $this->product->getById($productID); - $this->view->position[] = html::a($this->createLink('product', 'browse', "productID={$this->view->product->id}"), $this->view->product->name); - $this->product->setMenu($this->product->getPairs(), $productID); + $product = $this->product->getById($productID); + $this->view->product = $product; + $this->view->branch = $branch; + $this->view->branches = $product->type == 'normal' ? array() : $this->loadModel('branch')->getPairs($productID); + $this->view->position[] = html::a($this->createLink('product', 'browse', "productID={$this->view->product->id}&branch=$branch"), $this->view->product->name); + $this->product->setMenu($this->product->getPairs(), $productID, $branch); } /** @@ -33,17 +36,17 @@ class productplan extends control * @access public * @return void */ - public function create($product = '') + public function create($product = '', $branch = 0) { if(!empty($_POST)) { $planID = $this->productplan->create(); if(dao::isError()) die(js::error(dao::getError())); $this->loadModel('action')->create('productplan', $planID, 'opened'); - die(js::locate($this->createLink('productplan', 'browse', "productID=$product"), 'parent')); + die(js::locate($this->createLink('productplan', 'browse', "productID=$product&branch=$branch"), 'parent')); } - $this->commonAction($product); + $this->commonAction($product, $branch); $lastPlan = $this->productplan->getLast($product); if($lastPlan) { @@ -54,7 +57,7 @@ class productplan extends control $begin = date('Y-m-d', strtotime("+$delta days", $timestamp)); } - $this->view->begin = $lastPlan ? $begin : ''; + $this->view->begin = $lastPlan ? $begin : ''; $this->view->title = $this->view->product->name . $this->lang->colon . $this->lang->productplan->create; $this->view->position[] = $this->lang->productplan->common; @@ -84,7 +87,7 @@ class productplan extends control } $plan = $this->productplan->getByID($planID); - $this->commonAction($plan->product); + $this->commonAction($plan->product, $plan->branch); $this->view->title = $this->view->product->name . $this->lang->colon . $this->lang->productplan->edit; $this->view->position[] = $this->lang->productplan->edit; $this->view->plan = $plan; @@ -98,13 +101,13 @@ class productplan extends control * @access public * @return void */ - public function batchEdit($productID) + public function batchEdit($productID, $branch = 0) { if(isset($_POST['planIDList'])) { - $this->commonAction($productID); + $this->commonAction($productID, $branch); $this->view->title = $this->lang->productplan->batchEdit; - $this->view->position[] = html::a(inlink('browse', "productID=$productID"), $this->lang->productplan->common); + $this->view->position[] = html::a(inlink('browse', "productID=$productID&branch=$branch"), $this->lang->productplan->common); $this->view->position[] = $this->lang->productplan->batchEdit; $this->view->plans = $this->productplan->getByIDList($this->post->planIDList); @@ -119,7 +122,7 @@ class productplan extends control $actionID = $this->action->create('productplan', $planID, 'Edited'); $this->action->logHistory($actionID, $change); } - die(js::locate(inlink('browse', "productID=$productID"), 'parent')); + die(js::locate(inlink('browse', "productID=$productID&branch=$branch"), 'parent')); } die(js::locate('back')); } @@ -158,7 +161,7 @@ class productplan extends control } $this->send($response); } - die(js::locate(inlink('browse', "productID=$plan->product"), 'parent')); + die(js::locate(inlink('browse', "productID=$plan->product&branch=$plan->branch"), 'parent')); } } @@ -173,7 +176,7 @@ class productplan extends control * @access public * @return void */ - public function browse($productID = 0, $orderBy = 'begin_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1 ) + public function browse($productID = 0, $branch = 0, $orderBy = 'begin_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1 ) { /* Load pager. */ $this->app->loadClass('pager', $static = true); @@ -183,13 +186,13 @@ class productplan extends control $sort = $this->loadModel('common')->appendOrder($orderBy); $this->session->set('productPlanList', $this->app->getURI(true)); - $this->commonAction($productID); + $this->commonAction($productID, $branch); $products = $this->product->getPairs(); $this->view->title = $products[$productID] . $this->lang->colon . $this->lang->productplan->browse; $this->view->position[] = $this->lang->productplan->browse; $this->view->productID = $productID; $this->view->orderBy = $orderBy; - $this->view->plans = $this->productplan->getList($productID, $pager, $sort); + $this->view->plans = $this->productplan->getList($productID, $branch, $pager, $sort); $this->view->pager = $pager; $this->display(); } @@ -213,7 +216,7 @@ class productplan extends control $plan = $this->productplan->getByID($planID, true); if(!$plan) die(js::error($this->lang->notFound) . js::locate('back')); - $this->commonAction($plan->product); + $this->commonAction($plan->product, $plan->branch); $products = $this->product->getPairs(); $this->view->title = "PLAN #$plan->id $plan->title/" . $products[$plan->product]; $this->view->position[] = $this->lang->productplan->view; @@ -239,9 +242,9 @@ class productplan extends control * @access public * @return void */ - public function ajaxGetProductplans($productID) + public function ajaxGetProductplans($productID, $branch = 0) { - $plans = $this->productplan->getPairs($productID); + $plans = $this->productplan->getPairs($productID, $branch); die(html::select('plan', $plans, '', "class='form-control'")); } @@ -263,7 +266,7 @@ class productplan extends control $this->loadModel('story'); $this->loadModel('tree'); $plan = $this->productplan->getByID($planID); - $this->commonAction($plan->product); + $this->commonAction($plan->product, $plan->branch); $products = $this->product->getPairs(); /* Build search form. */ @@ -278,6 +281,15 @@ class productplan extends control $storyStatusList = $this->lang->story->statusList; unset($storyStatusList['closed']); $this->config->product->search['params']['status'] = array('operator' => '=', 'control' => 'select', 'values' => $storyStatusList); + if($this->view->product->type == 'normal') + { + unset($this->config->product->search['fields']['branch']); + unset($this->config->product->search['params']['branch']); + } + else + { + $this->config->product->search['params']['branch']['values'] = array('' => '') + $this->loadModel('branch')->getPairs($this->view->product->id, 'noempty'); + } $this->loadModel('search')->setSearchParams($this->config->product->search); if($browseType == 'bySearch') @@ -290,7 +302,7 @@ class productplan extends control } else { - $allStories = $this->story->getProductStories($this->view->product->id, $moduleID = '0', $status = 'draft,active,changed'); + $allStories = $this->story->getProductStories($this->view->product->id, $plan->branch, $moduleID = '0', $status = 'draft,active,changed'); } $this->view->allStories = $allStories; @@ -377,7 +389,7 @@ class productplan extends control $this->loadModel('bug'); $plan = $this->productplan->getByID($planID); - $this->commonAction($plan->product); + $this->commonAction($plan->product, $plan->branch); $products = $this->product->getPairs('nocode'); $productID = $plan->product; $queryID = ($browseType == 'bysearch') ? (int)$param : 0; diff --git a/module/productplan/lang/zh-cn.php b/module/productplan/lang/zh-cn.php index 65a34b28d3..ac2e427e1a 100644 --- a/module/productplan/lang/zh-cn.php +++ b/module/productplan/lang/zh-cn.php @@ -39,6 +39,7 @@ $lang->productplan->confirmUnlinkBug = "您确认移除该Bug吗?"; $lang->productplan->id = '编号'; $lang->productplan->product = $lang->productCommon; +$lang->productplan->branch = '所属分支'; $lang->productplan->title = '名称'; $lang->productplan->desc = '描述'; $lang->productplan->begin = '开始日期'; diff --git a/module/productplan/model.php b/module/productplan/model.php index f235daa7cd..ca1fd908f4 100644 --- a/module/productplan/model.php +++ b/module/productplan/model.php @@ -65,10 +65,11 @@ class productplanModel extends model * @access public * @return object */ - public function getList($product = 0, $pager = null, $orderBy = 'begin_desc') + public function getList($product = 0, $branch = 0, $pager = null, $orderBy = 'begin_desc') { return $this->dao->select('*')->from(TABLE_PRODUCTPLAN)->where('product')->eq($product) ->andWhere('deleted')->eq(0) + ->beginIF(!empty($branch))->andWhere('branch')->eq($branch)->fi() ->orderBy($orderBy) ->page($pager) ->fetchAll(); @@ -82,15 +83,14 @@ class productplanModel extends model * @access public * @return array */ - public function getPairs($product = 0, $expired = '') + public function getPairs($product = 0, $branch = 0, $expired = '') { $date = date('Y-m-d'); return array('' => '') + $this->dao->select('id,CONCAT(title, " [", begin, " ~ ", end, "]") as title')->from(TABLE_PRODUCTPLAN) ->where('product')->in($product) ->andWhere('deleted')->eq(0) - ->beginIF($expired == 'unexpired') - ->andWhere('end')->gt($date) - ->fi() + ->beginIF($branch)->andWhere("branch")->eq($branch)->fi() + ->beginIF($expired == 'unexpired')->andWhere('end')->gt($date)->fi() ->orderBy('begin desc')->fetchPairs(); } diff --git a/module/productplan/view/browse.html.php b/module/productplan/view/browse.html.php index d67135c221..7100e04144 100644 --- a/module/productplan/view/browse.html.php +++ b/module/productplan/view/browse.html.php @@ -15,13 +15,13 @@||||