diff --git a/VERSION b/VERSION index 0359f24328..5992115771 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -9.4 +9.5.stable diff --git a/bin/ztcli b/bin/ztcli index 027219cfa1..c5e19828b1 100755 --- a/bin/ztcli +++ b/bin/ztcli @@ -19,7 +19,8 @@ if($argc != 2) die('Usage: ' . basename(__FILE__) . " \n"); /* Parse the request into params. */ $request = parse_url(trim($argv[1])); -$_SERVER['HTTP_HOST'] = $request['host']; +$_SERVER['HTTP_HOST'] = $request['host']; +$_SERVER['SCRIPT_NAME'] = $request['path']; /* Load the framework. */ chdir(dirname(dirname(__FILE__))); @@ -27,7 +28,10 @@ include './framework/router.class.php'; include './framework/control.class.php'; include './framework/model.class.php'; include './framework/helper.class.php'; -include realpath('./config/config.php'); + +/* Instance the app and run it. */ +$app = router::createApp('pms', dirname(dirname(__FILE__)), 'router'); +$common = $app->loadCommon(); /* Set the PATH_INFO variable. */ if($config->requestType == 'PATH_INFO') @@ -62,8 +66,5 @@ else $_SERVER['REQUEST_URI'] = isset($request['query']) ? $request['query'] : ''; } -/* Instance the app and run it. */ -$app = router::createApp('pms', dirname(dirname(__FILE__)), 'router'); -$common = $app->loadCommon(); $app->parseRequest(); $app->loadModule(); diff --git a/config/config.php b/config/config.php index 997c8eb030..53475a302a 100644 --- a/config/config.php +++ b/config/config.php @@ -16,20 +16,20 @@ if(!class_exists('config')){class config{}} if(!function_exists('getWebRoot')){function getWebRoot(){}} /* 基本设置。Basic settings. */ -$config->version = '9.4'; // ZenTaoPHP的版本。 The version of ZenTaoPHP. Don't change it. -$config->charset = 'UTF-8'; // ZenTaoPHP的编码。 The encoding of ZenTaoPHP. -$config->cookieLife = time() + 2592000; // Cookie的生存时间。The cookie life time. +$config->version = '9.5'; // ZenTaoPHP的版本。 The version of ZenTaoPHP. Don't change it. +$config->charset = 'UTF-8'; // ZenTaoPHP的编码。 The encoding of ZenTaoPHP. +$config->cookieLife = time() + 2592000; // Cookie的生存时间。The cookie life time. $config->timezone = 'Asia/Shanghai'; // 时区设置。 The time zone setting, for more see http://www.php.net/manual/en/timezones.php. $config->webRoot = ''; // URL根目录。 The root path of the url. /* 框架路由相关设置。Routing settings. */ $config->requestType = 'PATH_INFO'; // 请求类型:PATH_INFO|PATHINFO2|GET。 The request type: PATH_INFO|PATH_INFO2|GET. -$config->requestFix = '-'; // PATH_INFO和PATH_INFO2模式的分隔符。 The divider in the url when PATH_INFO|PATH_INFO2. -$config->moduleVar = 'm'; // 请求类型为GET:模块变量名。 requestType=GET: the module var name. -$config->methodVar = 'f'; // 请求类型为GET:模块变量名。 requestType=GET: the method var name. -$config->viewVar = 't'; // 请求类型为GET:视图变量名。 requestType=GET: the view var name. -$config->sessionVar = 'zentaosid'; // 请求类型为GET:session变量名。 requestType=GET: the session var name. -$config->views = ',html,json,mhtml,'; // 支持的视图类型。 Supported view formats. +$config->requestFix = '-'; // PATH_INFO和PATH_INFO2模式的分隔符。 The divider in the url when PATH_INFO|PATH_INFO2. +$config->moduleVar = 'm'; // 请求类型为GET:模块变量名。 requestType=GET: the module var name. +$config->methodVar = 'f'; // 请求类型为GET:模块变量名。 requestType=GET: the method var name. +$config->viewVar = 't'; // 请求类型为GET:视图变量名。 requestType=GET: the view var name. +$config->sessionVar = 'zentaosid'; // 请求类型为GET:session变量名。 requestType=GET: the session var name. +$config->views = ',html,json,mhtml,'; // 支持的视图类型。 Supported view formats. /* 支持的主题和语言。Supported thems and languages. */ $config->themes['default'] = 'default'; diff --git a/doc/CHANGELOG b/doc/CHANGELOG index 0de231abec..d105e98637 100644 --- a/doc/CHANGELOG +++ b/doc/CHANGELOG @@ -1,17 +1,29 @@ +2017-08-25 9.5.stable +3124 取消工时记录的255字数限制 +3123 导出增加对个数字段的支持 +3122 文档附件库默认按照时间从新到旧的顺序显示 +3121 测试bug增加批量激活功能 已完成 +3120 测试报告导出功能增加相应的权限 +3119 每日提醒异步邮件列表中的发送人改成后台发信配置中的发信人 +3118 测试-用例 从用例库导入用例的时候增加搜索功能 +3117 已删除用户默认不再列出 +3116 文档库的附件库增加列表展示方式 +以及修改了大量的已知BUG。 + 2017-07-24 9.4 -3078 将跳回然之框架的功能默认设置为关闭 -3077 bug导出增加对 截止日期 字段的支持 -3076 把禅道数据库中所有的mailto字段都修改成 text 类型 -3075 增加bug提交和编辑表单编辑器的高度 -3074 数据库受损修复增加超级管理员验证 -3073 计划列表默认显示全部。 -3071 集成到然之之后右上角个人中心的菜单向左展开 -3070 批量操作的滚动条将选择和编辑按钮的边框去掉 -3069 测试-版本关联用例的时候过滤掉未评审的用例 -3068 发布关联需求的时候给默认的推荐列表 -3067 调整产品发布关联需求页面的排版 -3066 创建计划时提示之前的计划名称 -3065 附件库继承产品或者项目的访问权限 +3078 将跳回然之框架的功能默认设置为关闭 +3077 bug导出增加对 截止日期 字段的支持 +3076 把禅道数据库中所有的mailto字段都修改成 text 类型 +3075 增加bug提交和编辑表单编辑器的高度 +3074 数据库受损修复增加超级管理员验证 +3073 计划列表默认显示全部。 +3071 集成到然之之后右上角个人中心的菜单向左展开 +3070 批量操作的滚动条将选择和编辑按钮的边框去掉 +3069 测试-版本关联用例的时候过滤掉未评审的用例 +3068 发布关联需求的时候给默认的推荐列表 +3067 调整产品发布关联需求页面的排版 +3066 创建计划时提示之前的计划名称 +3065 附件库继承产品或者项目的访问权限 2017-06-21 9.3.beta 3038 修改loadModel改为单例模式,提升性能 diff --git a/lib/base/dao/dao.class.php b/lib/base/dao/dao.class.php index 24c2f7c80b..def92f96c1 100644 --- a/lib/base/dao/dao.class.php +++ b/lib/base/dao/dao.class.php @@ -1924,6 +1924,8 @@ class baseSQL $pos = stripos($order, 'limit'); $orders = $pos ? substr($order, 0, $pos) : $order; $limit = $pos ? substr($order, $pos) : ''; + if($limit and !preg_match('/^[0-9]+ *(, *[0-9]+)?$/', $limit)) $limit = ''; + $orders = trim($orders); if(empty($orders)) return $this; if(!preg_match('/^(\w+\.)?(`\w+`|\w+)( +(desc|asc))?( *(, *(\w+\.)?(`\w+`|\w+)( +(desc|asc))?)?)*$/i', $orders)) die("Order is bad request, The order is $orders"); diff --git a/lib/phpmailer/phpmailer.class.php b/lib/phpmailer/phpmailer.class.php index 7902a07c8a..19613f3828 100644 --- a/lib/phpmailer/phpmailer.class.php +++ b/lib/phpmailer/phpmailer.class.php @@ -1724,16 +1724,16 @@ class PHPMailer { switch (strtolower($position)) { case 'phrase': - $encoded = preg_replace("/([^A-Za-z0-9!*+\/ -])/e", "'='.sprintf('%02X', ord('\\1'))", $encoded); + $encoded = preg_replace_callback("/([^A-Za-z0-9!*+\/ -])/", array(&$this, 'ordChar'), $encoded); break; case 'comment': - $encoded = preg_replace("/([\(\)\"])/e", "'='.sprintf('%02X', ord('\\1'))", $encoded); + $encoded = preg_replace_callback("/([\(\)\"])/", array(&$this, 'ordChar'), $encoded); case 'text': default: // Replace every high ascii, control =, ? and _ characters //TODO using /e (equivalent to eval()) is probably not a good idea - $encoded = preg_replace('/([\000-\011\013\014\016-\037\075\077\137\177-\377])/e', - "'='.sprintf('%02X', ord('\\1'))", $encoded); + $encoded = preg_replace_callback('/([\000-\011\013\014\016-\037\075\077\137\177-\377])/', + array(&$this, 'ordChar'), $encoded); break; } @@ -2309,6 +2309,11 @@ class PHPMailer { call_user_func_array($this->action_function,$params); } } + + public function ordChar($match) + { + return '=' . sprintf('%02X', ord($match[1])); + } } class phpmailerException extends Exception { diff --git a/module/action/lang/en.php b/module/action/lang/en.php index a5aa9f1920..05fd1dd1cb 100755 --- a/module/action/lang/en.php +++ b/module/action/lang/en.php @@ -33,6 +33,13 @@ $lang->action->confirmHideAll = 'Do you want to hide all the records?'; $lang->action->needEdit = '%s you want to restore has already existed. Please edit it.'; $lang->action->historyEdit = 'The history editor cannot be empty.'; +$lang->action->history = new stdclass(); +$lang->action->history->action = 'Bound action'; +$lang->action->history->field = 'Field'; +$lang->action->history->old = 'Old value'; +$lang->action->history->new = 'New value'; +$lang->action->history->diff = 'Diff'; + $lang->action->dynamic = new stdclass(); $lang->action->dynamic->today = 'Today'; $lang->action->dynamic->yesterday = 'Yesterday'; @@ -106,6 +113,7 @@ $lang->action->desc->paused = '$date, paused by $actor. $lang->action->desc->diff1 = '%s has been changed. Its value was "%s" and the new value is "%s".
' . "\n"; $lang->action->desc->diff2 = '%s has been changed. The difference is ' . "\n" . "
%s
" . "\n"; $lang->action->desc->diff3 = 'File Name %s was changed to %s .' . "\n"; +$lang->action->desc->linked2bug = '$date Link to build $extra by $actor'; /* 关联用例和移除用例时的历史操作记录。*/ $lang->action->desc->linkrelatedcase = '$date, $actor linked relevant use case $extra.' . "\n"; @@ -168,6 +176,8 @@ $lang->action->label->suspended = 'Suspended'; $lang->action->label->login = 'Login'; $lang->action->label->logout = "Logout"; $lang->action->label->deleteestimate = "Deleted Man-Hour"; +$lang->action->label->linked2build = "Linked"; +$lang->action->label->linked2bug = "Linked"; /* 用来生成相应对象的链接。*/ $lang->action->label->product = $lang->productCommon . '|product|view|productID=%s'; diff --git a/module/action/lang/zh-cn.php b/module/action/lang/zh-cn.php index 2a9707252b..78f3a12eb0 100755 --- a/module/action/lang/zh-cn.php +++ b/module/action/lang/zh-cn.php @@ -33,6 +33,13 @@ $lang->action->confirmHideAll = '您确定要全部隐藏这些记录吗?'; $lang->action->needEdit = '要还原%s的名称或代号已经存在,请编辑更改。'; $lang->action->historyEdit = '历史记录编辑不能为空。'; +$lang->action->history = new stdclass(); +$lang->action->history->action = '关联日志'; +$lang->action->history->field = '字段'; +$lang->action->history->old = '旧值'; +$lang->action->history->new = '新值'; +$lang->action->history->diff = '不同'; + $lang->action->dynamic = new stdclass(); $lang->action->dynamic->today = '今天'; $lang->action->dynamic->yesterday = '昨天'; @@ -106,6 +113,7 @@ $lang->action->desc->paused = '$date, 由 $actor 暂停 $lang->action->desc->diff1 = '修改了 %s,旧值为 "%s",新值为 "%s"。
' . "\n"; $lang->action->desc->diff2 = '修改了 %s,区别为:' . "\n" . "
%s
" . "\n"; $lang->action->desc->diff3 = '将文件名 %s 改为 %s 。' . "\n"; +$lang->action->desc->linked2bug = '$date 由 $actor 关联到版本 $extra'; /* 关联用例和移除用例时的历史操作记录。*/ $lang->action->desc->linkrelatedcase = '$date, 由 $actor 关联相关用例 $extra。' . "\n"; @@ -168,8 +176,8 @@ $lang->action->label->suspended = '挂起'; $lang->action->label->login = '登录系统'; $lang->action->label->logout = "退出登录"; $lang->action->label->deleteestimate = "删除了工时"; -$lang->action->label->linked2build = "关联版本"; -$lang->action->label->linked2bug = "关联BUG"; +$lang->action->label->linked2build = "关联了"; +$lang->action->label->linked2bug = "关联了"; /* 用来生成相应对象的链接。*/ $lang->action->label->product = $lang->productCommon . '|product|view|productID=%s'; diff --git a/module/action/lang/zh-tw.php b/module/action/lang/zh-tw.php index 4ae7a62869..a5419411b8 100755 --- a/module/action/lang/zh-tw.php +++ b/module/action/lang/zh-tw.php @@ -33,6 +33,13 @@ $lang->action->confirmHideAll = '您確定要全部隱藏這些記錄嗎?'; $lang->action->needEdit = '要還原%s的名稱或代號已經存在,請編輯更改。'; $lang->action->historyEdit = '歷史記錄編輯不能為空。'; +$lang->action->history = new stdclass(); +$lang->action->history->action = '關聯日誌'; +$lang->action->history->field = '欄位'; +$lang->action->history->old = '舊值'; +$lang->action->history->new = '新值'; +$lang->action->history->diff = '不同'; + $lang->action->dynamic = new stdclass(); $lang->action->dynamic->today = '今天'; $lang->action->dynamic->yesterday = '昨天'; @@ -106,6 +113,7 @@ $lang->action->desc->paused = '$date, 由 $actor 暫停 $lang->action->desc->diff1 = '修改了 %s,舊值為 "%s",新值為 "%s"。
' . "\n"; $lang->action->desc->diff2 = '修改了 %s,區別為:' . "\n" . "
%s
" . "\n"; $lang->action->desc->diff3 = '將檔案名 %s 改為 %s 。' . "\n"; +$lang->action->desc->linked2bug = '$date 由 $actor 關聯到版本 $extra'; /* 關聯用例和移除用例時的歷史操作記錄。*/ $lang->action->desc->linkrelatedcase = '$date, 由 $actor 關聯相關用例 $extra。' . "\n"; @@ -168,6 +176,8 @@ $lang->action->label->suspended = '掛起'; $lang->action->label->login = '登錄系統'; $lang->action->label->logout = "退出登錄"; $lang->action->label->deleteestimate = "刪除了工時"; +$lang->action->label->linked2build = "關聯了"; +$lang->action->label->linked2bug = "關聯了"; /* 用來生成相應對象的連結。*/ $lang->action->label->product = $lang->productCommon . '|product|view|productID=%s'; diff --git a/module/action/model.php b/module/action/model.php index a95df52acf..ea946197c3 100755 --- a/module/action/model.php +++ b/module/action/model.php @@ -242,6 +242,11 @@ class actionModel extends model $name = $this->dao->select('name')->from(TABLE_BUILD)->where('id')->eq($action->extra)->fetch('name'); if($name) $action->extra = html::a(helper::createLink('build', 'view', "builID=$action->extra&type={$action->objectType}"), $name); } + elseif($actionName == 'linked2bug') + { + $name = $this->dao->select('name')->from(TABLE_BUILD)->where('id')->eq($action->extra)->fetch('name'); + if($name) $action->extra = html::a(helper::createLink('build', 'view', "builID=$action->extra&type={$action->objectType}"), $name); + } elseif($actionName == 'linked2release') { $name = $this->dao->select('name')->from(TABLE_RELEASE)->where('id')->eq($action->extra)->fetch('name'); diff --git a/module/block/control.php b/module/block/control.php index 7373da8e12..2b6c9a5d1d 100644 --- a/module/block/control.php +++ b/module/block/control.php @@ -21,7 +21,7 @@ class block extends control { parent::__construct($moduleName, $methodName); /* Mark the call from zentao or ranzhi. */ - $this->selfCall = strpos($this->server->http_referer, common::getSysURL()) === 0 || $this->session->blockModule; + $this->selfCall = strpos($this->server->http_referer, common::getSysURL() . $this->config->webRoot) === 0 || $this->session->blockModule; if($this->methodName != 'admin' and $this->methodName != 'dashboard' and !$this->selfCall and !$this->loadModel('sso')->checkKey()) die(''); } @@ -197,7 +197,7 @@ class block extends control */ public function dashboard($module) { - $this->session->set('blockModule', $module); + if($this->loadModel('user')->isLogon()) $this->session->set('blockModule', $module); $blocks = $this->block->getBlockList($module); $inited = empty($this->config->$module->common->blockInited) ? '' : $this->config->$module->common->blockInited; @@ -605,7 +605,7 @@ class block extends control public function printProductBlock() { $this->app->loadClass('pager', $static = true); - if(preg_match('/[^a-zA-Z0-9_]/', $this->params->type)) die(); + if(!empty($this->params->type) and preg_match('/[^a-zA-Z0-9_]/', $this->params->type)) die(); $num = isset($this->params->num) ? (int)$this->params->num : 0; $type = isset($this->params->type) ? $this->params->type : ''; $pager = pager::init(0, $num , 1); @@ -621,7 +621,7 @@ class block extends control public function printProjectBlock() { $this->app->loadClass('pager', $static = true); - if(preg_match('/[^a-zA-Z0-9_]/', $this->params->type)) die(); + if(!empty($this->params->type) and preg_match('/[^a-zA-Z0-9_]/', $this->params->type)) die(); $num = isset($this->params->num) ? (int)$this->params->num : 0; $type = isset($this->params->type) ? $this->params->type : 'all'; $pager = pager::init(0, $num, 1); diff --git a/module/block/lang/en.php b/module/block/lang/en.php index 178f40a75a..db1ae32a0c 100644 --- a/module/block/lang/en.php +++ b/module/block/lang/en.php @@ -16,6 +16,14 @@ $lang->block->style = 'Style'; $lang->block->grid = 'Grid'; $lang->block->color = 'Color'; +$lang->block->account = 'Account'; +$lang->block->module = 'Module'; +$lang->block->title = 'Title'; +$lang->block->source = 'Source module'; +$lang->block->block = 'Source block'; +$lang->block->order = 'Order'; +$lang->block->height = 'Height'; + $lang->block->lblModule = 'Module'; $lang->block->lblBlock = 'Widget'; $lang->block->lblNum = 'Number'; diff --git a/module/block/lang/zh-cn.php b/module/block/lang/zh-cn.php index 4c7a63691b..0bbfe758ae 100644 --- a/module/block/lang/zh-cn.php +++ b/module/block/lang/zh-cn.php @@ -16,6 +16,14 @@ $lang->block->style = '外观'; $lang->block->grid = '宽度'; $lang->block->color = '颜色'; +$lang->block->account = '所属用户'; +$lang->block->module = '所属模块'; +$lang->block->title = '区块名称'; +$lang->block->source = '来源模块'; +$lang->block->block = '来源区块'; +$lang->block->order = '排序'; +$lang->block->height = '高度'; + $lang->block->lblModule = '模块'; $lang->block->lblBlock = '区块'; $lang->block->lblNum = '条数'; diff --git a/module/block/lang/zh-tw.php b/module/block/lang/zh-tw.php index a29148c939..e4212b3b10 100644 --- a/module/block/lang/zh-tw.php +++ b/module/block/lang/zh-tw.php @@ -16,6 +16,14 @@ $lang->block->style = '外觀'; $lang->block->grid = '寬度'; $lang->block->color = '顏色'; +$lang->block->account = '所屬用戶'; +$lang->block->module = '所屬模組'; +$lang->block->title = '區塊名稱'; +$lang->block->source = '來源模組'; +$lang->block->block = '來源區塊'; +$lang->block->order = '排序'; +$lang->block->height = '高度'; + $lang->block->lblModule = '模組'; $lang->block->lblBlock = '區塊'; $lang->block->lblNum = '條數'; diff --git a/module/branch/lang/en.php b/module/branch/lang/en.php index 2d6f428b19..4e3208250c 100644 --- a/module/branch/lang/en.php +++ b/module/branch/lang/en.php @@ -7,5 +7,10 @@ $lang->branch->delete = 'Delete Branch'; $lang->branch->manageTitle = '%s Management'; $lang->branch->all = 'All'; +$lang->branch->id = 'ID'; +$lang->branch->product = 'Product'; +$lang->branch->name = 'Name'; +$lang->branch->order = 'Order'; + $lang->branch->confirmDelete = 'Do you want to delete this @branch@?'; $lang->branch->canNotDelete = 'There is data in @branch@. It cannot be deleted.'; diff --git a/module/branch/lang/zh-cn.php b/module/branch/lang/zh-cn.php index 3d327f9d12..3f8d2d374d 100644 --- a/module/branch/lang/zh-cn.php +++ b/module/branch/lang/zh-cn.php @@ -7,5 +7,10 @@ $lang->branch->delete = '分支删除'; $lang->branch->manageTitle = '%s管理'; $lang->branch->all = '所有'; +$lang->branch->id = '编号'; +$lang->branch->product = '所属产品'; +$lang->branch->name = '名称'; +$lang->branch->order = '排序'; + $lang->branch->confirmDelete = '是否删除该@branch@?'; $lang->branch->canNotDelete = '该@branch@下已经有数据,不能删除!'; diff --git a/module/branch/lang/zh-tw.php b/module/branch/lang/zh-tw.php index df6d1a0844..32b3cc684d 100644 --- a/module/branch/lang/zh-tw.php +++ b/module/branch/lang/zh-tw.php @@ -7,5 +7,10 @@ $lang->branch->delete = '分支刪除'; $lang->branch->manageTitle = '%s管理'; $lang->branch->all = '所有'; +$lang->branch->id = '編號'; +$lang->branch->product = '所屬產品'; +$lang->branch->name = '名稱'; +$lang->branch->order = '排序'; + $lang->branch->confirmDelete = '是否刪除該@branch@?'; $lang->branch->canNotDelete = '該@branch@下已經有數據,不能刪除!'; diff --git a/module/bug/control.php b/module/bug/control.php index 26461b31f1..685340f81d 100644 --- a/module/bug/control.php +++ b/module/bug/control.php @@ -513,18 +513,18 @@ class bug extends control } $bug = $this->bug->getById($bugID); - if($bug->toTask != 0) + if($bug->toTask != 0) { foreach($changes as $change) { - if($change['field'] == 'status') + if($change['field'] == 'status') { $confirmURL = $this->createLink('task', 'view', "taskID=$bug->toTask"); $cancelURL = $this->server->HTTP_REFERER; die(js::confirm(sprintf($this->lang->bug->remindTask, $bug->Task), $confirmURL, $cancelURL, 'parent', 'parent')); } } - } + } die(js::locate($this->createLink('bug', 'view', "bugID=$bugID"), 'parent')); } @@ -587,8 +587,8 @@ class bug extends control /** * Batch edit bug. - * - * @param int $productID + * + * @param int $productID * @access public * @return void */ @@ -618,7 +618,7 @@ class bug extends control die(js::confirm(sprintf($this->lang->bug->remindTask, $bug->task), $confirmURL, $cancelURL, 'parent', 'parent')); } } - } + } } die(js::locate($this->session->bugList, 'parent')); } @@ -933,8 +933,8 @@ class bug extends control /** * Activate a bug. - * - * @param int $bugID + * + * @param int $bugID * @access public * @return void */ @@ -1122,36 +1122,39 @@ class bug extends control } /** - * Batch activate bugs. - * + * Batch activate bugs. + * * @access public * @return void */ - public function batchActivate() + public function batchActivate($productID, $branch = 0) { - if($this->post->bugIDList) + if($this->post->statusList) { - $bugIDList = $this->post->bugIDList; - - /* Reset $_POST. Do not unset that because the function of close need that in model. */ - $_POST = array(); - - $bugs = $this->bug->getByList($bugIDList); - foreach($bugs as $bugID => $bug) + $activateBugs = $this->bug->batchActivate(); + foreach($activateBugs as $bugID => $bug) { - if($bug->status == 'active') - { - continue; - } - - $this->bug->activate($bugID); - - $actionID = $this->action->create('bug', $bugID, 'Activated'); + $actionID = $this->action->create('bug', $bugID, 'Activated', $bug['comment']); $this->bug->sendmail($bugID, $actionID); } + + die(js::locate($this->session->bugList, 'parent')); } - die(js::reload('parent')); + $bugIDList = $this->post->bugIDList ? $this->post->bugIDList : die(js::locate($this->session->bugList, 'parent')); + $bugs = $this->dao->select('id, title, status, resolvedBy, openedBuild')->from(TABLE_BUG)->where('id')->in($bugIDList)->fetchAll('id'); + + $this->bug->setMenu($this->products, $productID, $branch); + + $this->view->title = $this->products[$productID] . $this->lang->colon . $this->lang->bug->batchActivate; + $this->view->position[] = html::a($this->createLink('bug', 'browse', "productID=$productID"), $this->products[$productID]); + $this->view->position[] = $this->lang->bug->batchActivate; + + $this->view->bugs = $bugs; + $this->view->users = $this->user->getPairs(); + $this->view->builds = $this->loadModel('build')->getProductBuildPairs($productID, $branch, 'noempty'); + + $this->display(); } /** diff --git a/module/bug/js/common.js b/module/bug/js/common.js index 7734e9f505..fdd680d538 100644 --- a/module/bug/js/common.js +++ b/module/bug/js/common.js @@ -1,4 +1,4 @@ -$(function() +$(function() { setModal4List('iframe', 'bugList'); diff --git a/module/bug/lang/zh-cn.php b/module/bug/lang/zh-cn.php index b65bf946a1..ffeb250587 100644 --- a/module/bug/lang/zh-cn.php +++ b/module/bug/lang/zh-cn.php @@ -342,9 +342,9 @@ $lang->bug->report->bugHistories->graph->xAxisName = '处理步骤'; /* 操作记录。*/ $lang->bug->action = new stdclass(); -$lang->bug->action->resolved = array('main' => '$date, 由 $actor 解决,方案为 $extra $appendLink。', 'extra' => 'resolutionList'); -$lang->bug->action->tostory = array('main' => '$date, 由 $actor 转为需求,编号为 $extra。'); -$lang->bug->action->totask = array('main' => '$date, 由 $actor 导入为任务,编号为 $extra。'); +$lang->bug->action->resolved = array('main' => '$date, 由 $actor 解决,方案为 $extra $appendLink。', 'extra' => 'resolutionList'); +$lang->bug->action->tostory = array('main' => '$date, 由 $actor 转为需求,编号为 $extra。'); +$lang->bug->action->totask = array('main' => '$date, 由 $actor 导入为任务,编号为 $extra。'); $lang->bug->action->linked2plan = array('main' => '$date, 由 $actor 关联到计划 $extra。'); $lang->bug->action->unlinkedfromplan = array('main' => '$date, 由 $actor 从计划 $extra 移除。'); $lang->bug->action->linked2build = array('main' => '$date, 由 $actor 关联到版本 $extra。'); diff --git a/module/bug/lang/zh-tw.php b/module/bug/lang/zh-tw.php index f00994e5d8..0bb076e27a 100644 --- a/module/bug/lang/zh-tw.php +++ b/module/bug/lang/zh-tw.php @@ -150,9 +150,9 @@ $lang->bug->applyTemplate = '應用模板'; $lang->bug->confirmDeleteTemplate = '您確認要刪除該模板嗎?'; /* 模板。*/ -$lang->bug->tplStep = "

[步驟]

\n"; -$lang->bug->tplResult = "

[結果]

\n"; -$lang->bug->tplExpect = "

[期望]

"; +$lang->bug->tplStep = "

[步驟]

"; +$lang->bug->tplResult = "

[結果]

"; +$lang->bug->tplExpect = "

[期望]

"; /* 各個欄位取值列表。*/ $lang->bug->severityList[3] = '3'; @@ -342,9 +342,9 @@ $lang->bug->report->bugHistories->graph->xAxisName = '處理步驟'; /* 操作記錄。*/ $lang->bug->action = new stdclass(); -$lang->bug->action->resolved = array('main' => '$date, 由 $actor 解決,方案為 $extra $appendLink。', 'extra' => 'resolutionList'); -$lang->bug->action->tostory = array('main' => '$date, 由 $actor 轉為需求,編號為 $extra。'); -$lang->bug->action->totask = array('main' => '$date, 由 $actor 導入為任務,編號為 $extra。'); +$lang->bug->action->resolved = array('main' => '$date, 由 $actor 解決,方案為 $extra $appendLink。', 'extra' => 'resolutionList'); +$lang->bug->action->tostory = array('main' => '$date, 由 $actor 轉為需求,編號為 $extra。'); +$lang->bug->action->totask = array('main' => '$date, 由 $actor 導入為任務,編號為 $extra。'); $lang->bug->action->linked2plan = array('main' => '$date, 由 $actor 關聯到計劃 $extra。'); $lang->bug->action->unlinkedfromplan = array('main' => '$date, 由 $actor 從計劃 $extra 移除。'); $lang->bug->action->linked2build = array('main' => '$date, 由 $actor 關聯到版本 $extra。'); diff --git a/module/bug/model.php b/module/bug/model.php index 6a0114f9ed..afd6ecbeac 100644 --- a/module/bug/model.php +++ b/module/bug/model.php @@ -658,6 +658,57 @@ class bugModel extends model return $allChanges; } + /** + * Batch active bugs. + * + * @access public + * @return array + */ + public function batchActivate() + { + $now = helper::now(); + $data = fixer::input('post')->get(); + + $activateBugs = array(); + $bugIDList = $data->bugIDList ? $data->bugIDList : array(); + + if(empty($bugIDList)) return $activateBugs; + + foreach($bugIDList as $bugID) + { + if($data->statusList[$bugID] == 'active') continue; + + $activateBugs[$bugID]['assignedTo'] = $data->assignedToList[$bugID]; + $activateBugs[$bugID]['openedBuild'] = $data->openedBuildList[$bugID]; + $activateBugs[$bugID]['comment'] = $data->commentList[$bugID]; + + $activateBugs[$bugID]['assignedDate'] = $now; + $activateBugs[$bugID]['resolution'] = ''; + $activateBugs[$bugID]['status'] = 'active'; + $activateBugs[$bugID]['resolvedDate'] = '0000-00-00'; + $activateBugs[$bugID]['resolvedBy'] = ''; + $activateBugs[$bugID]['resolvedBuild'] = ''; + $activateBugs[$bugID]['closedBy'] = ''; + $activateBugs[$bugID]['closedDate'] = '0000-00-00'; + $activateBugs[$bugID]['duplicateBug'] = 0; + $activateBugs[$bugID]['toTask'] = 0; + $activateBugs[$bugID]['toStory'] = 0; + $activateBugs[$bugID]['lastEditedBy'] = $this->app->user->account; + $activateBugs[$bugID]['lastEditedDate'] = $now; + } + + /* Update bugs. */ + foreach($activateBugs as $bugID => $bug) + { + $this->dao->update(TABLE_BUG)->data($bug, $skipFields = 'comment')->autoCheck()->where('id')->eq((int)$bugID)->exec(); + if(dao::isError()) die(js::error('bug#' . $bugID . dao::getError(true))); + + $this->dao->update(TABLE_BUG)->set('activatedCount = activatedCount + 1')->where('id')->eq((int)$bugID)->exec(); + } + + return $activateBugs; + } + /** * Assign a bug to a user again. * @@ -1506,7 +1557,7 @@ class bugModel extends model { foreach($openBuildIDList as $buildID) { - if(isset($datas[$buildID])) + if(isset($datas[$buildID])) { $datas[$buildID]->value += $data->value; } @@ -1538,7 +1589,7 @@ class bugModel extends model { $datas = $this->dao->select('module as name, count(module) as value')->from(TABLE_BUG)->where($this->reportCondition())->groupBy('module')->orderBy('value DESC')->fetchAll('name'); if(!$datas) return array(); - $modules = $this->loadModel('tree')->getModulesName(array_keys($datas),true,true); + $modules = $this->loadModel('tree')->getModulesName(array_keys($datas), true, true); foreach($datas as $moduleID => $data) $data->name = isset($modules[$moduleID]) ? $modules[$moduleID] : '/'; return $datas; } diff --git a/module/bug/view/activate.html.php b/module/bug/view/activate.html.php index 3326acbfe5..d9f5f27db7 100644 --- a/module/bug/view/activate.html.php +++ b/module/bug/view/activate.html.php @@ -37,7 +37,7 @@ bug->files;?> fetch('file', 'buildform');?> - + goback, $this->session->bugList);?> diff --git a/module/bug/view/batchactivate.html.php b/module/bug/view/batchactivate.html.php new file mode 100644 index 0000000000..141f022093 --- /dev/null +++ b/module/bug/view/batchactivate.html.php @@ -0,0 +1,46 @@ + + * @package bug + * @version $Id$ + * @link http://www.zentao.net + */ +?> + +
+
+ bug->common . $lang->colon . $lang->bug->batchActivate;?> +
+
+
"> + + + + + + + + + + + + + + + + + + + + + + + + +
idAB;?>bug->title;?>bug->assignedTo;?>bug->openedBuild;?>bug->legendComment;?>
id . html::hidden("bugIDList[$bug->id]", $bug->id);?>title . html::hidden("statusList[$bug->id]", $bug->status);?>id]", $users, $bug->resolvedBy, "class='form-control chosen'");?>id]", $builds, $bug->openedBuild, 'size=4 multiple=multiple class="form-control chosen"');?>id]", '', "class='form-control'");?>
+
+ diff --git a/module/bug/view/browse.html.php b/module/bug/view/browse.html.php index 61cfed72b5..10e72a610e 100644 --- a/module/bug/view/browse.html.php +++ b/module/bug/view/browse.html.php @@ -193,15 +193,15 @@ js::set('branch', $branch); createLink('bug', 'batchConfirm'); - $misc = common::hasPriv('bug', 'batchConfirm') ? "onclick=\"setFormAction('$actionLink','hiddenwin')\"" : $class; + $misc = common::hasPriv('bug', 'batchConfirm') ? "onclick=\"setFormAction('$actionLink', 'hiddenwin')\"" : $class; if($misc) echo "
  • " . html::a('javascript:;', $lang->bug->confirmBug, '', $misc) . "
  • "; $actionLink = $this->createLink('bug', 'batchClose'); - $misc = common::hasPriv('bug', 'batchClose') ? "onclick=\"setFormAction('$actionLink','hiddenwin')\"" : $class; + $misc = common::hasPriv('bug', 'batchClose') ? "onclick=\"setFormAction('$actionLink', 'hiddenwin')\"" : $class; if($misc) echo "
  • " . html::a('javascript:;', $lang->bug->close, '', $misc) . "
  • "; - $actionLink = $this->createLink('bug', 'batchActivate'); - $misc = common::hasPriv('bug', 'batchActivate') ? "onclick=\"setFormAction('$actionLink','hiddenwin')\"" : $class; + $actionLink = $this->createLink('bug', 'batchActivate', "productID=$productID&branch=$branch"); + $misc = common::hasPriv('bug', 'batchActivate') ? "onclick=\"setFormAction('$actionLink')\"" : $class; if($misc) echo "
  • " . html::a('javascript:;', $lang->bug->activate, '', $misc) . "
  • "; if(common::hasPriv('bug', 'batchChangeModule')) diff --git a/module/bug/view/create.html.php b/module/bug/view/create.html.php index 8c494ad113..337126c021 100644 --- a/module/bug/view/create.html.php +++ b/module/bug/view/create.html.php @@ -1,4 +1,4 @@ - loadModel('product')->getByID($projectID); $products = $this->product->getPairs(); $this->product->setMenu($products, $projectID); + $this->lang->build->menu = $this->lang->product->menu; $productGroups = array(); $product->branch = 0; @@ -112,6 +113,7 @@ class build extends control $product = $this->loadModel('product')->getById($build->product); $products = $this->product->getPairs(); $this->product->setMenu($products, $build->product); + $this->lang->build->menu = $this->lang->product->menu; $productGroups = array(); $product->branch = 0; @@ -193,6 +195,7 @@ class build extends control { $products = $this->loadModel('product')->getPairs(); $this->product->setMenu($products, $build->product); + $this->lang->build->menu = $this->lang->product->menu; $this->view->title = "BUILD #$build->id $build->name - " . $build->productName; $this->view->position[] = html::a($this->createLink('product', 'build', "productID=$build->product"), $build->productName); diff --git a/module/build/js/view.js b/module/build/js/view.js index f587ae6909..bb88ba4864 100644 --- a/module/build/js/view.js +++ b/module/build/js/view.js @@ -14,15 +14,18 @@ function showLink(buildID, type, param) } $(function() { - if(link == 'true') showLink(buildID, type, param); - fixedTfootAction($('#' + type + 'List').closest('form')); - $('.nav.nav-tabs a[data-toggle="tab"]').on('shown.zui.tab', function(e) + if(flow != 'onlyTest') { - var href = $(e.target).attr('href'); - var tabPane = $(href + '.tab-pane'); - if(tabPane.size() == 0) return; - var formID = tabPane.find('.linkBox').find('form:last'); - if(formID.size() == 0) formID = tabPane.find('form:last'); - setTimeout(function(){fixedTfootAction(formID)}, 100); - }); + if(link == 'true') showLink(buildID, type, param); + fixedTfootAction($('#' + type + 'List').closest('form')); + $('.nav.nav-tabs a[data-toggle="tab"]').on('shown.zui.tab', function(e) + { + var href = $(e.target).attr('href'); + var tabPane = $(href + '.tab-pane'); + if(tabPane.size() == 0) return; + var formID = tabPane.find('.linkBox').find('form:last'); + if(formID.size() == 0) formID = tabPane.find('form:last'); + setTimeout(function(){fixedTfootAction(formID)}, 100); + }); + } }) diff --git a/module/build/lang/en.php b/module/build/lang/en.php index 45ec2696d2..a8d85a2806 100644 --- a/module/build/lang/en.php +++ b/module/build/lang/en.php @@ -13,7 +13,6 @@ $lang->build->common = "Build"; $lang->build->create = "Create"; $lang->build->edit = "Edit"; $lang->build->linkStory = "Link Story"; -$lang->build->linked2build = "Link build"; $lang->build->linkBug = "Link Bug"; $lang->build->delete = "Delete Build"; $lang->build->deleted = "Deleted"; @@ -30,6 +29,7 @@ $lang->build->basicInfo = 'Basic Info'; $lang->build->id = 'ID'; $lang->build->product = $lang->productCommon; +$lang->build->branch = 'Platform/Branch'; $lang->build->project = $lang->projectCommon; $lang->build->name = 'Name'; $lang->build->date = 'Date'; @@ -39,6 +39,7 @@ $lang->build->filePath = 'File Path'; $lang->build->desc = 'Description'; $lang->build->files = 'Upload Files'; $lang->build->last = 'Last Build'; +$lang->build->packageType = 'Package Type'; $lang->build->unlinkStory = 'Unlink Story'; $lang->build->unlinkBug = 'Unlink Bug'; $lang->build->stories = 'Finished Story'; diff --git a/module/build/lang/zh-cn.php b/module/build/lang/zh-cn.php index 4f6709773d..bc941c457d 100644 --- a/module/build/lang/zh-cn.php +++ b/module/build/lang/zh-cn.php @@ -29,6 +29,7 @@ $lang->build->basicInfo = '基本信息'; $lang->build->id = 'ID'; $lang->build->product = $lang->productCommon; +$lang->build->branch = '平台/分支'; $lang->build->project = '所属' . $lang->projectCommon; $lang->build->name = '名称编号'; $lang->build->date = '打包日期'; @@ -38,6 +39,7 @@ $lang->build->filePath = '下载地址'; $lang->build->desc = '描述'; $lang->build->files = '上传发行包'; $lang->build->last = '上个版本'; +$lang->build->packageType = '包类型'; $lang->build->unlinkStory = '移除需求'; $lang->build->unlinkBug = '移除Bug'; $lang->build->stories = '完成的需求'; diff --git a/module/build/lang/zh-tw.php b/module/build/lang/zh-tw.php index 396dd52dce..a1b2c948d1 100644 --- a/module/build/lang/zh-tw.php +++ b/module/build/lang/zh-tw.php @@ -13,7 +13,6 @@ $lang->build->common = "版本"; $lang->build->create = "創建版本"; $lang->build->edit = "編輯版本"; $lang->build->linkStory = "關聯需求"; -$lang->build->linked2build = "关联關聯版本"; $lang->build->linkBug = "關聯Bug"; $lang->build->delete = "刪除版本"; $lang->build->deleted = "已刪除"; @@ -30,6 +29,7 @@ $lang->build->basicInfo = '基本信息'; $lang->build->id = 'ID'; $lang->build->product = $lang->productCommon; +$lang->build->branch = '平台/分支'; $lang->build->project = '所屬' . $lang->projectCommon; $lang->build->name = '名稱編號'; $lang->build->date = '打包日期'; @@ -39,6 +39,7 @@ $lang->build->filePath = '下載地址'; $lang->build->desc = '描述'; $lang->build->files = '上傳發行包'; $lang->build->last = '上個版本'; +$lang->build->packageType = '包類型'; $lang->build->unlinkStory = '移除需求'; $lang->build->unlinkBug = '移除Bug'; $lang->build->stories = '完成的需求'; diff --git a/module/build/model.php b/module/build/model.php index 2d0c382285..7215c274c8 100644 --- a/module/build/model.php +++ b/module/build/model.php @@ -66,7 +66,7 @@ class buildModel extends model ->where('t1.project')->eq((int)$projectID) ->andWhere('t1.deleted')->eq(0) ->orderBy('t1.date DESC, t1.id desc') - ->fetchAll(); + ->fetchAll('id'); } /** @@ -200,6 +200,7 @@ class buildModel extends model ->stripTags($this->config->build->editor->create['id'], $this->config->allowedTags) ->remove('resolvedBy,allchecker,files,labels,uid') ->get(); + if($this->config->global->flow == 'onlyTest') $build->project = 0; $build = $this->loadModel('file')->processImgURL($build, $this->config->build->editor->create['id'], $this->post->uid); $this->dao->insert(TABLE_BUILD)->data($build) diff --git a/module/build/view/view.html.php b/module/build/view/view.html.php index e3c18e2d2b..c0a4059f57 100644 --- a/module/build/view/view.html.php +++ b/module/build/view/view.html.php @@ -13,6 +13,7 @@ build->confirmUnlinkStory)?> build->confirmUnlinkBug)?> +config->global->flow)?>