清除數據存在一定的風險,清楚數據之前,我們強烈建議您備份資料庫及相應的數據檔案,並保證清楚數據的時候,沒有其他人進行操作。 \n
+清除數據對資料庫的影響如下:
+1、清除數據不會對company, group, groupPriv表進行操作。
+2、如果安裝的時候有導入demo數據,則會刪除config表key=showDemoUsers的記錄,並刪除user表中的所有demo用戶。
+3、對於其他表則進行全部清除操作。
+EOT;
+
+$lang->admin->info = new stdclass();
+$lang->admin->info->caption = '禪道系統信息';
+$lang->admin->info->version = '當前系統的版本是%s,';
+$lang->admin->info->links = '您可以訪問以下連結:';
+$lang->admin->info->account = "您的禪道社區賬戶為%s。";
+
+$lang->admin->notice = new stdclass();
+$lang->admin->notice->register = "友情提示:您還未在禪道社區(www.zentao.net)登記,%s進行登記,以及時獲得禪道最新信息。";
+$lang->admin->notice->ignore = "不再提示";
+
+$lang->admin->register = new stdclass();
+$lang->admin->register->caption = '禪道社區登記';
+$lang->admin->register->click = '點擊此處';
+$lang->admin->register->lblAccount = '請設置您的用戶名,英文字母和數字的組合,三位以上。';
+$lang->admin->register->lblPasswd = '請設置您的密碼。數字和字母的組合,六位以上。';
+$lang->admin->register->submit = '登記';
+$lang->admin->register->bind = "如果您已經擁有社區賬號,%s關聯賬戶";
+$lang->admin->register->success = "登記賬戶成功";
+
+$lang->admin->bind = new stdclass();
+$lang->admin->bind->caption = '關聯社區賬號';
+$lang->admin->bind->action = '關聯';
+$lang->admin->bind->success = "關聯賬戶成功";
diff --git a/module/admin/model.php b/module/admin/model.php
index 8b4e2c1e55..b2cf839087 100644
--- a/module/admin/model.php
+++ b/module/admin/model.php
@@ -1,183 +1,183 @@
-
- * @package admin
- * @version $Id$
- * @link http://www.zentao.net
- */
-?>
-setAgent();
- }
-
- /**
- * Set the api agent.
- *
- * @access public
- * @return void
- */
- public function setAgent()
- {
- $this->agent = $this->app->loadClass('snoopy');
- }
-
- /**
- * Post data form API
- *
- * @param string $url
- * @param string $formvars
- * @access public
- * @return void
- */
- public function postAPI($url, $formvars = "")
- {
- $this->agent->cookies['lang'] = $this->cookie->lang;
- $this->agent->submit($url, $formvars);
- return $this->agent->results;
- }
-
- /**
- * Get status of zentaopms.
- *
- * @access public
- * @return void
- */
- public function getStatOfPMS()
- {
- $sql = "SHOW TABLE STATUS";
- $tables = $this->dbh->query($sql)->fetchALL();
- }
-
- /**
- * Get state of company.
- *
- * @param int $companyID
- * @access public
- * @return void
- */
- public function getStatOfCompany($companyID)
- {
- }
-
- /**
- * Get system info.
- *
- * @access public
- * @return void
- */
- public function getStatOfSys()
- {
-
- }
-
- /**
- * Register zentao by API.
- *
- * @access public
- * @return void
- */
- public function registerByAPI()
- {
- $apiURL = 'http://www.zentao.net/user-register.json';
- return $this->postAPI($apiURL, $_POST);
- }
-
- /**
- * Login zentao by API.
- *
- * @access public
- * @return void
- */
- public function bindByAPI()
- {
- $apiURL = 'http://www.zentao.net/user-login.json';
- return $this->postAPI($apiURL, $_POST);
- }
-
- /**
- * Get register information.
- *
- * @access public
- * @return object
- */
- public function getRegisterInfo()
- {
- $register = new stdclass();
- $register->company = $this->app->company->name;
- $register->email = $this->app->user->email;
- return $register;
- }
-
- /**
- * Clear data.
- *
- * @access public
- * @return void
- */
- public function clearData()
- {
- $result = $this->dbh->query('SHOW TABLES')->fetchAll();
- $showDemoUsers = $this->dao->select('value')->from(TABLE_CONFIG)->where('`key`')->eq('showDemoUsers')->fetch();
- foreach($result as $item)
- {
- $table = current((array)$item);
- if(strpos($table, 'company') !== false) continue;
- if(strpos($table, 'group') !== false) continue;
- if(strpos($table, 'user') !== false)
- {
- if($showDemoUsers)
- {
- $this->dao->delete()->from($table)
- ->where('account')->in(array('productManager', 'projectManager', 'testManager', 'dev1', 'dev2', 'dev3', 'tester1', 'tester2', 'tester3'))
- ->exec();
- if(dao::isError()) return false;
- }
- continue;
- }
- if(strpos($table, 'config') !== false)
- {
- if($showDemoUsers)
- {
- $this->dao->delete()->from($table)
- ->where('`key`')->eq('showDemoUsers')
- ->exec();
- if(dao::isError()) return false;
- }
- continue;
- }
- if(!$this->dbh->query("TRUNCATE TABLE `$table`")) return false;
- }
- return true;
- }
-}
+
+ * @package admin
+ * @version $Id$
+ * @link http://www.zentao.net
+ */
+?>
+setAgent();
+ }
+
+ /**
+ * Set the api agent.
+ *
+ * @access public
+ * @return void
+ */
+ public function setAgent()
+ {
+ $this->agent = $this->app->loadClass('snoopy');
+ }
+
+ /**
+ * Post data form API
+ *
+ * @param string $url
+ * @param string $formvars
+ * @access public
+ * @return void
+ */
+ public function postAPI($url, $formvars = "")
+ {
+ $this->agent->cookies['lang'] = $this->cookie->lang;
+ $this->agent->submit($url, $formvars);
+ return $this->agent->results;
+ }
+
+ /**
+ * Get status of zentaopms.
+ *
+ * @access public
+ * @return void
+ */
+ public function getStatOfPMS()
+ {
+ $sql = "SHOW TABLE STATUS";
+ $tables = $this->dbh->query($sql)->fetchALL();
+ }
+
+ /**
+ * Get state of company.
+ *
+ * @param int $companyID
+ * @access public
+ * @return void
+ */
+ public function getStatOfCompany($companyID)
+ {
+ }
+
+ /**
+ * Get system info.
+ *
+ * @access public
+ * @return void
+ */
+ public function getStatOfSys()
+ {
+
+ }
+
+ /**
+ * Register zentao by API.
+ *
+ * @access public
+ * @return void
+ */
+ public function registerByAPI()
+ {
+ $apiURL = 'http://www.zentao.net/user-register.json';
+ return $this->postAPI($apiURL, $_POST);
+ }
+
+ /**
+ * Login zentao by API.
+ *
+ * @access public
+ * @return void
+ */
+ public function bindByAPI()
+ {
+ $apiURL = 'http://www.zentao.net/user-login.json';
+ return $this->postAPI($apiURL, $_POST);
+ }
+
+ /**
+ * Get register information.
+ *
+ * @access public
+ * @return object
+ */
+ public function getRegisterInfo()
+ {
+ $register = new stdclass();
+ $register->company = $this->app->company->name;
+ $register->email = $this->app->user->email;
+ return $register;
+ }
+
+ /**
+ * Clear data.
+ *
+ * @access public
+ * @return void
+ */
+ public function clearData()
+ {
+ $result = $this->dbh->query('SHOW TABLES')->fetchAll();
+ $showDemoUsers = $this->dao->select('value')->from(TABLE_CONFIG)->where('`key`')->eq('showDemoUsers')->fetch();
+ foreach($result as $item)
+ {
+ $table = current((array)$item);
+ if(strpos($table, 'company') !== false) continue;
+ if(strpos($table, 'group') !== false) continue;
+ if(strpos($table, 'user') !== false)
+ {
+ if($showDemoUsers)
+ {
+ $this->dao->delete()->from($table)
+ ->where('account')->in(array('productManager', 'projectManager', 'testManager', 'dev1', 'dev2', 'dev3', 'tester1', 'tester2', 'tester3'))
+ ->exec();
+ if(dao::isError()) return false;
+ }
+ continue;
+ }
+ if(strpos($table, 'config') !== false)
+ {
+ if($showDemoUsers)
+ {
+ $this->dao->delete()->from($table)
+ ->where('`key`')->eq('showDemoUsers')
+ ->exec();
+ if(dao::isError()) return false;
+ }
+ continue;
+ }
+ if(!$this->dbh->query("TRUNCATE TABLE `$table`")) return false;
+ }
+ return true;
+ }
+}
diff --git a/module/admin/view/bind.html.php b/module/admin/view/bind.html.php
index a20fa9ccb1..2fed12b7e9 100644
--- a/module/admin/view/bind.html.php
+++ b/module/admin/view/bind.html.php
@@ -1,30 +1,30 @@
-
- * @package admin
- * @version $Id: view.html.php 2568 2012-02-09 06:56:35Z shiyangyangwork@yahoo.cn $
- * @link http://www.zentao.net
- */
-?>
-
-
-
+
+ * @package admin
+ * @version $Id: view.html.php 2568 2012-02-09 06:56:35Z shiyangyangwork@yahoo.cn $
+ * @link http://www.zentao.net
+ */
+?>
+
+
+
diff --git a/module/admin/view/browsecompany.html.php b/module/admin/view/browsecompany.html.php
index 643096fc46..2ff4586b57 100644
--- a/module/admin/view/browsecompany.html.php
+++ b/module/admin/view/browsecompany.html.php
@@ -1,47 +1,47 @@
-
- * @package admin
- * @version $Id$
- * @link http://www.zentao.net
- */
-?>
-
-
-
- company->id;?>
- company->name;?>
- company->phone;?>
- company->fax;?>
- company->address;?>
- company->zipcode;?>
- company->website;?>
- company->backyard;?>
- company->pms;?>
- company->guest;?>
- actions;?>
-
-
-
- id;?>
- name;?>
- phone;?>
- fax;?>
- address;?>
- zipcode;?>
- website, $company->website, '_blank');?>
- backyard,$company->backyard, '_blank');?>
- pms, $company->pms, '_blank');?>
- company->guestList[(int)$company->guest];?>
-
- createLink('company', 'edit', "companyID=$company->id"), $this->lang->company->edit);?>
- createLink('company', 'delete', "companyID=$company->id"), $this->lang->company->delete, "hiddenwin");?>
-
-
-
-
-
+
+ * @package admin
+ * @version $Id$
+ * @link http://www.zentao.net
+ */
+?>
+
+
+
+ company->id;?>
+ company->name;?>
+ company->phone;?>
+ company->fax;?>
+ company->address;?>
+ company->zipcode;?>
+ company->website;?>
+ company->backyard;?>
+ company->pms;?>
+ company->guest;?>
+ actions;?>
+
+
+
+ id;?>
+ name;?>
+ phone;?>
+ fax;?>
+ address;?>
+ zipcode;?>
+ website, $company->website, '_blank');?>
+ backyard,$company->backyard, '_blank');?>
+ pms, $company->pms, '_blank');?>
+ company->guestList[(int)$company->guest];?>
+
+ createLink('company', 'edit', "companyID=$company->id"), $this->lang->company->edit);?>
+ createLink('company', 'delete', "companyID=$company->id"), $this->lang->company->delete, "hiddenwin");?>
+
+
+
+
+
diff --git a/module/admin/view/cleardata.html.php b/module/admin/view/cleardata.html.php
index 54d8e27775..06e782e49e 100755
--- a/module/admin/view/cleardata.html.php
+++ b/module/admin/view/cleardata.html.php
@@ -1,21 +1,21 @@
-
- * @package admin
- * @version $Id: view.html.php 2568 2012-02-09 06:56:35Z shiyangyangwork@yahoo.cn $
- * @link http://www.zentao.net
- */
-?>
-
-
-
+
+ * @package admin
+ * @version $Id: view.html.php 2568 2012-02-09 06:56:35Z shiyangyangwork@yahoo.cn $
+ * @link http://www.zentao.net
+ */
+?>
+
+
+
diff --git a/module/admin/view/index.html.php b/module/admin/view/index.html.php
index fe9da0666d..69100b7957 100644
--- a/module/admin/view/index.html.php
+++ b/module/admin/view/index.html.php
@@ -1,28 +1,28 @@
-
- * @package admin
- * @version $Id: view.html.php 2568 2012-02-09 06:56:35Z shiyangyangwork@yahoo.cn $
- * @link http://www.zentao.net
- */
-?>
-
-
- admin->info->version, $config->version);
- if($bind) echo sprintf($lang->admin->info->account, '' . $account . ' ');
- echo $lang->admin->info->links;
- ?>
-
-
-
-
-
admin->notice->register, html::a(inlink('register'), $lang->admin->register->click));?>
-
admin->notice->ignore, 'hiddenwin');?>
-
-
-
+
+ * @package admin
+ * @version $Id: view.html.php 2568 2012-02-09 06:56:35Z shiyangyangwork@yahoo.cn $
+ * @link http://www.zentao.net
+ */
+?>
+
+
+ admin->info->version, $config->version);
+ if($bind) echo sprintf($lang->admin->info->account, '' . $account . ' ');
+ echo $lang->admin->info->links;
+ ?>
+
+
+
+
+
admin->notice->register, html::a(inlink('register'), $lang->admin->register->click));?>
+
admin->notice->ignore, 'hiddenwin');?>
+
+
+
diff --git a/module/admin/view/register.html.php b/module/admin/view/register.html.php
index 1d3fd24f43..9ae9c5424f 100644
--- a/module/admin/view/register.html.php
+++ b/module/admin/view/register.html.php
@@ -1,57 +1,57 @@
-
- * @package admin
- * @version $Id: view.html.php 2568 2012-02-09 06:56:35Z shiyangyangwork@yahoo.cn $
- * @link http://www.zentao.net
- */
-?>
-
-
-
+
+ * @package admin
+ * @version $Id: view.html.php 2568 2012-02-09 06:56:35Z shiyangyangwork@yahoo.cn $
+ * @link http://www.zentao.net
+ */
+?>
+
+
+
diff --git a/module/api/control.php b/module/api/control.php
index bf3a050b00..c481df2957 100644
--- a/module/api/control.php
+++ b/module/api/control.php
@@ -1,50 +1,50 @@
-
- * @package api
- * @version $Id$
- * @link http://www.zentao.net
- */
-class api extends control
-{
- /**
- * Return session to the client.
- *
- * @access public
- * @return void
- */
- public function getSessionID()
- {
- $this->session->set('rand', mt_rand(0, 10000));
- $this->view->sessionName = session_name();
- $this->view->sessionID = session_id();
- $this->view->rand = $this->session->rand;
- $this->display();
- }
-
- /**
- * Execute a module's model's method, return the result.
- *
- * @param string $moduleName
- * @param string $methodName
- * @param string $params param1=value1,param2=value2, don't use & to join them.
- * @access public
- * @return string
- */
- public function getModel($moduleName, $methodName, $params = '')
- {
- parse_str(str_replace(',', '&', $params), $params);
- $module = $this->loadModel($moduleName);
- $result = call_user_func_array(array(&$module, $methodName), $params);
- if(dao::isError()) die(json_encode(dao::getError()));
- $output['status'] = $result ? 'success' : 'fail';
- $output['data'] = json_encode($result);
- $output['md5'] = md5($output['data']);
- $this->output = json_encode($output);
- die($this->output);
- }
-}
+
+ * @package api
+ * @version $Id$
+ * @link http://www.zentao.net
+ */
+class api extends control
+{
+ /**
+ * Return session to the client.
+ *
+ * @access public
+ * @return void
+ */
+ public function getSessionID()
+ {
+ $this->session->set('rand', mt_rand(0, 10000));
+ $this->view->sessionName = session_name();
+ $this->view->sessionID = session_id();
+ $this->view->rand = $this->session->rand;
+ $this->display();
+ }
+
+ /**
+ * Execute a module's model's method, return the result.
+ *
+ * @param string $moduleName
+ * @param string $methodName
+ * @param string $params param1=value1,param2=value2, don't use & to join them.
+ * @access public
+ * @return string
+ */
+ public function getModel($moduleName, $methodName, $params = '')
+ {
+ parse_str(str_replace(',', '&', $params), $params);
+ $module = $this->loadModel($moduleName);
+ $result = call_user_func_array(array(&$module, $methodName), $params);
+ if(dao::isError()) die(json_encode(dao::getError()));
+ $output['status'] = $result ? 'success' : 'fail';
+ $output['data'] = json_encode($result);
+ $output['md5'] = md5($output['data']);
+ $this->output = json_encode($output);
+ die($this->output);
+ }
+}
diff --git a/module/api/lang/en.php b/module/api/lang/en.php
index db326bc1a1..90fbd1b0ad 100644
--- a/module/api/lang/en.php
+++ b/module/api/lang/en.php
@@ -1,13 +1,13 @@
-
- * @package api
- * @version $Id: English.php 824 2010-05-02 15:32:06Z wwccss $
- * @link http://www.zentao.net
- */
-$lang->api->common = 'API';
-$lang->api->getModel = 'Super Model API';
+
+ * @package api
+ * @version $Id: English.php 824 2010-05-02 15:32:06Z wwccss $
+ * @link http://www.zentao.net
+ */
+$lang->api->common = 'API';
+$lang->api->getModel = 'Super Model API';
diff --git a/module/api/lang/zh-cn.php b/module/api/lang/zh-cn.php
index eca46bcd28..6b1e7fb02c 100644
--- a/module/api/lang/zh-cn.php
+++ b/module/api/lang/zh-cn.php
@@ -1,13 +1,13 @@
-
- * @package api
- * @version $Id$
- * @link http://www.zentao.net
- */
-$lang->api->common = 'API接口';
-$lang->api->getModel = '超级model调用接口';
+
+ * @package api
+ * @version $Id$
+ * @link http://www.zentao.net
+ */
+$lang->api->common = 'API接口';
+$lang->api->getModel = '超级model调用接口';
diff --git a/module/api/lang/zh-tw.php b/module/api/lang/zh-tw.php
index 2ccf5b7f25..448c8a676c 100644
--- a/module/api/lang/zh-tw.php
+++ b/module/api/lang/zh-tw.php
@@ -1,13 +1,13 @@
-
- * @package api
- * @version $Id: zh-tw.php 2605 2012-02-21 07:22:58Z wwccss $
- * @link http://www.zentao.net
- */
-$lang->api->common = 'API介面';
-$lang->api->getModel = '超級model調用介面';
+
+ * @package api
+ * @version $Id: zh-tw.php 2605 2012-02-21 07:22:58Z wwccss $
+ * @link http://www.zentao.net
+ */
+$lang->api->common = 'API介面';
+$lang->api->getModel = '超級model調用介面';
diff --git a/module/api/model.php b/module/api/model.php
index 7b5d114ffe..dd017eca9f 100644
--- a/module/api/model.php
+++ b/module/api/model.php
@@ -1,15 +1,15 @@
-
- * @package api
- * @version $Id$
- * @link http://www.zentao.net
- */
-class apiModel extends model
-{
-}
-
+
+ * @package api
+ * @version $Id$
+ * @link http://www.zentao.net
+ */
+class apiModel extends model
+{
+}
+
diff --git a/module/bug/control.php b/module/bug/control.php
index 4fec877863..7386bde556 100644
--- a/module/bug/control.php
+++ b/module/bug/control.php
@@ -1,1098 +1,1098 @@
-
- * @package bug
- * @version $Id$
- * @link http://www.zentao.net
- */
-class bug extends control
-{
- public $products = array();
-
- /**
- * Construct function, load some modules auto.
- *
- * @access public
- * @return void
- */
- public function __construct()
- {
- parent::__construct();
- $this->loadModel('product');
- $this->loadModel('tree');
- $this->loadModel('user');
- $this->loadModel('action');
- $this->loadModel('story');
- $this->loadModel('task');
- $this->products = $this->product->getPairs();
- if(empty($this->products))
- {
- echo js::alert($this->lang->product->errorNoProduct);
- die(js::locate($this->createLink('product', 'create')));
- }
- $this->view->products = $this->products;
- }
-
- /**
- * The index page, locate to browse.
- *
- * @access public
- * @return void
- */
- public function index()
- {
- $this->locate($this->createLink('bug', 'browse'));
- }
-
- /**
- * Browse bugs.
- *
- * @param int $productID
- * @param string $browseType
- * @param int $param
- * @param string $orderBy
- * @param int $recTotal
- * @param int $recPerPage
- * @param int $pageID
- * @access public
- * @return void
- */
- public function browse($productID = 0, $browseType = 'byModule', $param = 0, $orderBy = '', $recTotal = 0, $recPerPage = 20, $pageID = 1)
- {
- /* Set browseType, productID, moduleID and queryID. */
- $browseType = strtolower($browseType);
- $productID = $this->product->saveState($productID, $this->products);
- $moduleID = ($browseType == 'bymodule') ? (int)$param : 0;
- $queryID = ($browseType == 'bysearch') ? (int)$param : 0;
-
- /* Set menu and save session. */
- $this->bug->setMenu($this->products, $productID);
- $this->session->set('bugList', $this->app->getURI(true));
-
- /* Process the order by field. */
- if(!$orderBy) $orderBy = $this->cookie->qaBugOrder ? $this->cookie->qaBugOrder : 'id_desc';
- setcookie('qaBugOrder', $orderBy, $this->config->cookieLife, $this->config->webRoot);
-
- /* Load pager. */
- $this->app->loadClass('pager', $static = true);
- $pager = pager::init($recTotal, $recPerPage, $pageID);
-
- $projects = $this->loadModel('project')->getPairs();
- $projects[0] = '';
-
- /* Get bugs. */
- $bugs = array();
- if($browseType == 'all') $bugs = $this->bug->getAllBugs($productID, $projects, $orderBy, $pager);
- elseif($browseType == "bymodule")
- {
- $childModuleIds = $this->tree->getAllChildId($moduleID);
- $bugs = $this->bug->getModuleBugs($productID, $childModuleIds, $projects, $orderBy, $pager);
- }
- elseif($browseType == 'assigntome') $bugs = $this->bug->getByAssigntome($productID, $projects, $orderBy, $pager);
- elseif($browseType == 'openedbyme') $bugs = $this->bug->getByOpenedbyme($productID, $projects, $orderBy, $pager);
- elseif($browseType == 'resolvedbyme') $bugs = $this->bug->getByResolvedbyme($productID, $projects, $orderBy, $pager);
- elseif($browseType == 'assigntonull') $bugs = $this->bug->getByAssigntonull($productID, $projects, $orderBy, $pager);
- elseif($browseType == 'unresolved') $bugs = $this->bug->getByStatus($productID, $projects, 'unresolved', $orderBy, $pager);
- elseif($browseType == 'unclosed') $bugs = $this->bug->getByStatus($productID, $projects, 'unclosed', $orderBy, $pager);
- elseif($browseType == 'longlifebugs') $bugs = $this->bug->getByLonglifebugs($productID, $projects, $orderBy, $pager);
- elseif($browseType == 'postponedbugs') $bugs = $this->bug->getByPostponedbugs($productID, $projects, $orderBy, $pager);
- elseif($browseType == 'needconfirm') $bugs = $this->bug->getByNeedconfirm($productID, $projects, $orderBy, $pager);
- elseif($browseType == 'bysearch') $bugs = $this->bug->getBySearch($productID, $projects, $queryID, $orderBy, $pager);
-
- /* Process the sql, get the conditon partion, save it to session. */
- $this->loadModel('common')->saveQueryCondition($this->dao->get(), 'bug', $browseType == 'needconfirm' ? false : true);
-
- /* Get custom fields. */
- $customFields = $this->cookie->bugFields != false ? $this->cookie->bugFields : $this->config->bug->list->defaultFields;
- $customed = !($customFields == $this->config->bug->list->defaultFields);
-
- /* If customed, get related name or titles. */
- if($customed) $bugs = $this->bug->formCustomedBugs($bugs);
-
- /* Build the search form. */
- $this->config->bug->search['actionURL'] = $this->createLink('bug', 'browse', "productID=$productID&browseType=bySearch&queryID=myQueryID");
- $this->config->bug->search['queryID'] = $queryID;
- $this->config->bug->search['params']['product']['values'] = array($productID => $this->products[$productID], 'all' => $this->lang->bug->allProduct);
- $this->config->bug->search['params']['module']['values'] = $this->tree->getOptionMenu($productID, $viewType = 'bug', $startModuleID = 0);
- $this->config->bug->search['params']['project']['values'] = $this->product->getProjectPairs($productID);
- $this->config->bug->search['params']['openedBuild']['values'] = $this->loadModel('build')->getProductBuildPairs($productID);
- $this->config->bug->search['params']['resolvedBuild']['values'] = $this->build->getProductBuildPairs($productID);
- $this->loadModel('search')->setSearchParams($this->config->bug->search);
-
- $users = $this->user->getPairs('noletter');
-
- /* Process the openedBuild and resolvedBuild fields. */
- $productIdList = array();
- foreach($bugs as $bug) $productIdList[$bug->id] = $bug->product;
- $builds = $this->loadModel('build')->getProductBuildPairs(array_unique($productIdList));
- foreach($bugs as $key => $bug)
- {
- $openBuildIdList = explode(',', $bug->openedBuild);
- $openedBuild = '';
- foreach($openBuildIdList as $buildID)
- {
- $openedBuild .= isset($builds[$buildID]) ? $builds[$buildID] : $buildID;
- $openedBuild .= ',';
- }
- $bug->openedBuild = rtrim($openedBuild, ',');
- $bug->resolvedBuild = isset($builds[$bug->resolvedBuild]) ? $builds[$bug->resolvedBuild] : $bug->resolvedBuild;
- }
-
- $header['title'] = $this->products[$productID] . $this->lang->colon . $this->lang->bug->common;
- $position[] = html::a($this->createLink('bug', 'browse', "productID=$productID"), $this->products[$productID]);
- $position[] = $this->lang->bug->common;
-
- $this->view->header = $header;
- $this->view->position = $position;
- $this->view->productID = $productID;
- $this->view->productName = $this->products[$productID];
- $this->view->moduleTree = $this->tree->getTreeMenu($productID, $viewType = 'bug', $startModuleID = 0, array('treeModel', 'createBugLink'));
- $this->view->browseType = $browseType;
- $this->view->bugs = $bugs;
- $this->view->users = $users;
- $this->view->pager = $pager;
- $this->view->param = $param;
- $this->view->orderBy = $orderBy;
- $this->view->moduleID = $moduleID;
- $this->view->customed = $customed;
- $this->view->customFields= explode(',', str_replace(' ', '', trim($customFields)));
- $this->view->treeClass = $browseType == 'bymodule' ? '' : 'hidden';
-
- $this->display();
- }
-
- /**
- * The report page.
- *
- * @param int $productID
- * @param string $browseType
- * @param int $moduleID
- * @access public
- * @return void
- */
- public function report($productID, $browseType, $moduleID)
- {
- $this->loadModel('report');
- $this->view->charts = array();
- $this->view->renderJS = '';
-
- if(!empty($_POST))
- {
- foreach($this->post->charts as $chart)
- {
- $chartFunc = 'getDataOf' . $chart;
- $chartData = $this->bug->$chartFunc();
- $chartOption = $this->lang->bug->report->$chart;
- $this->bug->mergeChartOption($chart);
-
- $chartXML = $this->report->createSingleXML($chartData, $chartOption->graph);
- $this->view->charts[$chart] = $this->report->createJSChart($chartOption->swf, $chartXML, $chartOption->width, $chartOption->height);
- $this->view->datas[$chart] = $this->report->computePercent($chartData);
- }
- $this->view->renderJS = $this->report->renderJsCharts(count($this->view->charts));
- }
-
- $this->bug->setMenu($this->products, $productID);
- $this->view->header->title = $this->products[$productID] . $this->lang->colon . $this->lang->bug->common;
- $this->view->productID = $productID;
- $this->view->browseType = $browseType;
- $this->view->moduleID = $moduleID;
- $this->view->checkedCharts = $this->post->charts ? join(',', $this->post->charts) : '';
- $this->display();
- }
-
- /**
- * Create a bug.
- *
- * @param int $productID
- * @param string $extras others params, forexample, projectID=10,moduleID=10
- * @access public
- * @return void
- */
- public function create($productID, $extras = '')
- {
- $this->view->users = $this->user->getPairs('nodeleted,devfirst');
- if(empty($this->products)) $this->locate($this->createLink('product', 'create'));
-
- if(!empty($_POST))
- {
- $bugID = $this->bug->create();
- if(dao::isError()) die(js::error(dao::getError()));
- $actionID = $this->action->create('bug', $bugID, 'Opened');
- $this->sendmail($bugID, $actionID);
- die(js::locate($this->createLink('bug', 'browse', "productID={$this->post->product}&type=byModule¶m={$this->post->module}"), 'parent'));
- }
-
- /* Get product, then set menu. */
- $productID = $this->product->saveState($productID, $this->products);
- $this->bug->setMenu($this->products, $productID);
-
- /* Remove the unused types. */
- unset($this->lang->bug->typeList['designchange']);
- unset($this->lang->bug->typeList['newfeature']);
- unset($this->lang->bug->typeList['trackthings']);
-
- /* Init vars. */
- $moduleID = 0;
- $projectID = 0;
- $taskID = 0;
- $storyID = 0;
- $buildID = 0;
- $caseID = 0;
- $runID = 0;
- $title = '';
- $steps = $this->lang->bug->tplStep . $this->lang->bug->tplResult . $this->lang->bug->tplExpect;
- $os = '';
- $browser = '';
- $assignedTo = '';
- $mailto = '';
- $keywords = '';
- $severity = 3;
- $type = 'codeerror';
-
- /* Parse the extras. */
- $extras = str_replace(array(',', ' '), array('&', ''), $extras);
- parse_str($extras);
-
- /* If set runID, get the last result info as the template. */
- if($runID > 0) $resultID = $this->dao->select('id')->from(TABLE_TESTRESULT)->where('run')->eq($runID)->orderBy('id desc')->limit(1)->fetch('id');
- if(isset($resultID) and $resultID > 0) extract($this->bug->getBugInfoFromResult($resultID));
-
- /* If set caseID and runID='', get the last result info as the template. */
- if($caseID > 0 && $runID == '')
- {
- $resultID = $this->dao->select('id')->from(TABLE_TESTRESULT)->where('`case`')->eq($caseID)->orderBy('date desc')->limit(1)->fetch('id');
- if(isset($resultID) and $resultID > 0) extract($this->bug->getBugInfoFromResult($resultID, $caseID, $version));
- }
-
- /* If bugID setted, use this bug as template. */
- if(isset($bugID))
- {
- $bug = $this->bug->getById($bugID);
- extract((array)$bug);
- $projectID = $bug->project;
- $moduleID = $bug->module;
- $taskID = $bug->task;
- $storyID = $bug->story;
- $buildID = $bug->openedBuild;
- $severity = $bug->severity;
- $type = $bug->type;
- }
-
- /* If projectID is setted, get builds and stories of this project. */
- if($projectID)
- {
- $builds = $this->loadModel('build')->getProjectBuildPairs($projectID, $productID, 'noempty');
- $stories = $this->story->getProjectStoryPairs($projectID);
- }
- else
- {
- $builds = $this->loadModel('build')->getProductBuildPairs($productID, 'noempty');
- $stories = $this->story->getProductStoryPairs($productID);
- }
- $this->view->header->title = $this->products[$productID] . $this->lang->colon . $this->lang->bug->create;
- $this->view->position[] = html::a($this->createLink('bug', 'browse', "productID=$productID"), $this->products[$productID]);
- $this->view->position[] = $this->lang->bug->create;
-
- $this->view->productID = $productID;
- $this->view->productName = $this->products[$productID];
- $this->view->moduleOptionMenu = $this->tree->getOptionMenu($productID, $viewType = 'bug', $startModuleID = 0);
- $this->view->stories = $stories;
- $this->view->projects = $this->product->getProjectPairs($productID, $params = 'nodeleted');
- $this->view->builds = $builds;
- $this->view->tasks = $this->loadModel('task')->getProjectTaskPairs($projectID);
- $this->view->moduleID = $moduleID;
- $this->view->projectID = $projectID;
- $this->view->taskID = $taskID;
- $this->view->storyID = $storyID;
- $this->view->buildID = $buildID;
- $this->view->caseID = $caseID;
- $this->view->title = $title;
- $this->view->steps = htmlspecialchars($steps);
- $this->view->os = $os;
- $this->view->browser = $browser;
- $this->view->assignedTo = $assignedTo;
- $this->view->mailto = $mailto;
- $this->view->contactLists = $this->user->getContactLists($this->app->user->account, 'withnote');
- $this->view->keywords = $keywords;
- $this->view->severity = $severity;
- $this->view->type = $type;
-
- $this->display();
- }
-
- /**
- * View a bug.
- *
- * @param int $bugID
- * @access public
- * @return void
- */
- public function view($bugID)
- {
- /* Judge bug exits or not. */
- $bug = $this->bug->getById($bugID, true);
- if(!$bug) die(js::error($this->lang->notFound) . js::locate('back'));
-
- /* Update action. */
- if($bug->assignedTo == $this->app->user->account) $this->loadModel('action')->read('bug', $bugID);
-
- /* Set menu. */
- $this->bug->setMenu($this->products, $bug->product);
-
- /* Get product info. */
- $productID = $bug->product;
- $productName = $this->products[$productID];
-
- /* Header and positon. */
- $this->view->header->title = "BUG #$bug->id $bug->title - " . $this->products[$productID];
- $this->view->position[] = html::a($this->createLink('bug', 'browse', "productID=$productID"), $productName);
- $this->view->position[] = $this->lang->bug->view;
-
- /* Assign. */
- $this->view->productID = $productID;
- $this->view->productName = $productName;
- $this->view->modulePath = $this->tree->getParents($bug->module);
- $this->view->bug = $bug;
- $this->view->users = $this->user->getPairs('noletter');
- $this->view->actions = $this->action->getList('bug', $bugID);
- $this->view->builds = $this->loadModel('build')->getProductBuildPairs($productID);
- $this->view->preAndNext = $this->loadModel('common')->getPreAndNextObject('bug', $bugID);
-
- $this->display();
- }
-
- /**
- * Edit a bug.
- *
- * @param int $bugID
- * @access public
- * @return void
- */
- public function edit($bugID, $comment = false)
- {
- if(!empty($_POST))
- {
- $changes = array();
- $files = array();
- if($comment == false)
- {
- $changes = $this->bug->update($bugID);
- if(dao::isError()) die(js::error(dao::getError()));
- $files = $this->loadModel('file')->saveUpload('bug', $bugID);
- }
- if($this->post->comment != '' or !empty($changes) or !empty($files))
- {
- $action = !empty($changes) ? 'Edited' : 'Commented';
- $fileAction = '';
- if(!empty($files)) $fileAction = $this->lang->addFiles . join(',', $files) . "\n" ;
- $actionID = $this->action->create('bug', $bugID, $action, $fileAction . $this->post->comment);
- $this->action->logHistory($actionID, $changes);
- $this->sendmail($bugID, $actionID);
- }
-
- $bug = $this->bug->getById($bugID);
- if($bug->toTask != 0)
- {
- foreach($changes as $change)
- {
- 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'));
- }
-
- /* Get the info of bug, current product and modue. */
- $bug = $this->bug->getById($bugID);
- $productID = $bug->product;
- $projectID = $bug->project;
- $currentModuleID = $bug->module;
-
- /**
- * Remove designchange, newfeature, trackings from the typeList, because should be tracked in story or task.
- * These thress types if upgrade from bugfree2.x.
- */
- if($bug->type != 'designchange') unset($this->lang->bug->typeList['designchange']);
- if($bug->type != 'newfeature') unset($this->lang->bug->typeList['newfeature']);
- if($bug->type != 'trackthings') unset($this->lang->bug->typeList['trackthings']);
-
- /* Set the menu. */
- $this->bug->setMenu($this->products, $productID);
-
- /* Set header and position. */
- $this->view->header->title = $this->products[$productID] . $this->lang->colon . $this->lang->bug->edit;
- $this->view->position[] = html::a($this->createLink('bug', 'browse', "productID=$productID"), $this->products[$productID]);
- $this->view->position[] = $this->lang->bug->edit;
-
- /* Assign. */
- if($projectID)
- {
- $this->view->openedBuilds = $this->loadModel('build')->getProjectBuildPairs($projectID, $productID, 'noempty');
- }
- else
- {
- $this->view->openedBuilds = $this->loadModel('build')->getProductBuildPairs($productID, 'noempty');
- }
- $this->view->bug = $bug;
- $this->view->productID = $productID;
- $this->view->productName = $this->products[$productID];
- $this->view->moduleOptionMenu = $this->tree->getOptionMenu($productID, $viewType = 'bug', $startModuleID = 0);
- $this->view->currentModuleID = $currentModuleID;
- $this->view->projects = $this->product->getProjectPairs($bug->product);
- $this->view->stories = $bug->project ? $this->story->getProjectStoryPairs($bug->project) : $this->story->getProductStoryPairs($bug->product);
- $this->view->tasks = $this->task->getProjectTaskPairs($bug->project);
- $this->view->users = $this->user->appendDeleted($this->user->getPairs('nodeleted'), "$bug->assignedTo,$bug->resolvedBy,$bug->closedBy");
- $this->view->resolvedBuilds = array('' => '') + $this->view->openedBuilds;
- $this->view->actions = $this->action->getList('bug', $bugID);
- $this->view->templates = $this->bug->getUserBugTemplates($this->app->user->account);
-
- $this->display();
- }
-
- /**
- * Batch edit bug.
- *
- * @param string $from example:bugBrowse, bugBatchEdit.
- * @param int $productID
- * @param string $orderBy
- * @access public
- * @return void
- */
- public function batchEdit($from = '', $productID = 0, $orderBy = '')
- {
- if($from == 'bugBrowse')
- {
- /* Initialize vars.*/
- if(!$orderBy) $orderBy = $this->cookie->qaBugOrder ? $this->cookie->qaBugOrder : 'id_desc';
- $editedBugs = array();
- $allBugs = $this->dao->select('*')->from(TABLE_BUG)->alias('t1')->where($this->session->bugQueryCondition)->orderBy($orderBy)->fetchAll('id');
- $bugIDList = $this->post->bugIDList ? $this->post->bugIDList : array();
- $product = $this->product->getByID($productID);
- $columns = 9;
- $showSuhosinInfo = false;
-
- /* Set product menu. */
- $this->bug->setMenu($this->products, $productID);
-
- /* Initialize the tasks whose need to edited. */
- foreach($allBugs as $bug) if(in_array($bug->id, $bugIDList)) $editedBugs[$bug->id] = $bug;
-
- /* Judge whether the editedTasks is too large. */
- $showSuhosinInfo = $this->loadModel('common')->judgeSuhosinSetting(count($editedBugs), $columns);
-
- /* Set the sessions. */
- $this->app->session->set('showSuhosinInfo', $showSuhosinInfo);
-
- /* Assign. */
- $this->view->header->title = $product->name . $this->lang->colon . $this->lang->bug->batchEdit;
- $this->view->position[] = html::a($this->createLink('bug', 'browse', "productID=$productID"), $this->products[$productID]);
- $this->view->position[] = $this->lang->bug->common;
- $this->view->position[] = $this->lang->bug->batchEdit;
-
- if($showSuhosinInfo) $this->view->suhosinInfo = $this->lang->suhosinInfo;
- $this->view->productID = $productID;
- $this->view->editedBugs = $editedBugs;
- $this->view->users = $this->user->getPairs('nodeleted,devfirst');
-
- $this->display();
- }
- elseif($from == 'bugBatchEdit')
- {
- $allChanges = $this->bug->batchUpdate();
-
- foreach($allChanges as $bugID => $changes)
- {
- $actionID = $this->action->create('bug', $bugID, 'Edited');
- $this->action->logHistory($actionID, $changes);
- $this->sendmail($bugID, $actionID);
-
- $bug = $this->bug->getById($bugID);
- if($bug->toTask != 0)
- {
- foreach($changes as $change)
- {
- 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->session->bugList, 'parent'));
- }
- }
-
- /**
- * Update assign of bug.
- *
- * @param int $bugID
- * @access public
- * @return void
- */
- public function assignTo($bugID)
- {
- $bug = $this->bug->getById($bugID);
-
- /* Set menu. */
- $this->bug->setMenu($this->products, $bug->product);
-
- if(!empty($_POST))
- {
- $this->loadModel('action');
- $changes = $this->bug->assign($bugID);
- if(dao::isError()) die(js::error(dao::getError()));
- $actionID = $this->action->create('bug', $bugID, 'Assigned', $this->post->comment, $this->post->assignedTo);
- $this->action->logHistory($actionID, $changes);
- $this->sendmail($bugID, $actionID);
-
- die(js::locate($this->createLink('bug', 'view', "bugID=$bugID"), 'parent'));
- }
-
- $this->view->header->title = $this->products[$bug->product] . $this->lang->colon . $this->lang->bug->assignedTo;
- $this->view->position[] = $this->lang->bug->assignedTo;
-
- $this->view->users = $this->user->getPairs('nodeleted');
- $this->view->bug = $bug;
- $this->view->bugID = $bugID;
- $this->view->actions = $this->action->getList('bug', $bugID);
- $this->display();
- }
-
- /**
- * confirm a bug.
- *
- * @param int $bugID
- * @access public
- * @return void
- */
- public function confirmBug($bugID)
- {
- if(!empty($_POST))
- {
- $this->bug->confirm($bugID);
- if(dao::isError()) die(js::error(dao::getError()));
- $actionID = $this->action->create('bug', $bugID, 'bugConfirmed', $this->post->comment);
- $this->sendmail($bugID, $actionID);
- die(js::locate($this->createLink('bug', 'view', "bugID=$bugID"), 'parent'));
- }
-
- $bug = $this->bug->getById($bugID);
- $productID = $bug->product;
- $this->bug->setMenu($this->products, $productID);
-
- $this->view->header->title = $this->products[$productID] . $this->lang->colon . $this->lang->bug->confirmBug;
- $this->view->position[] = html::a($this->createLink('bug', 'browse', "productID=$productID"), $this->products[$productID]);
- $this->view->position[] = $this->lang->bug->confirmBug;
-
- $this->view->bug = $bug;
- $this->view->users = $this->user->getPairs('noletter');
- $this->view->actions = $this->action->getList('bug', $bugID);
- $this->display();
- }
-
- /**
- * Resolve a bug.
- *
- * @param int $bugID
- * @access public
- * @return void
- */
- public function resolve($bugID)
- {
- $this->view->users = $this->user->getPairs('nodeleted');
- if(!empty($_POST))
- {
- $this->bug->resolve($bugID);
- if(dao::isError()) die(js::error(dao::getError()));
- $actionID = $this->action->create('bug', $bugID, 'Resolved', $this->post->comment, $this->post->resolution);
- $this->sendmail($bugID, $actionID);
-
- $bug = $this->bug->getById($bugID);
- if($bug->toTask != 0)
- {
- $confirmURL = $this->createLink('task', 'view', "taskID=$bug->toTask");
- $cancelURL = $this->createLink('bug', 'view', "bugID=$bugID");
- die(js::confirm(sprintf($this->lang->bug->remindTask, $bug->toTask), $confirmURL, $cancelURL, 'parent', 'parent'));
- }
- die(js::locate($this->createLink('bug', 'view', "bugID=$bugID"), 'parent'));
- }
-
- $bug = $this->bug->getById($bugID);
- $productID = $bug->product;
- $this->bug->setMenu($this->products, $productID);
-
- $this->view->header->title = $this->products[$productID] . $this->lang->colon . $this->lang->bug->resolve;
- $this->view->position[] = html::a($this->createLink('bug', 'browse', "productID=$productID"), $this->products[$productID]);
- $this->view->position[] = $this->lang->bug->resolve;
-
- $this->view->bug = $bug;
- $this->view->builds = $this->loadModel('build')->getProductBuildPairs($productID);
- $this->view->actions = $this->action->getList('bug', $bugID);
- $this->display();
- }
-
- /**
- * Activate a bug.
- *
- * @param int $bugID
- * @access public
- * @return void
- */
- public function activate($bugID)
- {
- $this->view->users = $this->user->getPairs('nodeleted');
-
- if(!empty($_POST))
- {
- $this->bug->activate($bugID);
- if(dao::isError()) die(js::error(dao::getError()));
- $files = $this->loadModel('file')->saveUpload('bug', $bugID);
- $actionID = $this->action->create('bug', $bugID, 'Activated', $this->post->comment);
- $this->sendmail($bugID, $actionID);
- die(js::locate($this->createLink('bug', 'view', "bugID=$bugID"), 'parent'));
- }
-
- $bug = $this->bug->getById($bugID);
- $productID = $bug->product;
- $this->bug->setMenu($this->products, $productID);
-
- $this->view->header->title = $this->products[$productID] . $this->lang->colon . $this->lang->bug->activate;
- $this->view->position[] = html::a($this->createLink('bug', 'browse', "productID=$productID"), $this->products[$productID]);
- $this->view->position[] = $this->lang->bug->activate;
-
- $this->view->bug = $bug;
- $this->view->builds = $this->loadModel('build')->getProductBuildPairs($productID, 'noempty');
- $this->view->actions = $this->action->getList('bug', $bugID);
-
- $this->display();
- }
-
- /**
- * Close a bug.
- *
- * @param int $bugID
- * @access public
- * @return void
- */
- public function close($bugID)
- {
- $this->view->users = $this->user->getPairs('noletter');
- if(!empty($_POST))
- {
- $this->bug->close($bugID);
- if(dao::isError()) die(js::error(dao::getError()));
- $actionID = $this->action->create('bug', $bugID, 'Closed', $this->post->comment);
- $this->sendmail($bugID, $actionID);
- die(js::locate($this->createLink('bug', 'view', "bugID=$bugID"), 'parent'));
- }
-
- $bug = $this->bug->getById($bugID);
- $productID = $bug->product;
- $this->bug->setMenu($this->products, $productID);
-
- $this->view->header->title = $this->products[$productID] . $this->lang->colon . $this->lang->bug->close;
- $this->view->position[] = html::a($this->createLink('bug', 'browse', "productID=$productID"), $this->products[$productID]);
- $this->view->position[] = $this->lang->bug->close;
-
- $this->view->bug = $bug;
- $this->view->actions = $this->action->getList('bug', $bugID);
- $this->display();
- }
-
- /**
- * Confirm story change.
- *
- * @param int $bugID
- * @access public
- * @return void
- */
- public function confirmStoryChange($bugID)
- {
- $bug = $this->bug->getById($bugID);
- $this->dao->update(TABLE_BUG)->set('storyVersion')->eq($bug->latestStoryVersion)->where('id')->eq($bugID)->exec();
- $this->loadModel('action')->create('bug', $bugID, 'confirmed', '', $bug->latestStoryVersion);
- die(js::reload('parent'));
- }
-
- /**
- * Delete a bug.
- *
- * @param int $bugID
- * @param string $confirm yes|no
- * @access public
- * @return void
- */
- public function delete($bugID, $confirm = 'no')
- {
- $bug = $this->bug->getById($bugID);
- if($confirm == 'no')
- {
- die(js::confirm($this->lang->bug->confirmDelete, inlink('delete', "bugID=$bugID&confirm=yes")));
- }
- else
- {
- $this->bug->delete(TABLE_BUG, $bugID);
- if($bug->toTask != 0) echo js::alert($this->lang->bug->remindTask . $bug->toTask);
- die(js::locate($this->session->bugList, 'parent'));
- }
- }
-
- /**
- * Save current template.
- *
- * @access public
- * @return string
- */
- public function saveTemplate()
- {
- $this->bug->saveUserBugTemplate();
- if(dao::isError()) die(js::error(dao::getError()));
- die($this->fetch('bug', 'buildTemplates'));
- }
-
- /**
- * Build the user templates selection code.
- *
- * @access public
- * @return void
- */
- public function buildTemplates()
- {
- $this->view->templates = $this->bug->getUserBugTemplates($this->app->user->account);
- $this->display('bug', 'buildTemplates');
- }
-
- /**
- * Delete a user template.
- *
- * @param int $templateID
- * @access public
- * @return void
- */
- public function deleteTemplate($templateID)
- {
- $this->dao->delete()->from(TABLE_USERTPL)->where('id')->eq($templateID)->andWhere('account')->eq($this->app->user->account)->exec();
- die();
- }
-
- /**
- * Custom fields.
- *
- * @access public
- * @return void
- */
- public function customFields()
- {
- if($_POST)
- {
- $customFields = $this->post->customFields;
- $customFields = join(',', $customFields);
- setcookie('bugFields', $customFields, $this->config->cookieLife, $this->config->webRoot);
- die(js::reload('parent'));
- }
-
- $customFields = $this->cookie->bugFields ? $this->cookie->bugFields : $this->config->bug->list->defaultFields;
-
- $this->view->allFields = $this->bug->getFieldPairs($this->config->bug->list->allFields);
- $this->view->customFields = $this->bug->getFieldPairs($customFields);
- $this->view->defaultFields = $this->bug->getFieldPairs($this->config->bug->list->defaultFields);
- die($this->display());
- }
-
- /**
- * AJAX: get bugs of a user in html select.
- *
- * @param string $account
- * @param string $id the id of the select control.
- * @access public
- * @return string
- */
- public function ajaxGetUserBugs($account = '', $id = '')
- {
- if($account == '') $account = $this->app->user->account;
- $bugs = $this->bug->getUserBugPairs($account);
-
- if($id) die(html::select("bugs[$id]", $bugs, '', 'class="select-1 f-left"'));
- die(html::select('bug', $bugs, '', 'class=select-1'));
- }
-
- /**
- * AJAX: Get bug owner of a module.
- *
- * @param int $moduleID
- * @param int $productID
- * @access public
- * @return string
- */
- public function ajaxGetModuleOwner($moduleID, $productID = 0)
- {
- $owner = '';
- if($moduleID) $owner = $this->dao->findByID($moduleID)->from(TABLE_MODULE)->fetch('owner');
- if(!$owner) $owner = $this->dao->findByID($productID)->from(TABLE_PRODUCT)->fetch('QD');
- die($owner);
- }
-
- /**
- * AJAX: get assignedTo list, make sure the members of the project at the first.
- *
- * @param int $projectID
- * @param string $selectedUser
- * @access public
- * @return string
- */
- public function ajaxLoadAssignedTo($projectID, $selectedUser = '')
- {
- $allUsers = $this->loadModel('user')->getPairs('nodeleted, devfirst');
- $projectMembers = $this->loadModel('project')->getTeamMemberPairs($projectID);
- $assignedToList = array_merge($projectMembers, $allUsers);
-
- die(html::select('assignedTo', $assignedToList, $selectedUser, 'class="select-3"'));
- }
-
- /**
- * Send email.
- *
- * @param int $bugID
- * @param int $actionID
- * @access public
- * @return void
- */
- public function sendmail($bugID, $actionID)
- {
- /* Set toList and ccList. */
- $bug = $this->bug->getByID($bugID);
- $productName = $this->products[$bug->product];
- $toList = $bug->assignedTo;
- $ccList = trim($bug->mailto, ',');
- if($toList == '')
- {
- if($ccList == '') return;
- if(strpos($ccList, ',') === false)
- {
- $toList = $ccList;
- $ccList = '';
- }
- else
- {
- $commaPos = strpos($ccList, ',');
- $toList = substr($ccList, 0, $commaPos);
- $ccList = substr($ccList, $commaPos + 1);
- }
- }
- elseif(strtolower($toList) == 'closed')
- {
- $toList = $bug->resolvedBy;
- }
-
- /* Get action info. */
- $action = $this->action->getById($actionID);
- $history = $this->action->getHistory($actionID);
- $action->history = isset($history[$actionID]) ? $history[$actionID] : array();
- if(strtolower($action->action) == 'opened') $action->comment = $bug->steps;
-
- /* Create the mail content. */
- if($action->action == 'opened') $action->comment = '';
- $this->view->bug = $bug;
- $this->view->action = $action;
- $mailContent = $this->parse($this->moduleName, 'sendmail');
-
- /* Send it. */
- $this->loadModel('mail')->send($toList, $productName . ':' . 'BUG #'. $bug->id . $this->lang->colon . $bug->title, $mailContent, $ccList);
- if($this->mail->isError()) echo js::error($this->mail->getError());
- }
-
- /**
- * Get data to export
- *
- * @param string $productID
- * @param string $orderBy
- * @access public
- * @return void
- */
- public function export($productID, $orderBy)
- {
- if($_POST)
- {
- $bugLang = $this->lang->bug;
- $bugConfig = $this->config->bug;
-
- /* Create field lists. */
- $fields = explode(',', $bugConfig->list->exportFields);
- foreach($fields as $key => $fieldName)
- {
- $fieldName = trim($fieldName);
- $fields[$fieldName] = isset($bugLang->$fieldName) ? $bugLang->$fieldName : $fieldName;
- unset($fields[$key]);
- }
-
- /* Get bugs. */
- $bugs = $this->dao->select('*')->from(TABLE_BUG)->where($this->session->bugQueryCondition)
- ->beginIF($this->post->exportType == 'selected')->andWhere('id')->in($this->cookie->checkedItem)->fi()
- ->orderBy($orderBy)->fetchAll('id');
-
- /* Get users, products and projects. */
- $users = $this->loadModel('user')->getPairs('noletter');
- $products = $this->loadModel('product')->getPairs();
- $projects = $this->loadModel('project')->getPairs('all');
-
- /* Get related objects id lists. */
- $relatedModuleIdList = array();
- $relatedStoryIdList = array();
- $relatedTaskIdList = array();
- $relatedBugIdList = array();
- $relatedCaseIdList = array();
- $relatedBuildIdList = array();
-
- foreach($bugs as $bug)
- {
- $relatedModuleIdList[$bug->module] = $bug->module;
- $relatedStoryIdList[$bug->story] = $bug->story;
- $relatedTaskIdList[$bug->task] = $bug->task;
- $relatedCaseIdList[$bug->case] = $bug->case;
- $relatedBugIdList[$bug->duplicateBug] = $bug->duplicateBug;
-
- /* Process link bugs. */
- $linkBugs = explode(',', $bug->linkBug);
- foreach($linkBugs as $linkBugID)
- {
- if($linkBugID) $relatedBugIdList[$linkBugID] = trim($linkBugID);
- }
-
- /* Process builds. */
- $builds = $bug->openedBuild . ',' . $bug->resolvedBuild;
- $builds = explode(',', $builds);
- foreach($builds as $buildID)
- {
- if($buildID) $relatedBuildIdList[$buildID] = trim($buildID);
- }
- }
-
- /* Get related objects title or names. */
- $relatedModules = $this->dao->select('id, name')->from(TABLE_MODULE)->where('id')->in($relatedModuleIdList)->fetchPairs();
- $relatedStories = $this->dao->select('id,title')->from(TABLE_STORY) ->where('id')->in($relatedStoryIdList)->fetchPairs();
- $relatedTasks = $this->dao->select('id, name')->from(TABLE_TASK)->where('id')->in($relatedTaskIdList)->fetchPairs();
- $relatedBugs = $this->dao->select('id, title')->from(TABLE_BUG)->where('id')->in($relatedBugIdList)->fetchPairs();
- $relatedCases = $this->dao->select('id, title')->from(TABLE_CASE)->where('id')->in($relatedCaseIdList)->fetchPairs();
- $relatedBuilds = $this->dao->select('id, name')->from(TABLE_BUILD)->where('id')->in($relatedBuildIdList)->fetchPairs();
- $relatedFiles = $this->dao->select('id, objectID, pathname, title')->from(TABLE_FILE)->where('objectType')->eq('bug')->andWhere('objectID')->in(@array_keys($bugs))->fetchGroup('objectID');
-
- foreach($bugs as $bug)
- {
- if($this->post->fileType == 'csv')
- {
- $bug->steps = htmlspecialchars_decode($bug->steps);
- $bug->steps = str_replace(" ", "\n", $bug->steps);
- $bug->steps = str_replace('"', '""', $bug->steps);
- $bug->steps = str_replace(' ', ' ', $bug->steps);
- $bug->steps = strip_tags($bug->steps);
- }
-
- /* fill some field with useful value. */
- if(isset($products[$bug->product])) $bug->product = $products[$bug->product];
- if(isset($projects[$bug->project])) $bug->project = $projects[$bug->project];
- if(isset($relatedModules[$bug->module])) $bug->module = $relatedModules[$bug->module];
- if(isset($relatedStories[$bug->story])) $bug->story = $relatedStories[$bug->story];
- if(isset($relatedTasks[$bug->task])) $bug->task = $relatedTasks[$bug->task];
- if(isset($relatedBugs[$bug->duplicateBug])) $bug->duplicateBug = $relatedBugs[$bug->duplicateBug];
- if(isset($relatedCases[$bug->case])) $bug->case = $relatedCases[$bug->case];
-
- if(isset($bugLang->priList[$bug->pri])) $bug->pri = $bugLang->priList[$bug->pri];
- if(isset($bugLang->typeList[$bug->type])) $bug->type = $bugLang->typeList[$bug->type];
- if(isset($bugLang->statusList[$bug->status])) $bug->status = $bugLang->statusList[$bug->status];
- if(isset($bugLang->confirmedList[$bug->confirmed])) $bug->confirmed = $bugLang->confirmedList[$bug->confirmed];
- if(isset($bugLang->resolutionList[$bug->resolution])) $bug->resolution = $bugLang->resolutionList[$bug->resolution];
-
- if(isset($users[$bug->openedBy])) $bug->openedBy = $users[$bug->openedBy];
- if(isset($users[$bug->assignedTo])) $bug->assignedTo = $users[$bug->assignedTo];
- if(isset($users[$bug->resolvedBy])) $bug->resolvedBy = $users[$bug->resolvedBy];
- if(isset($users[$bug->lastEditedBy])) $bug->lastEditedBy = $users[$bug->lastEditedBy];
- if(isset($users[$bug->closedBy])) $bug->closedBy = $users[$bug->closedBy];
-
- $bug->openedDate = substr($bug->openedDate, 0, 10);
- $bug->assignedDate = substr($bug->assignedDate, 0, 10);
- $bug->closedDate = substr($bug->closedDate, 0, 10);
- $bug->resolvedDate = substr($bug->resolvedDate, 0, 10);
- $bug->lastEditedDate = substr($bug->lastEditedDate, 0, 10);
-
- if($bug->linkBug)
- {
- $tmpLinkBugs = array();
- $linkBugIdList = explode(',', $bug->linkBug);
- foreach($linkBugIdList as $linkBugID)
- {
- $linkBugID = trim($linkBugID);
- $tmpLinkBugs[] = isset($relatedBugs[$linkBugID]) ? $relatedBugs[$linkBugID] : $linkBugID;
- }
- $bug->linkBug = join("; \n", $tmpLinkBugs);
- }
-
- if($bug->openedBuild)
- {
- $tmpOpenedBuilds = array();
- $tmpResolvedBuilds = array();
- $buildIdList = explode(',', $bug->openedBuild);
- foreach($buildIdList as $buildID)
- {
- $buildID = trim($buildID);
- $tmpOpenedBuilds[] = isset($relatedBuilds[$buildID]) ? $relatedBuilds[$buildID] : $buildID;
- }
- $bug->openedBuild = join("; \n", $tmpOpenedBuilds);
- }
-
- if($bug->resolvedBuild)
- {
- $buildIdList = explode(',', $bug->resolvedBuild);
- foreach($buildIdList as $buildID)
- {
- $buildID = trim($buildID);
- $tmpResolvedBuilds[] = isset($relatedBuilds[$buildID]) ? $relatedBuilds[$buildID] : $buildID;
- }
- $bug->resolvedBuild = join("; \n", $tmpResolvedBuilds);
- }
-
- /* Set related files. */
- if(isset($relatedFiles[$bug->id]))
- {
- foreach($relatedFiles[$bug->id] as $file)
- {
- $fileURL = 'http://' . $this->server->http_host . $this->config->webRoot . "data/upload/$bug->company/" . $file->pathname;
- $bug->files .= html::a($fileURL, $file->title, '_blank') . ' ';
- }
- }
-
- $bug->mailto = trim(trim($bug->mailto), ',');
- $mailtos = explode(',', $bug->mailto);
- $bug->mailto = '';
- foreach($mailtos as $mailto)
- {
- $mailto = trim($mailto);
- if(isset($users[$mailto])) $bug->mailto .= $users[$mailto] . ',';
- }
-
- /* drop some field that is not needed. */
- unset($bug->company);
- unset($bug->caseVersion);
- unset($bug->result);
- unset($bug->deleted);
- }
-
- $this->post->set('fields', $fields);
- $this->post->set('rows', $bugs);
- $this->post->set('kind', 'bug');
- $this->fetch('file', 'export2' . $this->post->fileType, $_POST);
- }
-
- $this->display();
- }
-}
+
+ * @package bug
+ * @version $Id$
+ * @link http://www.zentao.net
+ */
+class bug extends control
+{
+ public $products = array();
+
+ /**
+ * Construct function, load some modules auto.
+ *
+ * @access public
+ * @return void
+ */
+ public function __construct()
+ {
+ parent::__construct();
+ $this->loadModel('product');
+ $this->loadModel('tree');
+ $this->loadModel('user');
+ $this->loadModel('action');
+ $this->loadModel('story');
+ $this->loadModel('task');
+ $this->products = $this->product->getPairs();
+ if(empty($this->products))
+ {
+ echo js::alert($this->lang->product->errorNoProduct);
+ die(js::locate($this->createLink('product', 'create')));
+ }
+ $this->view->products = $this->products;
+ }
+
+ /**
+ * The index page, locate to browse.
+ *
+ * @access public
+ * @return void
+ */
+ public function index()
+ {
+ $this->locate($this->createLink('bug', 'browse'));
+ }
+
+ /**
+ * Browse bugs.
+ *
+ * @param int $productID
+ * @param string $browseType
+ * @param int $param
+ * @param string $orderBy
+ * @param int $recTotal
+ * @param int $recPerPage
+ * @param int $pageID
+ * @access public
+ * @return void
+ */
+ public function browse($productID = 0, $browseType = 'byModule', $param = 0, $orderBy = '', $recTotal = 0, $recPerPage = 20, $pageID = 1)
+ {
+ /* Set browseType, productID, moduleID and queryID. */
+ $browseType = strtolower($browseType);
+ $productID = $this->product->saveState($productID, $this->products);
+ $moduleID = ($browseType == 'bymodule') ? (int)$param : 0;
+ $queryID = ($browseType == 'bysearch') ? (int)$param : 0;
+
+ /* Set menu and save session. */
+ $this->bug->setMenu($this->products, $productID);
+ $this->session->set('bugList', $this->app->getURI(true));
+
+ /* Process the order by field. */
+ if(!$orderBy) $orderBy = $this->cookie->qaBugOrder ? $this->cookie->qaBugOrder : 'id_desc';
+ setcookie('qaBugOrder', $orderBy, $this->config->cookieLife, $this->config->webRoot);
+
+ /* Load pager. */
+ $this->app->loadClass('pager', $static = true);
+ $pager = pager::init($recTotal, $recPerPage, $pageID);
+
+ $projects = $this->loadModel('project')->getPairs();
+ $projects[0] = '';
+
+ /* Get bugs. */
+ $bugs = array();
+ if($browseType == 'all') $bugs = $this->bug->getAllBugs($productID, $projects, $orderBy, $pager);
+ elseif($browseType == "bymodule")
+ {
+ $childModuleIds = $this->tree->getAllChildId($moduleID);
+ $bugs = $this->bug->getModuleBugs($productID, $childModuleIds, $projects, $orderBy, $pager);
+ }
+ elseif($browseType == 'assigntome') $bugs = $this->bug->getByAssigntome($productID, $projects, $orderBy, $pager);
+ elseif($browseType == 'openedbyme') $bugs = $this->bug->getByOpenedbyme($productID, $projects, $orderBy, $pager);
+ elseif($browseType == 'resolvedbyme') $bugs = $this->bug->getByResolvedbyme($productID, $projects, $orderBy, $pager);
+ elseif($browseType == 'assigntonull') $bugs = $this->bug->getByAssigntonull($productID, $projects, $orderBy, $pager);
+ elseif($browseType == 'unresolved') $bugs = $this->bug->getByStatus($productID, $projects, 'unresolved', $orderBy, $pager);
+ elseif($browseType == 'unclosed') $bugs = $this->bug->getByStatus($productID, $projects, 'unclosed', $orderBy, $pager);
+ elseif($browseType == 'longlifebugs') $bugs = $this->bug->getByLonglifebugs($productID, $projects, $orderBy, $pager);
+ elseif($browseType == 'postponedbugs') $bugs = $this->bug->getByPostponedbugs($productID, $projects, $orderBy, $pager);
+ elseif($browseType == 'needconfirm') $bugs = $this->bug->getByNeedconfirm($productID, $projects, $orderBy, $pager);
+ elseif($browseType == 'bysearch') $bugs = $this->bug->getBySearch($productID, $projects, $queryID, $orderBy, $pager);
+
+ /* Process the sql, get the conditon partion, save it to session. */
+ $this->loadModel('common')->saveQueryCondition($this->dao->get(), 'bug', $browseType == 'needconfirm' ? false : true);
+
+ /* Get custom fields. */
+ $customFields = $this->cookie->bugFields != false ? $this->cookie->bugFields : $this->config->bug->list->defaultFields;
+ $customed = !($customFields == $this->config->bug->list->defaultFields);
+
+ /* If customed, get related name or titles. */
+ if($customed) $bugs = $this->bug->formCustomedBugs($bugs);
+
+ /* Build the search form. */
+ $this->config->bug->search['actionURL'] = $this->createLink('bug', 'browse', "productID=$productID&browseType=bySearch&queryID=myQueryID");
+ $this->config->bug->search['queryID'] = $queryID;
+ $this->config->bug->search['params']['product']['values'] = array($productID => $this->products[$productID], 'all' => $this->lang->bug->allProduct);
+ $this->config->bug->search['params']['module']['values'] = $this->tree->getOptionMenu($productID, $viewType = 'bug', $startModuleID = 0);
+ $this->config->bug->search['params']['project']['values'] = $this->product->getProjectPairs($productID);
+ $this->config->bug->search['params']['openedBuild']['values'] = $this->loadModel('build')->getProductBuildPairs($productID);
+ $this->config->bug->search['params']['resolvedBuild']['values'] = $this->build->getProductBuildPairs($productID);
+ $this->loadModel('search')->setSearchParams($this->config->bug->search);
+
+ $users = $this->user->getPairs('noletter');
+
+ /* Process the openedBuild and resolvedBuild fields. */
+ $productIdList = array();
+ foreach($bugs as $bug) $productIdList[$bug->id] = $bug->product;
+ $builds = $this->loadModel('build')->getProductBuildPairs(array_unique($productIdList));
+ foreach($bugs as $key => $bug)
+ {
+ $openBuildIdList = explode(',', $bug->openedBuild);
+ $openedBuild = '';
+ foreach($openBuildIdList as $buildID)
+ {
+ $openedBuild .= isset($builds[$buildID]) ? $builds[$buildID] : $buildID;
+ $openedBuild .= ',';
+ }
+ $bug->openedBuild = rtrim($openedBuild, ',');
+ $bug->resolvedBuild = isset($builds[$bug->resolvedBuild]) ? $builds[$bug->resolvedBuild] : $bug->resolvedBuild;
+ }
+
+ $header['title'] = $this->products[$productID] . $this->lang->colon . $this->lang->bug->common;
+ $position[] = html::a($this->createLink('bug', 'browse', "productID=$productID"), $this->products[$productID]);
+ $position[] = $this->lang->bug->common;
+
+ $this->view->header = $header;
+ $this->view->position = $position;
+ $this->view->productID = $productID;
+ $this->view->productName = $this->products[$productID];
+ $this->view->moduleTree = $this->tree->getTreeMenu($productID, $viewType = 'bug', $startModuleID = 0, array('treeModel', 'createBugLink'));
+ $this->view->browseType = $browseType;
+ $this->view->bugs = $bugs;
+ $this->view->users = $users;
+ $this->view->pager = $pager;
+ $this->view->param = $param;
+ $this->view->orderBy = $orderBy;
+ $this->view->moduleID = $moduleID;
+ $this->view->customed = $customed;
+ $this->view->customFields= explode(',', str_replace(' ', '', trim($customFields)));
+ $this->view->treeClass = $browseType == 'bymodule' ? '' : 'hidden';
+
+ $this->display();
+ }
+
+ /**
+ * The report page.
+ *
+ * @param int $productID
+ * @param string $browseType
+ * @param int $moduleID
+ * @access public
+ * @return void
+ */
+ public function report($productID, $browseType, $moduleID)
+ {
+ $this->loadModel('report');
+ $this->view->charts = array();
+ $this->view->renderJS = '';
+
+ if(!empty($_POST))
+ {
+ foreach($this->post->charts as $chart)
+ {
+ $chartFunc = 'getDataOf' . $chart;
+ $chartData = $this->bug->$chartFunc();
+ $chartOption = $this->lang->bug->report->$chart;
+ $this->bug->mergeChartOption($chart);
+
+ $chartXML = $this->report->createSingleXML($chartData, $chartOption->graph);
+ $this->view->charts[$chart] = $this->report->createJSChart($chartOption->swf, $chartXML, $chartOption->width, $chartOption->height);
+ $this->view->datas[$chart] = $this->report->computePercent($chartData);
+ }
+ $this->view->renderJS = $this->report->renderJsCharts(count($this->view->charts));
+ }
+
+ $this->bug->setMenu($this->products, $productID);
+ $this->view->header->title = $this->products[$productID] . $this->lang->colon . $this->lang->bug->common;
+ $this->view->productID = $productID;
+ $this->view->browseType = $browseType;
+ $this->view->moduleID = $moduleID;
+ $this->view->checkedCharts = $this->post->charts ? join(',', $this->post->charts) : '';
+ $this->display();
+ }
+
+ /**
+ * Create a bug.
+ *
+ * @param int $productID
+ * @param string $extras others params, forexample, projectID=10,moduleID=10
+ * @access public
+ * @return void
+ */
+ public function create($productID, $extras = '')
+ {
+ $this->view->users = $this->user->getPairs('nodeleted,devfirst');
+ if(empty($this->products)) $this->locate($this->createLink('product', 'create'));
+
+ if(!empty($_POST))
+ {
+ $bugID = $this->bug->create();
+ if(dao::isError()) die(js::error(dao::getError()));
+ $actionID = $this->action->create('bug', $bugID, 'Opened');
+ $this->sendmail($bugID, $actionID);
+ die(js::locate($this->createLink('bug', 'browse', "productID={$this->post->product}&type=byModule¶m={$this->post->module}"), 'parent'));
+ }
+
+ /* Get product, then set menu. */
+ $productID = $this->product->saveState($productID, $this->products);
+ $this->bug->setMenu($this->products, $productID);
+
+ /* Remove the unused types. */
+ unset($this->lang->bug->typeList['designchange']);
+ unset($this->lang->bug->typeList['newfeature']);
+ unset($this->lang->bug->typeList['trackthings']);
+
+ /* Init vars. */
+ $moduleID = 0;
+ $projectID = 0;
+ $taskID = 0;
+ $storyID = 0;
+ $buildID = 0;
+ $caseID = 0;
+ $runID = 0;
+ $title = '';
+ $steps = $this->lang->bug->tplStep . $this->lang->bug->tplResult . $this->lang->bug->tplExpect;
+ $os = '';
+ $browser = '';
+ $assignedTo = '';
+ $mailto = '';
+ $keywords = '';
+ $severity = 3;
+ $type = 'codeerror';
+
+ /* Parse the extras. */
+ $extras = str_replace(array(',', ' '), array('&', ''), $extras);
+ parse_str($extras);
+
+ /* If set runID, get the last result info as the template. */
+ if($runID > 0) $resultID = $this->dao->select('id')->from(TABLE_TESTRESULT)->where('run')->eq($runID)->orderBy('id desc')->limit(1)->fetch('id');
+ if(isset($resultID) and $resultID > 0) extract($this->bug->getBugInfoFromResult($resultID));
+
+ /* If set caseID and runID='', get the last result info as the template. */
+ if($caseID > 0 && $runID == '')
+ {
+ $resultID = $this->dao->select('id')->from(TABLE_TESTRESULT)->where('`case`')->eq($caseID)->orderBy('date desc')->limit(1)->fetch('id');
+ if(isset($resultID) and $resultID > 0) extract($this->bug->getBugInfoFromResult($resultID, $caseID, $version));
+ }
+
+ /* If bugID setted, use this bug as template. */
+ if(isset($bugID))
+ {
+ $bug = $this->bug->getById($bugID);
+ extract((array)$bug);
+ $projectID = $bug->project;
+ $moduleID = $bug->module;
+ $taskID = $bug->task;
+ $storyID = $bug->story;
+ $buildID = $bug->openedBuild;
+ $severity = $bug->severity;
+ $type = $bug->type;
+ }
+
+ /* If projectID is setted, get builds and stories of this project. */
+ if($projectID)
+ {
+ $builds = $this->loadModel('build')->getProjectBuildPairs($projectID, $productID, 'noempty');
+ $stories = $this->story->getProjectStoryPairs($projectID);
+ }
+ else
+ {
+ $builds = $this->loadModel('build')->getProductBuildPairs($productID, 'noempty');
+ $stories = $this->story->getProductStoryPairs($productID);
+ }
+ $this->view->header->title = $this->products[$productID] . $this->lang->colon . $this->lang->bug->create;
+ $this->view->position[] = html::a($this->createLink('bug', 'browse', "productID=$productID"), $this->products[$productID]);
+ $this->view->position[] = $this->lang->bug->create;
+
+ $this->view->productID = $productID;
+ $this->view->productName = $this->products[$productID];
+ $this->view->moduleOptionMenu = $this->tree->getOptionMenu($productID, $viewType = 'bug', $startModuleID = 0);
+ $this->view->stories = $stories;
+ $this->view->projects = $this->product->getProjectPairs($productID, $params = 'nodeleted');
+ $this->view->builds = $builds;
+ $this->view->tasks = $this->loadModel('task')->getProjectTaskPairs($projectID);
+ $this->view->moduleID = $moduleID;
+ $this->view->projectID = $projectID;
+ $this->view->taskID = $taskID;
+ $this->view->storyID = $storyID;
+ $this->view->buildID = $buildID;
+ $this->view->caseID = $caseID;
+ $this->view->title = $title;
+ $this->view->steps = htmlspecialchars($steps);
+ $this->view->os = $os;
+ $this->view->browser = $browser;
+ $this->view->assignedTo = $assignedTo;
+ $this->view->mailto = $mailto;
+ $this->view->contactLists = $this->user->getContactLists($this->app->user->account, 'withnote');
+ $this->view->keywords = $keywords;
+ $this->view->severity = $severity;
+ $this->view->type = $type;
+
+ $this->display();
+ }
+
+ /**
+ * View a bug.
+ *
+ * @param int $bugID
+ * @access public
+ * @return void
+ */
+ public function view($bugID)
+ {
+ /* Judge bug exits or not. */
+ $bug = $this->bug->getById($bugID, true);
+ if(!$bug) die(js::error($this->lang->notFound) . js::locate('back'));
+
+ /* Update action. */
+ if($bug->assignedTo == $this->app->user->account) $this->loadModel('action')->read('bug', $bugID);
+
+ /* Set menu. */
+ $this->bug->setMenu($this->products, $bug->product);
+
+ /* Get product info. */
+ $productID = $bug->product;
+ $productName = $this->products[$productID];
+
+ /* Header and positon. */
+ $this->view->header->title = "BUG #$bug->id $bug->title - " . $this->products[$productID];
+ $this->view->position[] = html::a($this->createLink('bug', 'browse', "productID=$productID"), $productName);
+ $this->view->position[] = $this->lang->bug->view;
+
+ /* Assign. */
+ $this->view->productID = $productID;
+ $this->view->productName = $productName;
+ $this->view->modulePath = $this->tree->getParents($bug->module);
+ $this->view->bug = $bug;
+ $this->view->users = $this->user->getPairs('noletter');
+ $this->view->actions = $this->action->getList('bug', $bugID);
+ $this->view->builds = $this->loadModel('build')->getProductBuildPairs($productID);
+ $this->view->preAndNext = $this->loadModel('common')->getPreAndNextObject('bug', $bugID);
+
+ $this->display();
+ }
+
+ /**
+ * Edit a bug.
+ *
+ * @param int $bugID
+ * @access public
+ * @return void
+ */
+ public function edit($bugID, $comment = false)
+ {
+ if(!empty($_POST))
+ {
+ $changes = array();
+ $files = array();
+ if($comment == false)
+ {
+ $changes = $this->bug->update($bugID);
+ if(dao::isError()) die(js::error(dao::getError()));
+ $files = $this->loadModel('file')->saveUpload('bug', $bugID);
+ }
+ if($this->post->comment != '' or !empty($changes) or !empty($files))
+ {
+ $action = !empty($changes) ? 'Edited' : 'Commented';
+ $fileAction = '';
+ if(!empty($files)) $fileAction = $this->lang->addFiles . join(',', $files) . "\n" ;
+ $actionID = $this->action->create('bug', $bugID, $action, $fileAction . $this->post->comment);
+ $this->action->logHistory($actionID, $changes);
+ $this->sendmail($bugID, $actionID);
+ }
+
+ $bug = $this->bug->getById($bugID);
+ if($bug->toTask != 0)
+ {
+ foreach($changes as $change)
+ {
+ 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'));
+ }
+
+ /* Get the info of bug, current product and modue. */
+ $bug = $this->bug->getById($bugID);
+ $productID = $bug->product;
+ $projectID = $bug->project;
+ $currentModuleID = $bug->module;
+
+ /**
+ * Remove designchange, newfeature, trackings from the typeList, because should be tracked in story or task.
+ * These thress types if upgrade from bugfree2.x.
+ */
+ if($bug->type != 'designchange') unset($this->lang->bug->typeList['designchange']);
+ if($bug->type != 'newfeature') unset($this->lang->bug->typeList['newfeature']);
+ if($bug->type != 'trackthings') unset($this->lang->bug->typeList['trackthings']);
+
+ /* Set the menu. */
+ $this->bug->setMenu($this->products, $productID);
+
+ /* Set header and position. */
+ $this->view->header->title = $this->products[$productID] . $this->lang->colon . $this->lang->bug->edit;
+ $this->view->position[] = html::a($this->createLink('bug', 'browse', "productID=$productID"), $this->products[$productID]);
+ $this->view->position[] = $this->lang->bug->edit;
+
+ /* Assign. */
+ if($projectID)
+ {
+ $this->view->openedBuilds = $this->loadModel('build')->getProjectBuildPairs($projectID, $productID, 'noempty');
+ }
+ else
+ {
+ $this->view->openedBuilds = $this->loadModel('build')->getProductBuildPairs($productID, 'noempty');
+ }
+ $this->view->bug = $bug;
+ $this->view->productID = $productID;
+ $this->view->productName = $this->products[$productID];
+ $this->view->moduleOptionMenu = $this->tree->getOptionMenu($productID, $viewType = 'bug', $startModuleID = 0);
+ $this->view->currentModuleID = $currentModuleID;
+ $this->view->projects = $this->product->getProjectPairs($bug->product);
+ $this->view->stories = $bug->project ? $this->story->getProjectStoryPairs($bug->project) : $this->story->getProductStoryPairs($bug->product);
+ $this->view->tasks = $this->task->getProjectTaskPairs($bug->project);
+ $this->view->users = $this->user->appendDeleted($this->user->getPairs('nodeleted'), "$bug->assignedTo,$bug->resolvedBy,$bug->closedBy");
+ $this->view->resolvedBuilds = array('' => '') + $this->view->openedBuilds;
+ $this->view->actions = $this->action->getList('bug', $bugID);
+ $this->view->templates = $this->bug->getUserBugTemplates($this->app->user->account);
+
+ $this->display();
+ }
+
+ /**
+ * Batch edit bug.
+ *
+ * @param string $from example:bugBrowse, bugBatchEdit.
+ * @param int $productID
+ * @param string $orderBy
+ * @access public
+ * @return void
+ */
+ public function batchEdit($from = '', $productID = 0, $orderBy = '')
+ {
+ if($from == 'bugBrowse')
+ {
+ /* Initialize vars.*/
+ if(!$orderBy) $orderBy = $this->cookie->qaBugOrder ? $this->cookie->qaBugOrder : 'id_desc';
+ $editedBugs = array();
+ $allBugs = $this->dao->select('*')->from(TABLE_BUG)->alias('t1')->where($this->session->bugQueryCondition)->orderBy($orderBy)->fetchAll('id');
+ $bugIDList = $this->post->bugIDList ? $this->post->bugIDList : array();
+ $product = $this->product->getByID($productID);
+ $columns = 9;
+ $showSuhosinInfo = false;
+
+ /* Set product menu. */
+ $this->bug->setMenu($this->products, $productID);
+
+ /* Initialize the tasks whose need to edited. */
+ foreach($allBugs as $bug) if(in_array($bug->id, $bugIDList)) $editedBugs[$bug->id] = $bug;
+
+ /* Judge whether the editedTasks is too large. */
+ $showSuhosinInfo = $this->loadModel('common')->judgeSuhosinSetting(count($editedBugs), $columns);
+
+ /* Set the sessions. */
+ $this->app->session->set('showSuhosinInfo', $showSuhosinInfo);
+
+ /* Assign. */
+ $this->view->header->title = $product->name . $this->lang->colon . $this->lang->bug->batchEdit;
+ $this->view->position[] = html::a($this->createLink('bug', 'browse', "productID=$productID"), $this->products[$productID]);
+ $this->view->position[] = $this->lang->bug->common;
+ $this->view->position[] = $this->lang->bug->batchEdit;
+
+ if($showSuhosinInfo) $this->view->suhosinInfo = $this->lang->suhosinInfo;
+ $this->view->productID = $productID;
+ $this->view->editedBugs = $editedBugs;
+ $this->view->users = $this->user->getPairs('nodeleted,devfirst');
+
+ $this->display();
+ }
+ elseif($from == 'bugBatchEdit')
+ {
+ $allChanges = $this->bug->batchUpdate();
+
+ foreach($allChanges as $bugID => $changes)
+ {
+ $actionID = $this->action->create('bug', $bugID, 'Edited');
+ $this->action->logHistory($actionID, $changes);
+ $this->sendmail($bugID, $actionID);
+
+ $bug = $this->bug->getById($bugID);
+ if($bug->toTask != 0)
+ {
+ foreach($changes as $change)
+ {
+ 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->session->bugList, 'parent'));
+ }
+ }
+
+ /**
+ * Update assign of bug.
+ *
+ * @param int $bugID
+ * @access public
+ * @return void
+ */
+ public function assignTo($bugID)
+ {
+ $bug = $this->bug->getById($bugID);
+
+ /* Set menu. */
+ $this->bug->setMenu($this->products, $bug->product);
+
+ if(!empty($_POST))
+ {
+ $this->loadModel('action');
+ $changes = $this->bug->assign($bugID);
+ if(dao::isError()) die(js::error(dao::getError()));
+ $actionID = $this->action->create('bug', $bugID, 'Assigned', $this->post->comment, $this->post->assignedTo);
+ $this->action->logHistory($actionID, $changes);
+ $this->sendmail($bugID, $actionID);
+
+ die(js::locate($this->createLink('bug', 'view', "bugID=$bugID"), 'parent'));
+ }
+
+ $this->view->header->title = $this->products[$bug->product] . $this->lang->colon . $this->lang->bug->assignedTo;
+ $this->view->position[] = $this->lang->bug->assignedTo;
+
+ $this->view->users = $this->user->getPairs('nodeleted');
+ $this->view->bug = $bug;
+ $this->view->bugID = $bugID;
+ $this->view->actions = $this->action->getList('bug', $bugID);
+ $this->display();
+ }
+
+ /**
+ * confirm a bug.
+ *
+ * @param int $bugID
+ * @access public
+ * @return void
+ */
+ public function confirmBug($bugID)
+ {
+ if(!empty($_POST))
+ {
+ $this->bug->confirm($bugID);
+ if(dao::isError()) die(js::error(dao::getError()));
+ $actionID = $this->action->create('bug', $bugID, 'bugConfirmed', $this->post->comment);
+ $this->sendmail($bugID, $actionID);
+ die(js::locate($this->createLink('bug', 'view', "bugID=$bugID"), 'parent'));
+ }
+
+ $bug = $this->bug->getById($bugID);
+ $productID = $bug->product;
+ $this->bug->setMenu($this->products, $productID);
+
+ $this->view->header->title = $this->products[$productID] . $this->lang->colon . $this->lang->bug->confirmBug;
+ $this->view->position[] = html::a($this->createLink('bug', 'browse', "productID=$productID"), $this->products[$productID]);
+ $this->view->position[] = $this->lang->bug->confirmBug;
+
+ $this->view->bug = $bug;
+ $this->view->users = $this->user->getPairs('noletter');
+ $this->view->actions = $this->action->getList('bug', $bugID);
+ $this->display();
+ }
+
+ /**
+ * Resolve a bug.
+ *
+ * @param int $bugID
+ * @access public
+ * @return void
+ */
+ public function resolve($bugID)
+ {
+ $this->view->users = $this->user->getPairs('nodeleted');
+ if(!empty($_POST))
+ {
+ $this->bug->resolve($bugID);
+ if(dao::isError()) die(js::error(dao::getError()));
+ $actionID = $this->action->create('bug', $bugID, 'Resolved', $this->post->comment, $this->post->resolution);
+ $this->sendmail($bugID, $actionID);
+
+ $bug = $this->bug->getById($bugID);
+ if($bug->toTask != 0)
+ {
+ $confirmURL = $this->createLink('task', 'view', "taskID=$bug->toTask");
+ $cancelURL = $this->createLink('bug', 'view', "bugID=$bugID");
+ die(js::confirm(sprintf($this->lang->bug->remindTask, $bug->toTask), $confirmURL, $cancelURL, 'parent', 'parent'));
+ }
+ die(js::locate($this->createLink('bug', 'view', "bugID=$bugID"), 'parent'));
+ }
+
+ $bug = $this->bug->getById($bugID);
+ $productID = $bug->product;
+ $this->bug->setMenu($this->products, $productID);
+
+ $this->view->header->title = $this->products[$productID] . $this->lang->colon . $this->lang->bug->resolve;
+ $this->view->position[] = html::a($this->createLink('bug', 'browse', "productID=$productID"), $this->products[$productID]);
+ $this->view->position[] = $this->lang->bug->resolve;
+
+ $this->view->bug = $bug;
+ $this->view->builds = $this->loadModel('build')->getProductBuildPairs($productID);
+ $this->view->actions = $this->action->getList('bug', $bugID);
+ $this->display();
+ }
+
+ /**
+ * Activate a bug.
+ *
+ * @param int $bugID
+ * @access public
+ * @return void
+ */
+ public function activate($bugID)
+ {
+ $this->view->users = $this->user->getPairs('nodeleted');
+
+ if(!empty($_POST))
+ {
+ $this->bug->activate($bugID);
+ if(dao::isError()) die(js::error(dao::getError()));
+ $files = $this->loadModel('file')->saveUpload('bug', $bugID);
+ $actionID = $this->action->create('bug', $bugID, 'Activated', $this->post->comment);
+ $this->sendmail($bugID, $actionID);
+ die(js::locate($this->createLink('bug', 'view', "bugID=$bugID"), 'parent'));
+ }
+
+ $bug = $this->bug->getById($bugID);
+ $productID = $bug->product;
+ $this->bug->setMenu($this->products, $productID);
+
+ $this->view->header->title = $this->products[$productID] . $this->lang->colon . $this->lang->bug->activate;
+ $this->view->position[] = html::a($this->createLink('bug', 'browse', "productID=$productID"), $this->products[$productID]);
+ $this->view->position[] = $this->lang->bug->activate;
+
+ $this->view->bug = $bug;
+ $this->view->builds = $this->loadModel('build')->getProductBuildPairs($productID, 'noempty');
+ $this->view->actions = $this->action->getList('bug', $bugID);
+
+ $this->display();
+ }
+
+ /**
+ * Close a bug.
+ *
+ * @param int $bugID
+ * @access public
+ * @return void
+ */
+ public function close($bugID)
+ {
+ $this->view->users = $this->user->getPairs('noletter');
+ if(!empty($_POST))
+ {
+ $this->bug->close($bugID);
+ if(dao::isError()) die(js::error(dao::getError()));
+ $actionID = $this->action->create('bug', $bugID, 'Closed', $this->post->comment);
+ $this->sendmail($bugID, $actionID);
+ die(js::locate($this->createLink('bug', 'view', "bugID=$bugID"), 'parent'));
+ }
+
+ $bug = $this->bug->getById($bugID);
+ $productID = $bug->product;
+ $this->bug->setMenu($this->products, $productID);
+
+ $this->view->header->title = $this->products[$productID] . $this->lang->colon . $this->lang->bug->close;
+ $this->view->position[] = html::a($this->createLink('bug', 'browse', "productID=$productID"), $this->products[$productID]);
+ $this->view->position[] = $this->lang->bug->close;
+
+ $this->view->bug = $bug;
+ $this->view->actions = $this->action->getList('bug', $bugID);
+ $this->display();
+ }
+
+ /**
+ * Confirm story change.
+ *
+ * @param int $bugID
+ * @access public
+ * @return void
+ */
+ public function confirmStoryChange($bugID)
+ {
+ $bug = $this->bug->getById($bugID);
+ $this->dao->update(TABLE_BUG)->set('storyVersion')->eq($bug->latestStoryVersion)->where('id')->eq($bugID)->exec();
+ $this->loadModel('action')->create('bug', $bugID, 'confirmed', '', $bug->latestStoryVersion);
+ die(js::reload('parent'));
+ }
+
+ /**
+ * Delete a bug.
+ *
+ * @param int $bugID
+ * @param string $confirm yes|no
+ * @access public
+ * @return void
+ */
+ public function delete($bugID, $confirm = 'no')
+ {
+ $bug = $this->bug->getById($bugID);
+ if($confirm == 'no')
+ {
+ die(js::confirm($this->lang->bug->confirmDelete, inlink('delete', "bugID=$bugID&confirm=yes")));
+ }
+ else
+ {
+ $this->bug->delete(TABLE_BUG, $bugID);
+ if($bug->toTask != 0) echo js::alert($this->lang->bug->remindTask . $bug->toTask);
+ die(js::locate($this->session->bugList, 'parent'));
+ }
+ }
+
+ /**
+ * Save current template.
+ *
+ * @access public
+ * @return string
+ */
+ public function saveTemplate()
+ {
+ $this->bug->saveUserBugTemplate();
+ if(dao::isError()) die(js::error(dao::getError()));
+ die($this->fetch('bug', 'buildTemplates'));
+ }
+
+ /**
+ * Build the user templates selection code.
+ *
+ * @access public
+ * @return void
+ */
+ public function buildTemplates()
+ {
+ $this->view->templates = $this->bug->getUserBugTemplates($this->app->user->account);
+ $this->display('bug', 'buildTemplates');
+ }
+
+ /**
+ * Delete a user template.
+ *
+ * @param int $templateID
+ * @access public
+ * @return void
+ */
+ public function deleteTemplate($templateID)
+ {
+ $this->dao->delete()->from(TABLE_USERTPL)->where('id')->eq($templateID)->andWhere('account')->eq($this->app->user->account)->exec();
+ die();
+ }
+
+ /**
+ * Custom fields.
+ *
+ * @access public
+ * @return void
+ */
+ public function customFields()
+ {
+ if($_POST)
+ {
+ $customFields = $this->post->customFields;
+ $customFields = join(',', $customFields);
+ setcookie('bugFields', $customFields, $this->config->cookieLife, $this->config->webRoot);
+ die(js::reload('parent'));
+ }
+
+ $customFields = $this->cookie->bugFields ? $this->cookie->bugFields : $this->config->bug->list->defaultFields;
+
+ $this->view->allFields = $this->bug->getFieldPairs($this->config->bug->list->allFields);
+ $this->view->customFields = $this->bug->getFieldPairs($customFields);
+ $this->view->defaultFields = $this->bug->getFieldPairs($this->config->bug->list->defaultFields);
+ die($this->display());
+ }
+
+ /**
+ * AJAX: get bugs of a user in html select.
+ *
+ * @param string $account
+ * @param string $id the id of the select control.
+ * @access public
+ * @return string
+ */
+ public function ajaxGetUserBugs($account = '', $id = '')
+ {
+ if($account == '') $account = $this->app->user->account;
+ $bugs = $this->bug->getUserBugPairs($account);
+
+ if($id) die(html::select("bugs[$id]", $bugs, '', 'class="select-1 f-left"'));
+ die(html::select('bug', $bugs, '', 'class=select-1'));
+ }
+
+ /**
+ * AJAX: Get bug owner of a module.
+ *
+ * @param int $moduleID
+ * @param int $productID
+ * @access public
+ * @return string
+ */
+ public function ajaxGetModuleOwner($moduleID, $productID = 0)
+ {
+ $owner = '';
+ if($moduleID) $owner = $this->dao->findByID($moduleID)->from(TABLE_MODULE)->fetch('owner');
+ if(!$owner) $owner = $this->dao->findByID($productID)->from(TABLE_PRODUCT)->fetch('QD');
+ die($owner);
+ }
+
+ /**
+ * AJAX: get assignedTo list, make sure the members of the project at the first.
+ *
+ * @param int $projectID
+ * @param string $selectedUser
+ * @access public
+ * @return string
+ */
+ public function ajaxLoadAssignedTo($projectID, $selectedUser = '')
+ {
+ $allUsers = $this->loadModel('user')->getPairs('nodeleted, devfirst');
+ $projectMembers = $this->loadModel('project')->getTeamMemberPairs($projectID);
+ $assignedToList = array_merge($projectMembers, $allUsers);
+
+ die(html::select('assignedTo', $assignedToList, $selectedUser, 'class="select-3"'));
+ }
+
+ /**
+ * Send email.
+ *
+ * @param int $bugID
+ * @param int $actionID
+ * @access public
+ * @return void
+ */
+ public function sendmail($bugID, $actionID)
+ {
+ /* Set toList and ccList. */
+ $bug = $this->bug->getByID($bugID);
+ $productName = $this->products[$bug->product];
+ $toList = $bug->assignedTo;
+ $ccList = trim($bug->mailto, ',');
+ if($toList == '')
+ {
+ if($ccList == '') return;
+ if(strpos($ccList, ',') === false)
+ {
+ $toList = $ccList;
+ $ccList = '';
+ }
+ else
+ {
+ $commaPos = strpos($ccList, ',');
+ $toList = substr($ccList, 0, $commaPos);
+ $ccList = substr($ccList, $commaPos + 1);
+ }
+ }
+ elseif(strtolower($toList) == 'closed')
+ {
+ $toList = $bug->resolvedBy;
+ }
+
+ /* Get action info. */
+ $action = $this->action->getById($actionID);
+ $history = $this->action->getHistory($actionID);
+ $action->history = isset($history[$actionID]) ? $history[$actionID] : array();
+ if(strtolower($action->action) == 'opened') $action->comment = $bug->steps;
+
+ /* Create the mail content. */
+ if($action->action == 'opened') $action->comment = '';
+ $this->view->bug = $bug;
+ $this->view->action = $action;
+ $mailContent = $this->parse($this->moduleName, 'sendmail');
+
+ /* Send it. */
+ $this->loadModel('mail')->send($toList, $productName . ':' . 'BUG #'. $bug->id . $this->lang->colon . $bug->title, $mailContent, $ccList);
+ if($this->mail->isError()) echo js::error($this->mail->getError());
+ }
+
+ /**
+ * Get data to export
+ *
+ * @param string $productID
+ * @param string $orderBy
+ * @access public
+ * @return void
+ */
+ public function export($productID, $orderBy)
+ {
+ if($_POST)
+ {
+ $bugLang = $this->lang->bug;
+ $bugConfig = $this->config->bug;
+
+ /* Create field lists. */
+ $fields = explode(',', $bugConfig->list->exportFields);
+ foreach($fields as $key => $fieldName)
+ {
+ $fieldName = trim($fieldName);
+ $fields[$fieldName] = isset($bugLang->$fieldName) ? $bugLang->$fieldName : $fieldName;
+ unset($fields[$key]);
+ }
+
+ /* Get bugs. */
+ $bugs = $this->dao->select('*')->from(TABLE_BUG)->where($this->session->bugQueryCondition)
+ ->beginIF($this->post->exportType == 'selected')->andWhere('id')->in($this->cookie->checkedItem)->fi()
+ ->orderBy($orderBy)->fetchAll('id');
+
+ /* Get users, products and projects. */
+ $users = $this->loadModel('user')->getPairs('noletter');
+ $products = $this->loadModel('product')->getPairs();
+ $projects = $this->loadModel('project')->getPairs('all');
+
+ /* Get related objects id lists. */
+ $relatedModuleIdList = array();
+ $relatedStoryIdList = array();
+ $relatedTaskIdList = array();
+ $relatedBugIdList = array();
+ $relatedCaseIdList = array();
+ $relatedBuildIdList = array();
+
+ foreach($bugs as $bug)
+ {
+ $relatedModuleIdList[$bug->module] = $bug->module;
+ $relatedStoryIdList[$bug->story] = $bug->story;
+ $relatedTaskIdList[$bug->task] = $bug->task;
+ $relatedCaseIdList[$bug->case] = $bug->case;
+ $relatedBugIdList[$bug->duplicateBug] = $bug->duplicateBug;
+
+ /* Process link bugs. */
+ $linkBugs = explode(',', $bug->linkBug);
+ foreach($linkBugs as $linkBugID)
+ {
+ if($linkBugID) $relatedBugIdList[$linkBugID] = trim($linkBugID);
+ }
+
+ /* Process builds. */
+ $builds = $bug->openedBuild . ',' . $bug->resolvedBuild;
+ $builds = explode(',', $builds);
+ foreach($builds as $buildID)
+ {
+ if($buildID) $relatedBuildIdList[$buildID] = trim($buildID);
+ }
+ }
+
+ /* Get related objects title or names. */
+ $relatedModules = $this->dao->select('id, name')->from(TABLE_MODULE)->where('id')->in($relatedModuleIdList)->fetchPairs();
+ $relatedStories = $this->dao->select('id,title')->from(TABLE_STORY) ->where('id')->in($relatedStoryIdList)->fetchPairs();
+ $relatedTasks = $this->dao->select('id, name')->from(TABLE_TASK)->where('id')->in($relatedTaskIdList)->fetchPairs();
+ $relatedBugs = $this->dao->select('id, title')->from(TABLE_BUG)->where('id')->in($relatedBugIdList)->fetchPairs();
+ $relatedCases = $this->dao->select('id, title')->from(TABLE_CASE)->where('id')->in($relatedCaseIdList)->fetchPairs();
+ $relatedBuilds = $this->dao->select('id, name')->from(TABLE_BUILD)->where('id')->in($relatedBuildIdList)->fetchPairs();
+ $relatedFiles = $this->dao->select('id, objectID, pathname, title')->from(TABLE_FILE)->where('objectType')->eq('bug')->andWhere('objectID')->in(@array_keys($bugs))->fetchGroup('objectID');
+
+ foreach($bugs as $bug)
+ {
+ if($this->post->fileType == 'csv')
+ {
+ $bug->steps = htmlspecialchars_decode($bug->steps);
+ $bug->steps = str_replace(" ", "\n", $bug->steps);
+ $bug->steps = str_replace('"', '""', $bug->steps);
+ $bug->steps = str_replace(' ', ' ', $bug->steps);
+ $bug->steps = strip_tags($bug->steps);
+ }
+
+ /* fill some field with useful value. */
+ if(isset($products[$bug->product])) $bug->product = $products[$bug->product];
+ if(isset($projects[$bug->project])) $bug->project = $projects[$bug->project];
+ if(isset($relatedModules[$bug->module])) $bug->module = $relatedModules[$bug->module];
+ if(isset($relatedStories[$bug->story])) $bug->story = $relatedStories[$bug->story];
+ if(isset($relatedTasks[$bug->task])) $bug->task = $relatedTasks[$bug->task];
+ if(isset($relatedBugs[$bug->duplicateBug])) $bug->duplicateBug = $relatedBugs[$bug->duplicateBug];
+ if(isset($relatedCases[$bug->case])) $bug->case = $relatedCases[$bug->case];
+
+ if(isset($bugLang->priList[$bug->pri])) $bug->pri = $bugLang->priList[$bug->pri];
+ if(isset($bugLang->typeList[$bug->type])) $bug->type = $bugLang->typeList[$bug->type];
+ if(isset($bugLang->statusList[$bug->status])) $bug->status = $bugLang->statusList[$bug->status];
+ if(isset($bugLang->confirmedList[$bug->confirmed])) $bug->confirmed = $bugLang->confirmedList[$bug->confirmed];
+ if(isset($bugLang->resolutionList[$bug->resolution])) $bug->resolution = $bugLang->resolutionList[$bug->resolution];
+
+ if(isset($users[$bug->openedBy])) $bug->openedBy = $users[$bug->openedBy];
+ if(isset($users[$bug->assignedTo])) $bug->assignedTo = $users[$bug->assignedTo];
+ if(isset($users[$bug->resolvedBy])) $bug->resolvedBy = $users[$bug->resolvedBy];
+ if(isset($users[$bug->lastEditedBy])) $bug->lastEditedBy = $users[$bug->lastEditedBy];
+ if(isset($users[$bug->closedBy])) $bug->closedBy = $users[$bug->closedBy];
+
+ $bug->openedDate = substr($bug->openedDate, 0, 10);
+ $bug->assignedDate = substr($bug->assignedDate, 0, 10);
+ $bug->closedDate = substr($bug->closedDate, 0, 10);
+ $bug->resolvedDate = substr($bug->resolvedDate, 0, 10);
+ $bug->lastEditedDate = substr($bug->lastEditedDate, 0, 10);
+
+ if($bug->linkBug)
+ {
+ $tmpLinkBugs = array();
+ $linkBugIdList = explode(',', $bug->linkBug);
+ foreach($linkBugIdList as $linkBugID)
+ {
+ $linkBugID = trim($linkBugID);
+ $tmpLinkBugs[] = isset($relatedBugs[$linkBugID]) ? $relatedBugs[$linkBugID] : $linkBugID;
+ }
+ $bug->linkBug = join("; \n", $tmpLinkBugs);
+ }
+
+ if($bug->openedBuild)
+ {
+ $tmpOpenedBuilds = array();
+ $tmpResolvedBuilds = array();
+ $buildIdList = explode(',', $bug->openedBuild);
+ foreach($buildIdList as $buildID)
+ {
+ $buildID = trim($buildID);
+ $tmpOpenedBuilds[] = isset($relatedBuilds[$buildID]) ? $relatedBuilds[$buildID] : $buildID;
+ }
+ $bug->openedBuild = join("; \n", $tmpOpenedBuilds);
+ }
+
+ if($bug->resolvedBuild)
+ {
+ $buildIdList = explode(',', $bug->resolvedBuild);
+ foreach($buildIdList as $buildID)
+ {
+ $buildID = trim($buildID);
+ $tmpResolvedBuilds[] = isset($relatedBuilds[$buildID]) ? $relatedBuilds[$buildID] : $buildID;
+ }
+ $bug->resolvedBuild = join("; \n", $tmpResolvedBuilds);
+ }
+
+ /* Set related files. */
+ if(isset($relatedFiles[$bug->id]))
+ {
+ foreach($relatedFiles[$bug->id] as $file)
+ {
+ $fileURL = 'http://' . $this->server->http_host . $this->config->webRoot . "data/upload/$bug->company/" . $file->pathname;
+ $bug->files .= html::a($fileURL, $file->title, '_blank') . ' ';
+ }
+ }
+
+ $bug->mailto = trim(trim($bug->mailto), ',');
+ $mailtos = explode(',', $bug->mailto);
+ $bug->mailto = '';
+ foreach($mailtos as $mailto)
+ {
+ $mailto = trim($mailto);
+ if(isset($users[$mailto])) $bug->mailto .= $users[$mailto] . ',';
+ }
+
+ /* drop some field that is not needed. */
+ unset($bug->company);
+ unset($bug->caseVersion);
+ unset($bug->result);
+ unset($bug->deleted);
+ }
+
+ $this->post->set('fields', $fields);
+ $this->post->set('rows', $bugs);
+ $this->post->set('kind', 'bug');
+ $this->fetch('file', 'export2' . $this->post->fileType, $_POST);
+ }
+
+ $this->display();
+ }
+}
diff --git a/module/bug/lang/en.php b/module/bug/lang/en.php
index 621622db5f..17a189d6bd 100644
--- a/module/bug/lang/en.php
+++ b/module/bug/lang/en.php
@@ -1,361 +1,361 @@
-
- * @package bug
- * @version $Id$
- * @link http://www.zentao.net
- */
-/* Fieldlist. */
-$lang->bug->common = 'Bug';
-$lang->bug->id = 'ID';
-$lang->bug->product = 'Product';
-$lang->bug->module = 'Module';
-$lang->bug->path = 'Path';
-$lang->bug->project = 'Project';
-$lang->bug->story = 'Story';
-$lang->bug->storyVersion = 'Story Version';
-$lang->bug->task = 'Task';
-$lang->bug->title = 'Title';
-$lang->bug->severity = 'Severity';
-$lang->bug->severityAB = 'S';
-$lang->bug->pri = 'Priority';
-$lang->bug->type = 'Type';
-$lang->bug->os = 'OS';
-$lang->bug->hardware = 'Hardware';
-$lang->bug->browser = 'Browser';
-$lang->bug->machine = 'Machine';
-$lang->bug->found = 'How found';
-$lang->bug->steps = 'Steps';
-$lang->bug->status = 'Status';
-$lang->bug->statusAB = 'Status';
-$lang->bug->activatedCount = 'Activated count';
-$lang->bug->activatedCountAB = 'Activated count';
-$lang->bug->confirmed = 'Confirmed';
-$lang->bug->toTask = 'To task';
-$lang->bug->toStory = 'To story';
-$lang->bug->mailto = 'Mailto';
-$lang->bug->openedBy = 'Opened By';
-$lang->bug->openedByAB = 'Opened';
-$lang->bug->openedDate = 'Opened date';
-$lang->bug->openedDateAB = 'Date';
-$lang->bug->openedBuild = 'Opened Build';
-$lang->bug->assignedTo = 'Assigned';
-$lang->bug->assignedDate = 'Assigned Date';
-$lang->bug->resolvedBy = 'Resolved By';
-$lang->bug->resolvedByAB = 'Resolve';
-$lang->bug->resolution = 'Resolution';
-$lang->bug->resolutionAB = 'Resolution';
-$lang->bug->resolvedBuild = 'Resolved Build';
-$lang->bug->resolvedDate = 'Resolved Date';
-$lang->bug->resolvedDateAB = 'Date';
-$lang->bug->closedBy = 'Closed By';
-$lang->bug->closedDate = 'Closed Date';
-$lang->bug->duplicateBug = 'Duplicate';
-$lang->bug->lastEditedBy = 'Last Edited By';
-$lang->bug->lastEditedDate = 'Last Edited Date';
-$lang->bug->linkBug = 'Related';
-$lang->bug->case = 'Case';
-$lang->bug->files = 'Files';
-$lang->bug->keywords = 'Keywords';
-$lang->bug->lastEditedByAB = 'Edited';
-$lang->bug->lastEditedDateAB = 'Edited Date';
-$lang->bug->fromCase = 'From case';
-$lang->bug->toCase = 'To case';
-
-/* Actions. */
-$lang->bug->index = 'Index';
-$lang->bug->create = 'Create Bug';
-$lang->bug->confirmBug = 'Confirm Bug';
-$lang->bug->edit = 'Edit Bug';
-$lang->bug->batchEdit = 'Batch edit';
-$lang->bug->assignTo = 'Assign';
-$lang->bug->browse = 'Browse Bug';
-$lang->bug->view = 'Bug Info';
-$lang->bug->resolve = 'Resolve Bug';
-$lang->bug->close = 'Close Bug';
-$lang->bug->activate = 'Activate Bug';
-$lang->bug->reportChart = 'Report';
-$lang->bug->export = 'Export data';
-$lang->bug->delete = 'Delete Bug';
-$lang->bug->saveTemplate = 'Save template';
-$lang->bug->deleteTemplate = 'Delete template';
-$lang->bug->customFields = 'Custom';
-$lang->bug->restoreDefault = 'Default';
-$lang->bug->ajaxGetUserBugs = 'API: My Bugs';
-$lang->bug->ajaxGetModuleOwner = 'API: Get module default owner';
-$lang->bug->confirmStoryChange = 'Confirm Story Change';
-
-/* Browse tabs. */
-$lang->bug->selectProduct = 'Select product';
-$lang->bug->byModule = 'ByModule';
-$lang->bug->assignToMe = 'MyBugs';
-$lang->bug->openedByMe = 'MyOpen';
-$lang->bug->resolvedByMe = 'MyResolve';
-$lang->bug->closedByMe = 'MyClose';
-$lang->bug->assignToNull = 'Unassigned';
-$lang->bug->unResolved = 'Unresolved';
-$lang->bug->unclosed = 'Unclosed';
-$lang->bug->longLifeBugs = 'Longlife';
-$lang->bug->postponedBugs = 'Postponed';
-$lang->bug->allBugs = 'Allbug';
-$lang->bug->moduleBugs = 'ByModule';
-$lang->bug->byQuery = 'Search';
-$lang->bug->needConfirm = 'StoryChanged';
-$lang->bug->allProduct = 'All products';
-
-/* Labels. */
-$lang->bug->lblProductAndModule = 'Product&Module';
-$lang->bug->lblProjectAndTask = 'Project&Task';
-$lang->bug->lblStory = 'Story';
-$lang->bug->lblTypeAndSeverity = 'Type&Severity';
-$lang->bug->lblSystemBrowserAndHardware = 'OS&Browser';
-$lang->bug->lblAssignedTo = 'Assigned to';
-$lang->bug->lblMailto = 'Mailto';
-$lang->bug->lblLastEdited = 'Last edited';
-$lang->bug->lblResolved = 'Resolved';
-$lang->bug->lblAllFields = 'All Fields';
-$lang->bug->lblCustomFields = 'Custom Fields';
-
-/* Legends. */
-$lang->bug->legendBasicInfo = 'Basic info';
-$lang->bug->legendMailto = 'Mailto';
-$lang->bug->legendAttatch = 'Files';
-$lang->bug->legendLinkBugs = 'Related bug';
-$lang->bug->legendPrjStoryTask = 'Project, story & task';
-$lang->bug->legendCases = 'Related case';
-$lang->bug->legendSteps = 'Steps';
-$lang->bug->legendAction = 'Action';
-$lang->bug->legendHistory = 'History';
-$lang->bug->legendComment = 'Comment';
-$lang->bug->legendLife = 'Lifetime';
-$lang->bug->legendMisc = 'Misc';
-
-/* Action buttons. */
-$lang->bug->buttonConfirm = 'Confirm';
-$lang->bug->buttonCopy = 'Copy';
-$lang->bug->buttonAssign = 'Assgin';
-$lang->bug->buttonEdit = 'Edit';
-$lang->bug->buttonActivate = 'Activate';
-$lang->bug->buttonResolve = 'Resolve';
-$lang->bug->buttonClose = 'Close';
-$lang->bug->buttonToList = 'Back';
-$lang->bug->buttonCreateTestcase = 'Create case';
-
-/* Confirm messags. */
-$lang->bug->confirmChangeProduct = 'Change product will change project, task and story also, are you sure?';
-$lang->bug->confirmDelete = 'Are you sure to delete this bug?';
-$lang->bug->setTemplateTitle = 'Please input the template title:';
-$lang->bug->remindTask = 'This bug has been to be a task, update the task:%s or not?';
-
-/* Templates. */
-$lang->bug->tplStep = "[Steps]
";
-$lang->bug->tplResult = "[Result]
";
-$lang->bug->tplExpect = "[Expect]
";
-
-/* Field options lists. */
-$lang->bug->severityList[3] = '3';
-$lang->bug->severityList[1] = '1';
-$lang->bug->severityList[2] = '2';
-$lang->bug->severityList[4] = '4';
-
-$lang->bug->priList[0] = '';
-$lang->bug->priList[3] = '3';
-$lang->bug->priList[1] = '1';
-$lang->bug->priList[2] = '2';
-$lang->bug->priList[4] = '4';
-
-$lang->bug->osList[''] = '';
-$lang->bug->osList['all'] = 'All';
-$lang->bug->osList['windows'] = 'Windows';
-$lang->bug->osList['winxp'] = 'Windows XP';
-$lang->bug->osList['win7'] = 'Windows 7';
-$lang->bug->osList['vista'] = 'Windows Vista';
-$lang->bug->osList['win2000'] = 'Windows 2000';
-$lang->bug->osList['win2003'] = 'Windows 2003';
-$lang->bug->osList['win2008'] = 'Windows 2008';
-$lang->bug->osList['winnt'] = 'Windows NT';
-$lang->bug->osList['win98'] = 'Windows 98';
-$lang->bug->osList['andriod'] = 'Andriod';
-$lang->bug->osList['ios'] = 'IOS';
-$lang->bug->osList['wp7'] = 'WP7';
-$lang->bug->osList['symbian'] = 'Symbian';
-$lang->bug->osList['linux'] = 'Linux';
-$lang->bug->osList['freebsd'] = 'FreeBSD';
-$lang->bug->osList['mac'] = 'Mac OS';
-$lang->bug->osList['unix'] = 'Unix';
-$lang->bug->osList['others'] = 'Others';
-
-$lang->bug->browserList[''] = '';
-$lang->bug->browserList['all'] = 'All';
-$lang->bug->browserList['ie'] = 'IE';
-$lang->bug->browserList['ie8'] = 'IE8';
-$lang->bug->browserList['ie9'] = 'IE9';
-$lang->bug->browserList['ie6'] = 'IE6';
-$lang->bug->browserList['ie7'] = 'IE7';
-$lang->bug->browserList['chrome'] = 'chrome';
-$lang->bug->browserList['firefox'] = 'Firefox';
-$lang->bug->browserList['firefox2'] = 'Firefox2';
-$lang->bug->browserList['firefox3'] = 'Firefox3';
-$lang->bug->browserList['firefox4'] = 'Firefox4';
-$lang->bug->browserList['opera'] = 'opera';
-$lang->bug->browserList['opera9'] = 'opera9';
-$lang->bug->browserList['oprea10'] = 'opera10';
-$lang->bug->browserList['oprea11'] = 'opera11';
-$lang->bug->browserList['safari'] = 'safari';
-$lang->bug->browserList['maxthon'] = '傲游';
-$lang->bug->browserList['uc'] = 'UC';
-$lang->bug->browserList['other'] = 'Others';
-
-$lang->bug->typeList[''] = '';
-$lang->bug->typeList['codeerror'] = 'Code error';
-$lang->bug->typeList['interface'] = 'Interface';
-$lang->bug->typeList['designchange'] = 'Design change';
-$lang->bug->typeList['newfeature'] = 'New feature';
-$lang->bug->typeList['designdefect'] = 'Design defect';
-$lang->bug->typeList['config'] = 'Config';
-$lang->bug->typeList['install'] = 'Install';
-$lang->bug->typeList['security'] = 'Security';
-$lang->bug->typeList['performance'] = 'Performance';
-$lang->bug->typeList['standard'] = 'Standard';
-$lang->bug->typeList['automation'] = 'Automation';
-$lang->bug->typeList['trackthings'] = 'Tracking';
-$lang->bug->typeList['others'] = 'Others';
-
-$lang->bug->statusList[''] = '';
-$lang->bug->statusList['active'] = 'Active';
-$lang->bug->statusList['resolved'] = 'Resolved';
-$lang->bug->statusList['closed'] = 'Closed';
-
-$lang->bug->confirmedList[1] = 'Confirmed';
-$lang->bug->confirmedList[0] = 'Unconfirmed';
-
-$lang->bug->resolutionList[''] = '';
-$lang->bug->resolutionList['bydesign'] = 'By design';
-$lang->bug->resolutionList['duplicate'] = 'Duplicate';
-$lang->bug->resolutionList['external'] = 'External';
-$lang->bug->resolutionList['fixed'] = 'Fixed';
-$lang->bug->resolutionList['notrepro'] = 'Not reproduce';
-$lang->bug->resolutionList['postponed'] = 'Postponed';
-$lang->bug->resolutionList['willnotfix'] = "Won't fix";
-$lang->bug->resolutionList['tostory'] = 'To story';
-
-/* Report. */
-$lang->bug->report = new stdclass();
-$lang->bug->report->common = 'Report';
-$lang->bug->report->select = 'Select';
-$lang->bug->report->create = 'Create';
-
-$lang->bug->report->charts['bugsPerProject'] = 'Project bugs';
-$lang->bug->report->charts['bugsPerBuild'] = 'Build bugs';
-$lang->bug->report->charts['bugsPerModule'] = 'Module bugs';
-$lang->bug->report->charts['openedBugsPerDay'] = 'Opened bugs per day';
-$lang->bug->report->charts['resolvedBugsPerDay'] = 'Resolved bugs per day';
-$lang->bug->report->charts['closedBugsPerDay'] = 'Closed bugs per day';
-$lang->bug->report->charts['openedBugsPerUser'] = 'Opened bugs per user';
-$lang->bug->report->charts['resolvedBugsPerUser'] = 'Resolved bugs per user';
-$lang->bug->report->charts['closedBugsPerUser'] = 'Closed bugs per user';
-$lang->bug->report->charts['bugsPerSeverity'] = 'Severity';
-$lang->bug->report->charts['bugsPerResolution'] = 'Resolution';
-$lang->bug->report->charts['bugsPerStatus'] = 'Status';
-$lang->bug->report->charts['bugsPerActivatedCount'] = 'Activated count';
-$lang->bug->report->charts['bugsPerType'] = 'Type';
-$lang->bug->report->charts['bugsPerAssignedTo'] = 'AssignedTo';
-//$lang->bug->report->charts['bugLiveDays'] = 'Bug处理时间统计';
-//$lang->bug->report->charts['bugHistories'] = 'Bug处理步骤统计';
-
-$lang->bug->report->options = new stdclass();
-$lang->bug->report->options->graph = new stdclass();
-$lang->bug->report->options->swf = 'pie2d';
-$lang->bug->report->options->width = 'auto';
-$lang->bug->report->options->height = 300;
-$lang->bug->report->options->graph->baseFontSize = 12;
-$lang->bug->report->options->graph->showNames = 1;
-$lang->bug->report->options->graph->formatNumber = 1;
-$lang->bug->report->options->graph->decimalPrecision = 0;
-$lang->bug->report->options->graph->animation = 0;
-$lang->bug->report->options->graph->rotateNames = 0;
-$lang->bug->report->options->graph->yAxisName = 'COUNT';
-$lang->bug->report->options->graph->pieRadius = 100;
-$lang->bug->report->options->graph->showColumnShadow = 0;
-
-$lang->bug->report->bugsPerProject = new stdclass();
-$lang->bug->report->bugsPerBuild = new stdclass();
-$lang->bug->report->bugsPerModule = new stdclass();
-$lang->bug->report->openedBugsPerDay = new stdclass();
-$lang->bug->report->resolvedBugsPerDay = new stdclass();
-$lang->bug->report->closedBugsPerDay = new stdclass();
-$lang->bug->report->openedBugsPerUser = new stdclass();
-$lang->bug->report->resolvedBugsPerUser = new stdclass();
-$lang->bug->report->closedBugsPerUser = new stdclass();
-$lang->bug->report->bugsPerSeverity = new stdclass();
-$lang->bug->report->bugsPerResolution = new stdclass();
-$lang->bug->report->bugsPerStatus = new stdclass();
-$lang->bug->report->bugsPerActivatedCount = new stdclass();
-$lang->bug->report->bugsPerType = new stdclass();
-$lang->bug->report->bugsPerAssignedTo = new stdclass();
-$lang->bug->report->bugLiveDays = new stdclass();
-$lang->bug->report->bugHistories = new stdclass();
-
-$lang->bug->report->bugsPerProject->graph = new stdclass();
-$lang->bug->report->bugsPerBuild->graph = new stdclass();
-$lang->bug->report->bugsPerModule->graph = new stdclass();
-$lang->bug->report->openedBugsPerDay->graph = new stdclass();
-$lang->bug->report->resolvedBugsPerDay->graph = new stdclass();
-$lang->bug->report->closedBugsPerDay->graph = new stdclass();
-$lang->bug->report->openedBugsPerUser->graph = new stdclass();
-$lang->bug->report->resolvedBugsPerUser->graph = new stdclass();
-$lang->bug->report->closedBugsPerUser->graph = new stdclass();
-$lang->bug->report->bugsPerSeverity->graph = new stdclass();
-$lang->bug->report->bugsPerResolution->graph = new stdclass();
-$lang->bug->report->bugsPerStatus->graph = new stdclass();
-$lang->bug->report->bugsPerActivatedCount->graph = new stdclass();
-$lang->bug->report->bugsPerType->graph = new stdclass();
-$lang->bug->report->bugsPerAssignedTo->graph = new stdclass();
-$lang->bug->report->bugLiveDays->graph = new stdclass();
-$lang->bug->report->bugHistories->graph = new stdclass();
-
-$lang->bug->report->bugsPerProject->graph->xAxisName = 'Project';
-$lang->bug->report->bugsPerBuild->graph->xAxisName = 'Build';
-$lang->bug->report->bugsPerModule->graph->xAxisName = 'Module';
-
-$lang->bug->report->openedBugsPerDay->swf = 'column2d';
-$lang->bug->report->openedBugsPerDay->height = 400;
-$lang->bug->report->openedBugsPerDay->graph->xAxisName = 'Date';
-$lang->bug->report->openedBugsPerDay->graph->rotateNames = 1;
-
-$lang->bug->report->resolvedBugsPerDay->swf = 'column2d';
-$lang->bug->report->resolvedBugsPerDay->height = 400;
-$lang->bug->report->resolvedBugsPerDay->graph->xAxisName = 'Date';
-$lang->bug->report->resolvedBugsPerDay->graph->rotateNames = 1;
-
-$lang->bug->report->closedBugsPerDay->swf = 'column2d';
-$lang->bug->report->closedBugsPerDay->height = 400;
-$lang->bug->report->closedBugsPerDay->graph->xAxisName = 'Date';
-$lang->bug->report->closedBugsPerDay->graph->rotateNames = 1;
-
-$lang->bug->report->openedBugsPerUser->graph->xAxisName = 'User';
-$lang->bug->report->resolvedBugsPerUser->graph->xAxisName= 'User';
-$lang->bug->report->closedBugsPerUser->graph->xAxisName = 'User';
-
-$lang->bug->report->bugsPerSeverity->graph->xAxisName = 'Severity';
-$lang->bug->report->bugsPerResolution->graph->xAxisName = 'Resolution';
-$lang->bug->report->bugsPerStatus->graph->xAxisName = 'Status';
-$lang->bug->report->bugsPerActivatedCount->graph->xAxisName = 'Activated count';
-$lang->bug->report->bugsPerType->graph->xAxisName = 'Type';
-$lang->bug->report->bugsPerAssignedTo->graph->xAxisName = 'AssignedTo';
-$lang->bug->report->bugLiveDays->graph->xAxisName = 'Live days';
-$lang->bug->report->bugHistories->graph->xAxisName = 'Histories';
-
-/* 操作记录。*/
-$lang->bug->action = new stdclass();
-$lang->bug->action->resolved = array('main' => '$date, Resolved by $actor , resolution is $extra .', 'extra' => $lang->bug->resolutionList);
-$lang->bug->action->tostory = array('main' => '$date, To story by $actor , ID is $extra .');
-$lang->bug->action->totask = array('main' => '$date, To task by $actor , ID is $extra .');
-
-$lang->bug->placeholder = new stdclass();
-$lang->bug->placeholder->mailto = 'you can input the user account to select users to mail to.';
-$lang->bug->placeholder->keywords = 'keywords';
+
+ * @package bug
+ * @version $Id$
+ * @link http://www.zentao.net
+ */
+/* Fieldlist. */
+$lang->bug->common = 'Bug';
+$lang->bug->id = 'ID';
+$lang->bug->product = 'Product';
+$lang->bug->module = 'Module';
+$lang->bug->path = 'Path';
+$lang->bug->project = 'Project';
+$lang->bug->story = 'Story';
+$lang->bug->storyVersion = 'Story Version';
+$lang->bug->task = 'Task';
+$lang->bug->title = 'Title';
+$lang->bug->severity = 'Severity';
+$lang->bug->severityAB = 'S';
+$lang->bug->pri = 'Priority';
+$lang->bug->type = 'Type';
+$lang->bug->os = 'OS';
+$lang->bug->hardware = 'Hardware';
+$lang->bug->browser = 'Browser';
+$lang->bug->machine = 'Machine';
+$lang->bug->found = 'How found';
+$lang->bug->steps = 'Steps';
+$lang->bug->status = 'Status';
+$lang->bug->statusAB = 'Status';
+$lang->bug->activatedCount = 'Activated count';
+$lang->bug->activatedCountAB = 'Activated count';
+$lang->bug->confirmed = 'Confirmed';
+$lang->bug->toTask = 'To task';
+$lang->bug->toStory = 'To story';
+$lang->bug->mailto = 'Mailto';
+$lang->bug->openedBy = 'Opened By';
+$lang->bug->openedByAB = 'Opened';
+$lang->bug->openedDate = 'Opened date';
+$lang->bug->openedDateAB = 'Date';
+$lang->bug->openedBuild = 'Opened Build';
+$lang->bug->assignedTo = 'Assigned';
+$lang->bug->assignedDate = 'Assigned Date';
+$lang->bug->resolvedBy = 'Resolved By';
+$lang->bug->resolvedByAB = 'Resolve';
+$lang->bug->resolution = 'Resolution';
+$lang->bug->resolutionAB = 'Resolution';
+$lang->bug->resolvedBuild = 'Resolved Build';
+$lang->bug->resolvedDate = 'Resolved Date';
+$lang->bug->resolvedDateAB = 'Date';
+$lang->bug->closedBy = 'Closed By';
+$lang->bug->closedDate = 'Closed Date';
+$lang->bug->duplicateBug = 'Duplicate';
+$lang->bug->lastEditedBy = 'Last Edited By';
+$lang->bug->lastEditedDate = 'Last Edited Date';
+$lang->bug->linkBug = 'Related';
+$lang->bug->case = 'Case';
+$lang->bug->files = 'Files';
+$lang->bug->keywords = 'Keywords';
+$lang->bug->lastEditedByAB = 'Edited';
+$lang->bug->lastEditedDateAB = 'Edited Date';
+$lang->bug->fromCase = 'From case';
+$lang->bug->toCase = 'To case';
+
+/* Actions. */
+$lang->bug->index = 'Index';
+$lang->bug->create = 'Create Bug';
+$lang->bug->confirmBug = 'Confirm Bug';
+$lang->bug->edit = 'Edit Bug';
+$lang->bug->batchEdit = 'Batch edit';
+$lang->bug->assignTo = 'Assign';
+$lang->bug->browse = 'Browse Bug';
+$lang->bug->view = 'Bug Info';
+$lang->bug->resolve = 'Resolve Bug';
+$lang->bug->close = 'Close Bug';
+$lang->bug->activate = 'Activate Bug';
+$lang->bug->reportChart = 'Report';
+$lang->bug->export = 'Export data';
+$lang->bug->delete = 'Delete Bug';
+$lang->bug->saveTemplate = 'Save template';
+$lang->bug->deleteTemplate = 'Delete template';
+$lang->bug->customFields = 'Custom';
+$lang->bug->restoreDefault = 'Default';
+$lang->bug->ajaxGetUserBugs = 'API: My Bugs';
+$lang->bug->ajaxGetModuleOwner = 'API: Get module default owner';
+$lang->bug->confirmStoryChange = 'Confirm Story Change';
+
+/* Browse tabs. */
+$lang->bug->selectProduct = 'Select product';
+$lang->bug->byModule = 'ByModule';
+$lang->bug->assignToMe = 'MyBugs';
+$lang->bug->openedByMe = 'MyOpen';
+$lang->bug->resolvedByMe = 'MyResolve';
+$lang->bug->closedByMe = 'MyClose';
+$lang->bug->assignToNull = 'Unassigned';
+$lang->bug->unResolved = 'Unresolved';
+$lang->bug->unclosed = 'Unclosed';
+$lang->bug->longLifeBugs = 'Longlife';
+$lang->bug->postponedBugs = 'Postponed';
+$lang->bug->allBugs = 'Allbug';
+$lang->bug->moduleBugs = 'ByModule';
+$lang->bug->byQuery = 'Search';
+$lang->bug->needConfirm = 'StoryChanged';
+$lang->bug->allProduct = 'All products';
+
+/* Labels. */
+$lang->bug->lblProductAndModule = 'Product&Module';
+$lang->bug->lblProjectAndTask = 'Project&Task';
+$lang->bug->lblStory = 'Story';
+$lang->bug->lblTypeAndSeverity = 'Type&Severity';
+$lang->bug->lblSystemBrowserAndHardware = 'OS&Browser';
+$lang->bug->lblAssignedTo = 'Assigned to';
+$lang->bug->lblMailto = 'Mailto';
+$lang->bug->lblLastEdited = 'Last edited';
+$lang->bug->lblResolved = 'Resolved';
+$lang->bug->lblAllFields = 'All Fields';
+$lang->bug->lblCustomFields = 'Custom Fields';
+
+/* Legends. */
+$lang->bug->legendBasicInfo = 'Basic info';
+$lang->bug->legendMailto = 'Mailto';
+$lang->bug->legendAttatch = 'Files';
+$lang->bug->legendLinkBugs = 'Related bug';
+$lang->bug->legendPrjStoryTask = 'Project, story & task';
+$lang->bug->legendCases = 'Related case';
+$lang->bug->legendSteps = 'Steps';
+$lang->bug->legendAction = 'Action';
+$lang->bug->legendHistory = 'History';
+$lang->bug->legendComment = 'Comment';
+$lang->bug->legendLife = 'Lifetime';
+$lang->bug->legendMisc = 'Misc';
+
+/* Action buttons. */
+$lang->bug->buttonConfirm = 'Confirm';
+$lang->bug->buttonCopy = 'Copy';
+$lang->bug->buttonAssign = 'Assgin';
+$lang->bug->buttonEdit = 'Edit';
+$lang->bug->buttonActivate = 'Activate';
+$lang->bug->buttonResolve = 'Resolve';
+$lang->bug->buttonClose = 'Close';
+$lang->bug->buttonToList = 'Back';
+$lang->bug->buttonCreateTestcase = 'Create case';
+
+/* Confirm messags. */
+$lang->bug->confirmChangeProduct = 'Change product will change project, task and story also, are you sure?';
+$lang->bug->confirmDelete = 'Are you sure to delete this bug?';
+$lang->bug->setTemplateTitle = 'Please input the template title:';
+$lang->bug->remindTask = 'This bug has been to be a task, update the task:%s or not?';
+
+/* Templates. */
+$lang->bug->tplStep = "[Steps]
";
+$lang->bug->tplResult = "[Result]
";
+$lang->bug->tplExpect = "[Expect]
";
+
+/* Field options lists. */
+$lang->bug->severityList[3] = '3';
+$lang->bug->severityList[1] = '1';
+$lang->bug->severityList[2] = '2';
+$lang->bug->severityList[4] = '4';
+
+$lang->bug->priList[0] = '';
+$lang->bug->priList[3] = '3';
+$lang->bug->priList[1] = '1';
+$lang->bug->priList[2] = '2';
+$lang->bug->priList[4] = '4';
+
+$lang->bug->osList[''] = '';
+$lang->bug->osList['all'] = 'All';
+$lang->bug->osList['windows'] = 'Windows';
+$lang->bug->osList['winxp'] = 'Windows XP';
+$lang->bug->osList['win7'] = 'Windows 7';
+$lang->bug->osList['vista'] = 'Windows Vista';
+$lang->bug->osList['win2000'] = 'Windows 2000';
+$lang->bug->osList['win2003'] = 'Windows 2003';
+$lang->bug->osList['win2008'] = 'Windows 2008';
+$lang->bug->osList['winnt'] = 'Windows NT';
+$lang->bug->osList['win98'] = 'Windows 98';
+$lang->bug->osList['andriod'] = 'Andriod';
+$lang->bug->osList['ios'] = 'IOS';
+$lang->bug->osList['wp7'] = 'WP7';
+$lang->bug->osList['symbian'] = 'Symbian';
+$lang->bug->osList['linux'] = 'Linux';
+$lang->bug->osList['freebsd'] = 'FreeBSD';
+$lang->bug->osList['mac'] = 'Mac OS';
+$lang->bug->osList['unix'] = 'Unix';
+$lang->bug->osList['others'] = 'Others';
+
+$lang->bug->browserList[''] = '';
+$lang->bug->browserList['all'] = 'All';
+$lang->bug->browserList['ie'] = 'IE';
+$lang->bug->browserList['ie8'] = 'IE8';
+$lang->bug->browserList['ie9'] = 'IE9';
+$lang->bug->browserList['ie6'] = 'IE6';
+$lang->bug->browserList['ie7'] = 'IE7';
+$lang->bug->browserList['chrome'] = 'chrome';
+$lang->bug->browserList['firefox'] = 'Firefox';
+$lang->bug->browserList['firefox2'] = 'Firefox2';
+$lang->bug->browserList['firefox3'] = 'Firefox3';
+$lang->bug->browserList['firefox4'] = 'Firefox4';
+$lang->bug->browserList['opera'] = 'opera';
+$lang->bug->browserList['opera9'] = 'opera9';
+$lang->bug->browserList['oprea10'] = 'opera10';
+$lang->bug->browserList['oprea11'] = 'opera11';
+$lang->bug->browserList['safari'] = 'safari';
+$lang->bug->browserList['maxthon'] = '傲游';
+$lang->bug->browserList['uc'] = 'UC';
+$lang->bug->browserList['other'] = 'Others';
+
+$lang->bug->typeList[''] = '';
+$lang->bug->typeList['codeerror'] = 'Code error';
+$lang->bug->typeList['interface'] = 'Interface';
+$lang->bug->typeList['designchange'] = 'Design change';
+$lang->bug->typeList['newfeature'] = 'New feature';
+$lang->bug->typeList['designdefect'] = 'Design defect';
+$lang->bug->typeList['config'] = 'Config';
+$lang->bug->typeList['install'] = 'Install';
+$lang->bug->typeList['security'] = 'Security';
+$lang->bug->typeList['performance'] = 'Performance';
+$lang->bug->typeList['standard'] = 'Standard';
+$lang->bug->typeList['automation'] = 'Automation';
+$lang->bug->typeList['trackthings'] = 'Tracking';
+$lang->bug->typeList['others'] = 'Others';
+
+$lang->bug->statusList[''] = '';
+$lang->bug->statusList['active'] = 'Active';
+$lang->bug->statusList['resolved'] = 'Resolved';
+$lang->bug->statusList['closed'] = 'Closed';
+
+$lang->bug->confirmedList[1] = 'Confirmed';
+$lang->bug->confirmedList[0] = 'Unconfirmed';
+
+$lang->bug->resolutionList[''] = '';
+$lang->bug->resolutionList['bydesign'] = 'By design';
+$lang->bug->resolutionList['duplicate'] = 'Duplicate';
+$lang->bug->resolutionList['external'] = 'External';
+$lang->bug->resolutionList['fixed'] = 'Fixed';
+$lang->bug->resolutionList['notrepro'] = 'Not reproduce';
+$lang->bug->resolutionList['postponed'] = 'Postponed';
+$lang->bug->resolutionList['willnotfix'] = "Won't fix";
+$lang->bug->resolutionList['tostory'] = 'To story';
+
+/* Report. */
+$lang->bug->report = new stdclass();
+$lang->bug->report->common = 'Report';
+$lang->bug->report->select = 'Select';
+$lang->bug->report->create = 'Create';
+
+$lang->bug->report->charts['bugsPerProject'] = 'Project bugs';
+$lang->bug->report->charts['bugsPerBuild'] = 'Build bugs';
+$lang->bug->report->charts['bugsPerModule'] = 'Module bugs';
+$lang->bug->report->charts['openedBugsPerDay'] = 'Opened bugs per day';
+$lang->bug->report->charts['resolvedBugsPerDay'] = 'Resolved bugs per day';
+$lang->bug->report->charts['closedBugsPerDay'] = 'Closed bugs per day';
+$lang->bug->report->charts['openedBugsPerUser'] = 'Opened bugs per user';
+$lang->bug->report->charts['resolvedBugsPerUser'] = 'Resolved bugs per user';
+$lang->bug->report->charts['closedBugsPerUser'] = 'Closed bugs per user';
+$lang->bug->report->charts['bugsPerSeverity'] = 'Severity';
+$lang->bug->report->charts['bugsPerResolution'] = 'Resolution';
+$lang->bug->report->charts['bugsPerStatus'] = 'Status';
+$lang->bug->report->charts['bugsPerActivatedCount'] = 'Activated count';
+$lang->bug->report->charts['bugsPerType'] = 'Type';
+$lang->bug->report->charts['bugsPerAssignedTo'] = 'AssignedTo';
+//$lang->bug->report->charts['bugLiveDays'] = 'Bug处理时间统计';
+//$lang->bug->report->charts['bugHistories'] = 'Bug处理步骤统计';
+
+$lang->bug->report->options = new stdclass();
+$lang->bug->report->options->graph = new stdclass();
+$lang->bug->report->options->swf = 'pie2d';
+$lang->bug->report->options->width = 'auto';
+$lang->bug->report->options->height = 300;
+$lang->bug->report->options->graph->baseFontSize = 12;
+$lang->bug->report->options->graph->showNames = 1;
+$lang->bug->report->options->graph->formatNumber = 1;
+$lang->bug->report->options->graph->decimalPrecision = 0;
+$lang->bug->report->options->graph->animation = 0;
+$lang->bug->report->options->graph->rotateNames = 0;
+$lang->bug->report->options->graph->yAxisName = 'COUNT';
+$lang->bug->report->options->graph->pieRadius = 100;
+$lang->bug->report->options->graph->showColumnShadow = 0;
+
+$lang->bug->report->bugsPerProject = new stdclass();
+$lang->bug->report->bugsPerBuild = new stdclass();
+$lang->bug->report->bugsPerModule = new stdclass();
+$lang->bug->report->openedBugsPerDay = new stdclass();
+$lang->bug->report->resolvedBugsPerDay = new stdclass();
+$lang->bug->report->closedBugsPerDay = new stdclass();
+$lang->bug->report->openedBugsPerUser = new stdclass();
+$lang->bug->report->resolvedBugsPerUser = new stdclass();
+$lang->bug->report->closedBugsPerUser = new stdclass();
+$lang->bug->report->bugsPerSeverity = new stdclass();
+$lang->bug->report->bugsPerResolution = new stdclass();
+$lang->bug->report->bugsPerStatus = new stdclass();
+$lang->bug->report->bugsPerActivatedCount = new stdclass();
+$lang->bug->report->bugsPerType = new stdclass();
+$lang->bug->report->bugsPerAssignedTo = new stdclass();
+$lang->bug->report->bugLiveDays = new stdclass();
+$lang->bug->report->bugHistories = new stdclass();
+
+$lang->bug->report->bugsPerProject->graph = new stdclass();
+$lang->bug->report->bugsPerBuild->graph = new stdclass();
+$lang->bug->report->bugsPerModule->graph = new stdclass();
+$lang->bug->report->openedBugsPerDay->graph = new stdclass();
+$lang->bug->report->resolvedBugsPerDay->graph = new stdclass();
+$lang->bug->report->closedBugsPerDay->graph = new stdclass();
+$lang->bug->report->openedBugsPerUser->graph = new stdclass();
+$lang->bug->report->resolvedBugsPerUser->graph = new stdclass();
+$lang->bug->report->closedBugsPerUser->graph = new stdclass();
+$lang->bug->report->bugsPerSeverity->graph = new stdclass();
+$lang->bug->report->bugsPerResolution->graph = new stdclass();
+$lang->bug->report->bugsPerStatus->graph = new stdclass();
+$lang->bug->report->bugsPerActivatedCount->graph = new stdclass();
+$lang->bug->report->bugsPerType->graph = new stdclass();
+$lang->bug->report->bugsPerAssignedTo->graph = new stdclass();
+$lang->bug->report->bugLiveDays->graph = new stdclass();
+$lang->bug->report->bugHistories->graph = new stdclass();
+
+$lang->bug->report->bugsPerProject->graph->xAxisName = 'Project';
+$lang->bug->report->bugsPerBuild->graph->xAxisName = 'Build';
+$lang->bug->report->bugsPerModule->graph->xAxisName = 'Module';
+
+$lang->bug->report->openedBugsPerDay->swf = 'column2d';
+$lang->bug->report->openedBugsPerDay->height = 400;
+$lang->bug->report->openedBugsPerDay->graph->xAxisName = 'Date';
+$lang->bug->report->openedBugsPerDay->graph->rotateNames = 1;
+
+$lang->bug->report->resolvedBugsPerDay->swf = 'column2d';
+$lang->bug->report->resolvedBugsPerDay->height = 400;
+$lang->bug->report->resolvedBugsPerDay->graph->xAxisName = 'Date';
+$lang->bug->report->resolvedBugsPerDay->graph->rotateNames = 1;
+
+$lang->bug->report->closedBugsPerDay->swf = 'column2d';
+$lang->bug->report->closedBugsPerDay->height = 400;
+$lang->bug->report->closedBugsPerDay->graph->xAxisName = 'Date';
+$lang->bug->report->closedBugsPerDay->graph->rotateNames = 1;
+
+$lang->bug->report->openedBugsPerUser->graph->xAxisName = 'User';
+$lang->bug->report->resolvedBugsPerUser->graph->xAxisName= 'User';
+$lang->bug->report->closedBugsPerUser->graph->xAxisName = 'User';
+
+$lang->bug->report->bugsPerSeverity->graph->xAxisName = 'Severity';
+$lang->bug->report->bugsPerResolution->graph->xAxisName = 'Resolution';
+$lang->bug->report->bugsPerStatus->graph->xAxisName = 'Status';
+$lang->bug->report->bugsPerActivatedCount->graph->xAxisName = 'Activated count';
+$lang->bug->report->bugsPerType->graph->xAxisName = 'Type';
+$lang->bug->report->bugsPerAssignedTo->graph->xAxisName = 'AssignedTo';
+$lang->bug->report->bugLiveDays->graph->xAxisName = 'Live days';
+$lang->bug->report->bugHistories->graph->xAxisName = 'Histories';
+
+/* 操作记录。*/
+$lang->bug->action = new stdclass();
+$lang->bug->action->resolved = array('main' => '$date, Resolved by $actor , resolution is $extra .', 'extra' => $lang->bug->resolutionList);
+$lang->bug->action->tostory = array('main' => '$date, To story by $actor , ID is $extra .');
+$lang->bug->action->totask = array('main' => '$date, To task by $actor , ID is $extra .');
+
+$lang->bug->placeholder = new stdclass();
+$lang->bug->placeholder->mailto = 'you can input the user account to select users to mail to.';
+$lang->bug->placeholder->keywords = 'keywords';
diff --git a/module/bug/lang/zh-cn.php b/module/bug/lang/zh-cn.php
index b5f2e3e88c..1288d98108 100644
--- a/module/bug/lang/zh-cn.php
+++ b/module/bug/lang/zh-cn.php
@@ -1,360 +1,360 @@
-
- * @package bug
- * @version $Id$
- * @link http://www.zentao.net
- */
-/* 字段列表。*/
-$lang->bug->common = '缺陷管理';
-$lang->bug->id = 'Bug编号';
-$lang->bug->product = '所属产品';
-$lang->bug->module = '所属模块';
-$lang->bug->path = '模块路径';
-$lang->bug->project = '所属项目';
-$lang->bug->story = '相关需求';
-$lang->bug->storyVersion = '需求版本';
-$lang->bug->task = '相关任务';
-$lang->bug->title = 'Bug标题';
-$lang->bug->severity = '严重程度';
-$lang->bug->severityAB = '级别';
-$lang->bug->pri = '优先级';
-$lang->bug->type = 'Bug类型';
-$lang->bug->os = '操作系统';
-$lang->bug->hardware = '硬件平台';
-$lang->bug->browser = '浏览器';
-$lang->bug->machine = '机器硬件';
-$lang->bug->found = '如何发现';
-$lang->bug->steps = '重现步骤';
-$lang->bug->status = 'Bug状态';
-$lang->bug->statusAB = '状态';
-$lang->bug->activatedCount = '激活次数';
-$lang->bug->activatedCountAB = '激活次数';
-$lang->bug->confirmed = '是否确认';
-$lang->bug->toTask = '转任务';
-$lang->bug->toStory = '转需求';
-$lang->bug->mailto = '抄送给';
-$lang->bug->openedBy = '由谁创建';
-$lang->bug->openedByAB = '创建';
-$lang->bug->openedDate = '创建日期';
-$lang->bug->openedDateAB = '创建日期';
-$lang->bug->openedBuild = '影响版本';
-$lang->bug->assignedTo = '指派给';
-$lang->bug->assignedDate = '指派日期';
-$lang->bug->resolvedBy = '解决者';
-$lang->bug->resolvedByAB = '解决';
-$lang->bug->resolution = '解决方案';
-$lang->bug->resolutionAB = '方案';
-$lang->bug->resolvedBuild = '解决版本';
-$lang->bug->resolvedDate = '解决日期';
-$lang->bug->resolvedDateAB = '解决日期';
-$lang->bug->closedBy = '由谁关闭';
-$lang->bug->closedDate = '关闭日期';
-$lang->bug->duplicateBug = '重复ID';
-$lang->bug->lastEditedBy = '最后修改者';
-$lang->bug->lastEditedDate = '最后修改日期';
-$lang->bug->linkBug = '相关Bug';
-$lang->bug->case = '相关用例';
-$lang->bug->files = '附件';
-$lang->bug->keywords = '关键词';
-$lang->bug->lastEditedByAB = '修改者';
-$lang->bug->lastEditedDateAB = '修改日期';
-$lang->bug->fromCase = '来源用例';
-$lang->bug->toCase = '生成用例';
-
-/* 方法列表。*/
-$lang->bug->index = '首页';
-$lang->bug->create = '提Bug';
-$lang->bug->confirmBug = '确认';
-$lang->bug->edit = '编辑';
-$lang->bug->batchEdit = '批量编辑';
-$lang->bug->assignTo = '指派';
-$lang->bug->browse = 'Bug列表';
-$lang->bug->view = 'Bug详情';
-$lang->bug->resolve = '解决';
-$lang->bug->close = '关闭';
-$lang->bug->activate = '激活Bug';
-$lang->bug->reportChart = '报表统计';
-$lang->bug->export = '导出';
-$lang->bug->delete = '删除';
-$lang->bug->saveTemplate = '保存模板';
-$lang->bug->deleteTemplate = '删除模板';
-$lang->bug->customFields = '自定义字段';
-$lang->bug->restoreDefault = '恢复默认';
-$lang->bug->ajaxGetUserBugs = '接口:我的Bug';
-$lang->bug->ajaxGetModuleOwner = '接口:获得模块的默认指派人';
-$lang->bug->confirmStoryChange = '确认需求变动';
-
-/* 查询条件列表。*/
-$lang->bug->selectProduct = '请选择产品';
-$lang->bug->byModule = '按模块';
-$lang->bug->assignToMe = '指派给我';
-$lang->bug->openedByMe = '由我创建';
-$lang->bug->resolvedByMe = '由我解决';
-$lang->bug->closedByMe = '由我关闭';
-$lang->bug->assignToNull = '未指派';
-$lang->bug->unResolved = '未解决';
-$lang->bug->unclosed = '未关闭';
-$lang->bug->longLifeBugs = '久未处理';
-$lang->bug->postponedBugs = '被延期';
-$lang->bug->allBugs = '所有';
-$lang->bug->moduleBugs = '按模块';
-$lang->bug->byQuery = '搜索';
-$lang->bug->needConfirm = '需求变动';
-$lang->bug->allProduct = '所有产品';
-
-/* 页面标签。*/
-$lang->bug->lblProductAndModule = '产品模块';
-$lang->bug->lblProjectAndTask = '项目任务';
-$lang->bug->lblStory = '相关需求';
-$lang->bug->lblTypeAndSeverity = '类型/严重程度';
-$lang->bug->lblSystemBrowserAndHardware = '系统/浏览器';
-$lang->bug->lblAssignedTo = '当前指派';
-$lang->bug->lblMailto = '抄送给';
-$lang->bug->lblLastEdited = '最后修改';
-$lang->bug->lblResolved = '由谁解决';
-$lang->bug->lblAllFields = '所有字段';
-$lang->bug->lblCustomFields = '自定义字段';
-
-/* legend列表。*/
-$lang->bug->legendBasicInfo = '基本信息';
-$lang->bug->legendMailto = '抄送给';
-$lang->bug->legendAttatch = '附件';
-$lang->bug->legendLinkBugs = '相关Bug';
-$lang->bug->legendPrjStoryTask = '项目/需求/任务';
-$lang->bug->legendCases = '相关用例';
-$lang->bug->legendSteps = '重现步骤';
-$lang->bug->legendAction = '操作';
-$lang->bug->legendHistory = '历史记录';
-$lang->bug->legendComment = '备注';
-$lang->bug->legendLife = 'BUG的一生';
-$lang->bug->legendMisc = '其他相关';
-
-/* 功能按钮。*/
-$lang->bug->buttonConfirm = '确认';
-$lang->bug->buttonCopy = '复制';
-$lang->bug->buttonAssign = '指派';
-$lang->bug->buttonEdit = '编辑';
-$lang->bug->buttonActivate = '激活';
-$lang->bug->buttonResolve = '解决';
-$lang->bug->buttonClose = '关闭';
-$lang->bug->buttonToList = '返回';
-$lang->bug->buttonCreateTestcase = '建用例';
-
-/* 交互提示。*/
-$lang->bug->confirmChangeProduct = '修改产品会导致相应的项目、需求和任务发生变化,确定吗?';
-$lang->bug->confirmDelete = '您确认要删除该Bug吗?';
-$lang->bug->setTemplateTitle = '请输入bug模板标题(保存之前请先填写bug重现步骤):';
-$lang->bug->remindTask = '该Bug已经转化为任务,是否更新任务(编号:%s)状态 ?';
-
-/* 模板。*/
-$lang->bug->tplStep = "[步骤]
";
-$lang->bug->tplResult = "[结果]
";
-$lang->bug->tplExpect = "[期望]
";
-
-/* 各个字段取值列表。*/
-$lang->bug->severityList[3] = '3';
-$lang->bug->severityList[1] = '1';
-$lang->bug->severityList[2] = '2';
-$lang->bug->severityList[4] = '4';
-
-$lang->bug->priList[0] = '';
-$lang->bug->priList[3] = '3';
-$lang->bug->priList[1] = '1';
-$lang->bug->priList[2] = '2';
-$lang->bug->priList[4] = '4';
-
-$lang->bug->osList[''] = '';
-$lang->bug->osList['all'] = '全部';
-$lang->bug->osList['windows'] = 'Windows';
-$lang->bug->osList['winxp'] = 'Windows XP';
-$lang->bug->osList['win7'] = 'Windows 7';
-$lang->bug->osList['vista'] = 'Windows Vista';
-$lang->bug->osList['win2000'] = 'Windows 2000';
-$lang->bug->osList['win2003'] = 'Windows 2003';
-$lang->bug->osList['win2008'] = 'Windows 2008';
-$lang->bug->osList['winnt'] = 'Windows NT';
-$lang->bug->osList['win98'] = 'Windows 98';
-$lang->bug->osList['andriod'] = 'Andriod';
-$lang->bug->osList['ios'] = 'IOS';
-$lang->bug->osList['wp7'] = 'WP7';
-$lang->bug->osList['symbian'] = 'Symbian';
-$lang->bug->osList['linux'] = 'Linux';
-$lang->bug->osList['freebsd'] = 'FreeBSD';
-$lang->bug->osList['mac'] = 'Mac OS';
-$lang->bug->osList['unix'] = 'Unix';
-$lang->bug->osList['others'] = '其他';
-
-$lang->bug->browserList[''] = '';
-$lang->bug->browserList['all'] = '全部';
-$lang->bug->browserList['ie'] = 'IE系列';
-$lang->bug->browserList['ie8'] = 'IE8';
-$lang->bug->browserList['ie9'] = 'IE9';
-$lang->bug->browserList['ie6'] = 'IE6';
-$lang->bug->browserList['ie7'] = 'IE7';
-$lang->bug->browserList['chrome'] = 'chrome';
-$lang->bug->browserList['firefox'] = 'firefox系列';
-$lang->bug->browserList['firefox2'] = 'firefox2';
-$lang->bug->browserList['firefox3'] = 'firefox3';
-$lang->bug->browserList['firefox4'] = 'firefox4';
-$lang->bug->browserList['opera'] = 'opera系列';
-$lang->bug->browserList['opera9'] = 'opera9';
-$lang->bug->browserList['oprea10'] = 'opera10';
-$lang->bug->browserList['oprea11'] = 'opera11';
-$lang->bug->browserList['safari'] = 'safari';
-$lang->bug->browserList['maxthon'] = '傲游';
-$lang->bug->browserList['uc'] = 'UC';
-$lang->bug->browserList['other'] = '其他';
-
-$lang->bug->typeList[''] = '';
-$lang->bug->typeList['codeerror'] = '代码错误';
-$lang->bug->typeList['interface'] = '界面优化';
-$lang->bug->typeList['designchange'] = '设计变更';
-$lang->bug->typeList['newfeature'] = '新增需求';
-$lang->bug->typeList['designdefect'] = '设计缺陷';
-$lang->bug->typeList['config'] = '配置相关';
-$lang->bug->typeList['install'] = '安装部署';
-$lang->bug->typeList['security'] = '安全相关';
-$lang->bug->typeList['performance'] = '性能问题';
-$lang->bug->typeList['standard'] = '标准规范';
-$lang->bug->typeList['automation'] = '测试脚本';
-$lang->bug->typeList['trackthings'] = '事务跟踪';
-$lang->bug->typeList['others'] = '其他';
-
-$lang->bug->statusList[''] = '';
-$lang->bug->statusList['active'] = '激活';
-$lang->bug->statusList['resolved'] = '已解决';
-$lang->bug->statusList['closed'] = '已关闭';
-
-$lang->bug->confirmedList[1] = '已确认';
-$lang->bug->confirmedList[0] = '未确认';
-
-$lang->bug->resolutionList[''] = '';
-$lang->bug->resolutionList['bydesign'] = '设计如此';
-$lang->bug->resolutionList['duplicate'] = '重复Bug';
-$lang->bug->resolutionList['external'] = '外部原因';
-$lang->bug->resolutionList['fixed'] = '已解决';
-$lang->bug->resolutionList['notrepro'] = '无法重现';
-$lang->bug->resolutionList['postponed'] = '延期处理';
-$lang->bug->resolutionList['willnotfix'] = "不予解决";
-$lang->bug->resolutionList['tostory'] = '转为需求';
-
-/* 统计报表。*/
-$lang->bug->report = new stdclass();
-$lang->bug->report->common = '报表';
-$lang->bug->report->select = '请选择报表类型';
-$lang->bug->report->create = '生成报表';
-
-$lang->bug->report->charts['bugsPerProject'] = '项目Bug数量';
-$lang->bug->report->charts['bugsPerBuild'] = '版本Bug数量';
-$lang->bug->report->charts['bugsPerModule'] = '模块Bug数量';
-$lang->bug->report->charts['openedBugsPerDay'] = '每天新增Bug数';
-$lang->bug->report->charts['resolvedBugsPerDay'] = '每天解决Bug数';
-$lang->bug->report->charts['closedBugsPerDay'] = '每天关闭的Bug数';
-$lang->bug->report->charts['openedBugsPerUser'] = '每人提交的Bug数';
-$lang->bug->report->charts['resolvedBugsPerUser'] = '每人解决的Bug数';
-$lang->bug->report->charts['closedBugsPerUser'] = '每人关闭的Bug数';
-$lang->bug->report->charts['bugsPerSeverity'] = 'Bug严重程度统计';
-$lang->bug->report->charts['bugsPerResolution'] = 'Bug解决方案统计';
-$lang->bug->report->charts['bugsPerStatus'] = 'Bug状态统计';
-$lang->bug->report->charts['bugsPerActivatedCount'] = 'Bug激活次数统计';
-$lang->bug->report->charts['bugsPerType'] = 'Bug类型统计';
-$lang->bug->report->charts['bugsPerAssignedTo'] = '指派给统计';
-//$lang->bug->report->charts['bugLiveDays'] = 'Bug处理时间统计';
-//$lang->bug->report->charts['bugHistories'] = 'Bug处理步骤统计';
-
-$lang->bug->report->options = new stdclass();
-$lang->bug->report->options->graph = new stdclass();
-$lang->bug->report->options->swf = 'pie2d';
-$lang->bug->report->options->width = 'auto';
-$lang->bug->report->options->height = 300;
-$lang->bug->report->options->graph->baseFontSize = 12;
-$lang->bug->report->options->graph->showNames = 1;
-$lang->bug->report->options->graph->formatNumber = 1;
-$lang->bug->report->options->graph->decimalPrecision = 0;
-$lang->bug->report->options->graph->animation = 0;
-$lang->bug->report->options->graph->rotateNames = 0;
-$lang->bug->report->options->graph->yAxisName = 'COUNT';
-$lang->bug->report->options->graph->pieRadius = 100; // 饼图直径。
-$lang->bug->report->options->graph->showColumnShadow = 0; // 是否显示柱状图阴影。
-
-$lang->bug->report->bugsPerProject = new stdclass();
-$lang->bug->report->bugsPerBuild = new stdclass();
-$lang->bug->report->bugsPerModule = new stdclass();
-$lang->bug->report->openedBugsPerDay = new stdclass();
-$lang->bug->report->resolvedBugsPerDay = new stdclass();
-$lang->bug->report->closedBugsPerDay = new stdclass();
-$lang->bug->report->openedBugsPerUser = new stdclass();
-$lang->bug->report->resolvedBugsPerUser = new stdclass();
-$lang->bug->report->closedBugsPerUser = new stdclass();
-$lang->bug->report->bugsPerSeverity = new stdclass();
-$lang->bug->report->bugsPerResolution = new stdclass();
-$lang->bug->report->bugsPerStatus = new stdclass();
-$lang->bug->report->bugsPerActivatedCount = new stdclass();
-$lang->bug->report->bugsPerType = new stdclass();
-$lang->bug->report->bugsPerAssignedTo = new stdclass();
-$lang->bug->report->bugLiveDays = new stdclass();
-$lang->bug->report->bugHistories = new stdclass();
-
-$lang->bug->report->bugsPerProject->graph = new stdclass();
-$lang->bug->report->bugsPerBuild->graph = new stdclass();
-$lang->bug->report->bugsPerModule->graph = new stdclass();
-$lang->bug->report->openedBugsPerDay->graph = new stdclass();
-$lang->bug->report->resolvedBugsPerDay->graph = new stdclass();
-$lang->bug->report->closedBugsPerDay->graph = new stdclass();
-$lang->bug->report->openedBugsPerUser->graph = new stdclass();
-$lang->bug->report->resolvedBugsPerUser->graph = new stdclass();
-$lang->bug->report->closedBugsPerUser->graph = new stdclass();
-$lang->bug->report->bugsPerSeverity->graph = new stdclass();
-$lang->bug->report->bugsPerResolution->graph = new stdclass();
-$lang->bug->report->bugsPerStatus->graph = new stdclass();
-$lang->bug->report->bugsPerActivatedCount->graph = new stdclass();
-$lang->bug->report->bugsPerType->graph = new stdclass();
-$lang->bug->report->bugsPerAssignedTo->graph = new stdclass();
-$lang->bug->report->bugLiveDays->graph = new stdclass();
-$lang->bug->report->bugHistories->graph = new stdclass();
-
-$lang->bug->report->bugsPerProject->graph->xAxisName = '项目';
-$lang->bug->report->bugsPerBuild->graph->xAxisName = '版本';
-$lang->bug->report->bugsPerModule->graph->xAxisName = '模块';
-
-$lang->bug->report->openedBugsPerDay->swf = 'column2d';
-$lang->bug->report->openedBugsPerDay->height = 400;
-$lang->bug->report->openedBugsPerDay->graph->xAxisName = '日期';
-$lang->bug->report->openedBugsPerDay->graph->rotateNames = 1;
-
-$lang->bug->report->resolvedBugsPerDay->swf = 'column2d';
-$lang->bug->report->resolvedBugsPerDay->height = 400;
-$lang->bug->report->resolvedBugsPerDay->graph->xAxisName = '日期';
-$lang->bug->report->resolvedBugsPerDay->graph->rotateNames = 1;
-
-$lang->bug->report->closedBugsPerDay->swf = 'column2d';
-$lang->bug->report->closedBugsPerDay->height = 400;
-$lang->bug->report->closedBugsPerDay->graph->xAxisName = '日期';
-$lang->bug->report->closedBugsPerDay->graph->rotateNames = 1;
-
-$lang->bug->report->openedBugsPerUser->graph->xAxisName = '用户';
-$lang->bug->report->resolvedBugsPerUser->graph->xAxisName= '用户';
-$lang->bug->report->closedBugsPerUser->graph->xAxisName = '用户';
-
-$lang->bug->report->bugsPerSeverity->graph->xAxisName = '严重程度';
-$lang->bug->report->bugsPerResolution->graph->xAxisName = '解决方案';
-$lang->bug->report->bugsPerStatus->graph->xAxisName = '状态';
-$lang->bug->report->bugsPerActivatedCount->graph->xAxisName = '激活次数';
-$lang->bug->report->bugsPerType->graph->xAxisName = '类型';
-$lang->bug->report->bugsPerAssignedTo->graph->xAxisName = '指派给';
-$lang->bug->report->bugLiveDays->graph->xAxisName = '处理时间';
-$lang->bug->report->bugHistories->graph->xAxisName = '处理步骤';
-
-/* 操作记录。*/
-$lang->bug->action = new stdclass();
-$lang->bug->action->resolved = array('main' => '$date, 由 $actor 解决,方案为 $extra 。', 'extra' => $lang->bug->resolutionList);
-$lang->bug->action->tostory = array('main' => '$date, 由 $actor 转为需求 ,编号为 $extra 。');
-$lang->bug->action->totask = array('main' => '$date, 由 $actor 导入为任务 ,编号为 $extra 。');
-
-$lang->bug->placeholder = new stdclass();
-$lang->bug->placeholder->mailto = '输入用户名自动选择';
+
+ * @package bug
+ * @version $Id$
+ * @link http://www.zentao.net
+ */
+/* 字段列表。*/
+$lang->bug->common = '缺陷管理';
+$lang->bug->id = 'Bug编号';
+$lang->bug->product = '所属产品';
+$lang->bug->module = '所属模块';
+$lang->bug->path = '模块路径';
+$lang->bug->project = '所属项目';
+$lang->bug->story = '相关需求';
+$lang->bug->storyVersion = '需求版本';
+$lang->bug->task = '相关任务';
+$lang->bug->title = 'Bug标题';
+$lang->bug->severity = '严重程度';
+$lang->bug->severityAB = '级别';
+$lang->bug->pri = '优先级';
+$lang->bug->type = 'Bug类型';
+$lang->bug->os = '操作系统';
+$lang->bug->hardware = '硬件平台';
+$lang->bug->browser = '浏览器';
+$lang->bug->machine = '机器硬件';
+$lang->bug->found = '如何发现';
+$lang->bug->steps = '重现步骤';
+$lang->bug->status = 'Bug状态';
+$lang->bug->statusAB = '状态';
+$lang->bug->activatedCount = '激活次数';
+$lang->bug->activatedCountAB = '激活次数';
+$lang->bug->confirmed = '是否确认';
+$lang->bug->toTask = '转任务';
+$lang->bug->toStory = '转需求';
+$lang->bug->mailto = '抄送给';
+$lang->bug->openedBy = '由谁创建';
+$lang->bug->openedByAB = '创建';
+$lang->bug->openedDate = '创建日期';
+$lang->bug->openedDateAB = '创建日期';
+$lang->bug->openedBuild = '影响版本';
+$lang->bug->assignedTo = '指派给';
+$lang->bug->assignedDate = '指派日期';
+$lang->bug->resolvedBy = '解决者';
+$lang->bug->resolvedByAB = '解决';
+$lang->bug->resolution = '解决方案';
+$lang->bug->resolutionAB = '方案';
+$lang->bug->resolvedBuild = '解决版本';
+$lang->bug->resolvedDate = '解决日期';
+$lang->bug->resolvedDateAB = '解决日期';
+$lang->bug->closedBy = '由谁关闭';
+$lang->bug->closedDate = '关闭日期';
+$lang->bug->duplicateBug = '重复ID';
+$lang->bug->lastEditedBy = '最后修改者';
+$lang->bug->lastEditedDate = '最后修改日期';
+$lang->bug->linkBug = '相关Bug';
+$lang->bug->case = '相关用例';
+$lang->bug->files = '附件';
+$lang->bug->keywords = '关键词';
+$lang->bug->lastEditedByAB = '修改者';
+$lang->bug->lastEditedDateAB = '修改日期';
+$lang->bug->fromCase = '来源用例';
+$lang->bug->toCase = '生成用例';
+
+/* 方法列表。*/
+$lang->bug->index = '首页';
+$lang->bug->create = '提Bug';
+$lang->bug->confirmBug = '确认';
+$lang->bug->edit = '编辑';
+$lang->bug->batchEdit = '批量编辑';
+$lang->bug->assignTo = '指派';
+$lang->bug->browse = 'Bug列表';
+$lang->bug->view = 'Bug详情';
+$lang->bug->resolve = '解决';
+$lang->bug->close = '关闭';
+$lang->bug->activate = '激活Bug';
+$lang->bug->reportChart = '报表统计';
+$lang->bug->export = '导出';
+$lang->bug->delete = '删除';
+$lang->bug->saveTemplate = '保存模板';
+$lang->bug->deleteTemplate = '删除模板';
+$lang->bug->customFields = '自定义字段';
+$lang->bug->restoreDefault = '恢复默认';
+$lang->bug->ajaxGetUserBugs = '接口:我的Bug';
+$lang->bug->ajaxGetModuleOwner = '接口:获得模块的默认指派人';
+$lang->bug->confirmStoryChange = '确认需求变动';
+
+/* 查询条件列表。*/
+$lang->bug->selectProduct = '请选择产品';
+$lang->bug->byModule = '按模块';
+$lang->bug->assignToMe = '指派给我';
+$lang->bug->openedByMe = '由我创建';
+$lang->bug->resolvedByMe = '由我解决';
+$lang->bug->closedByMe = '由我关闭';
+$lang->bug->assignToNull = '未指派';
+$lang->bug->unResolved = '未解决';
+$lang->bug->unclosed = '未关闭';
+$lang->bug->longLifeBugs = '久未处理';
+$lang->bug->postponedBugs = '被延期';
+$lang->bug->allBugs = '所有';
+$lang->bug->moduleBugs = '按模块';
+$lang->bug->byQuery = '搜索';
+$lang->bug->needConfirm = '需求变动';
+$lang->bug->allProduct = '所有产品';
+
+/* 页面标签。*/
+$lang->bug->lblProductAndModule = '产品模块';
+$lang->bug->lblProjectAndTask = '项目任务';
+$lang->bug->lblStory = '相关需求';
+$lang->bug->lblTypeAndSeverity = '类型/严重程度';
+$lang->bug->lblSystemBrowserAndHardware = '系统/浏览器';
+$lang->bug->lblAssignedTo = '当前指派';
+$lang->bug->lblMailto = '抄送给';
+$lang->bug->lblLastEdited = '最后修改';
+$lang->bug->lblResolved = '由谁解决';
+$lang->bug->lblAllFields = '所有字段';
+$lang->bug->lblCustomFields = '自定义字段';
+
+/* legend列表。*/
+$lang->bug->legendBasicInfo = '基本信息';
+$lang->bug->legendMailto = '抄送给';
+$lang->bug->legendAttatch = '附件';
+$lang->bug->legendLinkBugs = '相关Bug';
+$lang->bug->legendPrjStoryTask = '项目/需求/任务';
+$lang->bug->legendCases = '相关用例';
+$lang->bug->legendSteps = '重现步骤';
+$lang->bug->legendAction = '操作';
+$lang->bug->legendHistory = '历史记录';
+$lang->bug->legendComment = '备注';
+$lang->bug->legendLife = 'BUG的一生';
+$lang->bug->legendMisc = '其他相关';
+
+/* 功能按钮。*/
+$lang->bug->buttonConfirm = '确认';
+$lang->bug->buttonCopy = '复制';
+$lang->bug->buttonAssign = '指派';
+$lang->bug->buttonEdit = '编辑';
+$lang->bug->buttonActivate = '激活';
+$lang->bug->buttonResolve = '解决';
+$lang->bug->buttonClose = '关闭';
+$lang->bug->buttonToList = '返回';
+$lang->bug->buttonCreateTestcase = '建用例';
+
+/* 交互提示。*/
+$lang->bug->confirmChangeProduct = '修改产品会导致相应的项目、需求和任务发生变化,确定吗?';
+$lang->bug->confirmDelete = '您确认要删除该Bug吗?';
+$lang->bug->setTemplateTitle = '请输入bug模板标题(保存之前请先填写bug重现步骤):';
+$lang->bug->remindTask = '该Bug已经转化为任务,是否更新任务(编号:%s)状态 ?';
+
+/* 模板。*/
+$lang->bug->tplStep = "[步骤]
";
+$lang->bug->tplResult = "[结果]
";
+$lang->bug->tplExpect = "[期望]
";
+
+/* 各个字段取值列表。*/
+$lang->bug->severityList[3] = '3';
+$lang->bug->severityList[1] = '1';
+$lang->bug->severityList[2] = '2';
+$lang->bug->severityList[4] = '4';
+
+$lang->bug->priList[0] = '';
+$lang->bug->priList[3] = '3';
+$lang->bug->priList[1] = '1';
+$lang->bug->priList[2] = '2';
+$lang->bug->priList[4] = '4';
+
+$lang->bug->osList[''] = '';
+$lang->bug->osList['all'] = '全部';
+$lang->bug->osList['windows'] = 'Windows';
+$lang->bug->osList['winxp'] = 'Windows XP';
+$lang->bug->osList['win7'] = 'Windows 7';
+$lang->bug->osList['vista'] = 'Windows Vista';
+$lang->bug->osList['win2000'] = 'Windows 2000';
+$lang->bug->osList['win2003'] = 'Windows 2003';
+$lang->bug->osList['win2008'] = 'Windows 2008';
+$lang->bug->osList['winnt'] = 'Windows NT';
+$lang->bug->osList['win98'] = 'Windows 98';
+$lang->bug->osList['andriod'] = 'Andriod';
+$lang->bug->osList['ios'] = 'IOS';
+$lang->bug->osList['wp7'] = 'WP7';
+$lang->bug->osList['symbian'] = 'Symbian';
+$lang->bug->osList['linux'] = 'Linux';
+$lang->bug->osList['freebsd'] = 'FreeBSD';
+$lang->bug->osList['mac'] = 'Mac OS';
+$lang->bug->osList['unix'] = 'Unix';
+$lang->bug->osList['others'] = '其他';
+
+$lang->bug->browserList[''] = '';
+$lang->bug->browserList['all'] = '全部';
+$lang->bug->browserList['ie'] = 'IE系列';
+$lang->bug->browserList['ie8'] = 'IE8';
+$lang->bug->browserList['ie9'] = 'IE9';
+$lang->bug->browserList['ie6'] = 'IE6';
+$lang->bug->browserList['ie7'] = 'IE7';
+$lang->bug->browserList['chrome'] = 'chrome';
+$lang->bug->browserList['firefox'] = 'firefox系列';
+$lang->bug->browserList['firefox2'] = 'firefox2';
+$lang->bug->browserList['firefox3'] = 'firefox3';
+$lang->bug->browserList['firefox4'] = 'firefox4';
+$lang->bug->browserList['opera'] = 'opera系列';
+$lang->bug->browserList['opera9'] = 'opera9';
+$lang->bug->browserList['oprea10'] = 'opera10';
+$lang->bug->browserList['oprea11'] = 'opera11';
+$lang->bug->browserList['safari'] = 'safari';
+$lang->bug->browserList['maxthon'] = '傲游';
+$lang->bug->browserList['uc'] = 'UC';
+$lang->bug->browserList['other'] = '其他';
+
+$lang->bug->typeList[''] = '';
+$lang->bug->typeList['codeerror'] = '代码错误';
+$lang->bug->typeList['interface'] = '界面优化';
+$lang->bug->typeList['designchange'] = '设计变更';
+$lang->bug->typeList['newfeature'] = '新增需求';
+$lang->bug->typeList['designdefect'] = '设计缺陷';
+$lang->bug->typeList['config'] = '配置相关';
+$lang->bug->typeList['install'] = '安装部署';
+$lang->bug->typeList['security'] = '安全相关';
+$lang->bug->typeList['performance'] = '性能问题';
+$lang->bug->typeList['standard'] = '标准规范';
+$lang->bug->typeList['automation'] = '测试脚本';
+$lang->bug->typeList['trackthings'] = '事务跟踪';
+$lang->bug->typeList['others'] = '其他';
+
+$lang->bug->statusList[''] = '';
+$lang->bug->statusList['active'] = '激活';
+$lang->bug->statusList['resolved'] = '已解决';
+$lang->bug->statusList['closed'] = '已关闭';
+
+$lang->bug->confirmedList[1] = '已确认';
+$lang->bug->confirmedList[0] = '未确认';
+
+$lang->bug->resolutionList[''] = '';
+$lang->bug->resolutionList['bydesign'] = '设计如此';
+$lang->bug->resolutionList['duplicate'] = '重复Bug';
+$lang->bug->resolutionList['external'] = '外部原因';
+$lang->bug->resolutionList['fixed'] = '已解决';
+$lang->bug->resolutionList['notrepro'] = '无法重现';
+$lang->bug->resolutionList['postponed'] = '延期处理';
+$lang->bug->resolutionList['willnotfix'] = "不予解决";
+$lang->bug->resolutionList['tostory'] = '转为需求';
+
+/* 统计报表。*/
+$lang->bug->report = new stdclass();
+$lang->bug->report->common = '报表';
+$lang->bug->report->select = '请选择报表类型';
+$lang->bug->report->create = '生成报表';
+
+$lang->bug->report->charts['bugsPerProject'] = '项目Bug数量';
+$lang->bug->report->charts['bugsPerBuild'] = '版本Bug数量';
+$lang->bug->report->charts['bugsPerModule'] = '模块Bug数量';
+$lang->bug->report->charts['openedBugsPerDay'] = '每天新增Bug数';
+$lang->bug->report->charts['resolvedBugsPerDay'] = '每天解决Bug数';
+$lang->bug->report->charts['closedBugsPerDay'] = '每天关闭的Bug数';
+$lang->bug->report->charts['openedBugsPerUser'] = '每人提交的Bug数';
+$lang->bug->report->charts['resolvedBugsPerUser'] = '每人解决的Bug数';
+$lang->bug->report->charts['closedBugsPerUser'] = '每人关闭的Bug数';
+$lang->bug->report->charts['bugsPerSeverity'] = 'Bug严重程度统计';
+$lang->bug->report->charts['bugsPerResolution'] = 'Bug解决方案统计';
+$lang->bug->report->charts['bugsPerStatus'] = 'Bug状态统计';
+$lang->bug->report->charts['bugsPerActivatedCount'] = 'Bug激活次数统计';
+$lang->bug->report->charts['bugsPerType'] = 'Bug类型统计';
+$lang->bug->report->charts['bugsPerAssignedTo'] = '指派给统计';
+//$lang->bug->report->charts['bugLiveDays'] = 'Bug处理时间统计';
+//$lang->bug->report->charts['bugHistories'] = 'Bug处理步骤统计';
+
+$lang->bug->report->options = new stdclass();
+$lang->bug->report->options->graph = new stdclass();
+$lang->bug->report->options->swf = 'pie2d';
+$lang->bug->report->options->width = 'auto';
+$lang->bug->report->options->height = 300;
+$lang->bug->report->options->graph->baseFontSize = 12;
+$lang->bug->report->options->graph->showNames = 1;
+$lang->bug->report->options->graph->formatNumber = 1;
+$lang->bug->report->options->graph->decimalPrecision = 0;
+$lang->bug->report->options->graph->animation = 0;
+$lang->bug->report->options->graph->rotateNames = 0;
+$lang->bug->report->options->graph->yAxisName = 'COUNT';
+$lang->bug->report->options->graph->pieRadius = 100; // 饼图直径。
+$lang->bug->report->options->graph->showColumnShadow = 0; // 是否显示柱状图阴影。
+
+$lang->bug->report->bugsPerProject = new stdclass();
+$lang->bug->report->bugsPerBuild = new stdclass();
+$lang->bug->report->bugsPerModule = new stdclass();
+$lang->bug->report->openedBugsPerDay = new stdclass();
+$lang->bug->report->resolvedBugsPerDay = new stdclass();
+$lang->bug->report->closedBugsPerDay = new stdclass();
+$lang->bug->report->openedBugsPerUser = new stdclass();
+$lang->bug->report->resolvedBugsPerUser = new stdclass();
+$lang->bug->report->closedBugsPerUser = new stdclass();
+$lang->bug->report->bugsPerSeverity = new stdclass();
+$lang->bug->report->bugsPerResolution = new stdclass();
+$lang->bug->report->bugsPerStatus = new stdclass();
+$lang->bug->report->bugsPerActivatedCount = new stdclass();
+$lang->bug->report->bugsPerType = new stdclass();
+$lang->bug->report->bugsPerAssignedTo = new stdclass();
+$lang->bug->report->bugLiveDays = new stdclass();
+$lang->bug->report->bugHistories = new stdclass();
+
+$lang->bug->report->bugsPerProject->graph = new stdclass();
+$lang->bug->report->bugsPerBuild->graph = new stdclass();
+$lang->bug->report->bugsPerModule->graph = new stdclass();
+$lang->bug->report->openedBugsPerDay->graph = new stdclass();
+$lang->bug->report->resolvedBugsPerDay->graph = new stdclass();
+$lang->bug->report->closedBugsPerDay->graph = new stdclass();
+$lang->bug->report->openedBugsPerUser->graph = new stdclass();
+$lang->bug->report->resolvedBugsPerUser->graph = new stdclass();
+$lang->bug->report->closedBugsPerUser->graph = new stdclass();
+$lang->bug->report->bugsPerSeverity->graph = new stdclass();
+$lang->bug->report->bugsPerResolution->graph = new stdclass();
+$lang->bug->report->bugsPerStatus->graph = new stdclass();
+$lang->bug->report->bugsPerActivatedCount->graph = new stdclass();
+$lang->bug->report->bugsPerType->graph = new stdclass();
+$lang->bug->report->bugsPerAssignedTo->graph = new stdclass();
+$lang->bug->report->bugLiveDays->graph = new stdclass();
+$lang->bug->report->bugHistories->graph = new stdclass();
+
+$lang->bug->report->bugsPerProject->graph->xAxisName = '项目';
+$lang->bug->report->bugsPerBuild->graph->xAxisName = '版本';
+$lang->bug->report->bugsPerModule->graph->xAxisName = '模块';
+
+$lang->bug->report->openedBugsPerDay->swf = 'column2d';
+$lang->bug->report->openedBugsPerDay->height = 400;
+$lang->bug->report->openedBugsPerDay->graph->xAxisName = '日期';
+$lang->bug->report->openedBugsPerDay->graph->rotateNames = 1;
+
+$lang->bug->report->resolvedBugsPerDay->swf = 'column2d';
+$lang->bug->report->resolvedBugsPerDay->height = 400;
+$lang->bug->report->resolvedBugsPerDay->graph->xAxisName = '日期';
+$lang->bug->report->resolvedBugsPerDay->graph->rotateNames = 1;
+
+$lang->bug->report->closedBugsPerDay->swf = 'column2d';
+$lang->bug->report->closedBugsPerDay->height = 400;
+$lang->bug->report->closedBugsPerDay->graph->xAxisName = '日期';
+$lang->bug->report->closedBugsPerDay->graph->rotateNames = 1;
+
+$lang->bug->report->openedBugsPerUser->graph->xAxisName = '用户';
+$lang->bug->report->resolvedBugsPerUser->graph->xAxisName= '用户';
+$lang->bug->report->closedBugsPerUser->graph->xAxisName = '用户';
+
+$lang->bug->report->bugsPerSeverity->graph->xAxisName = '严重程度';
+$lang->bug->report->bugsPerResolution->graph->xAxisName = '解决方案';
+$lang->bug->report->bugsPerStatus->graph->xAxisName = '状态';
+$lang->bug->report->bugsPerActivatedCount->graph->xAxisName = '激活次数';
+$lang->bug->report->bugsPerType->graph->xAxisName = '类型';
+$lang->bug->report->bugsPerAssignedTo->graph->xAxisName = '指派给';
+$lang->bug->report->bugLiveDays->graph->xAxisName = '处理时间';
+$lang->bug->report->bugHistories->graph->xAxisName = '处理步骤';
+
+/* 操作记录。*/
+$lang->bug->action = new stdclass();
+$lang->bug->action->resolved = array('main' => '$date, 由 $actor 解决,方案为 $extra 。', 'extra' => $lang->bug->resolutionList);
+$lang->bug->action->tostory = array('main' => '$date, 由 $actor 转为需求 ,编号为 $extra 。');
+$lang->bug->action->totask = array('main' => '$date, 由 $actor 导入为任务 ,编号为 $extra 。');
+
+$lang->bug->placeholder = new stdclass();
+$lang->bug->placeholder->mailto = '输入用户名自动选择';
diff --git a/module/bug/lang/zh-tw.php b/module/bug/lang/zh-tw.php
index de43502e37..83abcc7aec 100644
--- a/module/bug/lang/zh-tw.php
+++ b/module/bug/lang/zh-tw.php
@@ -1,360 +1,360 @@
-
- * @package bug
- * @version $Id: zh-tw.php 3772 2012-12-12 02:18:16Z wwccss $
- * @link http://www.zentao.net
- */
-/* 欄位列表。*/
-$lang->bug->common = '缺陷管理';
-$lang->bug->id = 'Bug編號';
-$lang->bug->product = '所屬產品';
-$lang->bug->module = '所屬模組';
-$lang->bug->path = '模組路徑';
-$lang->bug->project = '所屬項目';
-$lang->bug->story = '相關需求';
-$lang->bug->storyVersion = '需求版本';
-$lang->bug->task = '相關任務';
-$lang->bug->title = 'Bug標題';
-$lang->bug->severity = '嚴重程度';
-$lang->bug->severityAB = '級別';
-$lang->bug->pri = '優先順序';
-$lang->bug->type = 'Bug類型';
-$lang->bug->os = '操作系統';
-$lang->bug->hardware = '硬件平台';
-$lang->bug->browser = '瀏覽器';
-$lang->bug->machine = '機器硬件';
-$lang->bug->found = '如何發現';
-$lang->bug->steps = '重現步驟';
-$lang->bug->status = 'Bug狀態';
-$lang->bug->statusAB = '狀態';
-$lang->bug->activatedCount = '激活次數';
-$lang->bug->activatedCountAB = '激活次數';
-$lang->bug->confirmed = '是否確認';
-$lang->bug->toTask = '轉任務';
-$lang->bug->toStory = '轉需求';
-$lang->bug->mailto = '抄送給';
-$lang->bug->openedBy = '由誰創建';
-$lang->bug->openedByAB = '創建';
-$lang->bug->openedDate = '創建日期';
-$lang->bug->openedDateAB = '創建日期';
-$lang->bug->openedBuild = '影響版本';
-$lang->bug->assignedTo = '指派給';
-$lang->bug->assignedDate = '指派日期';
-$lang->bug->resolvedBy = '解決者';
-$lang->bug->resolvedByAB = '解決';
-$lang->bug->resolution = '解決方案';
-$lang->bug->resolutionAB = '方案';
-$lang->bug->resolvedBuild = '解決版本';
-$lang->bug->resolvedDate = '解決日期';
-$lang->bug->resolvedDateAB = '解決日期';
-$lang->bug->closedBy = '由誰關閉';
-$lang->bug->closedDate = '關閉日期';
-$lang->bug->duplicateBug = '重複ID';
-$lang->bug->lastEditedBy = '最後修改者';
-$lang->bug->lastEditedDate = '最後修改日期';
-$lang->bug->linkBug = '相關Bug';
-$lang->bug->case = '相關用例';
-$lang->bug->files = '附件';
-$lang->bug->keywords = '關鍵詞';
-$lang->bug->lastEditedByAB = '修改者';
-$lang->bug->lastEditedDateAB = '修改日期';
-$lang->bug->fromCase = '來源用例';
-$lang->bug->toCase = '生成用例';
-
-/* 方法列表。*/
-$lang->bug->index = '首頁';
-$lang->bug->create = '創建';
-$lang->bug->confirmBug = '確認';
-$lang->bug->edit = '編輯';
-$lang->bug->batchEdit = '批量編輯';
-$lang->bug->assignTo = '指派';
-$lang->bug->browse = 'Bug列表';
-$lang->bug->view = 'Bug詳情';
-$lang->bug->resolve = '解決';
-$lang->bug->close = '關閉';
-$lang->bug->activate = '激活Bug';
-$lang->bug->reportChart = '報表統計';
-$lang->bug->export = '導出';
-$lang->bug->delete = '刪除';
-$lang->bug->saveTemplate = '保存模板';
-$lang->bug->deleteTemplate = '刪除模板';
-$lang->bug->customFields = '自定義欄位';
-$lang->bug->restoreDefault = '恢復預設';
-$lang->bug->ajaxGetUserBugs = '介面:我的Bug';
-$lang->bug->ajaxGetModuleOwner = '介面:獲得模組的預設指派人';
-$lang->bug->confirmStoryChange = '確認需求變動';
-
-/* 查詢條件列表。*/
-$lang->bug->selectProduct = '請選擇產品';
-$lang->bug->byModule = '按模組';
-$lang->bug->assignToMe = '指派給我';
-$lang->bug->openedByMe = '由我創建';
-$lang->bug->resolvedByMe = '由我解決';
-$lang->bug->closedByMe = '由我關閉';
-$lang->bug->assignToNull = '未指派';
-$lang->bug->unResolved = '未解決';
-$lang->bug->unclosed = '未關閉';
-$lang->bug->longLifeBugs = '久未處理';
-$lang->bug->postponedBugs = '被延期';
-$lang->bug->allBugs = '所有';
-$lang->bug->moduleBugs = '按模組';
-$lang->bug->byQuery = '搜索';
-$lang->bug->needConfirm = '需求變動';
-$lang->bug->allProduct = '所有產品';
-
-/* 頁面標籤。*/
-$lang->bug->lblProductAndModule = '產品模組';
-$lang->bug->lblProjectAndTask = '項目任務';
-$lang->bug->lblStory = '相關需求';
-$lang->bug->lblTypeAndSeverity = '類型/嚴重程度';
-$lang->bug->lblSystemBrowserAndHardware = '系統/瀏覽器';
-$lang->bug->lblAssignedTo = '當前指派';
-$lang->bug->lblMailto = '抄送給';
-$lang->bug->lblLastEdited = '最後修改';
-$lang->bug->lblResolved = '由誰解決';
-$lang->bug->lblAllFields = '所有欄位';
-$lang->bug->lblCustomFields = '自定義欄位';
-
-/* legend列表。*/
-$lang->bug->legendBasicInfo = '基本信息';
-$lang->bug->legendMailto = '抄送給';
-$lang->bug->legendAttatch = '附件';
-$lang->bug->legendLinkBugs = '相關Bug';
-$lang->bug->legendPrjStoryTask = '項目/需求/任務';
-$lang->bug->legendCases = '相關用例';
-$lang->bug->legendSteps = '重現步驟';
-$lang->bug->legendAction = '操作';
-$lang->bug->legendHistory = '歷史記錄';
-$lang->bug->legendComment = '備註';
-$lang->bug->legendLife = 'BUG的一生';
-$lang->bug->legendMisc = '其他相關';
-
-/* 功能按鈕。*/
-$lang->bug->buttonConfirm = '確認';
-$lang->bug->buttonCopy = '複製';
-$lang->bug->buttonAssign = '指派';
-$lang->bug->buttonEdit = '編輯';
-$lang->bug->buttonActivate = '激活';
-$lang->bug->buttonResolve = '解決';
-$lang->bug->buttonClose = '關閉';
-$lang->bug->buttonToList = '返回';
-$lang->bug->buttonCreateTestcase = '建用例';
-
-/* 交互提示。*/
-$lang->bug->confirmChangeProduct = '修改產品會導致相應的項目、需求和任務發生變化,確定嗎?';
-$lang->bug->confirmDelete = '您確認要刪除該Bug嗎?';
-$lang->bug->setTemplateTitle = '請輸入bug模板標題(保存之前請先填寫bug重現步驟):';
-$lang->bug->remindTask = '該Bug已經轉化為任務,是否更新任務(編號:%s)狀態 ?';
-
-/* 模板。*/
-$lang->bug->tplStep = "[步驟]
";
-$lang->bug->tplResult = "[結果]
";
-$lang->bug->tplExpect = "[期望]
";
-
-/* 各個欄位取值列表。*/
-$lang->bug->severityList[3] = '3';
-$lang->bug->severityList[1] = '1';
-$lang->bug->severityList[2] = '2';
-$lang->bug->severityList[4] = '4';
-
-$lang->bug->priList[0] = '';
-$lang->bug->priList[3] = '3';
-$lang->bug->priList[1] = '1';
-$lang->bug->priList[2] = '2';
-$lang->bug->priList[4] = '4';
-
-$lang->bug->osList[''] = '';
-$lang->bug->osList['all'] = '全部';
-$lang->bug->osList['windows'] = 'Windows';
-$lang->bug->osList['winxp'] = 'Windows XP';
-$lang->bug->osList['win7'] = 'Windows 7';
-$lang->bug->osList['vista'] = 'Windows Vista';
-$lang->bug->osList['win2000'] = 'Windows 2000';
-$lang->bug->osList['win2003'] = 'Windows 2003';
-$lang->bug->osList['win2008'] = 'Windows 2008';
-$lang->bug->osList['winnt'] = 'Windows NT';
-$lang->bug->osList['win98'] = 'Windows 98';
-$lang->bug->osList['andriod'] = 'Andriod';
-$lang->bug->osList['ios'] = 'IOS';
-$lang->bug->osList['wp7'] = 'WP7';
-$lang->bug->osList['symbian'] = 'Symbian';
-$lang->bug->osList['linux'] = 'Linux';
-$lang->bug->osList['freebsd'] = 'FreeBSD';
-$lang->bug->osList['mac'] = 'Mac OS';
-$lang->bug->osList['unix'] = 'Unix';
-$lang->bug->osList['others'] = '其他';
-
-$lang->bug->browserList[''] = '';
-$lang->bug->browserList['all'] = '全部';
-$lang->bug->browserList['ie'] = 'IE系列';
-$lang->bug->browserList['ie8'] = 'IE8';
-$lang->bug->browserList['ie9'] = 'IE9';
-$lang->bug->browserList['ie6'] = 'IE6';
-$lang->bug->browserList['ie7'] = 'IE7';
-$lang->bug->browserList['chrome'] = 'chrome';
-$lang->bug->browserList['firefox'] = 'firefox系列';
-$lang->bug->browserList['firefox2'] = 'firefox2';
-$lang->bug->browserList['firefox3'] = 'firefox3';
-$lang->bug->browserList['firefox4'] = 'firefox4';
-$lang->bug->browserList['opera'] = 'opera系列';
-$lang->bug->browserList['opera9'] = 'opera9';
-$lang->bug->browserList['oprea10'] = 'opera10';
-$lang->bug->browserList['oprea11'] = 'opera11';
-$lang->bug->browserList['safari'] = 'safari';
-$lang->bug->browserList['maxthon'] = '傲游';
-$lang->bug->browserList['uc'] = 'UC';
-$lang->bug->browserList['other'] = '其他';
-
-$lang->bug->typeList[''] = '';
-$lang->bug->typeList['codeerror'] = '代碼錯誤';
-$lang->bug->typeList['interface'] = '界面優化';
-$lang->bug->typeList['designchange'] = '設計變更';
-$lang->bug->typeList['newfeature'] = '新增需求';
-$lang->bug->typeList['designdefect'] = '設計缺陷';
-$lang->bug->typeList['config'] = '配置相關';
-$lang->bug->typeList['install'] = '安裝部署';
-$lang->bug->typeList['security'] = '安全相關';
-$lang->bug->typeList['performance'] = '性能問題';
-$lang->bug->typeList['standard'] = '標準規範';
-$lang->bug->typeList['automation'] = '測試腳本';
-$lang->bug->typeList['trackthings'] = '事務跟蹤';
-$lang->bug->typeList['others'] = '其他';
-
-$lang->bug->statusList[''] = '';
-$lang->bug->statusList['active'] = '激活';
-$lang->bug->statusList['resolved'] = '已解決';
-$lang->bug->statusList['closed'] = '已關閉';
-
-$lang->bug->confirmedList[1] = '已確認';
-$lang->bug->confirmedList[0] = '未確認';
-
-$lang->bug->resolutionList[''] = '';
-$lang->bug->resolutionList['bydesign'] = '設計如此';
-$lang->bug->resolutionList['duplicate'] = '重複Bug';
-$lang->bug->resolutionList['external'] = '外部原因';
-$lang->bug->resolutionList['fixed'] = '已解決';
-$lang->bug->resolutionList['notrepro'] = '無法重現';
-$lang->bug->resolutionList['postponed'] = '延期處理';
-$lang->bug->resolutionList['willnotfix'] = "不予解決";
-$lang->bug->resolutionList['tostory'] = '轉為需求';
-
-/* 統計報表。*/
-$lang->bug->report = new stdclass();
-$lang->bug->report->common = '報表';
-$lang->bug->report->select = '請選擇報表類型';
-$lang->bug->report->create = '生成報表';
-
-$lang->bug->report->charts['bugsPerProject'] = '項目Bug數量';
-$lang->bug->report->charts['bugsPerBuild'] = '版本Bug數量';
-$lang->bug->report->charts['bugsPerModule'] = '模組Bug數量';
-$lang->bug->report->charts['openedBugsPerDay'] = '每天新增Bug數';
-$lang->bug->report->charts['resolvedBugsPerDay'] = '每天解決Bug數';
-$lang->bug->report->charts['closedBugsPerDay'] = '每天關閉的Bug數';
-$lang->bug->report->charts['openedBugsPerUser'] = '每人提交的Bug數';
-$lang->bug->report->charts['resolvedBugsPerUser'] = '每人解決的Bug數';
-$lang->bug->report->charts['closedBugsPerUser'] = '每人關閉的Bug數';
-$lang->bug->report->charts['bugsPerSeverity'] = 'Bug嚴重程度統計';
-$lang->bug->report->charts['bugsPerResolution'] = 'Bug解決方案統計';
-$lang->bug->report->charts['bugsPerStatus'] = 'Bug狀態統計';
-$lang->bug->report->charts['bugsPerActivatedCount'] = 'Bug激活次數統計';
-$lang->bug->report->charts['bugsPerType'] = 'Bug類型統計';
-$lang->bug->report->charts['bugsPerAssignedTo'] = '指派給統計';
-//$lang->bug->report->charts['bugLiveDays'] = 'Bug處理時間統計';
-//$lang->bug->report->charts['bugHistories'] = 'Bug處理步驟統計';
-
-$lang->bug->report->options = new stdclass();
-$lang->bug->report->options->graph = new stdclass();
-$lang->bug->report->options->swf = 'pie2d';
-$lang->bug->report->options->width = 'auto';
-$lang->bug->report->options->height = 300;
-$lang->bug->report->options->graph->baseFontSize = 12;
-$lang->bug->report->options->graph->showNames = 1;
-$lang->bug->report->options->graph->formatNumber = 1;
-$lang->bug->report->options->graph->decimalPrecision = 0;
-$lang->bug->report->options->graph->animation = 0;
-$lang->bug->report->options->graph->rotateNames = 0;
-$lang->bug->report->options->graph->yAxisName = 'COUNT';
-$lang->bug->report->options->graph->pieRadius = 100; // 餅圖直徑。
-$lang->bug->report->options->graph->showColumnShadow = 0; // 是否顯示柱狀圖陰影。
-
-$lang->bug->report->bugsPerProject = new stdclass();
-$lang->bug->report->bugsPerBuild = new stdclass();
-$lang->bug->report->bugsPerModule = new stdclass();
-$lang->bug->report->openedBugsPerDay = new stdclass();
-$lang->bug->report->resolvedBugsPerDay = new stdclass();
-$lang->bug->report->closedBugsPerDay = new stdclass();
-$lang->bug->report->openedBugsPerUser = new stdclass();
-$lang->bug->report->resolvedBugsPerUser = new stdclass();
-$lang->bug->report->closedBugsPerUser = new stdclass();
-$lang->bug->report->bugsPerSeverity = new stdclass();
-$lang->bug->report->bugsPerResolution = new stdclass();
-$lang->bug->report->bugsPerStatus = new stdclass();
-$lang->bug->report->bugsPerActivatedCount = new stdclass();
-$lang->bug->report->bugsPerType = new stdclass();
-$lang->bug->report->bugsPerAssignedTo = new stdclass();
-$lang->bug->report->bugLiveDays = new stdclass();
-$lang->bug->report->bugHistories = new stdclass();
-
-$lang->bug->report->bugsPerProject->graph = new stdclass();
-$lang->bug->report->bugsPerBuild->graph = new stdclass();
-$lang->bug->report->bugsPerModule->graph = new stdclass();
-$lang->bug->report->openedBugsPerDay->graph = new stdclass();
-$lang->bug->report->resolvedBugsPerDay->graph = new stdclass();
-$lang->bug->report->closedBugsPerDay->graph = new stdclass();
-$lang->bug->report->openedBugsPerUser->graph = new stdclass();
-$lang->bug->report->resolvedBugsPerUser->graph = new stdclass();
-$lang->bug->report->closedBugsPerUser->graph = new stdclass();
-$lang->bug->report->bugsPerSeverity->graph = new stdclass();
-$lang->bug->report->bugsPerResolution->graph = new stdclass();
-$lang->bug->report->bugsPerStatus->graph = new stdclass();
-$lang->bug->report->bugsPerActivatedCount->graph = new stdclass();
-$lang->bug->report->bugsPerType->graph = new stdclass();
-$lang->bug->report->bugsPerAssignedTo->graph = new stdclass();
-$lang->bug->report->bugLiveDays->graph = new stdclass();
-$lang->bug->report->bugHistories->graph = new stdclass();
-
-$lang->bug->report->bugsPerProject->graph->xAxisName = '項目';
-$lang->bug->report->bugsPerBuild->graph->xAxisName = '版本';
-$lang->bug->report->bugsPerModule->graph->xAxisName = '模組';
-
-$lang->bug->report->openedBugsPerDay->swf = 'column2d';
-$lang->bug->report->openedBugsPerDay->height = 400;
-$lang->bug->report->openedBugsPerDay->graph->xAxisName = '日期';
-$lang->bug->report->openedBugsPerDay->graph->rotateNames = 1;
-
-$lang->bug->report->resolvedBugsPerDay->swf = 'column2d';
-$lang->bug->report->resolvedBugsPerDay->height = 400;
-$lang->bug->report->resolvedBugsPerDay->graph->xAxisName = '日期';
-$lang->bug->report->resolvedBugsPerDay->graph->rotateNames = 1;
-
-$lang->bug->report->closedBugsPerDay->swf = 'column2d';
-$lang->bug->report->closedBugsPerDay->height = 400;
-$lang->bug->report->closedBugsPerDay->graph->xAxisName = '日期';
-$lang->bug->report->closedBugsPerDay->graph->rotateNames = 1;
-
-$lang->bug->report->openedBugsPerUser->graph->xAxisName = '用戶';
-$lang->bug->report->resolvedBugsPerUser->graph->xAxisName= '用戶';
-$lang->bug->report->closedBugsPerUser->graph->xAxisName = '用戶';
-
-$lang->bug->report->bugsPerSeverity->graph->xAxisName = '嚴重程度';
-$lang->bug->report->bugsPerResolution->graph->xAxisName = '解決方案';
-$lang->bug->report->bugsPerStatus->graph->xAxisName = '狀態';
-$lang->bug->report->bugsPerActivatedCount->graph->xAxisName = '激活次數';
-$lang->bug->report->bugsPerType->graph->xAxisName = '類型';
-$lang->bug->report->bugsPerAssignedTo->graph->xAxisName = '指派給';
-$lang->bug->report->bugLiveDays->graph->xAxisName = '處理時間';
-$lang->bug->report->bugHistories->graph->xAxisName = '處理步驟';
-
-/* 操作記錄。*/
-$lang->bug->action = new stdclass();
-$lang->bug->action->resolved = array('main' => '$date, 由 $actor 解決,方案為 $extra 。', 'extra' => $lang->bug->resolutionList);
-$lang->bug->action->tostory = array('main' => '$date, 由 $actor 轉為需求 ,編號為 $extra 。');
-$lang->bug->action->totask = array('main' => '$date, 由 $actor 導入為任務 ,編號為 $extra 。');
-
-$lang->bug->placeholder = new stdclass();
-$lang->bug->placeholder->mailto = '輸入用戶名自動選擇';
+
+ * @package bug
+ * @version $Id: zh-tw.php 3772 2012-12-12 02:18:16Z wwccss $
+ * @link http://www.zentao.net
+ */
+/* 欄位列表。*/
+$lang->bug->common = '缺陷管理';
+$lang->bug->id = 'Bug編號';
+$lang->bug->product = '所屬產品';
+$lang->bug->module = '所屬模組';
+$lang->bug->path = '模組路徑';
+$lang->bug->project = '所屬項目';
+$lang->bug->story = '相關需求';
+$lang->bug->storyVersion = '需求版本';
+$lang->bug->task = '相關任務';
+$lang->bug->title = 'Bug標題';
+$lang->bug->severity = '嚴重程度';
+$lang->bug->severityAB = '級別';
+$lang->bug->pri = '優先順序';
+$lang->bug->type = 'Bug類型';
+$lang->bug->os = '操作系統';
+$lang->bug->hardware = '硬件平台';
+$lang->bug->browser = '瀏覽器';
+$lang->bug->machine = '機器硬件';
+$lang->bug->found = '如何發現';
+$lang->bug->steps = '重現步驟';
+$lang->bug->status = 'Bug狀態';
+$lang->bug->statusAB = '狀態';
+$lang->bug->activatedCount = '激活次數';
+$lang->bug->activatedCountAB = '激活次數';
+$lang->bug->confirmed = '是否確認';
+$lang->bug->toTask = '轉任務';
+$lang->bug->toStory = '轉需求';
+$lang->bug->mailto = '抄送給';
+$lang->bug->openedBy = '由誰創建';
+$lang->bug->openedByAB = '創建';
+$lang->bug->openedDate = '創建日期';
+$lang->bug->openedDateAB = '創建日期';
+$lang->bug->openedBuild = '影響版本';
+$lang->bug->assignedTo = '指派給';
+$lang->bug->assignedDate = '指派日期';
+$lang->bug->resolvedBy = '解決者';
+$lang->bug->resolvedByAB = '解決';
+$lang->bug->resolution = '解決方案';
+$lang->bug->resolutionAB = '方案';
+$lang->bug->resolvedBuild = '解決版本';
+$lang->bug->resolvedDate = '解決日期';
+$lang->bug->resolvedDateAB = '解決日期';
+$lang->bug->closedBy = '由誰關閉';
+$lang->bug->closedDate = '關閉日期';
+$lang->bug->duplicateBug = '重複ID';
+$lang->bug->lastEditedBy = '最後修改者';
+$lang->bug->lastEditedDate = '最後修改日期';
+$lang->bug->linkBug = '相關Bug';
+$lang->bug->case = '相關用例';
+$lang->bug->files = '附件';
+$lang->bug->keywords = '關鍵詞';
+$lang->bug->lastEditedByAB = '修改者';
+$lang->bug->lastEditedDateAB = '修改日期';
+$lang->bug->fromCase = '來源用例';
+$lang->bug->toCase = '生成用例';
+
+/* 方法列表。*/
+$lang->bug->index = '首頁';
+$lang->bug->create = '創建';
+$lang->bug->confirmBug = '確認';
+$lang->bug->edit = '編輯';
+$lang->bug->batchEdit = '批量編輯';
+$lang->bug->assignTo = '指派';
+$lang->bug->browse = 'Bug列表';
+$lang->bug->view = 'Bug詳情';
+$lang->bug->resolve = '解決';
+$lang->bug->close = '關閉';
+$lang->bug->activate = '激活Bug';
+$lang->bug->reportChart = '報表統計';
+$lang->bug->export = '導出';
+$lang->bug->delete = '刪除';
+$lang->bug->saveTemplate = '保存模板';
+$lang->bug->deleteTemplate = '刪除模板';
+$lang->bug->customFields = '自定義欄位';
+$lang->bug->restoreDefault = '恢復預設';
+$lang->bug->ajaxGetUserBugs = '介面:我的Bug';
+$lang->bug->ajaxGetModuleOwner = '介面:獲得模組的預設指派人';
+$lang->bug->confirmStoryChange = '確認需求變動';
+
+/* 查詢條件列表。*/
+$lang->bug->selectProduct = '請選擇產品';
+$lang->bug->byModule = '按模組';
+$lang->bug->assignToMe = '指派給我';
+$lang->bug->openedByMe = '由我創建';
+$lang->bug->resolvedByMe = '由我解決';
+$lang->bug->closedByMe = '由我關閉';
+$lang->bug->assignToNull = '未指派';
+$lang->bug->unResolved = '未解決';
+$lang->bug->unclosed = '未關閉';
+$lang->bug->longLifeBugs = '久未處理';
+$lang->bug->postponedBugs = '被延期';
+$lang->bug->allBugs = '所有';
+$lang->bug->moduleBugs = '按模組';
+$lang->bug->byQuery = '搜索';
+$lang->bug->needConfirm = '需求變動';
+$lang->bug->allProduct = '所有產品';
+
+/* 頁面標籤。*/
+$lang->bug->lblProductAndModule = '產品模組';
+$lang->bug->lblProjectAndTask = '項目任務';
+$lang->bug->lblStory = '相關需求';
+$lang->bug->lblTypeAndSeverity = '類型/嚴重程度';
+$lang->bug->lblSystemBrowserAndHardware = '系統/瀏覽器';
+$lang->bug->lblAssignedTo = '當前指派';
+$lang->bug->lblMailto = '抄送給';
+$lang->bug->lblLastEdited = '最後修改';
+$lang->bug->lblResolved = '由誰解決';
+$lang->bug->lblAllFields = '所有欄位';
+$lang->bug->lblCustomFields = '自定義欄位';
+
+/* legend列表。*/
+$lang->bug->legendBasicInfo = '基本信息';
+$lang->bug->legendMailto = '抄送給';
+$lang->bug->legendAttatch = '附件';
+$lang->bug->legendLinkBugs = '相關Bug';
+$lang->bug->legendPrjStoryTask = '項目/需求/任務';
+$lang->bug->legendCases = '相關用例';
+$lang->bug->legendSteps = '重現步驟';
+$lang->bug->legendAction = '操作';
+$lang->bug->legendHistory = '歷史記錄';
+$lang->bug->legendComment = '備註';
+$lang->bug->legendLife = 'BUG的一生';
+$lang->bug->legendMisc = '其他相關';
+
+/* 功能按鈕。*/
+$lang->bug->buttonConfirm = '確認';
+$lang->bug->buttonCopy = '複製';
+$lang->bug->buttonAssign = '指派';
+$lang->bug->buttonEdit = '編輯';
+$lang->bug->buttonActivate = '激活';
+$lang->bug->buttonResolve = '解決';
+$lang->bug->buttonClose = '關閉';
+$lang->bug->buttonToList = '返回';
+$lang->bug->buttonCreateTestcase = '建用例';
+
+/* 交互提示。*/
+$lang->bug->confirmChangeProduct = '修改產品會導致相應的項目、需求和任務發生變化,確定嗎?';
+$lang->bug->confirmDelete = '您確認要刪除該Bug嗎?';
+$lang->bug->setTemplateTitle = '請輸入bug模板標題(保存之前請先填寫bug重現步驟):';
+$lang->bug->remindTask = '該Bug已經轉化為任務,是否更新任務(編號:%s)狀態 ?';
+
+/* 模板。*/
+$lang->bug->tplStep = "[步驟]
";
+$lang->bug->tplResult = "[結果]
";
+$lang->bug->tplExpect = "[期望]
";
+
+/* 各個欄位取值列表。*/
+$lang->bug->severityList[3] = '3';
+$lang->bug->severityList[1] = '1';
+$lang->bug->severityList[2] = '2';
+$lang->bug->severityList[4] = '4';
+
+$lang->bug->priList[0] = '';
+$lang->bug->priList[3] = '3';
+$lang->bug->priList[1] = '1';
+$lang->bug->priList[2] = '2';
+$lang->bug->priList[4] = '4';
+
+$lang->bug->osList[''] = '';
+$lang->bug->osList['all'] = '全部';
+$lang->bug->osList['windows'] = 'Windows';
+$lang->bug->osList['winxp'] = 'Windows XP';
+$lang->bug->osList['win7'] = 'Windows 7';
+$lang->bug->osList['vista'] = 'Windows Vista';
+$lang->bug->osList['win2000'] = 'Windows 2000';
+$lang->bug->osList['win2003'] = 'Windows 2003';
+$lang->bug->osList['win2008'] = 'Windows 2008';
+$lang->bug->osList['winnt'] = 'Windows NT';
+$lang->bug->osList['win98'] = 'Windows 98';
+$lang->bug->osList['andriod'] = 'Andriod';
+$lang->bug->osList['ios'] = 'IOS';
+$lang->bug->osList['wp7'] = 'WP7';
+$lang->bug->osList['symbian'] = 'Symbian';
+$lang->bug->osList['linux'] = 'Linux';
+$lang->bug->osList['freebsd'] = 'FreeBSD';
+$lang->bug->osList['mac'] = 'Mac OS';
+$lang->bug->osList['unix'] = 'Unix';
+$lang->bug->osList['others'] = '其他';
+
+$lang->bug->browserList[''] = '';
+$lang->bug->browserList['all'] = '全部';
+$lang->bug->browserList['ie'] = 'IE系列';
+$lang->bug->browserList['ie8'] = 'IE8';
+$lang->bug->browserList['ie9'] = 'IE9';
+$lang->bug->browserList['ie6'] = 'IE6';
+$lang->bug->browserList['ie7'] = 'IE7';
+$lang->bug->browserList['chrome'] = 'chrome';
+$lang->bug->browserList['firefox'] = 'firefox系列';
+$lang->bug->browserList['firefox2'] = 'firefox2';
+$lang->bug->browserList['firefox3'] = 'firefox3';
+$lang->bug->browserList['firefox4'] = 'firefox4';
+$lang->bug->browserList['opera'] = 'opera系列';
+$lang->bug->browserList['opera9'] = 'opera9';
+$lang->bug->browserList['oprea10'] = 'opera10';
+$lang->bug->browserList['oprea11'] = 'opera11';
+$lang->bug->browserList['safari'] = 'safari';
+$lang->bug->browserList['maxthon'] = '傲游';
+$lang->bug->browserList['uc'] = 'UC';
+$lang->bug->browserList['other'] = '其他';
+
+$lang->bug->typeList[''] = '';
+$lang->bug->typeList['codeerror'] = '代碼錯誤';
+$lang->bug->typeList['interface'] = '界面優化';
+$lang->bug->typeList['designchange'] = '設計變更';
+$lang->bug->typeList['newfeature'] = '新增需求';
+$lang->bug->typeList['designdefect'] = '設計缺陷';
+$lang->bug->typeList['config'] = '配置相關';
+$lang->bug->typeList['install'] = '安裝部署';
+$lang->bug->typeList['security'] = '安全相關';
+$lang->bug->typeList['performance'] = '性能問題';
+$lang->bug->typeList['standard'] = '標準規範';
+$lang->bug->typeList['automation'] = '測試腳本';
+$lang->bug->typeList['trackthings'] = '事務跟蹤';
+$lang->bug->typeList['others'] = '其他';
+
+$lang->bug->statusList[''] = '';
+$lang->bug->statusList['active'] = '激活';
+$lang->bug->statusList['resolved'] = '已解決';
+$lang->bug->statusList['closed'] = '已關閉';
+
+$lang->bug->confirmedList[1] = '已確認';
+$lang->bug->confirmedList[0] = '未確認';
+
+$lang->bug->resolutionList[''] = '';
+$lang->bug->resolutionList['bydesign'] = '設計如此';
+$lang->bug->resolutionList['duplicate'] = '重複Bug';
+$lang->bug->resolutionList['external'] = '外部原因';
+$lang->bug->resolutionList['fixed'] = '已解決';
+$lang->bug->resolutionList['notrepro'] = '無法重現';
+$lang->bug->resolutionList['postponed'] = '延期處理';
+$lang->bug->resolutionList['willnotfix'] = "不予解決";
+$lang->bug->resolutionList['tostory'] = '轉為需求';
+
+/* 統計報表。*/
+$lang->bug->report = new stdclass();
+$lang->bug->report->common = '報表';
+$lang->bug->report->select = '請選擇報表類型';
+$lang->bug->report->create = '生成報表';
+
+$lang->bug->report->charts['bugsPerProject'] = '項目Bug數量';
+$lang->bug->report->charts['bugsPerBuild'] = '版本Bug數量';
+$lang->bug->report->charts['bugsPerModule'] = '模組Bug數量';
+$lang->bug->report->charts['openedBugsPerDay'] = '每天新增Bug數';
+$lang->bug->report->charts['resolvedBugsPerDay'] = '每天解決Bug數';
+$lang->bug->report->charts['closedBugsPerDay'] = '每天關閉的Bug數';
+$lang->bug->report->charts['openedBugsPerUser'] = '每人提交的Bug數';
+$lang->bug->report->charts['resolvedBugsPerUser'] = '每人解決的Bug數';
+$lang->bug->report->charts['closedBugsPerUser'] = '每人關閉的Bug數';
+$lang->bug->report->charts['bugsPerSeverity'] = 'Bug嚴重程度統計';
+$lang->bug->report->charts['bugsPerResolution'] = 'Bug解決方案統計';
+$lang->bug->report->charts['bugsPerStatus'] = 'Bug狀態統計';
+$lang->bug->report->charts['bugsPerActivatedCount'] = 'Bug激活次數統計';
+$lang->bug->report->charts['bugsPerType'] = 'Bug類型統計';
+$lang->bug->report->charts['bugsPerAssignedTo'] = '指派給統計';
+//$lang->bug->report->charts['bugLiveDays'] = 'Bug處理時間統計';
+//$lang->bug->report->charts['bugHistories'] = 'Bug處理步驟統計';
+
+$lang->bug->report->options = new stdclass();
+$lang->bug->report->options->graph = new stdclass();
+$lang->bug->report->options->swf = 'pie2d';
+$lang->bug->report->options->width = 'auto';
+$lang->bug->report->options->height = 300;
+$lang->bug->report->options->graph->baseFontSize = 12;
+$lang->bug->report->options->graph->showNames = 1;
+$lang->bug->report->options->graph->formatNumber = 1;
+$lang->bug->report->options->graph->decimalPrecision = 0;
+$lang->bug->report->options->graph->animation = 0;
+$lang->bug->report->options->graph->rotateNames = 0;
+$lang->bug->report->options->graph->yAxisName = 'COUNT';
+$lang->bug->report->options->graph->pieRadius = 100; // 餅圖直徑。
+$lang->bug->report->options->graph->showColumnShadow = 0; // 是否顯示柱狀圖陰影。
+
+$lang->bug->report->bugsPerProject = new stdclass();
+$lang->bug->report->bugsPerBuild = new stdclass();
+$lang->bug->report->bugsPerModule = new stdclass();
+$lang->bug->report->openedBugsPerDay = new stdclass();
+$lang->bug->report->resolvedBugsPerDay = new stdclass();
+$lang->bug->report->closedBugsPerDay = new stdclass();
+$lang->bug->report->openedBugsPerUser = new stdclass();
+$lang->bug->report->resolvedBugsPerUser = new stdclass();
+$lang->bug->report->closedBugsPerUser = new stdclass();
+$lang->bug->report->bugsPerSeverity = new stdclass();
+$lang->bug->report->bugsPerResolution = new stdclass();
+$lang->bug->report->bugsPerStatus = new stdclass();
+$lang->bug->report->bugsPerActivatedCount = new stdclass();
+$lang->bug->report->bugsPerType = new stdclass();
+$lang->bug->report->bugsPerAssignedTo = new stdclass();
+$lang->bug->report->bugLiveDays = new stdclass();
+$lang->bug->report->bugHistories = new stdclass();
+
+$lang->bug->report->bugsPerProject->graph = new stdclass();
+$lang->bug->report->bugsPerBuild->graph = new stdclass();
+$lang->bug->report->bugsPerModule->graph = new stdclass();
+$lang->bug->report->openedBugsPerDay->graph = new stdclass();
+$lang->bug->report->resolvedBugsPerDay->graph = new stdclass();
+$lang->bug->report->closedBugsPerDay->graph = new stdclass();
+$lang->bug->report->openedBugsPerUser->graph = new stdclass();
+$lang->bug->report->resolvedBugsPerUser->graph = new stdclass();
+$lang->bug->report->closedBugsPerUser->graph = new stdclass();
+$lang->bug->report->bugsPerSeverity->graph = new stdclass();
+$lang->bug->report->bugsPerResolution->graph = new stdclass();
+$lang->bug->report->bugsPerStatus->graph = new stdclass();
+$lang->bug->report->bugsPerActivatedCount->graph = new stdclass();
+$lang->bug->report->bugsPerType->graph = new stdclass();
+$lang->bug->report->bugsPerAssignedTo->graph = new stdclass();
+$lang->bug->report->bugLiveDays->graph = new stdclass();
+$lang->bug->report->bugHistories->graph = new stdclass();
+
+$lang->bug->report->bugsPerProject->graph->xAxisName = '項目';
+$lang->bug->report->bugsPerBuild->graph->xAxisName = '版本';
+$lang->bug->report->bugsPerModule->graph->xAxisName = '模組';
+
+$lang->bug->report->openedBugsPerDay->swf = 'column2d';
+$lang->bug->report->openedBugsPerDay->height = 400;
+$lang->bug->report->openedBugsPerDay->graph->xAxisName = '日期';
+$lang->bug->report->openedBugsPerDay->graph->rotateNames = 1;
+
+$lang->bug->report->resolvedBugsPerDay->swf = 'column2d';
+$lang->bug->report->resolvedBugsPerDay->height = 400;
+$lang->bug->report->resolvedBugsPerDay->graph->xAxisName = '日期';
+$lang->bug->report->resolvedBugsPerDay->graph->rotateNames = 1;
+
+$lang->bug->report->closedBugsPerDay->swf = 'column2d';
+$lang->bug->report->closedBugsPerDay->height = 400;
+$lang->bug->report->closedBugsPerDay->graph->xAxisName = '日期';
+$lang->bug->report->closedBugsPerDay->graph->rotateNames = 1;
+
+$lang->bug->report->openedBugsPerUser->graph->xAxisName = '用戶';
+$lang->bug->report->resolvedBugsPerUser->graph->xAxisName= '用戶';
+$lang->bug->report->closedBugsPerUser->graph->xAxisName = '用戶';
+
+$lang->bug->report->bugsPerSeverity->graph->xAxisName = '嚴重程度';
+$lang->bug->report->bugsPerResolution->graph->xAxisName = '解決方案';
+$lang->bug->report->bugsPerStatus->graph->xAxisName = '狀態';
+$lang->bug->report->bugsPerActivatedCount->graph->xAxisName = '激活次數';
+$lang->bug->report->bugsPerType->graph->xAxisName = '類型';
+$lang->bug->report->bugsPerAssignedTo->graph->xAxisName = '指派給';
+$lang->bug->report->bugLiveDays->graph->xAxisName = '處理時間';
+$lang->bug->report->bugHistories->graph->xAxisName = '處理步驟';
+
+/* 操作記錄。*/
+$lang->bug->action = new stdclass();
+$lang->bug->action->resolved = array('main' => '$date, 由 $actor 解決,方案為 $extra 。', 'extra' => $lang->bug->resolutionList);
+$lang->bug->action->tostory = array('main' => '$date, 由 $actor 轉為需求 ,編號為 $extra 。');
+$lang->bug->action->totask = array('main' => '$date, 由 $actor 導入為任務 ,編號為 $extra 。');
+
+$lang->bug->placeholder = new stdclass();
+$lang->bug->placeholder->mailto = '輸入用戶名自動選擇';
diff --git a/module/bug/model.php b/module/bug/model.php
index a633757505..bd1c6b201e 100644
--- a/module/bug/model.php
+++ b/module/bug/model.php
@@ -1,1214 +1,1214 @@
-
- * @package bug
- * @version $Id$
- * @link http://www.zentao.net
- */
-?>
-loadModel('product')->setMenu($products, $productID);
- $selectHtml = $this->product->select($products, $productID, 'bug', 'browse');
- foreach($this->lang->bug->menu as $key => $menu)
- {
- $replace = ($key == 'product') ? $selectHtml : $productID;
- common::setMenuVars($this->lang->bug->menu, $key, $replace);
- }
- }
-
- /**
- * Create a bug.
- *
- * @access public
- * @return int|bool
- */
- public function create()
- {
- $now = helper::now();
- $bug = fixer::input('post')
- ->add('openedBy', $this->app->user->account)
- ->add('openedDate', $now)
- ->setDefault('project,story,task', 0)
- ->setDefault('openedBuild', '')
- ->setIF($this->post->assignedTo != '', 'assignedDate', $now)
- ->setIF($this->post->story != false, 'storyVersion', $this->loadModel('story')->getVersion($this->post->story))
- ->specialChars('title,keyword')
- ->cleanInt('product, module, severity')
- ->join('openedBuild', ',')
- ->remove('files, labels')
- ->get();
- $this->dao->insert(TABLE_BUG)->data($bug)->autoCheck()->batchCheck($this->config->bug->create->requiredFields, 'notempty')->exec();
- if(!dao::isError())
- {
- $bugID = $this->dao->lastInsertID();
- $this->loadModel('file')->saveUpload('bug', $bugID);
- return $bugID;
- }
- return false;
- }
-
- /**
- * Get bugs of a module.
- *
- * @param int $productID
- * @param string|array $moduleIds
- * @param string $orderBy
- * @param object $pager
- * @access public
- * @return array
- */
- public function getModuleBugs($productID, $moduleIds = 0, $projects, $orderBy = 'id_desc', $pager = null)
- {
- return $this->dao->select('*')->from(TABLE_BUG)
- ->where('product')->eq((int)$productID)
- ->beginIF(!empty($moduleIds))->andWhere('module')->in($moduleIds)->fi()
- ->andWhere('project')->in(array_keys($projects))
- ->andWhere('deleted')->eq(0)
- ->orderBy($orderBy)->page($pager)->fetchAll();
- }
-
- /**
- * Get info of a bug.
- *
- * @param int $bugID
- * @param bool $setImgSize
- * @access public
- * @return object
- */
- public function getById($bugID, $setImgSize = false)
- {
- $bug = $this->dao->select('t1.*, t2.name AS projectName, t3.title AS storyTitle, t3.status AS storyStatus, t3.version AS latestStoryVersion, t4.name AS taskName')
- ->from(TABLE_BUG)->alias('t1')
- ->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.project = t2.id')
- ->leftJoin(TABLE_STORY)->alias('t3')->on('t1.story = t3.id')
- ->leftJoin(TABLE_TASK)->alias('t4')->on('t1.task = t4.id')
- ->where('t1.id')->eq((int)$bugID)->fetch();
- if(!$bug) return false;
-
- if($setImgSize) $bug->steps = $this->loadModel('file')->setImgSize($bug->steps);
- foreach($bug as $key => $value) if(strpos($key, 'Date') !== false and !(int)substr($value, 0, 4)) $bug->$key = '';
-
- if($bug->mailto)
- {
- $bug->mailto = ltrim(trim($bug->mailto), ','); // Remove the first ,
- $bug->mailto = str_replace(' ', '', $bug->mailto);
- $bug->mailto = rtrim($bug->mailto, ',') . ',';
- $bug->mailto = str_replace(',', ', ', $bug->mailto);
- }
-
- if($bug->duplicateBug) $bug->duplicateBugTitle = $this->dao->findById($bug->duplicateBug)->from(TABLE_BUG)->fields('title')->fetch('title');
- if($bug->case) $bug->caseTitle = $this->dao->findById($bug->case)->from(TABLE_CASE)->fields('title')->fetch('title');
- if($bug->linkBug) $bug->linkBugTitles = $this->dao->select('id,title')->from(TABLE_BUG)->where('id')->in($bug->linkBug)->fetchPairs();
- if($bug->toStory > 0) $bug->toStoryTitle = $this->dao->findById($bug->toStory)->from(TABLE_STORY)->fields('title')->fetch('title');
- if($bug->toTask > 0) $bug->toTaskTitle = $this->dao->findById($bug->toTask)->from(TABLE_TASK)->fields('name')->fetch('name');
-
- $bug->toCases = array();
- $toCases = $this->dao->select('id, title')->from(TABLE_CASE)->where('`fromBug`')->eq($bugID)->fetchAll();
- foreach($toCases as $toCase) $bug->toCases[$toCase->id] = $toCase->title;
-
- $bug->files = $this->loadModel('file')->getByObject('bug', $bugID);
-
- return $bug;
- }
-
- /**
- * getActiveBugs
- *
- * @param object $pager
- * @param int $projectID
- * @access public
- * @return array
- */
- public function getActiveBugs($pager, $projectID, $products)
- {
- return $this->dao->select('*')->from(TABLE_BUG)
- ->where('status')->eq('active')
- ->andWhere('toTask')->eq(0)
- ->andWhere('tostory')->eq(0)
- ->beginIF(!empty($products))->andWhere('product')->in($products)->fi()
- ->beginIF(empty($products))->andWhere('project')->eq($projectID)->fi()
- ->andWhere('deleted')->eq(0)
- ->orderBy('id desc')
- ->page($pager)
- ->fetchAll();
- }
-
- /**
- * Update a bug.
- *
- * @param int $bugID
- * @access public
- * @return void
- */
- public function update($bugID)
- {
- $oldBug = $this->getById($bugID);
- $now = helper::now();
- $bug = fixer::input('post')
- ->cleanInt('product,module,severity,project,story,task')
- ->specialChars('title,keyword')
- ->remove('comment,files,labels')
- ->setDefault('project,module,project,story,task,duplicateBug', 0)
- ->setDefault('openedBuild', '')
- ->add('lastEditedBy', $this->app->user->account)
- ->add('lastEditedDate', $now)
- ->join('openedBuild', ',')
- ->setIF($this->post->assignedTo != $oldBug->assignedTo, 'assignedDate', $now)
- ->setIF($this->post->resolvedBy != '' and $this->post->resolvedDate == '', 'resolvedDate', $now)
- ->setIF($this->post->resolution != '' and $this->post->resolvedDate == '', 'resolvedDate', $now)
- ->setIF($this->post->resolution != '' and $this->post->resolvedBy == '', 'resolvedBy', $this->app->user->account)
- ->setIF($this->post->closedBy != '' and $this->post->closedDate == '', 'closedDate', $now)
- ->setIF($this->post->closedDate != '' and $this->post->closedBy == '', 'closedBy', $this->app->user->account)
- ->setIF($this->post->closedBy != '' or $this->post->closedDate != '', 'assignedTo', 'closed')
- ->setIF($this->post->closedBy != '' or $this->post->closedDate != '', 'assignedDate', $now)
- ->setIF($this->post->resolution != '' or $this->post->resolvedDate != '', 'status', 'resolved')
- ->setIF($this->post->closedBy != '' or $this->post->closedDate != '', 'status', 'closed')
- ->setIF(($this->post->resolution != '' or $this->post->resolvedDate != '') and $this->post->assignedTo == '', 'assignedTo', $oldBug->openedBy)
- ->setIF(($this->post->resolution != '' or $this->post->resolvedDate != '') and $this->post->assignedTo == '', 'assignedDate', $now)
- ->setIF($this->post->resolution == '' and $this->post->resolvedDate =='', 'status', 'active')
- ->setIF($this->post->resolution != '', 'confirmed', 1)
- ->setIF($this->post->story != false and $this->post->story != $oldBug->story, 'storyVersion', $this->loadModel('story')->getVersion($this->post->story))
- ->get();
-
- $this->dao->update(TABLE_BUG)->data($bug)
- ->autoCheck()
- ->batchCheck($this->config->bug->edit->requiredFields, 'notempty')
- ->checkIF($bug->resolvedBy, 'resolution', 'notempty')
- ->checkIF($bug->closedBy, 'resolution', 'notempty')
- ->checkIF($bug->resolution == 'duplicate', 'duplicateBug', 'notempty')
- ->where('id')->eq((int)$bugID)
- ->exec();
- if(!dao::isError()) return common::createChanges($oldBug, $bug);
- }
-
- /**
- * Batch update bugs.
- *
- * @access public
- * @return array
- */
- public function batchUpdate()
- {
- $bugs = array();
- $allChanges = array();
- $now = helper::now();
- $bugIDList = $this->post->bugIDList ? $this->post->bugIDList : array();
-
- /* Adjust whether the post data is complete, if not, remove the last element of $bugIDList. */
- if($this->session->showSuhosinInfo) array_pop($bugIDList);
-
- if(!empty($bugIDList))
- {
- /* Initialize bugs from the post data.*/
- foreach($bugIDList as $bugID)
- {
- $oldBug = $this->getByID($bugID);
-
- $bug->lastEditedBy = $this->app->user->account;
- $bug->lastEditedDate = $now;
- $bug->type = $this->post->types[$bugID];
- $bug->severity = $this->post->severities[$bugID];
- $bug->pri = $this->post->pris[$bugID];
- $bug->status = $this->post->statuses[$bugID];
- $bug->title = htmlspecialchars($this->post->titles[$bugID]);
- $bug->assignedTo = $this->post->assignedTos[$bugID];
- $bug->resolvedBy = $this->post->resolvedBys[$bugID];
- $bug->resolution = $this->post->resolutions[$bugID];
- $bug->duplicateBug = $this->post->duplicateBugs[$bugID] ? $this->post->duplicateBugs[$bugID] : $oldBug->duplicateBug;
-
- if($bug->assignedTo != $oldBug->assignedTo) $bug->assignedDate = $now;
- if($bug->resolvedBy != '' or $bug->resolution != '') $bug->resolvedDate = $now;
- if($bug->resolution != '' and $bug->resolvedBy == '') $bug->resolvedBy = $this->app->user->account;
- if($bug->resolution != '')
- {
- $bug->status = 'resolved';
- $bug->confirmed = 1;
- }
- if($bug->resolution != '' and $bug->assignedTo == '')
- {
- $bug->assignedTo = $oldBug->openedBy;
- $bug->assignedDate = $now;
- }
-
- $bugs[$bugID] = $bug;
- unset($bug);
- }
-
- /* Update bugs. */
- foreach($bugs as $bugID => $bug)
- {
- $oldBug = $this->getByID($bugID);
-
- $this->dao->update(TABLE_BUG)->data($bug)
- ->autoCheck()
- ->batchCheck($this->config->bug->edit->requiredFields, 'notempty')
- ->checkIF($bug->resolvedBy, 'resolution', 'notempty')
- ->checkIF($bug->resolution == 'duplicate', 'duplicateBug', 'notempty')
- ->where('id')->eq((int)$bugID)
- ->exec();
-
- if(!dao::isError())
- {
- $allChanges[$bugID] = common::createChanges($oldBug, $bug);
- }
- else
- {
- die(js::error('bug#' . $bugID . dao::getError(true)));
- }
- }
- }
-
- return $allChanges;
- }
-
- /**
- * Assign a bug to a user again.
- *
- * @param int $bugID
- * @access public
- * @return void
- */
- public function assign($bugID)
- {
- $now = helper::now();
- $oldBug = $this->getById($bugID);
- $bug = fixer::input('post')
- ->setDefault('lastEditedBy', $this->app->user->account)
- ->setDefault('lastEditedDate', $now)
- ->remove('comment')
- ->get();
-
- $this->dao->update(TABLE_BUG)
- ->data($bug)
- ->autoCheck()
- ->where('id')->eq($bugID)->exec();
-
- if(!dao::isError()) return common::createChanges($oldBug, $bug);
- }
-
- /**
- * Confirm a bug.
- *
- * @param int $bugID
- * @access public
- * @return void
- */
- public function confirm($bugID)
- {
- $now = helper::now();
- $bug->confirmed = 1;
- $bug->lastEditedBy = $this->app->user->account;
- $bug->lastEditedDate = $now;
- $this->dao->update(TABLE_BUG)->data($bug)->where('id')->eq($bugID)->exec();
- }
-
- /**
- * Resolve a bug.
- *
- * @param int $bugID
- * @access public
- * @return void
- */
- public function resolve($bugID)
- {
- $now = helper::now();
- $oldBug = $this->getById($bugID);
- $bug = fixer::input('post')
- ->add('resolvedBy', $this->app->user->account)
- ->add('resolvedDate', $now)
- ->add('status', 'resolved')
- ->add('confirmed', 1)
- ->add('assignedDate', $now)
- ->add('lastEditedBy', $this->app->user->account)
- ->add('lastEditedDate', $now)
- ->setDefault('duplicateBug', 0)
- ->setDefault('assignedTo', $oldBug->openedBy)
- ->remove('comment')
- ->get();
-
- $this->dao->update(TABLE_BUG)->data($bug)
- ->autoCheck()
- ->batchCheck($this->config->bug->resolve->requiredFields, 'notempty')
- ->checkIF($bug->resolution == 'duplicate', 'duplicateBug', 'notempty')
- ->checkIF($bug->resolution == 'fixed', 'resolvedBuild','notempty')
- ->where('id')->eq((int)$bugID)
- ->exec();
- }
-
- /**
- * Activate a bug.
- *
- * @param int $bugID
- * @access public
- * @return void
- */
- public function activate($bugID)
- {
- $oldBug = $this->getById($bugID);
- $now = helper::now();
- $bug = fixer::input('post')
- ->setDefault('assignedTo', $oldBug->resolvedBy)
- ->add('assignedDate', $now)
- ->add('resolution', '')
- ->add('status', 'active')
- ->add('resolvedDate', '0000-00-00')
- ->add('resolvedBy', '')
- ->add('resolvedBuild', '')
- ->add('closedBy', '')
- ->add('closedDate', '0000-00-00')
- ->add('duplicateBug', 0)
- ->add('lastEditedBy', $this->app->user->account)
- ->add('lastEditedDate', $now)
- ->join('openedBuild', ',')
- ->remove('comment,files,labels')
- ->get();
-
- $this->dao->update(TABLE_BUG)->data($bug)->autoCheck()->where('id')->eq((int)$bugID)->exec();
- $this->dao->update(TABLE_BUG)->set('activatedCount = activatedCount + 1')->where('id')->eq((int)$bugID)->exec();
- }
-
- /**
- * Close a bug.
- *
- * @param int $bugID
- * @access public
- * @return void
- */
- public function close($bugID)
- {
- $oldBug = $this->getById($bugID);
- $now = helper::now();
- $bug = fixer::input('post')
- ->add('assignedTo', 'closed')
- ->add('assignedDate', $now)
- ->add('status', 'closed')
- ->add('closedBy', $this->app->user->account)
- ->add('closedDate', $now)
- ->add('lastEditedBy', $this->app->user->account)
- ->add('lastEditedDate', $now)
- ->add('confirmed', 1)
- ->remove('comment')
- ->get();
-
- $this->dao->update(TABLE_BUG)->data($bug)->autoCheck()->where('id')->eq((int)$bugID)->exec();
- }
-
- /**
- * Extract accounts from some bugs.
- *
- * @param int $bugs
- * @access public
- * @return array
- */
- public function extractAccountsFromList($bugs)
- {
- $accounts = array();
- foreach($bugs as $bug)
- {
- if(!empty($bug->openedBy)) $accounts[] = $bug->openedBy;
- if(!empty($bug->assignedTo)) $accounts[] = $bug->assignedTo;
- if(!empty($bug->resolvedBy)) $accounts[] = $bug->resolvedBy;
- if(!empty($bug->closedBy)) $accounts[] = $bug->closedBy;
- if(!empty($bug->lastEditedBy)) $accounts[] = $bug->lastEditedBy;
- }
- return array_unique($accounts);
- }
-
- /**
- * Extract accounts from a bug.
- *
- * @param object $bug
- * @access public
- * @return array
- */
- public function extractAccountsFromSingle($bug)
- {
- $accounts = array();
- if(!empty($bug->openedBy)) $accounts[] = $bug->openedBy;
- if(!empty($bug->assignedTo)) $accounts[] = $bug->assignedTo;
- if(!empty($bug->resolvedBy)) $accounts[] = $bug->resolvedBy;
- if(!empty($bug->closedBy)) $accounts[] = $bug->closedBy;
- if(!empty($bug->lastEditedBy)) $accounts[] = $bug->lastEditedBy;
- return array_unique($accounts);
- }
-
- /**
- * Get bug pairs of a user.
- *
- * @param int $account
- * @param bool $appendProduct
- * @param int $limit
- * @access public
- * @return array
- */
- public function getUserBugPairs($account, $appendProduct = true, $limit = 0)
- {
- $bugs = array();
- $stmt = $this->dao->select('t1.id, t1.title, t2.name as product')
- ->from(TABLE_BUG)->alias('t1')
- ->leftJoin(TABLE_PRODUCT)->alias('t2')
- ->on('t1.product=t2.id')
- ->where('t1.assignedTo')->eq($account)
- ->andWhere('t1.deleted')->eq(0)
- ->orderBy('id desc')
- ->beginIF($limit > 0)->limit($limit)->fi()
- ->query();
- while($bug = $stmt->fetch())
- {
- if($appendProduct) $bug->title = $bug->product . ' / ' . $bug->title;
- $bugs[$bug->id] = $bug->title;
- }
- return $bugs;
- }
-
- /**
- * Get bugs of a project.
- *
- * @param int $projectID
- * @param string $orderBy
- * @param object $pager
- * @access public
- * @return array
- */
- public function getProjectBugs($projectID, $orderBy = 'id_desc', $pager = null, $build = 0)
- {
- $bugs = $this->dao->select('*')->from(TABLE_BUG)
- ->where('project')->eq((int)$projectID)
- ->beginIF($build != 0)->andWhere('openedBuild')->eq($build)->fi()
- ->andWhere('deleted')->eq(0)
- ->orderBy($orderBy)->page($pager)->fetchAll();
-
- $this->loadModel('common')->saveQueryCondition($this->dao->get(), 'bug');
-
- return $bugs;
- }
-
- /**
- * Get bugs according to buildID and productID.
- *
- * @param int $buildID
- * @param int $productID
- * @access public
- * @return object
- */
- public function getReleaseBugs($buildID, $productID)
- {
- $project = $this->dao->select('t1.begin')
- ->from(TABLE_PROJECT)->alias('t1')
- ->leftJoin(TABLE_BUILD)->alias('t2')
- ->on('t1.id = t2.project')
- ->where('t2.id')->eq($buildID)
- ->fetch();
- $bugs = $this->dao->select('*')->from(TABLE_BUG)
- ->where('resolvedDate')->ge($project->begin)
- ->andWhere('product')->eq($productID)
- ->orderBy('openedDate ASC')
- ->fetchAll();
- return $bugs;
- }
-
- /**
- * Get bug info from a result.
- *
- * @param int $resultID
- * @param int $caseID
- * @param int $version
- * @access public
- * @return array
- */
- public function getBugInfoFromResult($resultID, $caseID = 0, $version = 0)
- {
- $title = '';
- $bugSteps = '';
-
- $result = $this->dao->findById($resultID)->from(TABLE_TESTRESULT)->fetch();
- if($caseID > 0)
- $run->case = $this->loadModel('testcase')->getById($caseID, $result->version);
- else
- $run = $this->loadModel('testtask')->getRunById($result->run);
- if($result and $result->caseResult == 'fail')
- {
- $title = $run->case->title;
- $caseSteps = $run->case->steps;
- $stepResults = unserialize($result->stepResults);
- if($run->case->precondition != '')
- {
- $bugSteps = "[" . $this->lang->testcase->precondition . "]
" . "\n" . $run->case->precondition;
- }
- $bugSteps .= $this->lang->bug->tplStep;
- if(!empty($stepResults))
- {
- foreach($caseSteps as $key => $step)
- {
- $bugSteps .= ($key + 1) . '. ' .$step->desc . " ";
- if($stepResults[$step->id]['result'] == 'fail')
- {
- $bugSteps .= $this->lang->bug->tplResult;
- $bugSteps .= $stepResults[$step->id]['real'] . " ";
- $bugSteps .= $this->lang->bug->tplExpect;
- $bugSteps .= $step->expect;
- break;
- }
- }
- }
- else
- {
- $bugSteps .= $this->lang->bug->tplResult;
- $bugSteps .= $this->lang->bug->tplExpect;
- }
- }
- return array('title' => $title, 'steps' => $bugSteps, 'storyID' => $run->case->story);
- }
-
- /**
- * Get report data of bugs per project
- *
- * @access public
- * @return array
- */
- public function getDataOfBugsPerProject()
- {
- $datas = $this->dao->select('project as name, count(project) as value')->from(TABLE_BUG)->where($this->reportCondition())->groupBy('project')->orderBy('value DESC')->fetchAll('name');
- if(!$datas) return array();
- $projects = $this->loadModel('project')->getPairs();
- foreach($datas as $projectID => $data) $data->name = isset($projects[$projectID]) ? $projects[$projectID] : $this->lang->report->undefined;
- return $datas;
- }
-
- /**
- * Get report data of bugs per build.
- *
- * @access public
- * @return void
- */
- public function getDataOfBugsPerBuild()
- {
- $datas = $this->dao->select('openedBuild as name, count(openedBuild) as value')->from(TABLE_BUG)->where($this->reportCondition())->groupBy('openedBuild')->orderBy('value DESC')->fetchAll('name');
- if(!$datas) return array();
- $builds = $this->loadModel('build')->getProductBuildPairs($this->session->product);
-
- /* Deal with the situation that a bug maybe associate more than one openedBuild. */
- foreach($datas as $buildIDList => $data)
- {
- $openBuildIDList = explode(',', $buildIDList);
- if(count($openBuildIDList) > 1)
- {
- foreach($openBuildIDList as $buildID)
- {
- if(isset($datas[$buildID]))
- {
- $datas[$buildID]->value++;
- }
- else
- {
- $datas[$buildID]->name = $buildID;
- $datas[$buildID]->value = 1;
- }
- }
- unset($datas[$buildIDList]);
- }
- }
-
- foreach($datas as $buildID => $data)
- {
- $data->name = isset($builds[$buildID]) ? $builds[$buildID] : $this->lang->report->undefined;
- }
- return $datas;
- }
-
- /**
- * Get report data of bugs per module
- *
- * @access public
- * @return array
- */
- public function getDataOfBugsPerModule()
- {
- $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->dao->select('id, name')->from(TABLE_MODULE)->where('id')->in(array_keys($datas))->fetchPairs();
- foreach($datas as $moduleID => $data) $data->name = isset($modules[$moduleID]) ? $modules[$moduleID] : '/';
- return $datas;
- }
-
- /**
- * Get report data of opened bugs per day.
- *
- * @access public
- * @return array
- */
- public function getDataOfOpenedBugsPerDay()
- {
- return $this->dao->select('DATE_FORMAT(openedDate, "%Y-%m-%d") AS name, COUNT(*) AS value')->from(TABLE_BUG)->where($this->reportCondition())->groupBy('name')->orderBy('openedDate')->fetchAll();
- }
-
- /**
- * Get report data of resolved bugs per day.
- *
- * @access public
- * @return array
- */
- public function getDataOfResolvedBugsPerDay()
- {
- return $this->dao->select('DATE_FORMAT(resolvedDate, "%Y-%m-%d") AS name, COUNT(*) AS value')->from(TABLE_BUG)
- ->where($this->reportCondition())->groupBy('name')
- ->having('name != 0000-00-00')
- ->orderBy('resolvedDate')
- ->fetchAll();
- }
-
- /**
- * Get report data of closed bugs per day.
- *
- * @access public
- * @return array
- */
- public function getDataOfClosedBugsPerDay()
- {
- return $this->dao->select('DATE_FORMAT(closedDate, "%Y-%m-%d") AS name, COUNT(*) AS value')->from(TABLE_BUG)
- ->where($this->reportCondition())->groupBy('name')
- ->having('name != 0000-00-00')
- ->orderBy('closedDate')->fetchAll();
- }
-
- /**
- * Get report data of openeded bugs per user.
- *
- * @access public
- * @return array
- */
- public function getDataOfOpenedBugsPerUser()
- {
- $datas = $this->dao->select('openedBy AS name, COUNT(*) AS value')->from(TABLE_BUG)->where($this->reportCondition())->groupBy('name')->orderBy('value DESC')->fetchAll('name');
- if(!$datas) return array();
- if(!isset($this->users)) $this->users = $this->loadModel('user')->getPairs('noletter');
- foreach($datas as $account => $data) if(isset($this->users[$account])) $data->name = $this->users[$account];
- return $datas;
- }
-
- /**
- * Get report data of resolved bugs per user.
- *
- * @access public
- * @return array
- */
- public function getDataOfResolvedBugsPerUser()
- {
- $datas = $this->dao->select('resolvedBy AS name, COUNT(*) AS value')
- ->from(TABLE_BUG)->where($this->reportCondition())
- ->andWhere('resolvedBy')->ne('')
- ->groupBy('name')
- ->orderBy('value DESC')->fetchAll('name');
- if(!$datas) return array();
- if(!isset($this->users)) $this->users = $this->loadModel('user')->getPairs('noletter');
- foreach($datas as $account => $data) if(isset($this->users[$account])) $data->name = $this->users[$account];
- return $datas;
- }
-
- /**
- * Get report data of closed bugs per user.
- *
- * @access public
- * @return array
- */
- public function getDataOfClosedBugsPerUser()
- {
- $datas = $this->dao->select('closedBy AS name, COUNT(*) AS value')
- ->from(TABLE_BUG)
- ->where($this->reportCondition())
- ->andWhere('closedBy')->ne('')
- ->groupBy('name')
- ->orderBy('value DESC')->fetchAll('name');
- if(!$datas) return array();
- if(!isset($this->users)) $this->users = $this->loadModel('user')->getPairs('noletter');
- foreach($datas as $account => $data) if(isset($this->users[$account])) $data->name = $this->users[$account];
- return $datas;
- }
-
- /**
- * Get report data of bugs per severity.
- *
- * @access public
- * @return array
- */
- public function getDataOfBugsPerSeverity()
- {
- $datas = $this->dao->select('severity AS name, COUNT(*) AS value')->from(TABLE_BUG)->where($this->reportCondition())->groupBy('name')->orderBy('value DESC')->fetchAll('name');
- if(!$datas) return array();
- foreach($datas as $severity => $data) if(isset($this->lang->bug->severityList[$severity])) $data->name = $this->lang->bug->severityList[$severity];
- return $datas;
- }
-
- /**
- * Get report data of bugs per resolution.
- *
- * @access public
- * @return array
- */
- public function getDataOfBugsPerResolution()
- {
- $datas = $this->dao->select('resolution AS name, COUNT(*) AS value')
- ->from(TABLE_BUG)
- ->where($this->reportCondition())
- ->andWhere('resolution')->ne('')
- ->groupBy('name')->orderBy('value DESC')
- ->fetchAll('name');
- if(!$datas) return array();
- foreach($datas as $resolution => $data) if(isset($this->lang->bug->resolutionList[$resolution])) $data->name = $this->lang->bug->resolutionList[$resolution];
- return $datas;
- }
-
- /**
- * Get report data of bugs per status.
- *
- * @access public
- * @return array
- */
- public function getDataOfBugsPerStatus()
- {
- $datas = $this->dao->select('status AS name, COUNT(*) AS value')->from(TABLE_BUG)->where($this->reportCondition())->groupBy('name')->orderBy('value DESC')->fetchAll('name');
- if(!$datas) return array();
- foreach($datas as $status => $data) if(isset($this->lang->bug->statusList[$status])) $data->name = $this->lang->bug->statusList[$status];
- return $datas;
- }
-
- /**
- * Get report data of bugs per status.
- *
- * @access public
- * @return array
- */
- public function getDataOfBugsPerActivatedCount()
- {
- $datas = $this->dao->select('activatedCount AS name, COUNT(*) AS value')->from(TABLE_BUG)->where($this->reportCondition())->groupBy('name')->orderBy('value DESC')->fetchAll('name');
- if(!$datas) return array();
- foreach($datas as $data) $data->name = $this->lang->bug->report->bugsPerActivatedCount->graph->xAxisName . ':' . $data->name;
- return $datas;
- }
-
- /**
- * Get report data of bugs per type.
- *
- * @access public
- * @return array
- */
- public function getDataOfBugsPerType()
- {
- $datas = $this->dao->select('type AS name, COUNT(*) AS value')->from(TABLE_BUG)->where($this->reportCondition())->groupBy('name')->orderBy('value DESC')->fetchAll('name');
- if(!$datas) return array();
- foreach($datas as $type => $data) if(isset($this->lang->bug->typeList[$type])) $data->name = $this->lang->bug->typeList[$type];
- return $datas;
- }
-
- /**
- * getDataOfBugsPerAssignedTo
- *
- * @access public
- * @return void
- */
- public function getDataOfBugsPerAssignedTo()
- {
- $datas = $this->dao->select('assignedTo AS name, COUNT(*) AS value')
- ->from(TABLE_BUG)->where($this->reportCondition())
- ->groupBy('name')
- ->orderBy('value DESC')->fetchAll('name');
- if(!$datas) return array();
- if(!isset($this->users)) $this->users = $this->loadModel('user')->getPairs('noletter');
- foreach($datas as $account => $data) if(isset($this->users[$account])) $data->name = $this->users[$account];
- return $datas;
- }
-
- /**
- * Merge the default chart settings and the settings of current chart.
- *
- * @param string $chartType
- * @access public
- * @return void
- */
- public function mergeChartOption($chartType)
- {
- $chartOption = $this->lang->bug->report->$chartType;
- $commonOption = $this->lang->bug->report->options;
-
- $chartOption->graph->caption = $this->lang->bug->report->charts[$chartType];
- if(!isset($chartOption->swf)) $chartOption->swf = $commonOption->swf;
- if(!isset($chartOption->width)) $chartOption->width = $commonOption->width;
- if(!isset($chartOption->height)) $chartOption->height = $commonOption->height;
-
- /* 合并配置。*/
- foreach($commonOption->graph as $key => $value) if(!isset($chartOption->graph->$key)) $chartOption->graph->$key = $value;
- }
-
- /**
- * Get bug templates of a user.
- *
- * @param string $account
- * @access public
- * @return array
- */
- public function getUserBugTemplates($account)
- {
- $templates = $this->dao->select('id, title, content')
- ->from(TABLE_USERTPL)
- ->where('account')->eq($account)
- ->orderBy('id')
- ->fetchAll();
- return $templates;
- }
-
- /**
- * Save user template.
- *
- * @access public
- * @return void
- */
- public function saveUserBugTemplate()
- {
- $template = fixer::input('post')
- ->specialChars('title')
- ->add('account', $this->app->user->account)
- ->add('type', 'bug')
- ->get();
- $this->dao->insert(TABLE_USERTPL)->data($template)->autoCheck('title, content', 'notempty')->check('title', 'unique')->exec();
- }
-
- /**
- * Return the file => label pairs of some fields.
- *
- * @param string $fields
- * @access public
- * @return array
- */
- public function getFieldPairs($fields)
- {
- $fields = explode(',', $fields);
- foreach($fields as $key => $field)
- {
- $field = trim($field);
- $fields[$field] = $this->lang->bug->$field;
- unset($fields[$key]);
- }
- return $fields;
- }
-
- /**
- * Get all bugs.
- *
- * @param int $productID
- * @param array $projects
- * @param int $queryID
- * @param string $orderBy
- * @param object $pager
- * @access public
- * @return array
- */
- public function getAllBugs($productID, $projects, $orderBy, $pager)
- {
- $bugs = $this->dao->select('*')->from(TABLE_BUG)->where('product')->eq($productID)
- ->andWhere('project')->in(array_keys($projects))
- ->andWhere('deleted')->eq(0)
- ->orderBy($orderBy)->page($pager)->fetchAll();
-
- $this->loadModel('common')->saveQueryCondition($this->dao->get(), 'bug');
-
- return $bugs;
- }
-
- /**
- * Get bugs of assign to me.
- *
- * @param int $productID
- * @param array $projects
- * @param int $queryID
- * @param string $orderBy
- * @param object $pager
- * @access public
- * @return array
- */
- public function getByAssigntome($productID, $projects, $orderBy, $pager)
- {
- return $this->dao->findByAssignedTo($this->app->user->account)->from(TABLE_BUG)->andWhere('product')->eq($productID)
- ->andWhere('project')->in(array_keys($projects))
- ->andWhere('deleted')->eq(0)
- ->orderBy($orderBy)->page($pager)->fetchAll();
- }
-
- /**
- * Get bugs of opened by me.
- *
- * @param int $productID
- * @param array $projects
- * @param int $queryID
- * @param string $orderBy
- * @param object $pager
- * @access public
- * @return array
- */
- public function getByOpenedbyme($productID, $projects, $orderBy, $pager)
- {
- return $this->dao->findByOpenedBy($this->app->user->account)->from(TABLE_BUG)->andWhere('product')->eq($productID)
- ->andWhere('project')->in(array_keys($projects))
- ->andWhere('deleted')->eq(0)
- ->orderBy($orderBy)->page($pager)->fetchAll();
- }
-
- /**
- * Get bugs of resolved by me.
- *
- * @param int $productID
- * @param array $projects
- * @param int $queryID
- * @param string $orderBy
- * @param object $pager
- * @access public
- * @return array
- */
- public function getByResolvedbyme($productID, $projects, $orderBy, $pager)
- {
- return $this->dao->findByResolvedBy($this->app->user->account)->from(TABLE_BUG)->andWhere('product')->eq($productID)
- ->andWhere('project')->in(array_keys($projects))
- ->andWhere('deleted')->eq(0)
- ->orderBy($orderBy)->page($pager)->fetchAll();
- }
-
- /**
- * Get bugs of nobody to do.
- *
- * @param int $productID
- * @param array $projects
- * @param int $queryID
- * @param string $orderBy
- * @param object $pager
- * @access public
- * @return array
- */
- public function getByAssigntonull($productID, $projects, $orderBy, $pager)
- {
-
- return $this->dao->findByAssignedTo('')->from(TABLE_BUG)->andWhere('product')->eq($productID)
- ->andWhere('project')->in(array_keys($projects))
- ->andWhere('deleted')->eq(0)
- ->orderBy($orderBy)->page($pager)->fetchAll();
- }
-
- /**
- * Get bugs the status is active or unclosed.
- *
- * @param int $productID
- * @param array $projects
- * @param string $status
- * @param int $queryID
- * @param string $orderBy
- * @param object $pager
- * @access public
- * @return array
- */
- public function getByStatus($productID, $projects, $status, $orderBy, $pager)
- {
- return $this->dao->select('*')->from(TABLE_BUG)
- ->where('project')->in(array_keys($projects))
- ->andWhere('product')->eq($productID)
- ->beginIF($status == 'unclosed')->andWhere('status')->ne('closed')->fi()
- ->beginIF($status == 'unresolved')->andWhere('status')->eq('active')->fi()
- ->andWhere('deleted')->eq(0)
- ->orderBy($orderBy)->page($pager)->fetchAll();
- }
-
- /**
- * Get unresolve bugs for long time.
- *
- * @param int $productID
- * @param array $projects
- * @param int $queryID
- * @param string $orderBy
- * @param object $pager
- * @access public
- * @return array
- */
- public function getByLonglifebugs($productID, $projects, $orderBy, $pager)
- {
- return $this->dao->findByLastEditedDate("<", date(DT_DATE1, strtotime('-7 days')))->from(TABLE_BUG)->andWhere('product')->eq($productID)
- ->andWhere('project')->in(array_keys($projects))
- ->andWhere('openedDate')->lt(date(DT_DATE1,strtotime('-7 days')))
- ->andWhere('deleted')->eq(0)
- ->andWhere('status')->ne('closed')->orderBy($orderBy)->page($pager)->fetchAll();
- }
-
- /**
- * Get postponed bugs.
- *
- * @param int $productID
- * @param array $projects
- * @param int $queryID
- * @param string $orderBy
- * @param object $pager
- * @access public
- * @return array
- */
- public function getByPostponedbugs($productID, $projects, $orderBy, $pager)
- {
- return $this->dao->findByResolution('postponed')->from(TABLE_BUG)->andWhere('product')->eq($productID)
- ->andWhere('project')->in(array_keys($projects))
- ->orderBy($orderBy)->page($pager)->fetchAll();
- }
-
- /**
- * Get bugs need confirm.
- *
- * @param int $productID
- * @param array $projects
- * @param int $queryID
- * @param string $orderBy
- * @param object $pager
- * @access public
- * @return array
- */
- public function getByNeedconfirm($productID, $projects, $orderBy, $pager)
- {
- return $this->dao->select('t1.*, t2.title AS storyTitle')->from(TABLE_BUG)->alias('t1')->leftJoin(TABLE_STORY)->alias('t2')->on('t1.story = t2.id')
- ->where("t2.status = 'active'")
- ->andWhere('t1.product')->eq($productID)
- ->andWhere('t1.deleted')->eq(0)
- ->andWhere('t2.version > t1.storyVersion')
- ->andWhere('t1.project')->in(array_keys($projects))
- ->orderBy($orderBy)
- ->page($pager)
- ->fetchAll();
- }
-
- /**
- * Get bugs by search.
- *
- * @param int $productID
- * @param array $projects
- * @param int $queryID
- * @param string $orderBy
- * @param object $pager
- * @access public
- * @return array
- */
- public function getBySearch($productID, $projects, $queryID, $orderBy, $pager)
- {
- if($queryID)
- {
- $query = $this->loadModel('search')->getQuery($queryID);
- if($query)
- {
- $this->session->set('bugQuery', $query->sql);
- $this->session->set('bugForm', $query->form);
- }
- else
- {
- $this->session->set('bugQuery', ' 1 = 1');
- }
- }
- else
- {
- if($this->session->bugQuery == false) $this->session->set('bugQuery', ' 1 = 1');
- }
-
- /* check the purview of projects.*/
- if(strpos($this->session->bugQuery, '`project`') === false)
- {
- $var = $this->session->bugQuery . ' AND `project`' . helper::dbIN(array_keys($projects));
- $this->session->set('bugQuery', "$var");
- }
-
- $bugQuery = str_replace("`product` = 'all'", '1', $this->session->bugQuery); // Search all product.
- $bugQuery = $this->loadModel('search')->replaceDynamic($bugQuery);
- $bugs = $this->dao->select('*')->from(TABLE_BUG)->where($bugQuery)
- ->andWhere('deleted')->eq(0)
- ->orderBy($orderBy)->page($pager)->fetchAll();
- return $bugs;
- }
-
- /**
- * Form customed bugs.
- *
- * @param array $bugs
- * @access public
- * @return array
- */
- public function formCustomedBugs($bugs)
- {
- /* Get related objects id lists. */
- $relatedModuleIdList = array();
- $relatedStoryIdList = array();
- $relatedTaskIdList = array();
- $relatedCaseIdList = array();
- $relatedProjectIdList = array();
-
- foreach($bugs as $bug)
- {
- $relatedModuleIdList[$bug->module] = $bug->module;
- $relatedStoryIdList[$bug->story] = $bug->story;
- $relatedTaskIdList[$bug->task] = $bug->task;
- $relatedCaseIdList[$bug->case] = $bug->case;
- $relatedProjectIdList[$bug->project] = $bug->project;
-
- /* Get related objects title or names. */
- $relatedModules = $this->dao->select('id, name')->from(TABLE_MODULE)->where('id')->in($relatedModuleIdList)->fetchPairs();
- $relatedStories = $this->dao->select('id, title')->from(TABLE_STORY) ->where('id')->in($relatedStoryIdList)->fetchPairs();
- $relatedTasks = $this->dao->select('id, name')->from(TABLE_TASK)->where('id')->in($relatedTaskIdList)->fetchPairs();
- $relatedCases = $this->dao->select('id, title')->from(TABLE_CASE)->where('id')->in($relatedCaseIdList)->fetchPairs();
- $relatedProjects = $this->dao->select('id, name')->from(TABLE_PROJECT)->where('id')->in($relatedProjectIdList)->fetchPairs();
-
- /* fill some field with useful value. */
- if(isset($relatedModules[$bug->module])) $bug->module = $relatedModules[$bug->module];
- if(isset($relatedStories[$bug->story])) $bug->story = $relatedStories[$bug->story];
- if(isset($relatedTasks[$bug->task])) $bug->task = $relatedTasks[$bug->task];
- if(isset($relatedCases[$bug->case])) $bug->case = $relatedCases[$bug->case];
- if(isset($relatedProjects[$bug->project])) $bug->project = $relatedProjects[$bug->project];
- }
- return $bugs;
- }
-
- /**
- * Adjust the action is clickable.
- *
- * @param string $bug
- * @param string $action
- * @access public
- * @return void
- */
- public function isClickable($object, $action)
- {
- $action = strtolower($action);
-
- if($action == 'confirmbug') return $object->status == 'active' and $object->confirmed == 0;
- if($action == 'resolve') return $object->status == 'active';
- if($action == 'close') return $object->status == 'resolved';
- if($action == 'activate') return $object->status != 'active';
- if($action == 'tostory') return $object->status == 'active';
-
- return true;
- }
-
- /**
- * Get report condition from session.
- *
- * @access public
- * @return void
- */
- public function reportCondition()
- {
- if(!$this->session->bugOnlyCondition) return 'id in (' . preg_replace('/SELECT .* FROM/', 'SELECT t1.id FROM', $this->session->bugQueryCondition) . ')';
- return $this->session->bugQueryCondition;
- }
-}
+
+ * @package bug
+ * @version $Id$
+ * @link http://www.zentao.net
+ */
+?>
+loadModel('product')->setMenu($products, $productID);
+ $selectHtml = $this->product->select($products, $productID, 'bug', 'browse');
+ foreach($this->lang->bug->menu as $key => $menu)
+ {
+ $replace = ($key == 'product') ? $selectHtml : $productID;
+ common::setMenuVars($this->lang->bug->menu, $key, $replace);
+ }
+ }
+
+ /**
+ * Create a bug.
+ *
+ * @access public
+ * @return int|bool
+ */
+ public function create()
+ {
+ $now = helper::now();
+ $bug = fixer::input('post')
+ ->add('openedBy', $this->app->user->account)
+ ->add('openedDate', $now)
+ ->setDefault('project,story,task', 0)
+ ->setDefault('openedBuild', '')
+ ->setIF($this->post->assignedTo != '', 'assignedDate', $now)
+ ->setIF($this->post->story != false, 'storyVersion', $this->loadModel('story')->getVersion($this->post->story))
+ ->specialChars('title,keyword')
+ ->cleanInt('product, module, severity')
+ ->join('openedBuild', ',')
+ ->remove('files, labels')
+ ->get();
+ $this->dao->insert(TABLE_BUG)->data($bug)->autoCheck()->batchCheck($this->config->bug->create->requiredFields, 'notempty')->exec();
+ if(!dao::isError())
+ {
+ $bugID = $this->dao->lastInsertID();
+ $this->loadModel('file')->saveUpload('bug', $bugID);
+ return $bugID;
+ }
+ return false;
+ }
+
+ /**
+ * Get bugs of a module.
+ *
+ * @param int $productID
+ * @param string|array $moduleIds
+ * @param string $orderBy
+ * @param object $pager
+ * @access public
+ * @return array
+ */
+ public function getModuleBugs($productID, $moduleIds = 0, $projects, $orderBy = 'id_desc', $pager = null)
+ {
+ return $this->dao->select('*')->from(TABLE_BUG)
+ ->where('product')->eq((int)$productID)
+ ->beginIF(!empty($moduleIds))->andWhere('module')->in($moduleIds)->fi()
+ ->andWhere('project')->in(array_keys($projects))
+ ->andWhere('deleted')->eq(0)
+ ->orderBy($orderBy)->page($pager)->fetchAll();
+ }
+
+ /**
+ * Get info of a bug.
+ *
+ * @param int $bugID
+ * @param bool $setImgSize
+ * @access public
+ * @return object
+ */
+ public function getById($bugID, $setImgSize = false)
+ {
+ $bug = $this->dao->select('t1.*, t2.name AS projectName, t3.title AS storyTitle, t3.status AS storyStatus, t3.version AS latestStoryVersion, t4.name AS taskName')
+ ->from(TABLE_BUG)->alias('t1')
+ ->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.project = t2.id')
+ ->leftJoin(TABLE_STORY)->alias('t3')->on('t1.story = t3.id')
+ ->leftJoin(TABLE_TASK)->alias('t4')->on('t1.task = t4.id')
+ ->where('t1.id')->eq((int)$bugID)->fetch();
+ if(!$bug) return false;
+
+ if($setImgSize) $bug->steps = $this->loadModel('file')->setImgSize($bug->steps);
+ foreach($bug as $key => $value) if(strpos($key, 'Date') !== false and !(int)substr($value, 0, 4)) $bug->$key = '';
+
+ if($bug->mailto)
+ {
+ $bug->mailto = ltrim(trim($bug->mailto), ','); // Remove the first ,
+ $bug->mailto = str_replace(' ', '', $bug->mailto);
+ $bug->mailto = rtrim($bug->mailto, ',') . ',';
+ $bug->mailto = str_replace(',', ', ', $bug->mailto);
+ }
+
+ if($bug->duplicateBug) $bug->duplicateBugTitle = $this->dao->findById($bug->duplicateBug)->from(TABLE_BUG)->fields('title')->fetch('title');
+ if($bug->case) $bug->caseTitle = $this->dao->findById($bug->case)->from(TABLE_CASE)->fields('title')->fetch('title');
+ if($bug->linkBug) $bug->linkBugTitles = $this->dao->select('id,title')->from(TABLE_BUG)->where('id')->in($bug->linkBug)->fetchPairs();
+ if($bug->toStory > 0) $bug->toStoryTitle = $this->dao->findById($bug->toStory)->from(TABLE_STORY)->fields('title')->fetch('title');
+ if($bug->toTask > 0) $bug->toTaskTitle = $this->dao->findById($bug->toTask)->from(TABLE_TASK)->fields('name')->fetch('name');
+
+ $bug->toCases = array();
+ $toCases = $this->dao->select('id, title')->from(TABLE_CASE)->where('`fromBug`')->eq($bugID)->fetchAll();
+ foreach($toCases as $toCase) $bug->toCases[$toCase->id] = $toCase->title;
+
+ $bug->files = $this->loadModel('file')->getByObject('bug', $bugID);
+
+ return $bug;
+ }
+
+ /**
+ * getActiveBugs
+ *
+ * @param object $pager
+ * @param int $projectID
+ * @access public
+ * @return array
+ */
+ public function getActiveBugs($pager, $projectID, $products)
+ {
+ return $this->dao->select('*')->from(TABLE_BUG)
+ ->where('status')->eq('active')
+ ->andWhere('toTask')->eq(0)
+ ->andWhere('tostory')->eq(0)
+ ->beginIF(!empty($products))->andWhere('product')->in($products)->fi()
+ ->beginIF(empty($products))->andWhere('project')->eq($projectID)->fi()
+ ->andWhere('deleted')->eq(0)
+ ->orderBy('id desc')
+ ->page($pager)
+ ->fetchAll();
+ }
+
+ /**
+ * Update a bug.
+ *
+ * @param int $bugID
+ * @access public
+ * @return void
+ */
+ public function update($bugID)
+ {
+ $oldBug = $this->getById($bugID);
+ $now = helper::now();
+ $bug = fixer::input('post')
+ ->cleanInt('product,module,severity,project,story,task')
+ ->specialChars('title,keyword')
+ ->remove('comment,files,labels')
+ ->setDefault('project,module,project,story,task,duplicateBug', 0)
+ ->setDefault('openedBuild', '')
+ ->add('lastEditedBy', $this->app->user->account)
+ ->add('lastEditedDate', $now)
+ ->join('openedBuild', ',')
+ ->setIF($this->post->assignedTo != $oldBug->assignedTo, 'assignedDate', $now)
+ ->setIF($this->post->resolvedBy != '' and $this->post->resolvedDate == '', 'resolvedDate', $now)
+ ->setIF($this->post->resolution != '' and $this->post->resolvedDate == '', 'resolvedDate', $now)
+ ->setIF($this->post->resolution != '' and $this->post->resolvedBy == '', 'resolvedBy', $this->app->user->account)
+ ->setIF($this->post->closedBy != '' and $this->post->closedDate == '', 'closedDate', $now)
+ ->setIF($this->post->closedDate != '' and $this->post->closedBy == '', 'closedBy', $this->app->user->account)
+ ->setIF($this->post->closedBy != '' or $this->post->closedDate != '', 'assignedTo', 'closed')
+ ->setIF($this->post->closedBy != '' or $this->post->closedDate != '', 'assignedDate', $now)
+ ->setIF($this->post->resolution != '' or $this->post->resolvedDate != '', 'status', 'resolved')
+ ->setIF($this->post->closedBy != '' or $this->post->closedDate != '', 'status', 'closed')
+ ->setIF(($this->post->resolution != '' or $this->post->resolvedDate != '') and $this->post->assignedTo == '', 'assignedTo', $oldBug->openedBy)
+ ->setIF(($this->post->resolution != '' or $this->post->resolvedDate != '') and $this->post->assignedTo == '', 'assignedDate', $now)
+ ->setIF($this->post->resolution == '' and $this->post->resolvedDate =='', 'status', 'active')
+ ->setIF($this->post->resolution != '', 'confirmed', 1)
+ ->setIF($this->post->story != false and $this->post->story != $oldBug->story, 'storyVersion', $this->loadModel('story')->getVersion($this->post->story))
+ ->get();
+
+ $this->dao->update(TABLE_BUG)->data($bug)
+ ->autoCheck()
+ ->batchCheck($this->config->bug->edit->requiredFields, 'notempty')
+ ->checkIF($bug->resolvedBy, 'resolution', 'notempty')
+ ->checkIF($bug->closedBy, 'resolution', 'notempty')
+ ->checkIF($bug->resolution == 'duplicate', 'duplicateBug', 'notempty')
+ ->where('id')->eq((int)$bugID)
+ ->exec();
+ if(!dao::isError()) return common::createChanges($oldBug, $bug);
+ }
+
+ /**
+ * Batch update bugs.
+ *
+ * @access public
+ * @return array
+ */
+ public function batchUpdate()
+ {
+ $bugs = array();
+ $allChanges = array();
+ $now = helper::now();
+ $bugIDList = $this->post->bugIDList ? $this->post->bugIDList : array();
+
+ /* Adjust whether the post data is complete, if not, remove the last element of $bugIDList. */
+ if($this->session->showSuhosinInfo) array_pop($bugIDList);
+
+ if(!empty($bugIDList))
+ {
+ /* Initialize bugs from the post data.*/
+ foreach($bugIDList as $bugID)
+ {
+ $oldBug = $this->getByID($bugID);
+
+ $bug->lastEditedBy = $this->app->user->account;
+ $bug->lastEditedDate = $now;
+ $bug->type = $this->post->types[$bugID];
+ $bug->severity = $this->post->severities[$bugID];
+ $bug->pri = $this->post->pris[$bugID];
+ $bug->status = $this->post->statuses[$bugID];
+ $bug->title = htmlspecialchars($this->post->titles[$bugID]);
+ $bug->assignedTo = $this->post->assignedTos[$bugID];
+ $bug->resolvedBy = $this->post->resolvedBys[$bugID];
+ $bug->resolution = $this->post->resolutions[$bugID];
+ $bug->duplicateBug = $this->post->duplicateBugs[$bugID] ? $this->post->duplicateBugs[$bugID] : $oldBug->duplicateBug;
+
+ if($bug->assignedTo != $oldBug->assignedTo) $bug->assignedDate = $now;
+ if($bug->resolvedBy != '' or $bug->resolution != '') $bug->resolvedDate = $now;
+ if($bug->resolution != '' and $bug->resolvedBy == '') $bug->resolvedBy = $this->app->user->account;
+ if($bug->resolution != '')
+ {
+ $bug->status = 'resolved';
+ $bug->confirmed = 1;
+ }
+ if($bug->resolution != '' and $bug->assignedTo == '')
+ {
+ $bug->assignedTo = $oldBug->openedBy;
+ $bug->assignedDate = $now;
+ }
+
+ $bugs[$bugID] = $bug;
+ unset($bug);
+ }
+
+ /* Update bugs. */
+ foreach($bugs as $bugID => $bug)
+ {
+ $oldBug = $this->getByID($bugID);
+
+ $this->dao->update(TABLE_BUG)->data($bug)
+ ->autoCheck()
+ ->batchCheck($this->config->bug->edit->requiredFields, 'notempty')
+ ->checkIF($bug->resolvedBy, 'resolution', 'notempty')
+ ->checkIF($bug->resolution == 'duplicate', 'duplicateBug', 'notempty')
+ ->where('id')->eq((int)$bugID)
+ ->exec();
+
+ if(!dao::isError())
+ {
+ $allChanges[$bugID] = common::createChanges($oldBug, $bug);
+ }
+ else
+ {
+ die(js::error('bug#' . $bugID . dao::getError(true)));
+ }
+ }
+ }
+
+ return $allChanges;
+ }
+
+ /**
+ * Assign a bug to a user again.
+ *
+ * @param int $bugID
+ * @access public
+ * @return void
+ */
+ public function assign($bugID)
+ {
+ $now = helper::now();
+ $oldBug = $this->getById($bugID);
+ $bug = fixer::input('post')
+ ->setDefault('lastEditedBy', $this->app->user->account)
+ ->setDefault('lastEditedDate', $now)
+ ->remove('comment')
+ ->get();
+
+ $this->dao->update(TABLE_BUG)
+ ->data($bug)
+ ->autoCheck()
+ ->where('id')->eq($bugID)->exec();
+
+ if(!dao::isError()) return common::createChanges($oldBug, $bug);
+ }
+
+ /**
+ * Confirm a bug.
+ *
+ * @param int $bugID
+ * @access public
+ * @return void
+ */
+ public function confirm($bugID)
+ {
+ $now = helper::now();
+ $bug->confirmed = 1;
+ $bug->lastEditedBy = $this->app->user->account;
+ $bug->lastEditedDate = $now;
+ $this->dao->update(TABLE_BUG)->data($bug)->where('id')->eq($bugID)->exec();
+ }
+
+ /**
+ * Resolve a bug.
+ *
+ * @param int $bugID
+ * @access public
+ * @return void
+ */
+ public function resolve($bugID)
+ {
+ $now = helper::now();
+ $oldBug = $this->getById($bugID);
+ $bug = fixer::input('post')
+ ->add('resolvedBy', $this->app->user->account)
+ ->add('resolvedDate', $now)
+ ->add('status', 'resolved')
+ ->add('confirmed', 1)
+ ->add('assignedDate', $now)
+ ->add('lastEditedBy', $this->app->user->account)
+ ->add('lastEditedDate', $now)
+ ->setDefault('duplicateBug', 0)
+ ->setDefault('assignedTo', $oldBug->openedBy)
+ ->remove('comment')
+ ->get();
+
+ $this->dao->update(TABLE_BUG)->data($bug)
+ ->autoCheck()
+ ->batchCheck($this->config->bug->resolve->requiredFields, 'notempty')
+ ->checkIF($bug->resolution == 'duplicate', 'duplicateBug', 'notempty')
+ ->checkIF($bug->resolution == 'fixed', 'resolvedBuild','notempty')
+ ->where('id')->eq((int)$bugID)
+ ->exec();
+ }
+
+ /**
+ * Activate a bug.
+ *
+ * @param int $bugID
+ * @access public
+ * @return void
+ */
+ public function activate($bugID)
+ {
+ $oldBug = $this->getById($bugID);
+ $now = helper::now();
+ $bug = fixer::input('post')
+ ->setDefault('assignedTo', $oldBug->resolvedBy)
+ ->add('assignedDate', $now)
+ ->add('resolution', '')
+ ->add('status', 'active')
+ ->add('resolvedDate', '0000-00-00')
+ ->add('resolvedBy', '')
+ ->add('resolvedBuild', '')
+ ->add('closedBy', '')
+ ->add('closedDate', '0000-00-00')
+ ->add('duplicateBug', 0)
+ ->add('lastEditedBy', $this->app->user->account)
+ ->add('lastEditedDate', $now)
+ ->join('openedBuild', ',')
+ ->remove('comment,files,labels')
+ ->get();
+
+ $this->dao->update(TABLE_BUG)->data($bug)->autoCheck()->where('id')->eq((int)$bugID)->exec();
+ $this->dao->update(TABLE_BUG)->set('activatedCount = activatedCount + 1')->where('id')->eq((int)$bugID)->exec();
+ }
+
+ /**
+ * Close a bug.
+ *
+ * @param int $bugID
+ * @access public
+ * @return void
+ */
+ public function close($bugID)
+ {
+ $oldBug = $this->getById($bugID);
+ $now = helper::now();
+ $bug = fixer::input('post')
+ ->add('assignedTo', 'closed')
+ ->add('assignedDate', $now)
+ ->add('status', 'closed')
+ ->add('closedBy', $this->app->user->account)
+ ->add('closedDate', $now)
+ ->add('lastEditedBy', $this->app->user->account)
+ ->add('lastEditedDate', $now)
+ ->add('confirmed', 1)
+ ->remove('comment')
+ ->get();
+
+ $this->dao->update(TABLE_BUG)->data($bug)->autoCheck()->where('id')->eq((int)$bugID)->exec();
+ }
+
+ /**
+ * Extract accounts from some bugs.
+ *
+ * @param int $bugs
+ * @access public
+ * @return array
+ */
+ public function extractAccountsFromList($bugs)
+ {
+ $accounts = array();
+ foreach($bugs as $bug)
+ {
+ if(!empty($bug->openedBy)) $accounts[] = $bug->openedBy;
+ if(!empty($bug->assignedTo)) $accounts[] = $bug->assignedTo;
+ if(!empty($bug->resolvedBy)) $accounts[] = $bug->resolvedBy;
+ if(!empty($bug->closedBy)) $accounts[] = $bug->closedBy;
+ if(!empty($bug->lastEditedBy)) $accounts[] = $bug->lastEditedBy;
+ }
+ return array_unique($accounts);
+ }
+
+ /**
+ * Extract accounts from a bug.
+ *
+ * @param object $bug
+ * @access public
+ * @return array
+ */
+ public function extractAccountsFromSingle($bug)
+ {
+ $accounts = array();
+ if(!empty($bug->openedBy)) $accounts[] = $bug->openedBy;
+ if(!empty($bug->assignedTo)) $accounts[] = $bug->assignedTo;
+ if(!empty($bug->resolvedBy)) $accounts[] = $bug->resolvedBy;
+ if(!empty($bug->closedBy)) $accounts[] = $bug->closedBy;
+ if(!empty($bug->lastEditedBy)) $accounts[] = $bug->lastEditedBy;
+ return array_unique($accounts);
+ }
+
+ /**
+ * Get bug pairs of a user.
+ *
+ * @param int $account
+ * @param bool $appendProduct
+ * @param int $limit
+ * @access public
+ * @return array
+ */
+ public function getUserBugPairs($account, $appendProduct = true, $limit = 0)
+ {
+ $bugs = array();
+ $stmt = $this->dao->select('t1.id, t1.title, t2.name as product')
+ ->from(TABLE_BUG)->alias('t1')
+ ->leftJoin(TABLE_PRODUCT)->alias('t2')
+ ->on('t1.product=t2.id')
+ ->where('t1.assignedTo')->eq($account)
+ ->andWhere('t1.deleted')->eq(0)
+ ->orderBy('id desc')
+ ->beginIF($limit > 0)->limit($limit)->fi()
+ ->query();
+ while($bug = $stmt->fetch())
+ {
+ if($appendProduct) $bug->title = $bug->product . ' / ' . $bug->title;
+ $bugs[$bug->id] = $bug->title;
+ }
+ return $bugs;
+ }
+
+ /**
+ * Get bugs of a project.
+ *
+ * @param int $projectID
+ * @param string $orderBy
+ * @param object $pager
+ * @access public
+ * @return array
+ */
+ public function getProjectBugs($projectID, $orderBy = 'id_desc', $pager = null, $build = 0)
+ {
+ $bugs = $this->dao->select('*')->from(TABLE_BUG)
+ ->where('project')->eq((int)$projectID)
+ ->beginIF($build != 0)->andWhere('openedBuild')->eq($build)->fi()
+ ->andWhere('deleted')->eq(0)
+ ->orderBy($orderBy)->page($pager)->fetchAll();
+
+ $this->loadModel('common')->saveQueryCondition($this->dao->get(), 'bug');
+
+ return $bugs;
+ }
+
+ /**
+ * Get bugs according to buildID and productID.
+ *
+ * @param int $buildID
+ * @param int $productID
+ * @access public
+ * @return object
+ */
+ public function getReleaseBugs($buildID, $productID)
+ {
+ $project = $this->dao->select('t1.begin')
+ ->from(TABLE_PROJECT)->alias('t1')
+ ->leftJoin(TABLE_BUILD)->alias('t2')
+ ->on('t1.id = t2.project')
+ ->where('t2.id')->eq($buildID)
+ ->fetch();
+ $bugs = $this->dao->select('*')->from(TABLE_BUG)
+ ->where('resolvedDate')->ge($project->begin)
+ ->andWhere('product')->eq($productID)
+ ->orderBy('openedDate ASC')
+ ->fetchAll();
+ return $bugs;
+ }
+
+ /**
+ * Get bug info from a result.
+ *
+ * @param int $resultID
+ * @param int $caseID
+ * @param int $version
+ * @access public
+ * @return array
+ */
+ public function getBugInfoFromResult($resultID, $caseID = 0, $version = 0)
+ {
+ $title = '';
+ $bugSteps = '';
+
+ $result = $this->dao->findById($resultID)->from(TABLE_TESTRESULT)->fetch();
+ if($caseID > 0)
+ $run->case = $this->loadModel('testcase')->getById($caseID, $result->version);
+ else
+ $run = $this->loadModel('testtask')->getRunById($result->run);
+ if($result and $result->caseResult == 'fail')
+ {
+ $title = $run->case->title;
+ $caseSteps = $run->case->steps;
+ $stepResults = unserialize($result->stepResults);
+ if($run->case->precondition != '')
+ {
+ $bugSteps = "[" . $this->lang->testcase->precondition . "]
" . "\n" . $run->case->precondition;
+ }
+ $bugSteps .= $this->lang->bug->tplStep;
+ if(!empty($stepResults))
+ {
+ foreach($caseSteps as $key => $step)
+ {
+ $bugSteps .= ($key + 1) . '. ' .$step->desc . " ";
+ if($stepResults[$step->id]['result'] == 'fail')
+ {
+ $bugSteps .= $this->lang->bug->tplResult;
+ $bugSteps .= $stepResults[$step->id]['real'] . " ";
+ $bugSteps .= $this->lang->bug->tplExpect;
+ $bugSteps .= $step->expect;
+ break;
+ }
+ }
+ }
+ else
+ {
+ $bugSteps .= $this->lang->bug->tplResult;
+ $bugSteps .= $this->lang->bug->tplExpect;
+ }
+ }
+ return array('title' => $title, 'steps' => $bugSteps, 'storyID' => $run->case->story);
+ }
+
+ /**
+ * Get report data of bugs per project
+ *
+ * @access public
+ * @return array
+ */
+ public function getDataOfBugsPerProject()
+ {
+ $datas = $this->dao->select('project as name, count(project) as value')->from(TABLE_BUG)->where($this->reportCondition())->groupBy('project')->orderBy('value DESC')->fetchAll('name');
+ if(!$datas) return array();
+ $projects = $this->loadModel('project')->getPairs();
+ foreach($datas as $projectID => $data) $data->name = isset($projects[$projectID]) ? $projects[$projectID] : $this->lang->report->undefined;
+ return $datas;
+ }
+
+ /**
+ * Get report data of bugs per build.
+ *
+ * @access public
+ * @return void
+ */
+ public function getDataOfBugsPerBuild()
+ {
+ $datas = $this->dao->select('openedBuild as name, count(openedBuild) as value')->from(TABLE_BUG)->where($this->reportCondition())->groupBy('openedBuild')->orderBy('value DESC')->fetchAll('name');
+ if(!$datas) return array();
+ $builds = $this->loadModel('build')->getProductBuildPairs($this->session->product);
+
+ /* Deal with the situation that a bug maybe associate more than one openedBuild. */
+ foreach($datas as $buildIDList => $data)
+ {
+ $openBuildIDList = explode(',', $buildIDList);
+ if(count($openBuildIDList) > 1)
+ {
+ foreach($openBuildIDList as $buildID)
+ {
+ if(isset($datas[$buildID]))
+ {
+ $datas[$buildID]->value++;
+ }
+ else
+ {
+ $datas[$buildID]->name = $buildID;
+ $datas[$buildID]->value = 1;
+ }
+ }
+ unset($datas[$buildIDList]);
+ }
+ }
+
+ foreach($datas as $buildID => $data)
+ {
+ $data->name = isset($builds[$buildID]) ? $builds[$buildID] : $this->lang->report->undefined;
+ }
+ return $datas;
+ }
+
+ /**
+ * Get report data of bugs per module
+ *
+ * @access public
+ * @return array
+ */
+ public function getDataOfBugsPerModule()
+ {
+ $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->dao->select('id, name')->from(TABLE_MODULE)->where('id')->in(array_keys($datas))->fetchPairs();
+ foreach($datas as $moduleID => $data) $data->name = isset($modules[$moduleID]) ? $modules[$moduleID] : '/';
+ return $datas;
+ }
+
+ /**
+ * Get report data of opened bugs per day.
+ *
+ * @access public
+ * @return array
+ */
+ public function getDataOfOpenedBugsPerDay()
+ {
+ return $this->dao->select('DATE_FORMAT(openedDate, "%Y-%m-%d") AS name, COUNT(*) AS value')->from(TABLE_BUG)->where($this->reportCondition())->groupBy('name')->orderBy('openedDate')->fetchAll();
+ }
+
+ /**
+ * Get report data of resolved bugs per day.
+ *
+ * @access public
+ * @return array
+ */
+ public function getDataOfResolvedBugsPerDay()
+ {
+ return $this->dao->select('DATE_FORMAT(resolvedDate, "%Y-%m-%d") AS name, COUNT(*) AS value')->from(TABLE_BUG)
+ ->where($this->reportCondition())->groupBy('name')
+ ->having('name != 0000-00-00')
+ ->orderBy('resolvedDate')
+ ->fetchAll();
+ }
+
+ /**
+ * Get report data of closed bugs per day.
+ *
+ * @access public
+ * @return array
+ */
+ public function getDataOfClosedBugsPerDay()
+ {
+ return $this->dao->select('DATE_FORMAT(closedDate, "%Y-%m-%d") AS name, COUNT(*) AS value')->from(TABLE_BUG)
+ ->where($this->reportCondition())->groupBy('name')
+ ->having('name != 0000-00-00')
+ ->orderBy('closedDate')->fetchAll();
+ }
+
+ /**
+ * Get report data of openeded bugs per user.
+ *
+ * @access public
+ * @return array
+ */
+ public function getDataOfOpenedBugsPerUser()
+ {
+ $datas = $this->dao->select('openedBy AS name, COUNT(*) AS value')->from(TABLE_BUG)->where($this->reportCondition())->groupBy('name')->orderBy('value DESC')->fetchAll('name');
+ if(!$datas) return array();
+ if(!isset($this->users)) $this->users = $this->loadModel('user')->getPairs('noletter');
+ foreach($datas as $account => $data) if(isset($this->users[$account])) $data->name = $this->users[$account];
+ return $datas;
+ }
+
+ /**
+ * Get report data of resolved bugs per user.
+ *
+ * @access public
+ * @return array
+ */
+ public function getDataOfResolvedBugsPerUser()
+ {
+ $datas = $this->dao->select('resolvedBy AS name, COUNT(*) AS value')
+ ->from(TABLE_BUG)->where($this->reportCondition())
+ ->andWhere('resolvedBy')->ne('')
+ ->groupBy('name')
+ ->orderBy('value DESC')->fetchAll('name');
+ if(!$datas) return array();
+ if(!isset($this->users)) $this->users = $this->loadModel('user')->getPairs('noletter');
+ foreach($datas as $account => $data) if(isset($this->users[$account])) $data->name = $this->users[$account];
+ return $datas;
+ }
+
+ /**
+ * Get report data of closed bugs per user.
+ *
+ * @access public
+ * @return array
+ */
+ public function getDataOfClosedBugsPerUser()
+ {
+ $datas = $this->dao->select('closedBy AS name, COUNT(*) AS value')
+ ->from(TABLE_BUG)
+ ->where($this->reportCondition())
+ ->andWhere('closedBy')->ne('')
+ ->groupBy('name')
+ ->orderBy('value DESC')->fetchAll('name');
+ if(!$datas) return array();
+ if(!isset($this->users)) $this->users = $this->loadModel('user')->getPairs('noletter');
+ foreach($datas as $account => $data) if(isset($this->users[$account])) $data->name = $this->users[$account];
+ return $datas;
+ }
+
+ /**
+ * Get report data of bugs per severity.
+ *
+ * @access public
+ * @return array
+ */
+ public function getDataOfBugsPerSeverity()
+ {
+ $datas = $this->dao->select('severity AS name, COUNT(*) AS value')->from(TABLE_BUG)->where($this->reportCondition())->groupBy('name')->orderBy('value DESC')->fetchAll('name');
+ if(!$datas) return array();
+ foreach($datas as $severity => $data) if(isset($this->lang->bug->severityList[$severity])) $data->name = $this->lang->bug->severityList[$severity];
+ return $datas;
+ }
+
+ /**
+ * Get report data of bugs per resolution.
+ *
+ * @access public
+ * @return array
+ */
+ public function getDataOfBugsPerResolution()
+ {
+ $datas = $this->dao->select('resolution AS name, COUNT(*) AS value')
+ ->from(TABLE_BUG)
+ ->where($this->reportCondition())
+ ->andWhere('resolution')->ne('')
+ ->groupBy('name')->orderBy('value DESC')
+ ->fetchAll('name');
+ if(!$datas) return array();
+ foreach($datas as $resolution => $data) if(isset($this->lang->bug->resolutionList[$resolution])) $data->name = $this->lang->bug->resolutionList[$resolution];
+ return $datas;
+ }
+
+ /**
+ * Get report data of bugs per status.
+ *
+ * @access public
+ * @return array
+ */
+ public function getDataOfBugsPerStatus()
+ {
+ $datas = $this->dao->select('status AS name, COUNT(*) AS value')->from(TABLE_BUG)->where($this->reportCondition())->groupBy('name')->orderBy('value DESC')->fetchAll('name');
+ if(!$datas) return array();
+ foreach($datas as $status => $data) if(isset($this->lang->bug->statusList[$status])) $data->name = $this->lang->bug->statusList[$status];
+ return $datas;
+ }
+
+ /**
+ * Get report data of bugs per status.
+ *
+ * @access public
+ * @return array
+ */
+ public function getDataOfBugsPerActivatedCount()
+ {
+ $datas = $this->dao->select('activatedCount AS name, COUNT(*) AS value')->from(TABLE_BUG)->where($this->reportCondition())->groupBy('name')->orderBy('value DESC')->fetchAll('name');
+ if(!$datas) return array();
+ foreach($datas as $data) $data->name = $this->lang->bug->report->bugsPerActivatedCount->graph->xAxisName . ':' . $data->name;
+ return $datas;
+ }
+
+ /**
+ * Get report data of bugs per type.
+ *
+ * @access public
+ * @return array
+ */
+ public function getDataOfBugsPerType()
+ {
+ $datas = $this->dao->select('type AS name, COUNT(*) AS value')->from(TABLE_BUG)->where($this->reportCondition())->groupBy('name')->orderBy('value DESC')->fetchAll('name');
+ if(!$datas) return array();
+ foreach($datas as $type => $data) if(isset($this->lang->bug->typeList[$type])) $data->name = $this->lang->bug->typeList[$type];
+ return $datas;
+ }
+
+ /**
+ * getDataOfBugsPerAssignedTo
+ *
+ * @access public
+ * @return void
+ */
+ public function getDataOfBugsPerAssignedTo()
+ {
+ $datas = $this->dao->select('assignedTo AS name, COUNT(*) AS value')
+ ->from(TABLE_BUG)->where($this->reportCondition())
+ ->groupBy('name')
+ ->orderBy('value DESC')->fetchAll('name');
+ if(!$datas) return array();
+ if(!isset($this->users)) $this->users = $this->loadModel('user')->getPairs('noletter');
+ foreach($datas as $account => $data) if(isset($this->users[$account])) $data->name = $this->users[$account];
+ return $datas;
+ }
+
+ /**
+ * Merge the default chart settings and the settings of current chart.
+ *
+ * @param string $chartType
+ * @access public
+ * @return void
+ */
+ public function mergeChartOption($chartType)
+ {
+ $chartOption = $this->lang->bug->report->$chartType;
+ $commonOption = $this->lang->bug->report->options;
+
+ $chartOption->graph->caption = $this->lang->bug->report->charts[$chartType];
+ if(!isset($chartOption->swf)) $chartOption->swf = $commonOption->swf;
+ if(!isset($chartOption->width)) $chartOption->width = $commonOption->width;
+ if(!isset($chartOption->height)) $chartOption->height = $commonOption->height;
+
+ /* 合并配置。*/
+ foreach($commonOption->graph as $key => $value) if(!isset($chartOption->graph->$key)) $chartOption->graph->$key = $value;
+ }
+
+ /**
+ * Get bug templates of a user.
+ *
+ * @param string $account
+ * @access public
+ * @return array
+ */
+ public function getUserBugTemplates($account)
+ {
+ $templates = $this->dao->select('id, title, content')
+ ->from(TABLE_USERTPL)
+ ->where('account')->eq($account)
+ ->orderBy('id')
+ ->fetchAll();
+ return $templates;
+ }
+
+ /**
+ * Save user template.
+ *
+ * @access public
+ * @return void
+ */
+ public function saveUserBugTemplate()
+ {
+ $template = fixer::input('post')
+ ->specialChars('title')
+ ->add('account', $this->app->user->account)
+ ->add('type', 'bug')
+ ->get();
+ $this->dao->insert(TABLE_USERTPL)->data($template)->autoCheck('title, content', 'notempty')->check('title', 'unique')->exec();
+ }
+
+ /**
+ * Return the file => label pairs of some fields.
+ *
+ * @param string $fields
+ * @access public
+ * @return array
+ */
+ public function getFieldPairs($fields)
+ {
+ $fields = explode(',', $fields);
+ foreach($fields as $key => $field)
+ {
+ $field = trim($field);
+ $fields[$field] = $this->lang->bug->$field;
+ unset($fields[$key]);
+ }
+ return $fields;
+ }
+
+ /**
+ * Get all bugs.
+ *
+ * @param int $productID
+ * @param array $projects
+ * @param int $queryID
+ * @param string $orderBy
+ * @param object $pager
+ * @access public
+ * @return array
+ */
+ public function getAllBugs($productID, $projects, $orderBy, $pager)
+ {
+ $bugs = $this->dao->select('*')->from(TABLE_BUG)->where('product')->eq($productID)
+ ->andWhere('project')->in(array_keys($projects))
+ ->andWhere('deleted')->eq(0)
+ ->orderBy($orderBy)->page($pager)->fetchAll();
+
+ $this->loadModel('common')->saveQueryCondition($this->dao->get(), 'bug');
+
+ return $bugs;
+ }
+
+ /**
+ * Get bugs of assign to me.
+ *
+ * @param int $productID
+ * @param array $projects
+ * @param int $queryID
+ * @param string $orderBy
+ * @param object $pager
+ * @access public
+ * @return array
+ */
+ public function getByAssigntome($productID, $projects, $orderBy, $pager)
+ {
+ return $this->dao->findByAssignedTo($this->app->user->account)->from(TABLE_BUG)->andWhere('product')->eq($productID)
+ ->andWhere('project')->in(array_keys($projects))
+ ->andWhere('deleted')->eq(0)
+ ->orderBy($orderBy)->page($pager)->fetchAll();
+ }
+
+ /**
+ * Get bugs of opened by me.
+ *
+ * @param int $productID
+ * @param array $projects
+ * @param int $queryID
+ * @param string $orderBy
+ * @param object $pager
+ * @access public
+ * @return array
+ */
+ public function getByOpenedbyme($productID, $projects, $orderBy, $pager)
+ {
+ return $this->dao->findByOpenedBy($this->app->user->account)->from(TABLE_BUG)->andWhere('product')->eq($productID)
+ ->andWhere('project')->in(array_keys($projects))
+ ->andWhere('deleted')->eq(0)
+ ->orderBy($orderBy)->page($pager)->fetchAll();
+ }
+
+ /**
+ * Get bugs of resolved by me.
+ *
+ * @param int $productID
+ * @param array $projects
+ * @param int $queryID
+ * @param string $orderBy
+ * @param object $pager
+ * @access public
+ * @return array
+ */
+ public function getByResolvedbyme($productID, $projects, $orderBy, $pager)
+ {
+ return $this->dao->findByResolvedBy($this->app->user->account)->from(TABLE_BUG)->andWhere('product')->eq($productID)
+ ->andWhere('project')->in(array_keys($projects))
+ ->andWhere('deleted')->eq(0)
+ ->orderBy($orderBy)->page($pager)->fetchAll();
+ }
+
+ /**
+ * Get bugs of nobody to do.
+ *
+ * @param int $productID
+ * @param array $projects
+ * @param int $queryID
+ * @param string $orderBy
+ * @param object $pager
+ * @access public
+ * @return array
+ */
+ public function getByAssigntonull($productID, $projects, $orderBy, $pager)
+ {
+
+ return $this->dao->findByAssignedTo('')->from(TABLE_BUG)->andWhere('product')->eq($productID)
+ ->andWhere('project')->in(array_keys($projects))
+ ->andWhere('deleted')->eq(0)
+ ->orderBy($orderBy)->page($pager)->fetchAll();
+ }
+
+ /**
+ * Get bugs the status is active or unclosed.
+ *
+ * @param int $productID
+ * @param array $projects
+ * @param string $status
+ * @param int $queryID
+ * @param string $orderBy
+ * @param object $pager
+ * @access public
+ * @return array
+ */
+ public function getByStatus($productID, $projects, $status, $orderBy, $pager)
+ {
+ return $this->dao->select('*')->from(TABLE_BUG)
+ ->where('project')->in(array_keys($projects))
+ ->andWhere('product')->eq($productID)
+ ->beginIF($status == 'unclosed')->andWhere('status')->ne('closed')->fi()
+ ->beginIF($status == 'unresolved')->andWhere('status')->eq('active')->fi()
+ ->andWhere('deleted')->eq(0)
+ ->orderBy($orderBy)->page($pager)->fetchAll();
+ }
+
+ /**
+ * Get unresolve bugs for long time.
+ *
+ * @param int $productID
+ * @param array $projects
+ * @param int $queryID
+ * @param string $orderBy
+ * @param object $pager
+ * @access public
+ * @return array
+ */
+ public function getByLonglifebugs($productID, $projects, $orderBy, $pager)
+ {
+ return $this->dao->findByLastEditedDate("<", date(DT_DATE1, strtotime('-7 days')))->from(TABLE_BUG)->andWhere('product')->eq($productID)
+ ->andWhere('project')->in(array_keys($projects))
+ ->andWhere('openedDate')->lt(date(DT_DATE1,strtotime('-7 days')))
+ ->andWhere('deleted')->eq(0)
+ ->andWhere('status')->ne('closed')->orderBy($orderBy)->page($pager)->fetchAll();
+ }
+
+ /**
+ * Get postponed bugs.
+ *
+ * @param int $productID
+ * @param array $projects
+ * @param int $queryID
+ * @param string $orderBy
+ * @param object $pager
+ * @access public
+ * @return array
+ */
+ public function getByPostponedbugs($productID, $projects, $orderBy, $pager)
+ {
+ return $this->dao->findByResolution('postponed')->from(TABLE_BUG)->andWhere('product')->eq($productID)
+ ->andWhere('project')->in(array_keys($projects))
+ ->orderBy($orderBy)->page($pager)->fetchAll();
+ }
+
+ /**
+ * Get bugs need confirm.
+ *
+ * @param int $productID
+ * @param array $projects
+ * @param int $queryID
+ * @param string $orderBy
+ * @param object $pager
+ * @access public
+ * @return array
+ */
+ public function getByNeedconfirm($productID, $projects, $orderBy, $pager)
+ {
+ return $this->dao->select('t1.*, t2.title AS storyTitle')->from(TABLE_BUG)->alias('t1')->leftJoin(TABLE_STORY)->alias('t2')->on('t1.story = t2.id')
+ ->where("t2.status = 'active'")
+ ->andWhere('t1.product')->eq($productID)
+ ->andWhere('t1.deleted')->eq(0)
+ ->andWhere('t2.version > t1.storyVersion')
+ ->andWhere('t1.project')->in(array_keys($projects))
+ ->orderBy($orderBy)
+ ->page($pager)
+ ->fetchAll();
+ }
+
+ /**
+ * Get bugs by search.
+ *
+ * @param int $productID
+ * @param array $projects
+ * @param int $queryID
+ * @param string $orderBy
+ * @param object $pager
+ * @access public
+ * @return array
+ */
+ public function getBySearch($productID, $projects, $queryID, $orderBy, $pager)
+ {
+ if($queryID)
+ {
+ $query = $this->loadModel('search')->getQuery($queryID);
+ if($query)
+ {
+ $this->session->set('bugQuery', $query->sql);
+ $this->session->set('bugForm', $query->form);
+ }
+ else
+ {
+ $this->session->set('bugQuery', ' 1 = 1');
+ }
+ }
+ else
+ {
+ if($this->session->bugQuery == false) $this->session->set('bugQuery', ' 1 = 1');
+ }
+
+ /* check the purview of projects.*/
+ if(strpos($this->session->bugQuery, '`project`') === false)
+ {
+ $var = $this->session->bugQuery . ' AND `project`' . helper::dbIN(array_keys($projects));
+ $this->session->set('bugQuery', "$var");
+ }
+
+ $bugQuery = str_replace("`product` = 'all'", '1', $this->session->bugQuery); // Search all product.
+ $bugQuery = $this->loadModel('search')->replaceDynamic($bugQuery);
+ $bugs = $this->dao->select('*')->from(TABLE_BUG)->where($bugQuery)
+ ->andWhere('deleted')->eq(0)
+ ->orderBy($orderBy)->page($pager)->fetchAll();
+ return $bugs;
+ }
+
+ /**
+ * Form customed bugs.
+ *
+ * @param array $bugs
+ * @access public
+ * @return array
+ */
+ public function formCustomedBugs($bugs)
+ {
+ /* Get related objects id lists. */
+ $relatedModuleIdList = array();
+ $relatedStoryIdList = array();
+ $relatedTaskIdList = array();
+ $relatedCaseIdList = array();
+ $relatedProjectIdList = array();
+
+ foreach($bugs as $bug)
+ {
+ $relatedModuleIdList[$bug->module] = $bug->module;
+ $relatedStoryIdList[$bug->story] = $bug->story;
+ $relatedTaskIdList[$bug->task] = $bug->task;
+ $relatedCaseIdList[$bug->case] = $bug->case;
+ $relatedProjectIdList[$bug->project] = $bug->project;
+
+ /* Get related objects title or names. */
+ $relatedModules = $this->dao->select('id, name')->from(TABLE_MODULE)->where('id')->in($relatedModuleIdList)->fetchPairs();
+ $relatedStories = $this->dao->select('id, title')->from(TABLE_STORY) ->where('id')->in($relatedStoryIdList)->fetchPairs();
+ $relatedTasks = $this->dao->select('id, name')->from(TABLE_TASK)->where('id')->in($relatedTaskIdList)->fetchPairs();
+ $relatedCases = $this->dao->select('id, title')->from(TABLE_CASE)->where('id')->in($relatedCaseIdList)->fetchPairs();
+ $relatedProjects = $this->dao->select('id, name')->from(TABLE_PROJECT)->where('id')->in($relatedProjectIdList)->fetchPairs();
+
+ /* fill some field with useful value. */
+ if(isset($relatedModules[$bug->module])) $bug->module = $relatedModules[$bug->module];
+ if(isset($relatedStories[$bug->story])) $bug->story = $relatedStories[$bug->story];
+ if(isset($relatedTasks[$bug->task])) $bug->task = $relatedTasks[$bug->task];
+ if(isset($relatedCases[$bug->case])) $bug->case = $relatedCases[$bug->case];
+ if(isset($relatedProjects[$bug->project])) $bug->project = $relatedProjects[$bug->project];
+ }
+ return $bugs;
+ }
+
+ /**
+ * Adjust the action is clickable.
+ *
+ * @param string $bug
+ * @param string $action
+ * @access public
+ * @return void
+ */
+ public function isClickable($object, $action)
+ {
+ $action = strtolower($action);
+
+ if($action == 'confirmbug') return $object->status == 'active' and $object->confirmed == 0;
+ if($action == 'resolve') return $object->status == 'active';
+ if($action == 'close') return $object->status == 'resolved';
+ if($action == 'activate') return $object->status != 'active';
+ if($action == 'tostory') return $object->status == 'active';
+
+ return true;
+ }
+
+ /**
+ * Get report condition from session.
+ *
+ * @access public
+ * @return void
+ */
+ public function reportCondition()
+ {
+ if(!$this->session->bugOnlyCondition) return 'id in (' . preg_replace('/SELECT .* FROM/', 'SELECT t1.id FROM', $this->session->bugQueryCondition) . ')';
+ return $this->session->bugQueryCondition;
+ }
+}
diff --git a/module/bug/view/activate.html.php b/module/bug/view/activate.html.php
index 8d056326c9..b8cab88ac8 100644
--- a/module/bug/view/activate.html.php
+++ b/module/bug/view/activate.html.php
@@ -1,43 +1,43 @@
-
- * @package bug
- * @version $Id$
- * @link http://www.zentao.net
- */
-?>
-
-
-
+
+ * @package bug
+ * @version $Id$
+ * @link http://www.zentao.net
+ */
+?>
+
+
+
diff --git a/module/bug/view/assignto.html.php b/module/bug/view/assignto.html.php
index 10b8f35672..843b432b78 100644
--- a/module/bug/view/assignto.html.php
+++ b/module/bug/view/assignto.html.php
@@ -1,31 +1,31 @@
-
- * @package task
- * @version $Id: complete.html.php 935 2010-07-06 07:49:24Z jajacn@126.com $
- * @link http://www.zentao.net
- */
-?>
-
-
-
+
+ * @package task
+ * @version $Id: complete.html.php 935 2010-07-06 07:49:24Z jajacn@126.com $
+ * @link http://www.zentao.net
+ */
+?>
+
+
+
diff --git a/module/bug/view/batchedit.html.php b/module/bug/view/batchedit.html.php
index d1f2d7da59..0e91e4752f 100644
--- a/module/bug/view/batchedit.html.php
+++ b/module/bug/view/batchedit.html.php
@@ -1,59 +1,59 @@
-
- * @package bug
- * @version $Id$
- * @link http://www.zentao.net
- */
-?>
-
-
-
+
+ * @package bug
+ * @version $Id$
+ * @link http://www.zentao.net
+ */
+?>
+
+
+
diff --git a/module/bug/view/browse.html.php b/module/bug/view/browse.html.php
index ac6693bbd5..a9b7211e10 100644
--- a/module/bug/view/browse.html.php
+++ b/module/bug/view/browse.html.php
@@ -1,183 +1,183 @@
-
- * @package bug
- * @version $Id$
- * @link http://www.zentao.net
- */
-?>
-
-
-
-
-
" . $lang->bug->moduleBugs . " ";
- echo "
" . html::a($this->createLink('bug', 'browse', "productid=$productID&browseType=assignToMe¶m=0"), $lang->bug->assignToMe) . " ";
- echo "
" . html::a($this->createLink('bug', 'browse', "productid=$productID&browseType=openedByMe¶m=0"), $lang->bug->openedByMe) . " ";
- echo "
" . html::a($this->createLink('bug', 'browse', "productid=$productID&browseType=resolvedByMe¶m=0"), $lang->bug->resolvedByMe) . " ";
- echo "
" . html::a($this->createLink('bug', 'browse', "productid=$productID&browseType=assignToNull¶m=0"), $lang->bug->assignToNull) . " ";
- echo "
" . html::a($this->createLink('bug', 'browse', "productid=$productID&browseType=unResolved¶m=0"), $lang->bug->unResolved) . " ";
- echo "
" . html::a($this->createLink('bug', 'browse', "productid=$productID&browseType=unclosed¶m=0"), $lang->bug->unclosed) . " ";
- echo "
" . html::a($this->createLink('bug', 'browse', "productid=$productID&browseType=longLifeBugs¶m=0"), $lang->bug->longLifeBugs) . " ";
- echo "
" . html::a($this->createLink('bug', 'browse', "productid=$productID&browseType=postponedBugs¶m=0"), $lang->bug->postponedBugs) . " ";
- echo "
" . html::a($this->createLink('bug', 'browse', "productid=$productID&browseType=all¶m=0&orderBy=$orderBy&recTotal=0&recPerPage=200"), $lang->bug->allBugs) . " ";
- echo "
" . html::a($this->createLink('bug', 'browse', "productid=$productID&browseType=needconfirm¶m=0"), $lang->bug->needConfirm) . " ";
- echo "
{$lang->bug->byQuery} ";
- ?>
-
-
-
-
-
-'>
-
-
-
-
-
+
+ * @package bug
+ * @version $Id$
+ * @link http://www.zentao.net
+ */
+?>
+
+
+
+
+
" . $lang->bug->moduleBugs . " ";
+ echo "
" . html::a($this->createLink('bug', 'browse', "productid=$productID&browseType=assignToMe¶m=0"), $lang->bug->assignToMe) . " ";
+ echo "
" . html::a($this->createLink('bug', 'browse', "productid=$productID&browseType=openedByMe¶m=0"), $lang->bug->openedByMe) . " ";
+ echo "
" . html::a($this->createLink('bug', 'browse', "productid=$productID&browseType=resolvedByMe¶m=0"), $lang->bug->resolvedByMe) . " ";
+ echo "
" . html::a($this->createLink('bug', 'browse', "productid=$productID&browseType=assignToNull¶m=0"), $lang->bug->assignToNull) . " ";
+ echo "
" . html::a($this->createLink('bug', 'browse', "productid=$productID&browseType=unResolved¶m=0"), $lang->bug->unResolved) . " ";
+ echo "
" . html::a($this->createLink('bug', 'browse', "productid=$productID&browseType=unclosed¶m=0"), $lang->bug->unclosed) . " ";
+ echo "
" . html::a($this->createLink('bug', 'browse', "productid=$productID&browseType=longLifeBugs¶m=0"), $lang->bug->longLifeBugs) . " ";
+ echo "
" . html::a($this->createLink('bug', 'browse', "productid=$productID&browseType=postponedBugs¶m=0"), $lang->bug->postponedBugs) . " ";
+ echo "
" . html::a($this->createLink('bug', 'browse', "productid=$productID&browseType=all¶m=0&orderBy=$orderBy&recTotal=0&recPerPage=200"), $lang->bug->allBugs) . " ";
+ echo "
" . html::a($this->createLink('bug', 'browse', "productid=$productID&browseType=needconfirm¶m=0"), $lang->bug->needConfirm) . " ";
+ echo "
{$lang->bug->byQuery} ";
+ ?>
+
+
+
+
+
+'>
+
+
+
+
+
diff --git a/module/bug/view/close.html.php b/module/bug/view/close.html.php
index 678f8e599c..cf452f2f25 100644
--- a/module/bug/view/close.html.php
+++ b/module/bug/view/close.html.php
@@ -1,31 +1,31 @@
-
- * @package bug
- * @version $Id$
- * @link http://www.zentao.net
- */
-?>
-
-
-
+
+ * @package bug
+ * @version $Id$
+ * @link http://www.zentao.net
+ */
+?>
+
+
+
diff --git a/module/bug/view/confirmbug.html.php b/module/bug/view/confirmbug.html.php
index d3c562b5fe..a3fd0b6c7a 100755
--- a/module/bug/view/confirmbug.html.php
+++ b/module/bug/view/confirmbug.html.php
@@ -1,31 +1,31 @@
-
- * @package bug
- * @version $Id: resolve.html.php 1914 2011-06-24 10:11:25Z yidong@cnezsoft.com $
- * @link http://www.zentao.net
- */
-?>
-
-
-
+
+ * @package bug
+ * @version $Id: resolve.html.php 1914 2011-06-24 10:11:25Z yidong@cnezsoft.com $
+ * @link http://www.zentao.net
+ */
+?>
+
+
+
diff --git a/module/bug/view/create.html.php b/module/bug/view/create.html.php
index 3b89729b70..f035a74a9d 100644
--- a/module/bug/view/create.html.php
+++ b/module/bug/view/create.html.php
@@ -1,112 +1,112 @@
-
- * @package bug
- * @version $Id$
- * @link http://www.zentao.net
- */
-?>
-bug->placeholder, 'json');
-js::set('userList', array_keys($users), 'json');
-js::set('page', 'create');
-?>
-
-
-
+
+ * @package bug
+ * @version $Id$
+ * @link http://www.zentao.net
+ */
+?>
+bug->placeholder, 'json');
+js::set('userList', array_keys($users), 'json');
+js::set('page', 'create');
+?>
+
+
+
diff --git a/module/bug/view/customfields.html.php b/module/bug/view/customfields.html.php
index bcef9b5dbe..7ad89572b7 100644
--- a/module/bug/view/customfields.html.php
+++ b/module/bug/view/customfields.html.php
@@ -1,49 +1,49 @@
-
- * @package product
- * @version $Id$
- * @link http://www.zentao.net
- */
-?>
-
-
-
-
+
+ * @package product
+ * @version $Id$
+ * @link http://www.zentao.net
+ */
+?>
+
+
+
+
diff --git a/module/bug/view/edit.html.php b/module/bug/view/edit.html.php
index 6e454288fe..4d055bce3f 100644
--- a/module/bug/view/edit.html.php
+++ b/module/bug/view/edit.html.php
@@ -1,205 +1,205 @@
-
- * @package bug
- * @version $Id$
- * @link http://www.zentao.net
- */
-?>
-bug->confirmChangeProduct);
-js::set('oldProjectID' , $bug->project);
-js::set('oldStoryID' , $bug->story);
-js::set('oldTaskID' , $bug->task);
-js::set('oldOpenedBuild' , $bug->openedBuild);
-js::set('oldResolvedBuild' , $bug->resolvedBuild);
-js::set('userList' , array_keys($users), 'json');
-?>
-
-
-
-
-
-
+
+ * @package bug
+ * @version $Id$
+ * @link http://www.zentao.net
+ */
+?>
+
+
+
+
+
+
diff --git a/module/bug/view/sendmail.html.php b/module/bug/view/sendmail.html.php
index faa4c96b61..849af86b24 100644
--- a/module/bug/view/sendmail.html.php
+++ b/module/bug/view/sendmail.html.php
@@ -1,39 +1,39 @@
-
- * @package bug
- * @version $Id$
- * @link http://www.zentao.net
- */
-?>
-
-
-
-
-
- bug->legendSteps;?>
-
- steps, 'src="data/upload'))
- {
- $bug->steps = str_replace('
server->http_host . $this->config->webRoot, $bug->steps);
- $bug->steps = str_replace('
server->http_host . $this->config->webRoot, $bug->steps);
- }
- echo $bug->steps;
- ?>
-
-
-
-
-
-
-
-
+
+ * @package bug
+ * @version $Id$
+ * @link http://www.zentao.net
+ */
+?>
+
+
+
+
+
+ bug->legendSteps;?>
+
+ steps, 'src="data/upload'))
+ {
+ $bug->steps = str_replace('
server->http_host . $this->config->webRoot, $bug->steps);
+ $bug->steps = str_replace('
server->http_host . $this->config->webRoot, $bug->steps);
+ }
+ echo $bug->steps;
+ ?>
+
+
+
+
+
+
+
+
diff --git a/module/bug/view/view.html.php b/module/bug/view/view.html.php
index 6d526e2882..81de9cbd0f 100644
--- a/module/bug/view/view.html.php
+++ b/module/bug/view/view.html.php
@@ -1,286 +1,286 @@
-
- * @package bug
- * @version $Id$
- * @link http://www.zentao.net
- */
-?>
-
-
-
deleted) echo "class='deleted'";?>>BUG #id . ' ' . $bug->title;?>
-
- session->bugList != false ? $app->session->bugList : inlink('browse', "productID=$bug->product");
- $params = "bugID=$bug->id";
- $copyParams = "productID=$productID&extras=bugID=$bug->id";
- $convertParams = "productID=$productID&moduleID=0&from=bug&bugID=$bug->id";
- if(!$bug->deleted)
- {
- ob_start();
- common::printIcon('bug', 'confirmBug', $params, $bug);
- common::printIcon('bug', 'assignTo', $params);
- common::printIcon('bug', 'resolve', $params, $bug);
- common::printIcon('bug', 'close', $params, $bug);
- common::printIcon('bug', 'activate', $params, $bug);
-
- common::printIcon('bug', 'toStory', "product=$bug->product&module=0&story=0&project=0&bugID=$bug->id", $bug, 'button', 'toStory');
- common::printIcon('bug', 'createCase', $convertParams, '', 'button', 'createCase');
-
- common::printDivider();
- common::printIcon('bug', 'edit', $params);
- common::printCommentIcon('bug');
- common::printIcon('bug', 'create', $copyParams, '', 'button', 'copy');
- common::printIcon('bug', 'delete', $params, '', 'button', '', 'hiddenwin');
-
- common::printDivider();
- common::printRPN($browseLink, $preAndNext);
-
- $actionLinks = ob_get_contents();
- ob_end_clean();
- echo $actionLinks;
- }
- else
- {
- common::printRPN($browseLink);
- }
- ?>
-
-
-
-
-
-
-
- bug->legendSteps;?>
-
-
- fetch('file', 'printFiles', array('files' => $bug->files, 'fieldset' => 'true'));?>
-
- deleted) echo $actionLinks;?>
-
-
-
-
-
- bug->legendBasicInfo;?>
-
-
- bug->product;?>
- product", $productName)) echo $productName;?>
-
-
- bug->module;?>
-
- $module)
- {
- if(!common::printLink('bug', 'browse', "productID=$bug->product&browseType=byModule¶m=$module->id", $module->name)) echo $module->name;
- if(isset($modulePath[$key + 1])) echo $lang->arrow;
- }
- }
- ?>
-
-
-
- bug->type;?>
- bug->typeList[$bug->type])) echo $lang->bug->typeList[$bug->type]; else echo $bug->type;?>
-
-
- bug->severity;?>
- bug->severityList[$bug->severity];?>
-
-
- bug->pri;?>
- bug->priList[$bug->pri];?>
-
-
- bug->status;?>
- bug->statusList[$bug->status];?>
-
-
- bug->activatedCount;?>
- activatedCount;?>
-
-
- bug->confirmed;?>
- bug->confirmedList[$bug->confirmed];?>
-
-
- bug->lblAssignedTo;?>
- assignedTo) echo $users[$bug->assignedTo] . $lang->at . $bug->assignedDate;?>
-
-
- bug->os;?>
- bug->osList[$bug->os];?>
-
-
- bug->browser;?>
- bug->browserList[$bug->browser];?>
-
-
- bug->keywords;?>
- keywords;?>
-
-
-
-
-
- bug->case;?>
-
-
- bug->fromCase;?>
- case) echo html::a($this->createLink('case', 'view', "caseID=$bug->case"), $bug->caseTitle);?>
-
-
- bug->toCase;?>
-
- toCases as $caseID => $case)
- {
- echo '' . html::a($this->createLink('testcase', 'view', "caseID=$caseID"), $case) . '
';
- }
- ?>
-
-
-
-
-
-
- bug->legendLife;?>
-
-
- bug->openedBy;?>
- openedBy] . $lang->at . $bug->openedDate;?>
-
-
- bug->openedBuild;?>
-
- openedBuild)
- {
- $openedBuilds = explode(',', $bug->openedBuild);
- foreach($openedBuilds as $openedBuild) isset($builds[$openedBuild]) ? print($builds[$openedBuild] . ' ') : print($openedBuild . ' ');
- }
- else
- {
- echo $bug->openedBuild;
- }
- ?>
-
-
-
- bug->lblResolved;?>
- resolvedBy) echo $users[$bug->resolvedBy] . $lang->at . $bug->resolvedDate;?>
-
-
- bug->resolvedBuild;?>
- resolvedBuild])) echo $builds[$bug->resolvedBuild]; else echo $bug->resolvedBuild;?>
-
-
- bug->resolution;?>
-
- bug->resolutionList[$bug->resolution];
- if(isset($bug->duplicateBugTitle)) echo " #$bug->duplicateBug:" . html::a($this->createLink('bug', 'view', "bugID=$bug->duplicateBug"), $bug->duplicateBugTitle);
- ?>
-
-
-
- bug->closedBy;?>
- closedBy) echo $users[$bug->closedBy] . $lang->at . $bug->closedDate;?>
-
-
- bug->lblLastEdited;?>
- lastEditedBy) echo $users[$bug->lastEditedBy] . $lang->at . $bug->lastEditedDate?>
-
-
-
-
-
- bug->legendPrjStoryTask;?>
-
-
- bug->project;?>
- project) echo html::a($this->createLink('project', 'browse', "projectid=$bug->project"), $bug->projectName);?>
-
-
- bug->story;?>
-
- story) echo html::a($this->createLink('story', 'view', "storyID=$bug->story"), "#$bug->story $bug->storyTitle");
- if($bug->storyStatus == 'active' and $bug->latestStoryVersion > $bug->storyVersion)
- {
- echo "({$lang->story->changed} ";
- echo html::a($this->createLink('bug', 'confirmStoryChange', "bugID=$bug->id"), $lang->confirm, 'hiddenwin');
- echo ")";
- }
- ?>
-
-
-
- bug->task;?>
- task) echo html::a($this->createLink('task', 'view', "taskID=$bug->task"), $bug->taskName);?>
-
-
-
-
- bug->legendMisc;?>
-
-
- bug->mailto;?>
- mailto)); foreach($mailto as $account) echo ' ' . $users[$account]; ?>
-
-
- bug->linkBug;?>
-
- linkBugTitles))
- {
- foreach($bug->linkBugTitles as $linkBugID => $linkBugTitle)
- {
- echo html::a($this->createLink('bug', 'view', "bugID=$linkBugID"), "#$linkBugID $linkBugTitle", '_blank') . ' ';
- }
- }
- ?>
-
-
-
- bug->case;?>
- caseTitle)) echo html::a($this->createLink('testcase', 'view', "caseID=$bug->case"), "#$bug->case $bug->caseTitle", '_blank');?>
-
-
- bug->toStory;?>
- toStory != 0) echo html::a($this->createLink('story', 'view', "storyID=$bug->toStory"), "#$bug->toStory $bug->toStoryTitle", '_blank');?>
-
-
- bug->toTask;?>
- toTask != 0) echo html::a($this->createLink('task', 'view', "taskID=$bug->toTask"), "#$bug->toTask $bug->toTaskTitle", '_blank');?>
-
-
-
-
-
-
-
-
+
+ * @package bug
+ * @version $Id$
+ * @link http://www.zentao.net
+ */
+?>
+
+
+
deleted) echo "class='deleted'";?>>BUG #id . ' ' . $bug->title;?>
+
+ session->bugList != false ? $app->session->bugList : inlink('browse', "productID=$bug->product");
+ $params = "bugID=$bug->id";
+ $copyParams = "productID=$productID&extras=bugID=$bug->id";
+ $convertParams = "productID=$productID&moduleID=0&from=bug&bugID=$bug->id";
+ if(!$bug->deleted)
+ {
+ ob_start();
+ common::printIcon('bug', 'confirmBug', $params, $bug);
+ common::printIcon('bug', 'assignTo', $params);
+ common::printIcon('bug', 'resolve', $params, $bug);
+ common::printIcon('bug', 'close', $params, $bug);
+ common::printIcon('bug', 'activate', $params, $bug);
+
+ common::printIcon('bug', 'toStory', "product=$bug->product&module=0&story=0&project=0&bugID=$bug->id", $bug, 'button', 'toStory');
+ common::printIcon('bug', 'createCase', $convertParams, '', 'button', 'createCase');
+
+ common::printDivider();
+ common::printIcon('bug', 'edit', $params);
+ common::printCommentIcon('bug');
+ common::printIcon('bug', 'create', $copyParams, '', 'button', 'copy');
+ common::printIcon('bug', 'delete', $params, '', 'button', '', 'hiddenwin');
+
+ common::printDivider();
+ common::printRPN($browseLink, $preAndNext);
+
+ $actionLinks = ob_get_contents();
+ ob_end_clean();
+ echo $actionLinks;
+ }
+ else
+ {
+ common::printRPN($browseLink);
+ }
+ ?>
+
+
+
+
+
+
+
+ bug->legendSteps;?>
+
+
+ fetch('file', 'printFiles', array('files' => $bug->files, 'fieldset' => 'true'));?>
+
+ deleted) echo $actionLinks;?>
+
+
+
+
+
+ bug->legendBasicInfo;?>
+
+
+ bug->product;?>
+ product", $productName)) echo $productName;?>
+
+
+ bug->module;?>
+
+ $module)
+ {
+ if(!common::printLink('bug', 'browse', "productID=$bug->product&browseType=byModule¶m=$module->id", $module->name)) echo $module->name;
+ if(isset($modulePath[$key + 1])) echo $lang->arrow;
+ }
+ }
+ ?>
+
+
+
+ bug->type;?>
+ bug->typeList[$bug->type])) echo $lang->bug->typeList[$bug->type]; else echo $bug->type;?>
+
+
+ bug->severity;?>
+ bug->severityList[$bug->severity];?>
+
+
+ bug->pri;?>
+ bug->priList[$bug->pri];?>
+
+
+ bug->status;?>
+ bug->statusList[$bug->status];?>
+
+
+ bug->activatedCount;?>
+ activatedCount;?>
+
+
+ bug->confirmed;?>
+ bug->confirmedList[$bug->confirmed];?>
+
+
+ bug->lblAssignedTo;?>
+ assignedTo) echo $users[$bug->assignedTo] . $lang->at . $bug->assignedDate;?>
+
+
+ bug->os;?>
+ bug->osList[$bug->os];?>
+
+
+ bug->browser;?>
+ bug->browserList[$bug->browser];?>
+
+
+ bug->keywords;?>
+ keywords;?>
+
+
+
+
+
+ bug->case;?>
+
+
+ bug->fromCase;?>
+ case) echo html::a($this->createLink('case', 'view', "caseID=$bug->case"), $bug->caseTitle);?>
+
+
+ bug->toCase;?>
+
+ toCases as $caseID => $case)
+ {
+ echo '' . html::a($this->createLink('testcase', 'view', "caseID=$caseID"), $case) . '
';
+ }
+ ?>
+
+
+
+
+
+
+ bug->legendLife;?>
+
+
+ bug->openedBy;?>
+ openedBy] . $lang->at . $bug->openedDate;?>
+
+
+ bug->openedBuild;?>
+
+ openedBuild)
+ {
+ $openedBuilds = explode(',', $bug->openedBuild);
+ foreach($openedBuilds as $openedBuild) isset($builds[$openedBuild]) ? print($builds[$openedBuild] . ' ') : print($openedBuild . ' ');
+ }
+ else
+ {
+ echo $bug->openedBuild;
+ }
+ ?>
+
+
+
+ bug->lblResolved;?>
+ resolvedBy) echo $users[$bug->resolvedBy] . $lang->at . $bug->resolvedDate;?>
+
+
+ bug->resolvedBuild;?>
+ resolvedBuild])) echo $builds[$bug->resolvedBuild]; else echo $bug->resolvedBuild;?>
+
+
+ bug->resolution;?>
+
+ bug->resolutionList[$bug->resolution];
+ if(isset($bug->duplicateBugTitle)) echo " #$bug->duplicateBug:" . html::a($this->createLink('bug', 'view', "bugID=$bug->duplicateBug"), $bug->duplicateBugTitle);
+ ?>
+
+
+
+ bug->closedBy;?>
+ closedBy) echo $users[$bug->closedBy] . $lang->at . $bug->closedDate;?>
+
+
+ bug->lblLastEdited;?>
+ lastEditedBy) echo $users[$bug->lastEditedBy] . $lang->at . $bug->lastEditedDate?>
+
+
+
+
+
+ bug->legendPrjStoryTask;?>
+
+
+ bug->project;?>
+ project) echo html::a($this->createLink('project', 'browse', "projectid=$bug->project"), $bug->projectName);?>
+
+
+ bug->story;?>
+
+ story) echo html::a($this->createLink('story', 'view', "storyID=$bug->story"), "#$bug->story $bug->storyTitle");
+ if($bug->storyStatus == 'active' and $bug->latestStoryVersion > $bug->storyVersion)
+ {
+ echo "({$lang->story->changed} ";
+ echo html::a($this->createLink('bug', 'confirmStoryChange', "bugID=$bug->id"), $lang->confirm, 'hiddenwin');
+ echo ")";
+ }
+ ?>
+
+
+
+ bug->task;?>
+ task) echo html::a($this->createLink('task', 'view', "taskID=$bug->task"), $bug->taskName);?>
+
+
+
+
+ bug->legendMisc;?>
+
+
+ bug->mailto;?>
+ mailto)); foreach($mailto as $account) echo ' ' . $users[$account]; ?>
+
+
+ bug->linkBug;?>
+
+ linkBugTitles))
+ {
+ foreach($bug->linkBugTitles as $linkBugID => $linkBugTitle)
+ {
+ echo html::a($this->createLink('bug', 'view', "bugID=$linkBugID"), "#$linkBugID $linkBugTitle", '_blank') . ' ';
+ }
+ }
+ ?>
+
+
+
+ bug->case;?>
+ caseTitle)) echo html::a($this->createLink('testcase', 'view', "caseID=$bug->case"), "#$bug->case $bug->caseTitle", '_blank');?>
+
+
+ bug->toStory;?>
+ toStory != 0) echo html::a($this->createLink('story', 'view', "storyID=$bug->toStory"), "#$bug->toStory $bug->toStoryTitle", '_blank');?>
+
+
+ bug->toTask;?>
+ toTask != 0) echo html::a($this->createLink('task', 'view', "taskID=$bug->toTask"), "#$bug->toTask $bug->toTaskTitle", '_blank');?>
+
+
+
+
+
+
+
+
diff --git a/module/build/control.php b/module/build/control.php
index ca45408850..f7fef037bc 100644
--- a/module/build/control.php
+++ b/module/build/control.php
@@ -1,192 +1,192 @@
-
- * @package build
- * @version $Id$
- * @link http://www.zentao.net
- */
-class build extends control
-{
- /**
- * Create a buld.
- *
- * @param int $projectID
- * @access public
- * @return void
- */
- public function create($projectID)
- {
- if(!empty($_POST))
- {
- $buildID = $this->build->create($projectID);
- if(dao::isError()) die(js::error(dao::getError()));
- $this->loadModel('action')->create('build', $buildID, 'opened');
- die(js::locate($this->createLink('project', 'build', "project=$projectID"), 'parent'));
- }
-
- /* Load these models. */
- $this->loadModel('story');
- $this->loadModel('bug');
- $this->loadModel('task');
- $this->loadModel('project');
- $this->loadModel('user');
-
- /* Set menu. */
- $this->project->setMenu($this->project->getPairs(), $projectID);
-
- /* Get stories and bugs. */
- $orderBy = 'status_asc, stage_asc, id_desc';
- $stories = $this->story->getProjectStories($projectID, $orderBy);
- $bugs = $this->bug->getProjectBugs($projectID);
-
- /* Assign. */
- $this->view->header->title = $this->lang->build->create;
- $this->view->products = $this->project->getProducts($projectID);
- $this->view->projectID = $projectID;
- $this->view->users = $this->user->getPairs();
- $this->view->stories = $stories;
- $this->view->bugs = $bugs;
- $this->view->orderBy = $orderBy;
- $this->display();
- }
-
- /**
- * Edit a build.
- *
- * @param int $buildID
- * @access public
- * @return void
- */
- public function edit($buildID)
- {
- if(!empty($_POST))
- {
- $changes = $this->build->update($buildID);
- if(dao::isError()) die(js::error(dao::getError()));
- if($changes)
- {
- $actionID = $this->loadModel('action')->create('build', $buildID, 'edited');
- $this->action->logHistory($actionID, $changes);
- }
- die(js::locate(inlink('view', "buildID=$buildID"), 'parent'));
- }
-
- $this->loadModel('story');
- $this->loadModel('bug');
- $this->loadModel('project');
-
- /* Set menu. */
- $build = $this->build->getById((int)$buildID);
- $this->project->setMenu($this->project->getPairs(), $build->project);
-
- /* Get stories and bugs. */
- $orderBy = 'status_asc, stage_asc, id_desc';
- $stories = $this->story->getProjectStories($build->project, $orderBy);
- $bugs = $this->bug->getProjectBugs($build->project);
-
- /* Assign. */
- $this->view->header->title = $this->lang->build->edit;
- $this->view->position[] = $this->lang->build->edit;
- $this->view->products = $this->project->getProducts($build->project);
- $this->view->users = $this->loadModel('user')->getPairs();
- $this->view->build = $build;
- $this->view->stories = $stories;
- $this->view->bugs = $bugs;
- $this->view->orderBy = $orderBy;
- $this->display();
- }
-
- /**
- * View a build.
- *
- * @param int $buildID
- * @access public
- * @return void
- */
- public function view($buildID)
- {
- $this->loadModel('story');
- $this->loadModel('bug');
-
- /* Set menu. */
- $build = $this->build->getById((int)$buildID, true);
- if(!$build) die(js::error($this->lang->notFound) . js::locate('back'));
-
- $stories = $this->dao->select('*')->from(TABLE_STORY)->where('id')->in($build->stories)->fetchAll();
- $this->loadModel('common')->saveQueryCondition($this->dao->get(), 'story');
-
- $bugs = $this->dao->select('*')->from(TABLE_BUG)->where('id')->in($build->bugs)->fetchAll();
- $this->loadModel('common')->saveQueryCondition($this->dao->get(), 'bug');
-
- $this->loadModel('project')->setMenu($this->project->getPairs(), $build->project);
-
- /* Assign. */
- $projects = $this->project->getPairs();
- $this->view->header->title = "BUILD #$build->id $build->name - " . $projects[$build->project];
- $this->view->position[] = $this->lang->build->view;
- $this->view->products = $this->project->getProducts($build->project);
- $this->view->users = $this->loadModel('user')->getPairs('noletter');
- $this->view->build = $build;
- $this->view->stories = $stories;
- $this->view->bugs = $bugs;
- $this->view->actions = $this->loadModel('action')->getList('build', $buildID);
- $this->display();
- }
-
- /**
- * Delete a build.
- *
- * @param int $buildID
- * @param string $confirm yes|noe
- * @access public
- * @return void
- */
- public function delete($buildID, $confirm = 'no')
- {
- if($confirm == 'no')
- {
- die(js::confirm($this->lang->build->confirmDelete, $this->createLink('build', 'delete', "buildID=$buildID&confirm=yes")));
- }
- else
- {
- $build = $this->build->getById($buildID);
- $this->build->delete(TABLE_BUILD, $buildID);
- die(js::locate($this->createLink('project', 'build', "projectID=$build->project"), 'parent'));
- }
- }
-
- /**
- * AJAX: get builds of a product in html select.
- *
- * @param int $productID
- * @param string $varName the name of the select object to create
- * @param string $build build to selected
- * @access public
- * @return string
- */
- public function ajaxGetProductBuilds($productID, $varName, $build = '')
- {
- if($varName == 'openedBuild') die(html::select($varName . '[]', $this->build->getProductBuildPairs($productID, 'noempty'), $build, 'size=4 class=select-3 multiple'));
- if($varName == 'resolvedBuild') die(html::select($varName, $this->build->getProductBuildPairs($productID, 'noempty'), $build, 'class=select-3'));
- }
-
- /**
- * AJAX: get builds of a project in html select.
- *
- * @param int $projectID
- * @param string $varName the name of the select object to create
- * @param string $build build to selected
- * @access public
- * @return string
- */
- public function ajaxGetProjectBuilds($projectID, $productID, $varName, $build = '')
- {
- if($varName == 'openedBuild') die(html::select($varName . '[]', $this->build->getProjectBuildPairs($projectID, $productID, 'noempty'), $build, 'size=4 class=select-3 multiple'));
- if($varName == 'resolvedBuild') die(html::select($varName, $this->build->getProjectBuildPairs($projectID, $productID, 'noempty'), $build, 'class=select-3'));
- if($varName == 'testTaskBuild') die(html::select('build', $this->build->getProjectBuildPairs($projectID, $productID, 'noempty'), $build, 'class=select-3'));
- }
-}
+
+ * @package build
+ * @version $Id$
+ * @link http://www.zentao.net
+ */
+class build extends control
+{
+ /**
+ * Create a buld.
+ *
+ * @param int $projectID
+ * @access public
+ * @return void
+ */
+ public function create($projectID)
+ {
+ if(!empty($_POST))
+ {
+ $buildID = $this->build->create($projectID);
+ if(dao::isError()) die(js::error(dao::getError()));
+ $this->loadModel('action')->create('build', $buildID, 'opened');
+ die(js::locate($this->createLink('project', 'build', "project=$projectID"), 'parent'));
+ }
+
+ /* Load these models. */
+ $this->loadModel('story');
+ $this->loadModel('bug');
+ $this->loadModel('task');
+ $this->loadModel('project');
+ $this->loadModel('user');
+
+ /* Set menu. */
+ $this->project->setMenu($this->project->getPairs(), $projectID);
+
+ /* Get stories and bugs. */
+ $orderBy = 'status_asc, stage_asc, id_desc';
+ $stories = $this->story->getProjectStories($projectID, $orderBy);
+ $bugs = $this->bug->getProjectBugs($projectID);
+
+ /* Assign. */
+ $this->view->header->title = $this->lang->build->create;
+ $this->view->products = $this->project->getProducts($projectID);
+ $this->view->projectID = $projectID;
+ $this->view->users = $this->user->getPairs();
+ $this->view->stories = $stories;
+ $this->view->bugs = $bugs;
+ $this->view->orderBy = $orderBy;
+ $this->display();
+ }
+
+ /**
+ * Edit a build.
+ *
+ * @param int $buildID
+ * @access public
+ * @return void
+ */
+ public function edit($buildID)
+ {
+ if(!empty($_POST))
+ {
+ $changes = $this->build->update($buildID);
+ if(dao::isError()) die(js::error(dao::getError()));
+ if($changes)
+ {
+ $actionID = $this->loadModel('action')->create('build', $buildID, 'edited');
+ $this->action->logHistory($actionID, $changes);
+ }
+ die(js::locate(inlink('view', "buildID=$buildID"), 'parent'));
+ }
+
+ $this->loadModel('story');
+ $this->loadModel('bug');
+ $this->loadModel('project');
+
+ /* Set menu. */
+ $build = $this->build->getById((int)$buildID);
+ $this->project->setMenu($this->project->getPairs(), $build->project);
+
+ /* Get stories and bugs. */
+ $orderBy = 'status_asc, stage_asc, id_desc';
+ $stories = $this->story->getProjectStories($build->project, $orderBy);
+ $bugs = $this->bug->getProjectBugs($build->project);
+
+ /* Assign. */
+ $this->view->header->title = $this->lang->build->edit;
+ $this->view->position[] = $this->lang->build->edit;
+ $this->view->products = $this->project->getProducts($build->project);
+ $this->view->users = $this->loadModel('user')->getPairs();
+ $this->view->build = $build;
+ $this->view->stories = $stories;
+ $this->view->bugs = $bugs;
+ $this->view->orderBy = $orderBy;
+ $this->display();
+ }
+
+ /**
+ * View a build.
+ *
+ * @param int $buildID
+ * @access public
+ * @return void
+ */
+ public function view($buildID)
+ {
+ $this->loadModel('story');
+ $this->loadModel('bug');
+
+ /* Set menu. */
+ $build = $this->build->getById((int)$buildID, true);
+ if(!$build) die(js::error($this->lang->notFound) . js::locate('back'));
+
+ $stories = $this->dao->select('*')->from(TABLE_STORY)->where('id')->in($build->stories)->fetchAll();
+ $this->loadModel('common')->saveQueryCondition($this->dao->get(), 'story');
+
+ $bugs = $this->dao->select('*')->from(TABLE_BUG)->where('id')->in($build->bugs)->fetchAll();
+ $this->loadModel('common')->saveQueryCondition($this->dao->get(), 'bug');
+
+ $this->loadModel('project')->setMenu($this->project->getPairs(), $build->project);
+
+ /* Assign. */
+ $projects = $this->project->getPairs();
+ $this->view->header->title = "BUILD #$build->id $build->name - " . $projects[$build->project];
+ $this->view->position[] = $this->lang->build->view;
+ $this->view->products = $this->project->getProducts($build->project);
+ $this->view->users = $this->loadModel('user')->getPairs('noletter');
+ $this->view->build = $build;
+ $this->view->stories = $stories;
+ $this->view->bugs = $bugs;
+ $this->view->actions = $this->loadModel('action')->getList('build', $buildID);
+ $this->display();
+ }
+
+ /**
+ * Delete a build.
+ *
+ * @param int $buildID
+ * @param string $confirm yes|noe
+ * @access public
+ * @return void
+ */
+ public function delete($buildID, $confirm = 'no')
+ {
+ if($confirm == 'no')
+ {
+ die(js::confirm($this->lang->build->confirmDelete, $this->createLink('build', 'delete', "buildID=$buildID&confirm=yes")));
+ }
+ else
+ {
+ $build = $this->build->getById($buildID);
+ $this->build->delete(TABLE_BUILD, $buildID);
+ die(js::locate($this->createLink('project', 'build', "projectID=$build->project"), 'parent'));
+ }
+ }
+
+ /**
+ * AJAX: get builds of a product in html select.
+ *
+ * @param int $productID
+ * @param string $varName the name of the select object to create
+ * @param string $build build to selected
+ * @access public
+ * @return string
+ */
+ public function ajaxGetProductBuilds($productID, $varName, $build = '')
+ {
+ if($varName == 'openedBuild') die(html::select($varName . '[]', $this->build->getProductBuildPairs($productID, 'noempty'), $build, 'size=4 class=select-3 multiple'));
+ if($varName == 'resolvedBuild') die(html::select($varName, $this->build->getProductBuildPairs($productID, 'noempty'), $build, 'class=select-3'));
+ }
+
+ /**
+ * AJAX: get builds of a project in html select.
+ *
+ * @param int $projectID
+ * @param string $varName the name of the select object to create
+ * @param string $build build to selected
+ * @access public
+ * @return string
+ */
+ public function ajaxGetProjectBuilds($projectID, $productID, $varName, $build = '')
+ {
+ if($varName == 'openedBuild') die(html::select($varName . '[]', $this->build->getProjectBuildPairs($projectID, $productID, 'noempty'), $build, 'size=4 class=select-3 multiple'));
+ if($varName == 'resolvedBuild') die(html::select($varName, $this->build->getProjectBuildPairs($projectID, $productID, 'noempty'), $build, 'class=select-3'));
+ if($varName == 'testTaskBuild') die(html::select('build', $this->build->getProjectBuildPairs($projectID, $productID, 'noempty'), $build, 'class=select-3'));
+ }
+}
diff --git a/module/build/lang/en.php b/module/build/lang/en.php
index 3f38c5da77..d1d5cb0daf 100644
--- a/module/build/lang/en.php
+++ b/module/build/lang/en.php
@@ -1,42 +1,42 @@
-
- * @package build
- * @version $Id$
- * @link http://www.zentao.net
- */
-$lang->build->common = 'Build';
-$lang->build->create = "Create";
-$lang->build->edit = "Edit";
-$lang->build->delete = "Delete";
-$lang->build->view = "Info";
-$lang->build->ajaxGetProductBuilds = 'API:Product builds';
-$lang->build->ajaxGetProjectBuilds = 'API:Project builds';
-
-$lang->build->confirmDelete = "Are sure to delete this build?";
-
-$lang->build->basicInfo='Basic Info';
-
-$lang->build->id = 'ID';
-$lang->build->product = 'Product';
-$lang->build->project = 'Project';
-$lang->build->name = 'Name';
-$lang->build->date = 'Build date';
-$lang->build->builder = 'Builder';
-$lang->build->scmPath = 'Source code path';
-$lang->build->filePath = 'Package file path';
-$lang->build->desc = 'Desc';
-$lang->build->linkStoriesAndBugs = 'stories and bugs';
-$lang->build->linkStories = 'Stories';
-$lang->build->linkBugs = 'Bugs';
-$lang->build->stories = 'Linked stories';
-$lang->build->bugs = 'Linked bugs';
-
-$lang->build->finishStories = 'The total demand for a complete %s';
-$lang->build->resolvedBugs = 'The total solution of bug%s';
-
-$lang->build->notice = "Please create a build in project view's build page.";
+
+ * @package build
+ * @version $Id$
+ * @link http://www.zentao.net
+ */
+$lang->build->common = 'Build';
+$lang->build->create = "Create";
+$lang->build->edit = "Edit";
+$lang->build->delete = "Delete";
+$lang->build->view = "Info";
+$lang->build->ajaxGetProductBuilds = 'API:Product builds';
+$lang->build->ajaxGetProjectBuilds = 'API:Project builds';
+
+$lang->build->confirmDelete = "Are sure to delete this build?";
+
+$lang->build->basicInfo='Basic Info';
+
+$lang->build->id = 'ID';
+$lang->build->product = 'Product';
+$lang->build->project = 'Project';
+$lang->build->name = 'Name';
+$lang->build->date = 'Build date';
+$lang->build->builder = 'Builder';
+$lang->build->scmPath = 'Source code path';
+$lang->build->filePath = 'Package file path';
+$lang->build->desc = 'Desc';
+$lang->build->linkStoriesAndBugs = 'stories and bugs';
+$lang->build->linkStories = 'Stories';
+$lang->build->linkBugs = 'Bugs';
+$lang->build->stories = 'Linked stories';
+$lang->build->bugs = 'Linked bugs';
+
+$lang->build->finishStories = 'The total demand for a complete %s';
+$lang->build->resolvedBugs = 'The total solution of bug%s';
+
+$lang->build->notice = "Please create a build in project view's build page.";
diff --git a/module/build/lang/zh-cn.php b/module/build/lang/zh-cn.php
index 8ee155d78a..daa005bb4a 100644
--- a/module/build/lang/zh-cn.php
+++ b/module/build/lang/zh-cn.php
@@ -1,42 +1,42 @@
-
- * @package build
- * @version $Id$
- * @link http://www.zentao.net
- */
-$lang->build->common = "Build";
-$lang->build->create = "创建版本";
-$lang->build->edit = "编辑版本";
-$lang->build->delete = "删除版本";
-$lang->build->view = "版本详情";
-$lang->build->ajaxGetProductBuilds = '接口:产品版本列表';
-$lang->build->ajaxGetProjectBuilds = '接口:项目版本列表';
-
-$lang->build->confirmDelete = "您确认删除该版本吗?";
-
-$lang->build->basicInfo ='基本信息';
-
-$lang->build->id = 'ID';
-$lang->build->product = '产品';
-$lang->build->project = '项目';
-$lang->build->name = '名称编号';
-$lang->build->date = '打包日期';
-$lang->build->builder = '构建者';
-$lang->build->scmPath = '源代码地址';
-$lang->build->filePath = '存储地址';
-$lang->build->desc = '描述';
-$lang->build->linkStoriesAndBugs = '关联需求和Bug';
-$lang->build->linkStories = '相关需求';
-$lang->build->linkBugs = '相关Bug';
-$lang->build->stories = '已关联需求';
-$lang->build->bugs = '已关联Bug';
-
-$lang->build->finishStories = '本次共完成需求%s个';
-$lang->build->resolvedBugs = '本次共解决Bug%s个';
-
-$lang->build->notice = '版本请到[项目视图]-[版本]创建。';
+
+ * @package build
+ * @version $Id$
+ * @link http://www.zentao.net
+ */
+$lang->build->common = "Build";
+$lang->build->create = "创建版本";
+$lang->build->edit = "编辑版本";
+$lang->build->delete = "删除版本";
+$lang->build->view = "版本详情";
+$lang->build->ajaxGetProductBuilds = '接口:产品版本列表';
+$lang->build->ajaxGetProjectBuilds = '接口:项目版本列表';
+
+$lang->build->confirmDelete = "您确认删除该版本吗?";
+
+$lang->build->basicInfo ='基本信息';
+
+$lang->build->id = 'ID';
+$lang->build->product = '产品';
+$lang->build->project = '项目';
+$lang->build->name = '名称编号';
+$lang->build->date = '打包日期';
+$lang->build->builder = '构建者';
+$lang->build->scmPath = '源代码地址';
+$lang->build->filePath = '存储地址';
+$lang->build->desc = '描述';
+$lang->build->linkStoriesAndBugs = '关联需求和Bug';
+$lang->build->linkStories = '相关需求';
+$lang->build->linkBugs = '相关Bug';
+$lang->build->stories = '已关联需求';
+$lang->build->bugs = '已关联Bug';
+
+$lang->build->finishStories = '本次共完成需求%s个';
+$lang->build->resolvedBugs = '本次共解决Bug%s个';
+
+$lang->build->notice = '版本请到[项目视图]-[版本]创建。';
diff --git a/module/build/lang/zh-tw.php b/module/build/lang/zh-tw.php
index a03b301f37..912f63a657 100644
--- a/module/build/lang/zh-tw.php
+++ b/module/build/lang/zh-tw.php
@@ -1,42 +1,42 @@
-
- * @package build
- * @version $Id: zh-tw.php 3309 2012-07-03 02:53:55Z wwccss $
- * @link http://www.zentao.net
- */
-$lang->build->common = "Build";
-$lang->build->create = "創建版本";
-$lang->build->edit = "編輯版本";
-$lang->build->delete = "刪除版本";
-$lang->build->view = "版本詳情";
-$lang->build->ajaxGetProductBuilds = '介面:產品版本列表';
-$lang->build->ajaxGetProjectBuilds = '介面:項目版本列表';
-
-$lang->build->confirmDelete = "您確認刪除該版本嗎?";
-
-$lang->build->basicInfo ='基本信息';
-
-$lang->build->id = 'ID';
-$lang->build->product = '產品';
-$lang->build->project = '項目';
-$lang->build->name = '名稱編號';
-$lang->build->date = '打包日期';
-$lang->build->builder = '構建者';
-$lang->build->scmPath = '原始碼地址';
-$lang->build->filePath = '存儲地址';
-$lang->build->desc = '描述';
-$lang->build->linkStoriesAndBugs = '關聯需求和Bug';
-$lang->build->linkStories = '相關需求';
-$lang->build->linkBugs = '相關Bug';
-$lang->build->stories = '已關聯需求';
-$lang->build->bugs = '已關聯Bug';
-
-$lang->build->finishStories = '本次共完成需求%s個';
-$lang->build->resolvedBugs = '本次共解決Bug%s個';
-
-$lang->build->notice = '版本請到[項目視圖]-[版本]創建。';
+
+ * @package build
+ * @version $Id: zh-tw.php 3309 2012-07-03 02:53:55Z wwccss $
+ * @link http://www.zentao.net
+ */
+$lang->build->common = "Build";
+$lang->build->create = "創建版本";
+$lang->build->edit = "編輯版本";
+$lang->build->delete = "刪除版本";
+$lang->build->view = "版本詳情";
+$lang->build->ajaxGetProductBuilds = '介面:產品版本列表';
+$lang->build->ajaxGetProjectBuilds = '介面:項目版本列表';
+
+$lang->build->confirmDelete = "您確認刪除該版本嗎?";
+
+$lang->build->basicInfo ='基本信息';
+
+$lang->build->id = 'ID';
+$lang->build->product = '產品';
+$lang->build->project = '項目';
+$lang->build->name = '名稱編號';
+$lang->build->date = '打包日期';
+$lang->build->builder = '構建者';
+$lang->build->scmPath = '原始碼地址';
+$lang->build->filePath = '存儲地址';
+$lang->build->desc = '描述';
+$lang->build->linkStoriesAndBugs = '關聯需求和Bug';
+$lang->build->linkStories = '相關需求';
+$lang->build->linkBugs = '相關Bug';
+$lang->build->stories = '已關聯需求';
+$lang->build->bugs = '已關聯Bug';
+
+$lang->build->finishStories = '本次共完成需求%s個';
+$lang->build->resolvedBugs = '本次共解決Bug%s個';
+
+$lang->build->notice = '版本請到[項目視圖]-[版本]創建。';
diff --git a/module/build/model.php b/module/build/model.php
index f03c75a983..cda6824d56 100644
--- a/module/build/model.php
+++ b/module/build/model.php
@@ -1,154 +1,154 @@
-
- * @package build
- * @version $Id$
- * @link http://www.zentao.net
- */
-?>
-dao->select('t1.*, t2.name as projectName, t3.name as productName')
- ->from(TABLE_BUILD)->alias('t1')
- ->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.project = t2.id')
- ->leftJoin(TABLE_PRODUCT)->alias('t3')->on('t1.product = t3.id')
- ->where('t1.id')->eq((int)$buildID)
- ->fetch();
- if(!$build) return false;
- if($setImgSize) $build->desc = $this->loadModel('file')->setImgSize($build->desc);
- return $build;
- }
-
- /**
- * Get builds of a project.
- *
- * @param int $projectID
- * @access public
- * @return array
- */
- public function getProjectBuilds($projectID)
- {
- return $this->dao->select('t1.*, t2.name as projectName, t3.name as productName')
- ->from(TABLE_BUILD)->alias('t1')
- ->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.project = t2.id')
- ->leftJoin(TABLE_PRODUCT)->alias('t3')->on('t1.product = t3.id')
- ->where('t1.project')->eq((int)$projectID)
- ->andWhere('t1.deleted')->eq(0)
- ->orderBy('t1.date DESC, t1.id desc')
- ->fetchAll();
- }
-
- /**
- * Get builds of a project in pairs.
- *
- * @param int $projectID
- * @param int $productID
- * @param string $params noempty|notrunk, can be a set of them
- * @access public
- * @return array
- */
- public function getProjectBuildPairs($projectID, $productID, $params = '')
- {
- $sysBuilds = array();
- if(strpos($params, 'noempty') === false) $sysBuilds = array('' => '');
- if(strpos($params, 'notrunk') === false) $sysBuilds = $sysBuilds + array('trunk' => 'Trunk');
-
- $builds = $this->dao->select('id,name')->from(TABLE_BUILD)
- ->where('project')->eq((int)$projectID)
- ->beginIF($productID)->andWhere('product')->eq((int)$productID)->fi()
- ->andWhere('deleted')->eq(0)
- ->orderBy('date desc, id desc')->fetchPairs();
- if(!$builds) return $sysBuilds;
- $releases = $this->dao->select('build,name')->from(TABLE_RELEASE)
- ->where('build')->in(array_keys($builds))
- ->andWhere('deleted')->eq(0)
- ->fetchPairs();
- foreach($releases as $buildID => $releaseName) $builds[$buildID] = $releaseName;
- return $sysBuilds + $builds;
- }
-
- /**
- * Get builds of a product in pairs.
- *
- * @param mix $products int|array
- * @param string $params noempty|notrunk, can be a set of them
- * @access public
- * @return string
- */
- public function getProductBuildPairs($products, $params = '')
- {
- $sysBuilds = array();
- if(strpos($params, 'noempty') === false) $sysBuilds = array('' => '');
- if(strpos($params, 'notrunk') === false) $sysBuilds = $sysBuilds + array('trunk' => 'Trunk');
-
- $builds = $this->dao->select('id,name')->from(TABLE_BUILD)
- ->where('product')->in($products)
- ->andWhere('deleted')->eq(0)
- ->orderBy('date desc, id desc')->fetchPairs();
- if(!$builds) return $sysBuilds;
- return $sysBuilds + $builds;
- }
-
- /**
- * Create a build
- *
- * @param int $projectID
- * @access public
- * @return void
- */
- public function create($projectID)
- {
- $build->stories = '';
- $build->bugs = '';
-
- $build = fixer::input('post')->stripTags('name')
- ->join('stories', ',')
- ->join('bugs', ',')
- ->remove('allchecker')
- ->add('project', (int)$projectID)->get();
- $this->dao->insert(TABLE_BUILD)->data($build)->autoCheck()->batchCheck($this->config->build->create->requiredFields, 'notempty')->check('name','unique')->exec();
- if(!dao::isError()) return $this->dao->lastInsertID();
- }
-
- /**
- * Update a build.
- *
- * @param int $buildID
- * @access public
- * @return void
- */
- public function update($buildID)
- {
- $oldBuild = $this->getByID($buildID);
- $build = fixer::input('post')
- ->stripTags('name')
- ->setDefault('stories', '')
- ->setDefault('bugs', '')
- ->join('stories', ',')
- ->join('bugs', ',')
- ->remove('allchecker')
- ->get();
- $this->dao->update(TABLE_BUILD)->data($build)
- ->autoCheck()
- ->batchCheck($this->config->build->edit->requiredFields, 'notempty')
- ->where('id')->eq((int)$buildID)
- ->check('name','unique', "id != $buildID")
- ->exec();
- if(!dao::isError()) return common::createChanges($oldBuild, $build);
- }
-}
+
+ * @package build
+ * @version $Id$
+ * @link http://www.zentao.net
+ */
+?>
+dao->select('t1.*, t2.name as projectName, t3.name as productName')
+ ->from(TABLE_BUILD)->alias('t1')
+ ->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.project = t2.id')
+ ->leftJoin(TABLE_PRODUCT)->alias('t3')->on('t1.product = t3.id')
+ ->where('t1.id')->eq((int)$buildID)
+ ->fetch();
+ if(!$build) return false;
+ if($setImgSize) $build->desc = $this->loadModel('file')->setImgSize($build->desc);
+ return $build;
+ }
+
+ /**
+ * Get builds of a project.
+ *
+ * @param int $projectID
+ * @access public
+ * @return array
+ */
+ public function getProjectBuilds($projectID)
+ {
+ return $this->dao->select('t1.*, t2.name as projectName, t3.name as productName')
+ ->from(TABLE_BUILD)->alias('t1')
+ ->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.project = t2.id')
+ ->leftJoin(TABLE_PRODUCT)->alias('t3')->on('t1.product = t3.id')
+ ->where('t1.project')->eq((int)$projectID)
+ ->andWhere('t1.deleted')->eq(0)
+ ->orderBy('t1.date DESC, t1.id desc')
+ ->fetchAll();
+ }
+
+ /**
+ * Get builds of a project in pairs.
+ *
+ * @param int $projectID
+ * @param int $productID
+ * @param string $params noempty|notrunk, can be a set of them
+ * @access public
+ * @return array
+ */
+ public function getProjectBuildPairs($projectID, $productID, $params = '')
+ {
+ $sysBuilds = array();
+ if(strpos($params, 'noempty') === false) $sysBuilds = array('' => '');
+ if(strpos($params, 'notrunk') === false) $sysBuilds = $sysBuilds + array('trunk' => 'Trunk');
+
+ $builds = $this->dao->select('id,name')->from(TABLE_BUILD)
+ ->where('project')->eq((int)$projectID)
+ ->beginIF($productID)->andWhere('product')->eq((int)$productID)->fi()
+ ->andWhere('deleted')->eq(0)
+ ->orderBy('date desc, id desc')->fetchPairs();
+ if(!$builds) return $sysBuilds;
+ $releases = $this->dao->select('build,name')->from(TABLE_RELEASE)
+ ->where('build')->in(array_keys($builds))
+ ->andWhere('deleted')->eq(0)
+ ->fetchPairs();
+ foreach($releases as $buildID => $releaseName) $builds[$buildID] = $releaseName;
+ return $sysBuilds + $builds;
+ }
+
+ /**
+ * Get builds of a product in pairs.
+ *
+ * @param mix $products int|array
+ * @param string $params noempty|notrunk, can be a set of them
+ * @access public
+ * @return string
+ */
+ public function getProductBuildPairs($products, $params = '')
+ {
+ $sysBuilds = array();
+ if(strpos($params, 'noempty') === false) $sysBuilds = array('' => '');
+ if(strpos($params, 'notrunk') === false) $sysBuilds = $sysBuilds + array('trunk' => 'Trunk');
+
+ $builds = $this->dao->select('id,name')->from(TABLE_BUILD)
+ ->where('product')->in($products)
+ ->andWhere('deleted')->eq(0)
+ ->orderBy('date desc, id desc')->fetchPairs();
+ if(!$builds) return $sysBuilds;
+ return $sysBuilds + $builds;
+ }
+
+ /**
+ * Create a build
+ *
+ * @param int $projectID
+ * @access public
+ * @return void
+ */
+ public function create($projectID)
+ {
+ $build->stories = '';
+ $build->bugs = '';
+
+ $build = fixer::input('post')->stripTags('name')
+ ->join('stories', ',')
+ ->join('bugs', ',')
+ ->remove('allchecker')
+ ->add('project', (int)$projectID)->get();
+ $this->dao->insert(TABLE_BUILD)->data($build)->autoCheck()->batchCheck($this->config->build->create->requiredFields, 'notempty')->check('name','unique')->exec();
+ if(!dao::isError()) return $this->dao->lastInsertID();
+ }
+
+ /**
+ * Update a build.
+ *
+ * @param int $buildID
+ * @access public
+ * @return void
+ */
+ public function update($buildID)
+ {
+ $oldBuild = $this->getByID($buildID);
+ $build = fixer::input('post')
+ ->stripTags('name')
+ ->setDefault('stories', '')
+ ->setDefault('bugs', '')
+ ->join('stories', ',')
+ ->join('bugs', ',')
+ ->remove('allchecker')
+ ->get();
+ $this->dao->update(TABLE_BUILD)->data($build)
+ ->autoCheck()
+ ->batchCheck($this->config->build->edit->requiredFields, 'notempty')
+ ->where('id')->eq((int)$buildID)
+ ->check('name','unique', "id != $buildID")
+ ->exec();
+ if(!dao::isError()) return common::createChanges($oldBuild, $build);
+ }
+}
diff --git a/module/build/view/create.html.php b/module/build/view/create.html.php
index 4358abdd74..52cfdfd683 100644
--- a/module/build/view/create.html.php
+++ b/module/build/view/create.html.php
@@ -1,132 +1,132 @@
-
- * @package build
- * @version $Id$
- * @link http://www.zentao.net
- */
-?>
-
-
-
-
-
- build->create;?>
-
- build->product;?>
-
-
-
- build->name;?>
-
-
-
- build->builder;?>
- user->account, 'class="select-3"');?>
-
-
- build->date;?>
-
-
-
- build->scmPath;?>
-
-
-
- build->filePath;?>
-
-
-
- build->linkStoriesAndBugs;?>
-
-
-
-
-
-
-
-
- build->linkStories;?>
-
- idAB;?>
- story->title;?>
- statusAB;?>
- story->stageAB;?>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- build->linkBugs;?>
-
- idAB;?>
- bug->title;?>
- bug->status;?>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- build->desc;?>
-
-
-
-
-
-
+
+ * @package build
+ * @version $Id$
+ * @link http://www.zentao.net
+ */
+?>
+
+
+
+
+
+ build->create;?>
+
+ build->product;?>
+
+
+
+ build->name;?>
+
+
+
+ build->builder;?>
+ user->account, 'class="select-3"');?>
+
+
+ build->date;?>
+
+
+
+ build->scmPath;?>
+
+
+
+ build->filePath;?>
+
+
+
+ build->linkStoriesAndBugs;?>
+
+
+
+
+
+
+
+
+ build->linkStories;?>
+
+ idAB;?>
+ story->title;?>
+ statusAB;?>
+ story->stageAB;?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ build->linkBugs;?>
+
+ idAB;?>
+ bug->title;?>
+ bug->status;?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ build->desc;?>
+
+
+
+
+
+
diff --git a/module/build/view/edit.html.php b/module/build/view/edit.html.php
index 8b9d6dce05..a31eb1f038 100644
--- a/module/build/view/edit.html.php
+++ b/module/build/view/edit.html.php
@@ -1,126 +1,126 @@
-
- * @package build
- * @version $Id$
- * @link http://www.zentao.net
- */
-?>
-
-
-
-
-
- build->edit;?>
-
- build->product;?>
- product, "class='select-3'");?>
-
-
- build->name;?>
- name, "class='text-3'");?>
-
-
- build->builder;?>
- builder, 'class="select-3"');?>
-
-
- build->date;?>
- date, "class='text-3 date'");?>
-
-
- build->scmPath;?>
- scmPath, "class='text-1'");?>
-
-
- build->filePath;?>
- filePath, "class='text-1'");?>
-
-
- build->linkStoriesAndBugs;?>
-
-
-
-
-
-
-
-
- build->linkStories;?>
-
- idAB;?>
- story->title;?>
- statusAB;?>
- story->stageAB;?>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- build->linkBugs;?>
-
- idAB;?>
- bug->title;?>
- bug->status;?>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- build->desc;?>
- desc), "rows='15' class='area-1'");?>
-
- project);?>
-
-
-
+
+ * @package build
+ * @version $Id$
+ * @link http://www.zentao.net
+ */
+?>
+
+
+
+
+
+ build->edit;?>
+
+ build->product;?>
+ product, "class='select-3'");?>
+
+
+ build->name;?>
+ name, "class='text-3'");?>
+
+
+ build->builder;?>
+ builder, 'class="select-3"');?>
+
+
+ build->date;?>
+ date, "class='text-3 date'");?>
+
+
+ build->scmPath;?>
+ scmPath, "class='text-1'");?>
+
+
+ build->filePath;?>
+ filePath, "class='text-1'");?>
+
+
+ build->linkStoriesAndBugs;?>
+
+
+
+
+
+
+
+
+ build->linkStories;?>
+
+ idAB;?>
+ story->title;?>
+ statusAB;?>
+ story->stageAB;?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ build->linkBugs;?>
+
+ idAB;?>
+ bug->title;?>
+ bug->status;?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ build->desc;?>
+ desc), "rows='15' class='area-1'");?>
+
+ project);?>
+
+
+
diff --git a/module/build/view/view.html.php b/module/build/view/view.html.php
index 32736b6a54..530da83f7a 100644
--- a/module/build/view/view.html.php
+++ b/module/build/view/view.html.php
@@ -1,119 +1,119 @@
-
- * @package build
- * @version $Id$
- * @link http://www.zentao.net
- */
-?>
-
-
- '>BUILD #id . ' ' . $build->name;?>
-
-
-
- build->desc;?>
- desc;?>
-
-
-
- session->buildList ? $this->session->buildList : $this->createLink('project', 'build', "projectID=$build->project");
- if(!$build->deleted)
- {
- common::printIcon('build', 'edit', "buildID=$build->id");
- common::printIcon('build', 'delete', "buildID=$build->id", '', 'button', '', 'hiddenwin');
- }
- echo common::printRPN($browseLink);
- ?>
-
-
- build->stories;?>
-
- idAB;?>
- priAB;?>
- story->title;?>
- openedByAB;?>
- story->estimateAB;?>
- statusAB;?>
- story->stageAB;?>
-
- $story):?>
- createLink('story', 'view', "storyID=$story->id");?>
-
- id);?>
- story->priList[$story->pri]?>'>story->priList[$story->pri];?>
- title, '', "class='preview'");?>
- openedBy];?>
- estimate;?>
- story->statusList[$story->status];?>
- story->stageList[$story->stage];?>
-
-
- build->finishStories, count($stories));?>
-
-
- build->bugs;?>
-
- idAB;?>
- bug->title;?>
- bug->status;?>
- openedByAB;?>
- bug->openedDateAB;?>
- bug->resolvedByAB;?>
- bug->resolvedDateAB;?>
-
-
- createLink('bug', 'view', "bugID=$bug->id");?>
-
- id);?>
- title, '', "class='preview'");?>
- bug->statusList[$bug->status];?>
- openedBy];?>
- openedDate, 5, 11)?>
- resolvedBy];?>
- resolvedDate, 5, 11)?>
-
-
- build->resolvedBugs, count($bugs));?>
-
-
-
-
-
- build->basicInfo?>
-
-
- build->product;?>
- productName;?>
-
-
- build->name;?>
- name;?>
-
-
- build->builder;?>
- builder];?>
-
-
- build->date;?>
- date;?>
-
-
- build->scmPath;?>
- scmPath, 'http') === 0 ? printf(html::a($build->scmPath)) : printf($build->scmPath);?>
-
-
- build->filePath;?>
- filePath, 'http') === 0 ? printf(html::a($build->filePath)) : printf($build->filePath);?>
-
-
-
-
-
-
-
+
+ * @package build
+ * @version $Id$
+ * @link http://www.zentao.net
+ */
+?>
+
+
+ '>BUILD #id . ' ' . $build->name;?>
+
+
+
+ build->desc;?>
+ desc;?>
+
+
+
+ session->buildList ? $this->session->buildList : $this->createLink('project', 'build', "projectID=$build->project");
+ if(!$build->deleted)
+ {
+ common::printIcon('build', 'edit', "buildID=$build->id");
+ common::printIcon('build', 'delete', "buildID=$build->id", '', 'button', '', 'hiddenwin');
+ }
+ echo common::printRPN($browseLink);
+ ?>
+
+
+ build->stories;?>
+
+ idAB;?>
+ priAB;?>
+ story->title;?>
+ openedByAB;?>
+ story->estimateAB;?>
+ statusAB;?>
+ story->stageAB;?>
+
+ $story):?>
+ createLink('story', 'view', "storyID=$story->id");?>
+
+ id);?>
+ story->priList[$story->pri]?>'>story->priList[$story->pri];?>
+ title, '', "class='preview'");?>
+ openedBy];?>
+ estimate;?>
+ story->statusList[$story->status];?>
+ story->stageList[$story->stage];?>
+
+
+ build->finishStories, count($stories));?>
+
+
+ build->bugs;?>
+
+ idAB;?>
+ bug->title;?>
+ bug->status;?>
+ openedByAB;?>
+ bug->openedDateAB;?>
+ bug->resolvedByAB;?>
+ bug->resolvedDateAB;?>
+
+
+ createLink('bug', 'view', "bugID=$bug->id");?>
+
+ id);?>
+ title, '', "class='preview'");?>
+ bug->statusList[$bug->status];?>
+ openedBy];?>
+ openedDate, 5, 11)?>
+ resolvedBy];?>
+ resolvedDate, 5, 11)?>
+
+
+ build->resolvedBugs, count($bugs));?>
+
+
+
+
+
+ build->basicInfo?>
+
+
+ build->product;?>
+ productName;?>
+
+
+ build->name;?>
+ name;?>
+
+
+ build->builder;?>
+ builder];?>
+
+
+ build->date;?>
+ date;?>
+
+
+ build->scmPath;?>
+ scmPath, 'http') === 0 ? printf(html::a($build->scmPath)) : printf($build->scmPath);?>
+
+
+ build->filePath;?>
+ filePath, 'http') === 0 ? printf(html::a($build->filePath)) : printf($build->filePath);?>
+
+
+
+
+
+
+
diff --git a/module/common/control.php b/module/common/control.php
index c330e625ee..7a6ffeb040 100644
--- a/module/common/control.php
+++ b/module/common/control.php
@@ -1,414 +1,414 @@
-
- * @package common
- * @version $Id$
- * @link http://www.zentao.net
- */
-class common extends control
-{
- /**
- * The construc method, to do some auto things.
- *
- * @access public
- * @return void
- */
- public function __construct()
- {
- parent::__construct();
- $this->common->startSession();
- $this->common->sendHeader();
- $this->common->setCompany();
- $this->common->setUser();
- $this->common->loadConfigFromDB();
- $this->app->loadLang('company');
- }
-
- /**
- * Check the user has permission to access this method, if not, locate to the login page or deny page.
- *
- * @access public
- * @return void
- */
- public function checkPriv()
- {
- $module = $this->app->getModuleName();
- $method = $this->app->getMethodName();
- if($this->common->isOpenMethod($module, $method)) return true;
- if(!$this->loadModel('user')->isLogon() and $this->server->php_auth_user) $this->user->identifyByPhpAuth();
- if(!$this->loadModel('user')->isLogon() and $this->cookie->za) $this->user->identifyByCookie();
-
- if(isset($this->app->user))
- {
- if(!common::hasPriv($module, $method)) $this->common->deny($module, $method);
- }
- else
- {
- $referer = helper::safe64Encode($this->app->getURI(true));
- $this->locate($this->createLink('user', 'login', "referer=$referer"));
- }
- }
-
- /**
- * Check upgrade's status file is ok or not.
- *
- * @access public
- * @return void
- */
- public function checkUpgradeStatus()
- {
- $statusFile = $this->app->getAppRoot() . 'www' . $this->pathFix . 'ok';
- if(!file_exists($statusFile) or time() - filemtime($statusFile) > 3600)
- {
- $this->app->loadLang('upgrade');
- echo " ";
- echo "";
- printf($this->lang->upgrade->setStatusFile, $statusFile, $statusFile, $statusFile);
- die('
');
- }
- }
-
- /**
- * Check the user has permisson of one method of one module.
- *
- * @param string $module
- * @param string $method
- * @static
- * @access public
- * @return bool
- */
- public static function hasPriv($module, $method)
- {
- global $app;
-
- /* Check is the super admin or not. */
- $account = ',' . $app->user->account . ',';
- if(strpos($app->company->admins, $account) !== false) return true;
-
- /* If not super admin, check the rights. */
- $rights = $app->user->rights;
- if(isset($rights[strtolower($module)][strtolower($method)])) return true;
- return false;
- }
-
- /**
- * Replace the %s of one key of a menu by $params.
- *
- * All the menus are defined in the common's language file. But there're many dynamic params, so in the defination,
- * we used %s as placeholder. These %s should be setted in one module.
- *
- * The items of one module's menu may be an string or array. For example, please see module/common/lang.
- *
- * @param string $object the menus of one module
- * @param string $key the menu item to be replaced
- * @param string $params the params passed to the menu item
- * @access public
- * @return void
- */
- public function setMenuVars($menu, $key, $params)
- {
- if(is_array($params))
- {
- if(is_array($menu->$key))
- {
- $menu->$key = (object)$menu->$key;
- $menu->$key->link = vsprintf($menu->$key->link, $params);
- $menu->$key = (array)$menu->$key;
- }
- else
- {
- $menu->$key = vsprintf($menu->$key, $params);
- }
- }
- else
- {
- if(is_array($menu->$key))
- {
- $menu->$key = (object)$menu->$key;
- $menu->$key->link = sprintf($menu->$key->link, $params);
- $menu->$key = (array)$menu->$key;
- }
- else
- {
- $menu->$key = sprintf($menu->$key, $params);
- }
- }
- }
-
- /**
- * Print the link contains orderBy field.
- *
- * This method will auto set the orderby param according the params. Fox example, if the order by is desc,
- * will be changed to asc.
- *
- * @param string $fieldName the field name to sort by
- * @param string $orderBy the order by string
- * @param string $vars the vars to be passed
- * @param string $label the label of the link
- * @param string $module the module name
- * @param string $method the method name
- * @static
- * @access public
- * @return void
- */
- public static function printOrderLink($fieldName, $orderBy, $vars, $label, $module = '', $method = '')
- {
- global $lang, $app;
- if(empty($module)) $module= $app->getModuleName();
- if(empty($method)) $method= $app->getMethodName();
- $className = 'header';
-
- if(strpos($orderBy, $fieldName) !== false)
- {
- if(stripos($orderBy, 'desc') !== false)
- {
- $orderBy = str_ireplace('desc', 'asc', $orderBy);
- $className = 'headerSortUp';
- }
- elseif(stripos($orderBy, 'asc') !== false)
- {
- $orderBy = str_ireplace('asc', 'desc', $orderBy);
- $className = 'headerSortDown';
- }
- }
- else
- {
- $orderBy = $fieldName . '_' . 'asc';
- $className = 'header';
- }
- $link = helper::createLink($module, $method, sprintf($vars, $orderBy));
- echo "" . html::a($link, $label) . '
';
- }
-
- /**
- * Print link to an modules' methd.
- *
- * Before printing, check the privilege first. If no privilege, return fasle. Else, print the link, return true.
- *
- * @param string $module the module name
- * @param string $method the method
- * @param string $vars vars to be passed
- * @param string $label the label of the link
- * @param string $target the target of the link
- * @param string $misc others
- * @param bool $newline
- * @static
- * @access public
- * @return bool
- */
- public static function printLink($module, $method, $vars = '', $label, $target = '', $misc = '', $newline = true, $onlyBody = false)
- {
- if(!common::hasPriv($module, $method)) return false;
- echo html::a(helper::createLink($module, $method, $vars, '', $onlyBody), $label, $target, $misc, $newline);
- return true;
- }
-
- /**
- * Print icon of split line.
- *
- * @static
- * @access public
- * @return void
- */
- public static function printDivider()
- {
- echo " ";
- }
-
- /**
- * Print icon of comment.
- *
- * @param string $module
- * @static
- * @access public
- * @return void
- */
- public static function printCommentIcon($module)
- {
- global $lang;
-
- if(!common::hasPriv($module, 'edit')) return false;
- echo "";
- echo html::a('#comment', ' ', '', "class='icon-green-common-comment' title='$lang->comment' onclick='setComment()'");
- echo " ";
- }
-
- /**
- * Print link icon.
- *
- * @param string $module
- * @param string $method
- * @param string $vars
- * @param object $object
- * @param string $type button|list
- * @param string $icon
- * @param string $target
- * @static
- * @access public
- * @return void
- */
- public static function printIcon($module, $method, $vars = '', $object = '', $type = 'button', $icon = '', $target = '', $extraClass = '', $onlyBody = false)
- {
- global $app, $lang;
-
- /* Judge the $method of $module clickable or not, default is clickable. */
- $clickable = true;
- if(is_object($object))
- {
- if($app->getModuleName() != $module) $app->control->loadModel($module);
- $modelClass = class_exists("ext{$module}Model") ? "ext{$module}Model" : $module . "Model";
- if(class_exists($modelClass) and is_callable(array($modelClass, 'isClickable')))
- {
- $clickable = call_user_func_array(array($modelClass, 'isClickable'), array('object' => $object, 'method' => $method));
- }
- }
-
- /* Set module and method, then create link to it. */
- if(strtolower($module) == 'testcase' and strtolower($method) == 'createbug') ($module = 'bug') and ($method = 'create');
- if(strtolower($module) == 'story' and strtolower($method) == 'createcase') ($module = 'testcase') and ($method = 'create');
- if(strtolower($module) == 'bug' and strtolower($method) == 'tostory') ($module = 'story') and ($method = 'create');
- if(strtolower($module) == 'bug' and strtolower($method) == 'createcase') ($module = 'testcase') and ($method = 'create');
- if(!common::hasPriv($module, $method)) return false;
- $link = helper::createLink($module, $method, $vars, '', $onlyBody);
-
- /* Set the icon title, try search the $method defination in $module's lang or $common's lang. */
- $title = $method;
- if($method == 'create' and $icon == 'copy') $method = 'copy';
- if(isset($lang->$method) and is_string($lang->$method)) $title = $lang->$method;
- if((isset($lang->$module->$method) or $app->loadLang($module)) and isset($lang->$module->$method))
- {
- $title = $method == 'report' ? $lang->$module->$method->common : $lang->$module->$method;
- }
- if($icon == 'toStory') $title = $lang->bug->toStory;
- if($icon == 'createBug') $title = $lang->testtask->createBug;
-
- /* set the class. */
- if(!$icon) $icon = $method;
- if(strpos(',edit,copy,report,export,delete,', ",$icon,") !== false) $module = 'common';
- $color = $type == 'button' ? 'green' : ($clickable ? 'green' : 'gray');
- $extraClass = strpos(',export,customFields,runCase,results,', ",$method,") !== false ? $method : $extraClass;
- $class = $extraClass ? "icon-$color-$module-$icon $extraClass" : "icon-$color-$module-$icon";
-
- /* Create the icon link. */
- if($clickable)
- {
- if($type == 'button')
- {
- echo "";
- echo html::a($link, ' ', $target, "class='$class' title='$title'", true);
- if($method != 'edit' and $method != 'copy' and $method != 'delete')
- {
- echo html::a($link, $title, $target, "class='$extraClass'", true);
- }
- echo " ";
- }
- else
- {
- echo html::a($link, ' ', $target, "class='$class' title='$title'", false);
- }
- }
- else
- {
- if($type == 'list')
- {
- echo " ";
- }
- }
- }
-
- /**
- * Print backLink and preLink and nextLink.
- *
- * @param string $backLink
- * @param object $preAndNext
- * @access public
- * @return void
- */
- public function printRPN($backLink, $preAndNext = '')
- {
- global $lang;
-
- echo "";
- echo html::a($backLink, ' ', '', "class='icon-goback' title={$lang->goback}");
- echo " ";
-
- if(isset($preAndNext->pre) and $preAndNext->pre)
- {
- $title = isset($preAndNext->pre->title) ? $preAndNext->pre->title : $preAndNext->pre->name;
- $title = '#' . $preAndNext->pre->id . ' ' . $title;
- echo "";
- echo html::a($this->inLink('view', "ID={$preAndNext->pre->id}"), ' ', '', "id='pre' class='icon-pre' title='{$title}'");
- echo " ";
- }
- if(isset($preAndNext->next) and $preAndNext->next)
- {
- $title = isset($preAndNext->next->title) ? $preAndNext->next->title : $preAndNext->next->name;
- $title = '#' . $preAndNext->next->id . ' ' . $title;
- echo "";
- echo html::a($this->inLink('view', "ID={$preAndNext->next->id}"), ' ', '', "id='next' class='icon-next' title='$title'");
- echo " ";
- }
- }
-
- /**
- * Create changes of one object.
- *
- * @param mixed $old the old object
- * @param mixed $new the new object
- * @static
- * @access public
- * @return array
- */
- public static function createChanges($old, $new)
- {
- global $config;
- $changes = array();
- $magicQuote = get_magic_quotes_gpc();
- foreach($new as $key => $value)
- {
- if(strtolower($key) == 'lastediteddate') continue;
- if(strtolower($key) == 'lasteditedby') continue;
- if(strtolower($key) == 'assigneddate') continue;
- if(strtolower($key) == 'editedby') continue;
- if(strtolower($key) == 'editeddate') continue;
-
- if($magicQuote) $value = stripslashes($value);
- if($value != stripslashes($old->$key))
- {
- $diff = '';
- if(substr_count($value, "\n") > 1 or substr_count($old->$key, "\n") > 1 or strpos('name,title,desc,spec,steps,content,digest,verify', strtolower($key)) !== false) $diff = commonModel::diff($old->$key, $value);
- $changes[] = array('field' => $key, 'old' => $old->$key, 'new' => $value, 'diff' => $diff);
- }
- }
- return $changes;
- }
-
- /**
- * Get the full url of the system.
- *
- * @access public
- * @return string
- */
- public function getSysURL()
- {
- $httpType = (isset($_SERVER["HTTPS"]) && $_SERVER["HTTPS"] == 'on') ? 'https' : 'http';
- $httpHost = $_SERVER['HTTP_HOST'];
- return "$httpType://$httpHost";
- }
-
- /**
- * Print the run info.
- *
- * @param mixed $startTime the start time.
- * @access public
- * @return void
- */
- public function printRunInfo($startTime)
- {
- vprintf($this->lang->runInfo, $this->common->getRunInfo($startTime));
- }
-}
+
+ * @package common
+ * @version $Id$
+ * @link http://www.zentao.net
+ */
+class common extends control
+{
+ /**
+ * The construc method, to do some auto things.
+ *
+ * @access public
+ * @return void
+ */
+ public function __construct()
+ {
+ parent::__construct();
+ $this->common->startSession();
+ $this->common->sendHeader();
+ $this->common->setCompany();
+ $this->common->setUser();
+ $this->common->loadConfigFromDB();
+ $this->app->loadLang('company');
+ }
+
+ /**
+ * Check the user has permission to access this method, if not, locate to the login page or deny page.
+ *
+ * @access public
+ * @return void
+ */
+ public function checkPriv()
+ {
+ $module = $this->app->getModuleName();
+ $method = $this->app->getMethodName();
+ if($this->common->isOpenMethod($module, $method)) return true;
+ if(!$this->loadModel('user')->isLogon() and $this->server->php_auth_user) $this->user->identifyByPhpAuth();
+ if(!$this->loadModel('user')->isLogon() and $this->cookie->za) $this->user->identifyByCookie();
+
+ if(isset($this->app->user))
+ {
+ if(!common::hasPriv($module, $method)) $this->common->deny($module, $method);
+ }
+ else
+ {
+ $referer = helper::safe64Encode($this->app->getURI(true));
+ $this->locate($this->createLink('user', 'login', "referer=$referer"));
+ }
+ }
+
+ /**
+ * Check upgrade's status file is ok or not.
+ *
+ * @access public
+ * @return void
+ */
+ public function checkUpgradeStatus()
+ {
+ $statusFile = $this->app->getAppRoot() . 'www' . $this->pathFix . 'ok';
+ if(!file_exists($statusFile) or time() - filemtime($statusFile) > 3600)
+ {
+ $this->app->loadLang('upgrade');
+ echo " ";
+ echo "";
+ printf($this->lang->upgrade->setStatusFile, $statusFile, $statusFile, $statusFile);
+ die('
');
+ }
+ }
+
+ /**
+ * Check the user has permisson of one method of one module.
+ *
+ * @param string $module
+ * @param string $method
+ * @static
+ * @access public
+ * @return bool
+ */
+ public static function hasPriv($module, $method)
+ {
+ global $app;
+
+ /* Check is the super admin or not. */
+ $account = ',' . $app->user->account . ',';
+ if(strpos($app->company->admins, $account) !== false) return true;
+
+ /* If not super admin, check the rights. */
+ $rights = $app->user->rights;
+ if(isset($rights[strtolower($module)][strtolower($method)])) return true;
+ return false;
+ }
+
+ /**
+ * Replace the %s of one key of a menu by $params.
+ *
+ * All the menus are defined in the common's language file. But there're many dynamic params, so in the defination,
+ * we used %s as placeholder. These %s should be setted in one module.
+ *
+ * The items of one module's menu may be an string or array. For example, please see module/common/lang.
+ *
+ * @param string $object the menus of one module
+ * @param string $key the menu item to be replaced
+ * @param string $params the params passed to the menu item
+ * @access public
+ * @return void
+ */
+ public function setMenuVars($menu, $key, $params)
+ {
+ if(is_array($params))
+ {
+ if(is_array($menu->$key))
+ {
+ $menu->$key = (object)$menu->$key;
+ $menu->$key->link = vsprintf($menu->$key->link, $params);
+ $menu->$key = (array)$menu->$key;
+ }
+ else
+ {
+ $menu->$key = vsprintf($menu->$key, $params);
+ }
+ }
+ else
+ {
+ if(is_array($menu->$key))
+ {
+ $menu->$key = (object)$menu->$key;
+ $menu->$key->link = sprintf($menu->$key->link, $params);
+ $menu->$key = (array)$menu->$key;
+ }
+ else
+ {
+ $menu->$key = sprintf($menu->$key, $params);
+ }
+ }
+ }
+
+ /**
+ * Print the link contains orderBy field.
+ *
+ * This method will auto set the orderby param according the params. Fox example, if the order by is desc,
+ * will be changed to asc.
+ *
+ * @param string $fieldName the field name to sort by
+ * @param string $orderBy the order by string
+ * @param string $vars the vars to be passed
+ * @param string $label the label of the link
+ * @param string $module the module name
+ * @param string $method the method name
+ * @static
+ * @access public
+ * @return void
+ */
+ public static function printOrderLink($fieldName, $orderBy, $vars, $label, $module = '', $method = '')
+ {
+ global $lang, $app;
+ if(empty($module)) $module= $app->getModuleName();
+ if(empty($method)) $method= $app->getMethodName();
+ $className = 'header';
+
+ if(strpos($orderBy, $fieldName) !== false)
+ {
+ if(stripos($orderBy, 'desc') !== false)
+ {
+ $orderBy = str_ireplace('desc', 'asc', $orderBy);
+ $className = 'headerSortUp';
+ }
+ elseif(stripos($orderBy, 'asc') !== false)
+ {
+ $orderBy = str_ireplace('asc', 'desc', $orderBy);
+ $className = 'headerSortDown';
+ }
+ }
+ else
+ {
+ $orderBy = $fieldName . '_' . 'asc';
+ $className = 'header';
+ }
+ $link = helper::createLink($module, $method, sprintf($vars, $orderBy));
+ echo "" . html::a($link, $label) . '
';
+ }
+
+ /**
+ * Print link to an modules' methd.
+ *
+ * Before printing, check the privilege first. If no privilege, return fasle. Else, print the link, return true.
+ *
+ * @param string $module the module name
+ * @param string $method the method
+ * @param string $vars vars to be passed
+ * @param string $label the label of the link
+ * @param string $target the target of the link
+ * @param string $misc others
+ * @param bool $newline
+ * @static
+ * @access public
+ * @return bool
+ */
+ public static function printLink($module, $method, $vars = '', $label, $target = '', $misc = '', $newline = true, $onlyBody = false)
+ {
+ if(!common::hasPriv($module, $method)) return false;
+ echo html::a(helper::createLink($module, $method, $vars, '', $onlyBody), $label, $target, $misc, $newline);
+ return true;
+ }
+
+ /**
+ * Print icon of split line.
+ *
+ * @static
+ * @access public
+ * @return void
+ */
+ public static function printDivider()
+ {
+ echo " ";
+ }
+
+ /**
+ * Print icon of comment.
+ *
+ * @param string $module
+ * @static
+ * @access public
+ * @return void
+ */
+ public static function printCommentIcon($module)
+ {
+ global $lang;
+
+ if(!common::hasPriv($module, 'edit')) return false;
+ echo "";
+ echo html::a('#comment', ' ', '', "class='icon-green-common-comment' title='$lang->comment' onclick='setComment()'");
+ echo " ";
+ }
+
+ /**
+ * Print link icon.
+ *
+ * @param string $module
+ * @param string $method
+ * @param string $vars
+ * @param object $object
+ * @param string $type button|list
+ * @param string $icon
+ * @param string $target
+ * @static
+ * @access public
+ * @return void
+ */
+ public static function printIcon($module, $method, $vars = '', $object = '', $type = 'button', $icon = '', $target = '', $extraClass = '', $onlyBody = false)
+ {
+ global $app, $lang;
+
+ /* Judge the $method of $module clickable or not, default is clickable. */
+ $clickable = true;
+ if(is_object($object))
+ {
+ if($app->getModuleName() != $module) $app->control->loadModel($module);
+ $modelClass = class_exists("ext{$module}Model") ? "ext{$module}Model" : $module . "Model";
+ if(class_exists($modelClass) and is_callable(array($modelClass, 'isClickable')))
+ {
+ $clickable = call_user_func_array(array($modelClass, 'isClickable'), array('object' => $object, 'method' => $method));
+ }
+ }
+
+ /* Set module and method, then create link to it. */
+ if(strtolower($module) == 'testcase' and strtolower($method) == 'createbug') ($module = 'bug') and ($method = 'create');
+ if(strtolower($module) == 'story' and strtolower($method) == 'createcase') ($module = 'testcase') and ($method = 'create');
+ if(strtolower($module) == 'bug' and strtolower($method) == 'tostory') ($module = 'story') and ($method = 'create');
+ if(strtolower($module) == 'bug' and strtolower($method) == 'createcase') ($module = 'testcase') and ($method = 'create');
+ if(!common::hasPriv($module, $method)) return false;
+ $link = helper::createLink($module, $method, $vars, '', $onlyBody);
+
+ /* Set the icon title, try search the $method defination in $module's lang or $common's lang. */
+ $title = $method;
+ if($method == 'create' and $icon == 'copy') $method = 'copy';
+ if(isset($lang->$method) and is_string($lang->$method)) $title = $lang->$method;
+ if((isset($lang->$module->$method) or $app->loadLang($module)) and isset($lang->$module->$method))
+ {
+ $title = $method == 'report' ? $lang->$module->$method->common : $lang->$module->$method;
+ }
+ if($icon == 'toStory') $title = $lang->bug->toStory;
+ if($icon == 'createBug') $title = $lang->testtask->createBug;
+
+ /* set the class. */
+ if(!$icon) $icon = $method;
+ if(strpos(',edit,copy,report,export,delete,', ",$icon,") !== false) $module = 'common';
+ $color = $type == 'button' ? 'green' : ($clickable ? 'green' : 'gray');
+ $extraClass = strpos(',export,customFields,runCase,results,', ",$method,") !== false ? $method : $extraClass;
+ $class = $extraClass ? "icon-$color-$module-$icon $extraClass" : "icon-$color-$module-$icon";
+
+ /* Create the icon link. */
+ if($clickable)
+ {
+ if($type == 'button')
+ {
+ echo "";
+ echo html::a($link, ' ', $target, "class='$class' title='$title'", true);
+ if($method != 'edit' and $method != 'copy' and $method != 'delete')
+ {
+ echo html::a($link, $title, $target, "class='$extraClass'", true);
+ }
+ echo " ";
+ }
+ else
+ {
+ echo html::a($link, ' ', $target, "class='$class' title='$title'", false);
+ }
+ }
+ else
+ {
+ if($type == 'list')
+ {
+ echo " ";
+ }
+ }
+ }
+
+ /**
+ * Print backLink and preLink and nextLink.
+ *
+ * @param string $backLink
+ * @param object $preAndNext
+ * @access public
+ * @return void
+ */
+ public function printRPN($backLink, $preAndNext = '')
+ {
+ global $lang;
+
+ echo "";
+ echo html::a($backLink, ' ', '', "class='icon-goback' title={$lang->goback}");
+ echo " ";
+
+ if(isset($preAndNext->pre) and $preAndNext->pre)
+ {
+ $title = isset($preAndNext->pre->title) ? $preAndNext->pre->title : $preAndNext->pre->name;
+ $title = '#' . $preAndNext->pre->id . ' ' . $title;
+ echo "";
+ echo html::a($this->inLink('view', "ID={$preAndNext->pre->id}"), ' ', '', "id='pre' class='icon-pre' title='{$title}'");
+ echo " ";
+ }
+ if(isset($preAndNext->next) and $preAndNext->next)
+ {
+ $title = isset($preAndNext->next->title) ? $preAndNext->next->title : $preAndNext->next->name;
+ $title = '#' . $preAndNext->next->id . ' ' . $title;
+ echo "";
+ echo html::a($this->inLink('view', "ID={$preAndNext->next->id}"), ' ', '', "id='next' class='icon-next' title='$title'");
+ echo " ";
+ }
+ }
+
+ /**
+ * Create changes of one object.
+ *
+ * @param mixed $old the old object
+ * @param mixed $new the new object
+ * @static
+ * @access public
+ * @return array
+ */
+ public static function createChanges($old, $new)
+ {
+ global $config;
+ $changes = array();
+ $magicQuote = get_magic_quotes_gpc();
+ foreach($new as $key => $value)
+ {
+ if(strtolower($key) == 'lastediteddate') continue;
+ if(strtolower($key) == 'lasteditedby') continue;
+ if(strtolower($key) == 'assigneddate') continue;
+ if(strtolower($key) == 'editedby') continue;
+ if(strtolower($key) == 'editeddate') continue;
+
+ if($magicQuote) $value = stripslashes($value);
+ if($value != stripslashes($old->$key))
+ {
+ $diff = '';
+ if(substr_count($value, "\n") > 1 or substr_count($old->$key, "\n") > 1 or strpos('name,title,desc,spec,steps,content,digest,verify', strtolower($key)) !== false) $diff = commonModel::diff($old->$key, $value);
+ $changes[] = array('field' => $key, 'old' => $old->$key, 'new' => $value, 'diff' => $diff);
+ }
+ }
+ return $changes;
+ }
+
+ /**
+ * Get the full url of the system.
+ *
+ * @access public
+ * @return string
+ */
+ public function getSysURL()
+ {
+ $httpType = (isset($_SERVER["HTTPS"]) && $_SERVER["HTTPS"] == 'on') ? 'https' : 'http';
+ $httpHost = $_SERVER['HTTP_HOST'];
+ return "$httpType://$httpHost";
+ }
+
+ /**
+ * Print the run info.
+ *
+ * @param mixed $startTime the start time.
+ * @access public
+ * @return void
+ */
+ public function printRunInfo($startTime)
+ {
+ vprintf($this->lang->runInfo, $this->common->getRunInfo($startTime));
+ }
+}
diff --git a/module/common/lang/en.php b/module/common/lang/en.php
index b750dcdb98..ae77c6d4a8 100644
--- a/module/common/lang/en.php
+++ b/module/common/lang/en.php
@@ -1,395 +1,395 @@
-
- * @package ZenTaoPMS
- * @version $Id$
- * @link http://www.zentao.net
- */
-$lang->arrow = ' ';
-$lang->colon = '::';
-$lang->comma = ',';
-$lang->dot = '.';
-$lang->at = ' at ';
-$lang->downArrow = '↓';
-
-$lang->ZenTaoPMS = 'ZenTaoPMS';
-$lang->welcome = "Welcome to『%s』{$lang->colon} {$lang->ZenTaoPMS}";
-$lang->myControl = "Dashboard";
-$lang->currentPos = 'Current';
-$lang->logout = 'Logout';
-$lang->login = 'Login';
-$lang->aboutZenTao = 'About';
-$lang->todayIs = '%s, ';
-$lang->runInfo = "Time: %s ms, Memory: %s KB, Queries: %s.
";
-
-$lang->reset = 'Reset';
-$lang->edit = 'Edit';
-$lang->copy = 'Copy';
-$lang->delete = 'Delete';
-$lang->close = 'Close';
-$lang->link = 'Link';
-$lang->unlink = 'Unlink';
-$lang->import = 'Import';
-$lang->export = 'Export';
-$lang->exportType = 'Exprot Type';
-$lang->setFileName = 'Filename:';
-$lang->activate = 'Activate';
-$lang->submitting = 'Saving...';
-$lang->save = 'Save';
-$lang->confirm = 'Confirm';
-$lang->preview = 'View';
-$lang->goback = 'Back';
-$lang->go = 'GO';
-$lang->more = 'More';
-
-$lang->actions = 'Actions';
-$lang->comment = 'Comment';
-$lang->history = 'History';
-$lang->attatch = 'Attatch';
-$lang->reverse = 'Reverse';
-$lang->switchDisplay= 'Toggle Show';
-$lang->switchHelp = 'Toggle Help';
-$lang->addFiles = 'Add Files';
-$lang->files = 'Files ';
-$lang->unfold = '+';
-$lang->fold = '-';
-
-$lang->selectAll = 'Select All';
-$lang->selectReverse = 'Select Reverse';
-$lang->notFound = 'Sorry, the object not found.';
-$lang->showAll = '++ Show All ++';
-$lang->hideClosed = '-- Show Progressing --';
-
-$lang->future = 'Future';
-$lang->year = 'Year';
-$lang->workingHour = 'Hour';
-
-$lang->idAB = 'ID';
-$lang->priAB = 'P';
-$lang->statusAB = 'Status';
-$lang->openedByAB = 'Open';
-$lang->assignedToAB = 'To';
-$lang->typeAB = 'Type';
-
-$lang->common = new stdclass();
-$lang->common->common = 'Common module';
-
-/* The main menu. */
-$lang->menu = new stdclass();
-$lang->menu->my = ' Dashboard|my|index';
-$lang->menu->product = 'Product|product|index';
-$lang->menu->project = 'Project|project|index';
-$lang->menu->qa = 'Test|qa|index';
-$lang->menu->doc = 'Doc|doc|index';
-$lang->menu->report = 'Report|report|index';
-$lang->menu->webapp = 'Web App|webapp|index';
-$lang->menu->company = 'Company|company|index';
-$lang->menu->admin = 'Admin|admin|index';
-
-/* The objects in the search box. */
-$lang->searchObjects['bug'] = 'Bug';
-$lang->searchObjects['story'] = 'Story';
-$lang->searchObjects['task'] = 'Task';
-$lang->searchObjects['testcase'] = 'Test Case';
-$lang->searchObjects['project'] = 'Project';
-$lang->searchObjects['product'] = 'Product';
-$lang->searchObjects['user'] = 'User';
-$lang->searchObjects['build'] = 'Build';
-$lang->searchObjects['release'] = 'Release';
-$lang->searchObjects['productplan'] = 'Plan';
-$lang->searchObjects['testtask'] = 'Test Task';
-$lang->searchObjects['doc'] = 'Doc';
-$lang->searchTips = 'Id here(ctrl+g)';
-
-/* Encode list of impot. */
-$lang->importEncodeList['gbk'] = 'GBK';
-$lang->importEncodeList['big5'] = 'BIG5';
-$lang->importEncodeList['utf-8'] = 'UTF-8';
-
-/* File type of export. */
-$lang->exportFileTypeList['csv'] = 'csv';
-$lang->exportFileTypeList['xml'] = 'xml';
-$lang->exportFileTypeList['html'] = 'html';
-
-$lang->exportTypeList['all'] = 'Export ALL';
-$lang->exportTypeList['selected'] = 'Export Checked';
-
-/* Support charset. */
-$lang->exportEncodeList['gbk'] = 'GBK';
-$lang->exportEncodeList['big5'] = 'BIG5';
-$lang->exportEncodeList['utf-8'] = 'UTF-8';
-
-/* Themes. */
-$lang->themes['default'] = 'Default';
-$lang->themes['green'] = 'Green';
-$lang->themes['red'] = 'Red';
-$lang->themes['classblue'] = 'Blue';
-
-/* Index mododule menu. */
-$lang->index = new stdclass();
-$lang->index->menu = new stdclass();
-
-$lang->index->menu->product = 'Products|product|browse';
-$lang->index->menu->project = 'Projects|project|browse';
-
-/* Dashboard menu. */
-$lang->my = new stdclass();
-$lang->my->menu = new stdclass();
-
-$lang->my->menu->account = ' %s' . $lang->arrow;
-$lang->my->menu->index = 'Index|my|index';
-$lang->my->menu->todo = array('link' => 'Todo|my|todo|', 'subModule' => 'todo');
-$lang->my->menu->task = 'Task|my|task|';
-$lang->my->menu->bug = 'Bug|my|bug|';
-$lang->my->menu->testtask = array('link' => 'Test|my|testtask|', 'alias' => 'testcase');
-$lang->my->menu->story = 'Story|my|story|';
-$lang->my->menu->myProject = 'Project|my|project|';
-$lang->my->menu->dynamic = 'Dynamic|my|dynamic|';
-$lang->my->menu->profile = array('link' => 'Profile|my|profile|', 'alias' => 'editprofile');
-$lang->my->menu->changePassword = 'Change Password|my|changepassword|';
-
-$lang->todo = new stdclass();
-$lang->todo->menu = $lang->my->menu;
-
-/* Product menu. */
-$lang->product = new stdclass();
-$lang->product->menu = new stdclass();
-
-$lang->product->menu->list = '%s';
-$lang->product->menu->story = array('link' => 'Story|product|browse|productID=%s', 'alias' => 'batchedit', 'subModule' => 'story');
-$lang->product->menu->dynamic = 'Dynamic|product|dynamic|productID=%s';
-$lang->product->menu->plan = array('link' => 'Plan|productplan|browse|productID=%s', 'subModule' => 'productplan');
-$lang->product->menu->release = array('link' => 'Release|release|browse|productID=%s', 'subModule' => 'release');
-$lang->product->menu->roadmap = 'Roadmap|product|roadmap|productID=%s';
-$lang->product->menu->doc = array('link' => 'Doc|product|doc|productID=%s', 'subModule' => 'doc');
-$lang->product->menu->view = array('link' => 'Manage|product|view|productID=%s', 'alias' => 'edit');
-$lang->product->menu->module = 'Modules|tree|browse|productID=%s&view=story';
-$lang->product->menu->project = 'Projects|product|project|status=all&productID=%s';
-$lang->product->menu->order = 'Order|product|order|productID=%s';
-$lang->product->menu->create = array('link' => ' New|product|create', 'float' => 'right');
-$lang->product->menu->all = array('link' => ' All|product|index|locate=no&productID=%s', 'float' => 'right');
-
-$lang->story = new stdclass();
-$lang->productplan = new stdclass();
-$lang->release = new stdclass();
-
-$lang->story->menu = $lang->product->menu;
-$lang->productplan->menu = $lang->product->menu;
-$lang->release->menu = $lang->product->menu;
-
-/* Project menu. */
-$lang->project = new stdclass();
-$lang->project->menu = new stdclass();
-
-$lang->project->menu->list = '%s';
-$lang->project->menu->task = array('link' => 'Task|project|task|projectID=%s', 'subModule' => 'task', 'alias' => 'grouptask,importtask,importbug,burn');
-$lang->project->menu->story = array('link' => 'Story|project|story|projectID=%s', 'subModule' => 'story', 'alias' => 'linkstory');
-$lang->project->menu->bug = 'Bug|project|bug|projectID=%s';
-$lang->project->menu->dynamic = 'Dynamic|project|dynamic|projectID=%s';
-$lang->project->menu->build = array('link' => 'Build|project|build|projectID=%s', 'subModule' => 'build');
-$lang->project->menu->testtask = 'Testtask|project|testtask|projectID=%s';
-$lang->project->menu->team = array('link' => 'Team|project|team|projectID=%s', 'alias' => 'managemembers');
-$lang->project->menu->doc = array('link' => 'Doc|project|doc|porjectID=%s', 'subModule' => 'doc');
-$lang->project->menu->product = array('link' => 'Product|project|manageproducts|projectID=%s', 'alias' => 'edit,start,suspend,delay,close');
-$lang->project->menu->view = 'Manage|project|view|projectID=%s';
-$lang->project->menu->order = 'Order|project|order|projectID=%s';
-$lang->project->menu->create = array('link' => ' New|project|create', 'float' => 'right');
-$lang->project->menu->all = array('link' => ' Projects|project|index|locate=no&status=all&projectID=%s', 'float' => 'right');
-
-$lang->task = new stdclass();
-$lang->build = new stdclass();
-$lang->task->menu = $lang->project->menu;
-$lang->build->menu = $lang->project->menu;
-
-/* QA menu. */
-$lang->bug = new stdclass();
-$lang->bug->menu = new stdclass();
-
-$lang->bug->menu->product = '%s';
-$lang->bug->menu->bug = array('link' => 'Bug|bug|browse|productID=%s', 'alias' => 'view,create,edit,resolve,close,activate,report,batchedit,confirmbug,assignto', 'subModule' => 'tree');
-$lang->bug->menu->testcase = array('link' => 'Test Case|testcase|browse|productID=%s', 'alias' => 'view,create,edit');
-$lang->bug->menu->testtask = array('link' => 'Test Task|testtask|browse|productID=%s');
-
-$lang->testcase = new stdclass();
-$lang->testcase->menu = new stdclass();
-
-$lang->testcase->menu->product = '%s';
-$lang->testcase->menu->bug = array('link' => 'Bug|bug|browse|productID=%s');
-$lang->testcase->menu->testcase = array('link' => 'Test Case|testcase|browse|productID=%s', 'alias' => 'view,create,batchcreate,edit,batchedit', 'subModule' => 'tree');
-$lang->testcase->menu->testtask = array('link' => 'Test Task|testtask|browse|productID=%s', 'alias' => 'view,create,edit,linkcase,cases');
-
-$lang->testtask = new stdclass();
-$lang->testtask->menu = $lang->testcase->menu;
-
-/* Doc menu. */
-$lang->doc = new stdclass();
-$lang->doc->menu = new stdclass();
-
-$lang->doc->menu->list = '%s';
-$lang->doc->menu->browse = array('link' => 'Doc|doc|browse|libID=%s', 'alias' => 'view,create,edit');
-$lang->doc->menu->edit = 'Edit Library|doc|editLib|libID=%s';
-$lang->doc->menu->module = 'Modules|tree|browse|libID=%s&viewType=doc';
-$lang->doc->menu->delete = array('link' => 'Delete Library|doc|deleteLib|libID=%s', 'target' => 'hiddenwin');
-$lang->doc->menu->create = array('link' => ' New Library|doc|createLib', 'float' => 'right');
-
-/* Report menu. */
-$lang->report = new stdclass();
-$lang->report->menu = new stdclass();
-
-$lang->report->menu->product = array('link' => 'Product|report|productinfo');
-$lang->report->menu->prj = array('link' => 'Project|report|projectdeviation');
-$lang->report->menu->test = array('link' => 'Test|report|bugsummary', 'alias' => 'bugassign');
-$lang->report->menu->staff = array('link' => 'Company|report|workload');
-
-/* Resource menu. */
-$lang->webapp = new stdclass();
-$lang->webapp->menu = new stdclass();
-$lang->webapp->menu->obtain = array('link' => 'App Store|webapp|obtain');
-
-/* Company menu. */
-$lang->company = new stdclass();
-$lang->company->menu = new stdclass();
-$lang->company->menu->name = '%s' . $lang->arrow;
-$lang->company->menu->browseUser = array('link' => 'Users|company|browse', 'subModule' => 'user');
-$lang->company->menu->dept = array('link' => 'Department|dept|browse', 'subModule' => 'dept');
-$lang->company->menu->browseGroup = array('link' => 'Group|group|browse', 'subModule' => 'group');
-$lang->company->menu->edit = array('link' => 'Company|company|edit');
-$lang->company->menu->dynamic = 'Dynamic|company|dynamic|';
-$lang->company->menu->addGroup = array('link' => ' Add Group|group|create', 'float' => 'right');
-$lang->company->menu->batchAddUser = array('link' => ' Batch Add|user|batchCreate', 'subModule' => 'user', 'float' => 'right');
-$lang->company->menu->addUser = array('link' => ' Add User|user|create|dept=%s&from=company', 'subModule' => 'user', 'float' => 'right');
-
-$lang->dept = new stdclass();
-$lang->group = new stdclass();
-$lang->user = new stdclass();
-
-$lang->dept->menu = $lang->company->menu;
-$lang->group->menu = $lang->company->menu;
-$lang->user->menu = $lang->company->menu;
-
-/* Admin menu. */
-$lang->admin = new stdclass();
-$lang->admin->menu = new stdclass();
-$lang->admin->menu->index = array('link' => 'Index|admin|index');
-$lang->admin->menu->extension = array('link' => 'Extension|extension|browse', 'subModule' => 'extension');
-$lang->admin->menu->editor = array('link' => 'Scaffold|editor|index', 'subModule' => 'editor');
-$lang->admin->menu->mail = array('link' => 'Email|mail|index', 'subModule' => 'mail');
-$lang->admin->menu->convert = array('link' => 'Import|convert|index', 'subModule' => 'convert');
-$lang->admin->menu->trashes = array('link' => 'Trash|action|trash', 'subModule' => 'action');
-
-$lang->convert = new stdclass();
-$lang->upgrade = new stdclass();
-$lang->action = new stdclass();
-$lang->extension = new stdclass();
-$lang->editor = new stdclass();
-$lang->mail = new stdclass();
-
-$lang->convert->menu = $lang->admin->menu;
-$lang->upgrade->menu = $lang->admin->menu;
-$lang->action->menu = $lang->admin->menu;
-$lang->extension->menu = $lang->admin->menu;
-$lang->editor->menu = $lang->admin->menu;
-$lang->mail->menu = $lang->admin->menu;
-
-/* Groups. */
-$lang->menugroup = new stdclass();
-$lang->menugroup->release = 'product';
-$lang->menugroup->story = 'product';
-$lang->menugroup->productplan = 'product';
-$lang->menugroup->task = 'project';
-$lang->menugroup->build = 'project';
-$lang->menugroup->convert = 'admin';
-$lang->menugroup->upgrade = 'admin';
-$lang->menugroup->user = 'company';
-$lang->menugroup->group = 'company';
-$lang->menugroup->bug = 'qa';
-$lang->menugroup->testcase = 'qa';
-$lang->menugroup->testtask = 'qa';
-$lang->menugroup->people = 'company';
-$lang->menugroup->dept = 'company';
-$lang->menugroup->todo = 'my';
-$lang->menugroup->action = 'admin';
-$lang->menugroup->extension = 'admin';
-$lang->menugroup->editor = 'admin';
-$lang->menugroup->mail = 'admin';
-
-/* Error info. */
-$lang->error = new stdclass();
-$lang->error->companyNotFound = "The domain %s does not exist.";
-$lang->error->length = array("『%s』length should be『%s』", "『%s』length should between『%s』and 『%s』.");
-$lang->error->reg = "『%s』should like『%s』";
-$lang->error->unique = "『%s』has『%s』already. If you are sure this record has been deleted, you can restore it in admin panel, trash page.";
-$lang->error->gt = "『%s』must greater than『%s』.";
-$lang->error->ge = "『%s』must greater than or equal『%s』.";
-$lang->error->notempty = "『%s』can not be empty.";
-$lang->error->empty = "『%s』 must be empty.";
-$lang->error->equal = "『%s』must be『%s』.";
-$lang->error->int = array("『%s』should be interger", "『%s』should between『%s-%s』.");
-$lang->error->float = "『%s』should be a interger or float.";
-$lang->error->email = "『%s』should be email.";
-$lang->error->date = "『%s』should be date";
-$lang->error->account = "『%s』should be a valid account.";
-$lang->error->passwordsame = "Two passwords must be the same";
-$lang->error->passwordrule = "Password should more than six letters.";
-$lang->error->accessDenied = 'No purview';
-
-/* Pager. */
-$lang->pager = new stdclass();
-$lang->pager->noRecord = "No records yet.";
-$lang->pager->digest = "%s records, %s per page, %s/%s ";
-$lang->pager->first = "First";
-$lang->pager->pre = "Previous";
-$lang->pager->next = "Next";
-$lang->pager->last = "Last";
-$lang->pager->locate = "GO!";
-
-$lang->zentaoSite = "Official Site";
-$lang->chinaScrum = "Scrum community ";
-$lang->agileTraining = "Training ";
-$lang->donate = "Donate ";
-$lang->proVersion = "Try pro version! ";
-$lang->downNotify = "Down notify";
-
-$lang->suhosinInfo = "Warming:data is too large! Please enlarge the setting of sohusin.post.max_vars and sohusin.request.max_vars in php.ini. Otherwise partial data can't be saved.";
-
-$lang->noResultsMatch = "No results match";
-
-/* Date times. */
-define('DT_DATETIME1', 'Y-m-d H:i:s');
-define('DT_DATETIME2', 'y-m-d H:i');
-define('DT_MONTHTIME1', 'n/d H:i');
-define('DT_MONTHTIME2', 'F j, H:i');
-define('DT_DATE1', 'Y-m-d');
-define('DT_DATE2', 'Ymd');
-define('DT_DATE3', 'F j, Y ');
-define('DT_DATE4', 'M j');
-define('DT_TIME1', 'H:i:s');
-define('DT_TIME2', 'H:i');
-
-/* datepicker 时间*/
-$lang->datepicker = new stdclass();
-
-$lang->datepicker->dpText = new stdclass();
-$lang->datepicker->dpText->TEXT_OR = 'Or ';
-$lang->datepicker->dpText->TEXT_PREV_YEAR = 'Last year';
-$lang->datepicker->dpText->TEXT_PREV_MONTH = 'Last month';
-$lang->datepicker->dpText->TEXT_PREV_WEEK = 'Last week';
-$lang->datepicker->dpText->TEXT_YESTERDAY = 'Yesterday';
-$lang->datepicker->dpText->TEXT_THIS_MONTH = 'This month';
-$lang->datepicker->dpText->TEXT_THIS_WEEK = 'This week';
-$lang->datepicker->dpText->TEXT_TODAY = 'Today';
-$lang->datepicker->dpText->TEXT_NEXT_YEAR = 'Next year';
-$lang->datepicker->dpText->TEXT_NEXT_MONTH = 'Next month';
-$lang->datepicker->dpText->TEXT_CLOSE = 'Close';
-$lang->datepicker->dpText->TEXT_DATE = 'Please select date range';
-$lang->datepicker->dpText->TEXT_CHOOSE_DATE = 'Choose date';
-
-$lang->datepicker->dayNames = array('Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday');
-$lang->datepicker->abbrDayNames = array('Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat');
-$lang->datepicker->monthNames = array('January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December');
-
-include (dirname(__FILE__) . '/menuOrder.php');
+
+ * @package ZenTaoPMS
+ * @version $Id$
+ * @link http://www.zentao.net
+ */
+$lang->arrow = ' ';
+$lang->colon = '::';
+$lang->comma = ',';
+$lang->dot = '.';
+$lang->at = ' at ';
+$lang->downArrow = '↓';
+
+$lang->ZenTaoPMS = 'ZenTaoPMS';
+$lang->welcome = "Welcome to『%s』{$lang->colon} {$lang->ZenTaoPMS}";
+$lang->myControl = "Dashboard";
+$lang->currentPos = 'Current';
+$lang->logout = 'Logout';
+$lang->login = 'Login';
+$lang->aboutZenTao = 'About';
+$lang->todayIs = '%s, ';
+$lang->runInfo = "Time: %s ms, Memory: %s KB, Queries: %s.
";
+
+$lang->reset = 'Reset';
+$lang->edit = 'Edit';
+$lang->copy = 'Copy';
+$lang->delete = 'Delete';
+$lang->close = 'Close';
+$lang->link = 'Link';
+$lang->unlink = 'Unlink';
+$lang->import = 'Import';
+$lang->export = 'Export';
+$lang->exportType = 'Exprot Type';
+$lang->setFileName = 'Filename:';
+$lang->activate = 'Activate';
+$lang->submitting = 'Saving...';
+$lang->save = 'Save';
+$lang->confirm = 'Confirm';
+$lang->preview = 'View';
+$lang->goback = 'Back';
+$lang->go = 'GO';
+$lang->more = 'More';
+
+$lang->actions = 'Actions';
+$lang->comment = 'Comment';
+$lang->history = 'History';
+$lang->attatch = 'Attatch';
+$lang->reverse = 'Reverse';
+$lang->switchDisplay= 'Toggle Show';
+$lang->switchHelp = 'Toggle Help';
+$lang->addFiles = 'Add Files';
+$lang->files = 'Files ';
+$lang->unfold = '+';
+$lang->fold = '-';
+
+$lang->selectAll = 'Select All';
+$lang->selectReverse = 'Select Reverse';
+$lang->notFound = 'Sorry, the object not found.';
+$lang->showAll = '++ Show All ++';
+$lang->hideClosed = '-- Show Progressing --';
+
+$lang->future = 'Future';
+$lang->year = 'Year';
+$lang->workingHour = 'Hour';
+
+$lang->idAB = 'ID';
+$lang->priAB = 'P';
+$lang->statusAB = 'Status';
+$lang->openedByAB = 'Open';
+$lang->assignedToAB = 'To';
+$lang->typeAB = 'Type';
+
+$lang->common = new stdclass();
+$lang->common->common = 'Common module';
+
+/* The main menu. */
+$lang->menu = new stdclass();
+$lang->menu->my = ' Dashboard|my|index';
+$lang->menu->product = 'Product|product|index';
+$lang->menu->project = 'Project|project|index';
+$lang->menu->qa = 'Test|qa|index';
+$lang->menu->doc = 'Doc|doc|index';
+$lang->menu->report = 'Report|report|index';
+$lang->menu->webapp = 'Web App|webapp|index';
+$lang->menu->company = 'Company|company|index';
+$lang->menu->admin = 'Admin|admin|index';
+
+/* The objects in the search box. */
+$lang->searchObjects['bug'] = 'Bug';
+$lang->searchObjects['story'] = 'Story';
+$lang->searchObjects['task'] = 'Task';
+$lang->searchObjects['testcase'] = 'Test Case';
+$lang->searchObjects['project'] = 'Project';
+$lang->searchObjects['product'] = 'Product';
+$lang->searchObjects['user'] = 'User';
+$lang->searchObjects['build'] = 'Build';
+$lang->searchObjects['release'] = 'Release';
+$lang->searchObjects['productplan'] = 'Plan';
+$lang->searchObjects['testtask'] = 'Test Task';
+$lang->searchObjects['doc'] = 'Doc';
+$lang->searchTips = 'Id here(ctrl+g)';
+
+/* Encode list of impot. */
+$lang->importEncodeList['gbk'] = 'GBK';
+$lang->importEncodeList['big5'] = 'BIG5';
+$lang->importEncodeList['utf-8'] = 'UTF-8';
+
+/* File type of export. */
+$lang->exportFileTypeList['csv'] = 'csv';
+$lang->exportFileTypeList['xml'] = 'xml';
+$lang->exportFileTypeList['html'] = 'html';
+
+$lang->exportTypeList['all'] = 'Export ALL';
+$lang->exportTypeList['selected'] = 'Export Checked';
+
+/* Support charset. */
+$lang->exportEncodeList['gbk'] = 'GBK';
+$lang->exportEncodeList['big5'] = 'BIG5';
+$lang->exportEncodeList['utf-8'] = 'UTF-8';
+
+/* Themes. */
+$lang->themes['default'] = 'Default';
+$lang->themes['green'] = 'Green';
+$lang->themes['red'] = 'Red';
+$lang->themes['classblue'] = 'Blue';
+
+/* Index mododule menu. */
+$lang->index = new stdclass();
+$lang->index->menu = new stdclass();
+
+$lang->index->menu->product = 'Products|product|browse';
+$lang->index->menu->project = 'Projects|project|browse';
+
+/* Dashboard menu. */
+$lang->my = new stdclass();
+$lang->my->menu = new stdclass();
+
+$lang->my->menu->account = ' %s' . $lang->arrow;
+$lang->my->menu->index = 'Index|my|index';
+$lang->my->menu->todo = array('link' => 'Todo|my|todo|', 'subModule' => 'todo');
+$lang->my->menu->task = 'Task|my|task|';
+$lang->my->menu->bug = 'Bug|my|bug|';
+$lang->my->menu->testtask = array('link' => 'Test|my|testtask|', 'alias' => 'testcase');
+$lang->my->menu->story = 'Story|my|story|';
+$lang->my->menu->myProject = 'Project|my|project|';
+$lang->my->menu->dynamic = 'Dynamic|my|dynamic|';
+$lang->my->menu->profile = array('link' => 'Profile|my|profile|', 'alias' => 'editprofile');
+$lang->my->menu->changePassword = 'Change Password|my|changepassword|';
+
+$lang->todo = new stdclass();
+$lang->todo->menu = $lang->my->menu;
+
+/* Product menu. */
+$lang->product = new stdclass();
+$lang->product->menu = new stdclass();
+
+$lang->product->menu->list = '%s';
+$lang->product->menu->story = array('link' => 'Story|product|browse|productID=%s', 'alias' => 'batchedit', 'subModule' => 'story');
+$lang->product->menu->dynamic = 'Dynamic|product|dynamic|productID=%s';
+$lang->product->menu->plan = array('link' => 'Plan|productplan|browse|productID=%s', 'subModule' => 'productplan');
+$lang->product->menu->release = array('link' => 'Release|release|browse|productID=%s', 'subModule' => 'release');
+$lang->product->menu->roadmap = 'Roadmap|product|roadmap|productID=%s';
+$lang->product->menu->doc = array('link' => 'Doc|product|doc|productID=%s', 'subModule' => 'doc');
+$lang->product->menu->view = array('link' => 'Manage|product|view|productID=%s', 'alias' => 'edit');
+$lang->product->menu->module = 'Modules|tree|browse|productID=%s&view=story';
+$lang->product->menu->project = 'Projects|product|project|status=all&productID=%s';
+$lang->product->menu->order = 'Order|product|order|productID=%s';
+$lang->product->menu->create = array('link' => ' New|product|create', 'float' => 'right');
+$lang->product->menu->all = array('link' => ' All|product|index|locate=no&productID=%s', 'float' => 'right');
+
+$lang->story = new stdclass();
+$lang->productplan = new stdclass();
+$lang->release = new stdclass();
+
+$lang->story->menu = $lang->product->menu;
+$lang->productplan->menu = $lang->product->menu;
+$lang->release->menu = $lang->product->menu;
+
+/* Project menu. */
+$lang->project = new stdclass();
+$lang->project->menu = new stdclass();
+
+$lang->project->menu->list = '%s';
+$lang->project->menu->task = array('link' => 'Task|project|task|projectID=%s', 'subModule' => 'task', 'alias' => 'grouptask,importtask,importbug,burn');
+$lang->project->menu->story = array('link' => 'Story|project|story|projectID=%s', 'subModule' => 'story', 'alias' => 'linkstory');
+$lang->project->menu->bug = 'Bug|project|bug|projectID=%s';
+$lang->project->menu->dynamic = 'Dynamic|project|dynamic|projectID=%s';
+$lang->project->menu->build = array('link' => 'Build|project|build|projectID=%s', 'subModule' => 'build');
+$lang->project->menu->testtask = 'Testtask|project|testtask|projectID=%s';
+$lang->project->menu->team = array('link' => 'Team|project|team|projectID=%s', 'alias' => 'managemembers');
+$lang->project->menu->doc = array('link' => 'Doc|project|doc|porjectID=%s', 'subModule' => 'doc');
+$lang->project->menu->product = array('link' => 'Product|project|manageproducts|projectID=%s', 'alias' => 'edit,start,suspend,delay,close');
+$lang->project->menu->view = 'Manage|project|view|projectID=%s';
+$lang->project->menu->order = 'Order|project|order|projectID=%s';
+$lang->project->menu->create = array('link' => ' New|project|create', 'float' => 'right');
+$lang->project->menu->all = array('link' => ' Projects|project|index|locate=no&status=all&projectID=%s', 'float' => 'right');
+
+$lang->task = new stdclass();
+$lang->build = new stdclass();
+$lang->task->menu = $lang->project->menu;
+$lang->build->menu = $lang->project->menu;
+
+/* QA menu. */
+$lang->bug = new stdclass();
+$lang->bug->menu = new stdclass();
+
+$lang->bug->menu->product = '%s';
+$lang->bug->menu->bug = array('link' => 'Bug|bug|browse|productID=%s', 'alias' => 'view,create,edit,resolve,close,activate,report,batchedit,confirmbug,assignto', 'subModule' => 'tree');
+$lang->bug->menu->testcase = array('link' => 'Test Case|testcase|browse|productID=%s', 'alias' => 'view,create,edit');
+$lang->bug->menu->testtask = array('link' => 'Test Task|testtask|browse|productID=%s');
+
+$lang->testcase = new stdclass();
+$lang->testcase->menu = new stdclass();
+
+$lang->testcase->menu->product = '%s';
+$lang->testcase->menu->bug = array('link' => 'Bug|bug|browse|productID=%s');
+$lang->testcase->menu->testcase = array('link' => 'Test Case|testcase|browse|productID=%s', 'alias' => 'view,create,batchcreate,edit,batchedit', 'subModule' => 'tree');
+$lang->testcase->menu->testtask = array('link' => 'Test Task|testtask|browse|productID=%s', 'alias' => 'view,create,edit,linkcase,cases');
+
+$lang->testtask = new stdclass();
+$lang->testtask->menu = $lang->testcase->menu;
+
+/* Doc menu. */
+$lang->doc = new stdclass();
+$lang->doc->menu = new stdclass();
+
+$lang->doc->menu->list = '%s';
+$lang->doc->menu->browse = array('link' => 'Doc|doc|browse|libID=%s', 'alias' => 'view,create,edit');
+$lang->doc->menu->edit = 'Edit Library|doc|editLib|libID=%s';
+$lang->doc->menu->module = 'Modules|tree|browse|libID=%s&viewType=doc';
+$lang->doc->menu->delete = array('link' => 'Delete Library|doc|deleteLib|libID=%s', 'target' => 'hiddenwin');
+$lang->doc->menu->create = array('link' => ' New Library|doc|createLib', 'float' => 'right');
+
+/* Report menu. */
+$lang->report = new stdclass();
+$lang->report->menu = new stdclass();
+
+$lang->report->menu->product = array('link' => 'Product|report|productinfo');
+$lang->report->menu->prj = array('link' => 'Project|report|projectdeviation');
+$lang->report->menu->test = array('link' => 'Test|report|bugsummary', 'alias' => 'bugassign');
+$lang->report->menu->staff = array('link' => 'Company|report|workload');
+
+/* Resource menu. */
+$lang->webapp = new stdclass();
+$lang->webapp->menu = new stdclass();
+$lang->webapp->menu->obtain = array('link' => 'App Store|webapp|obtain');
+
+/* Company menu. */
+$lang->company = new stdclass();
+$lang->company->menu = new stdclass();
+$lang->company->menu->name = '%s' . $lang->arrow;
+$lang->company->menu->browseUser = array('link' => 'Users|company|browse', 'subModule' => 'user');
+$lang->company->menu->dept = array('link' => 'Department|dept|browse', 'subModule' => 'dept');
+$lang->company->menu->browseGroup = array('link' => 'Group|group|browse', 'subModule' => 'group');
+$lang->company->menu->edit = array('link' => 'Company|company|edit');
+$lang->company->menu->dynamic = 'Dynamic|company|dynamic|';
+$lang->company->menu->addGroup = array('link' => ' Add Group|group|create', 'float' => 'right');
+$lang->company->menu->batchAddUser = array('link' => ' Batch Add|user|batchCreate', 'subModule' => 'user', 'float' => 'right');
+$lang->company->menu->addUser = array('link' => ' Add User|user|create|dept=%s&from=company', 'subModule' => 'user', 'float' => 'right');
+
+$lang->dept = new stdclass();
+$lang->group = new stdclass();
+$lang->user = new stdclass();
+
+$lang->dept->menu = $lang->company->menu;
+$lang->group->menu = $lang->company->menu;
+$lang->user->menu = $lang->company->menu;
+
+/* Admin menu. */
+$lang->admin = new stdclass();
+$lang->admin->menu = new stdclass();
+$lang->admin->menu->index = array('link' => 'Index|admin|index');
+$lang->admin->menu->extension = array('link' => 'Extension|extension|browse', 'subModule' => 'extension');
+$lang->admin->menu->editor = array('link' => 'Scaffold|editor|index', 'subModule' => 'editor');
+$lang->admin->menu->mail = array('link' => 'Email|mail|index', 'subModule' => 'mail');
+$lang->admin->menu->convert = array('link' => 'Import|convert|index', 'subModule' => 'convert');
+$lang->admin->menu->trashes = array('link' => 'Trash|action|trash', 'subModule' => 'action');
+
+$lang->convert = new stdclass();
+$lang->upgrade = new stdclass();
+$lang->action = new stdclass();
+$lang->extension = new stdclass();
+$lang->editor = new stdclass();
+$lang->mail = new stdclass();
+
+$lang->convert->menu = $lang->admin->menu;
+$lang->upgrade->menu = $lang->admin->menu;
+$lang->action->menu = $lang->admin->menu;
+$lang->extension->menu = $lang->admin->menu;
+$lang->editor->menu = $lang->admin->menu;
+$lang->mail->menu = $lang->admin->menu;
+
+/* Groups. */
+$lang->menugroup = new stdclass();
+$lang->menugroup->release = 'product';
+$lang->menugroup->story = 'product';
+$lang->menugroup->productplan = 'product';
+$lang->menugroup->task = 'project';
+$lang->menugroup->build = 'project';
+$lang->menugroup->convert = 'admin';
+$lang->menugroup->upgrade = 'admin';
+$lang->menugroup->user = 'company';
+$lang->menugroup->group = 'company';
+$lang->menugroup->bug = 'qa';
+$lang->menugroup->testcase = 'qa';
+$lang->menugroup->testtask = 'qa';
+$lang->menugroup->people = 'company';
+$lang->menugroup->dept = 'company';
+$lang->menugroup->todo = 'my';
+$lang->menugroup->action = 'admin';
+$lang->menugroup->extension = 'admin';
+$lang->menugroup->editor = 'admin';
+$lang->menugroup->mail = 'admin';
+
+/* Error info. */
+$lang->error = new stdclass();
+$lang->error->companyNotFound = "The domain %s does not exist.";
+$lang->error->length = array("『%s』length should be『%s』", "『%s』length should between『%s』and 『%s』.");
+$lang->error->reg = "『%s』should like『%s』";
+$lang->error->unique = "『%s』has『%s』already. If you are sure this record has been deleted, you can restore it in admin panel, trash page.";
+$lang->error->gt = "『%s』must greater than『%s』.";
+$lang->error->ge = "『%s』must greater than or equal『%s』.";
+$lang->error->notempty = "『%s』can not be empty.";
+$lang->error->empty = "『%s』 must be empty.";
+$lang->error->equal = "『%s』must be『%s』.";
+$lang->error->int = array("『%s』should be interger", "『%s』should between『%s-%s』.");
+$lang->error->float = "『%s』should be a interger or float.";
+$lang->error->email = "『%s』should be email.";
+$lang->error->date = "『%s』should be date";
+$lang->error->account = "『%s』should be a valid account.";
+$lang->error->passwordsame = "Two passwords must be the same";
+$lang->error->passwordrule = "Password should more than six letters.";
+$lang->error->accessDenied = 'No purview';
+
+/* Pager. */
+$lang->pager = new stdclass();
+$lang->pager->noRecord = "No records yet.";
+$lang->pager->digest = "%s records, %s per page, %s/%s ";
+$lang->pager->first = "First";
+$lang->pager->pre = "Previous";
+$lang->pager->next = "Next";
+$lang->pager->last = "Last";
+$lang->pager->locate = "GO!";
+
+$lang->zentaoSite = "Official Site";
+$lang->chinaScrum = "Scrum community ";
+$lang->agileTraining = "Training ";
+$lang->donate = "Donate ";
+$lang->proVersion = "Try pro version! ";
+$lang->downNotify = "Down notify";
+
+$lang->suhosinInfo = "Warming:data is too large! Please enlarge the setting of sohusin.post.max_vars and sohusin.request.max_vars in php.ini. Otherwise partial data can't be saved.";
+
+$lang->noResultsMatch = "No results match";
+
+/* Date times. */
+define('DT_DATETIME1', 'Y-m-d H:i:s');
+define('DT_DATETIME2', 'y-m-d H:i');
+define('DT_MONTHTIME1', 'n/d H:i');
+define('DT_MONTHTIME2', 'F j, H:i');
+define('DT_DATE1', 'Y-m-d');
+define('DT_DATE2', 'Ymd');
+define('DT_DATE3', 'F j, Y ');
+define('DT_DATE4', 'M j');
+define('DT_TIME1', 'H:i:s');
+define('DT_TIME2', 'H:i');
+
+/* datepicker 时间*/
+$lang->datepicker = new stdclass();
+
+$lang->datepicker->dpText = new stdclass();
+$lang->datepicker->dpText->TEXT_OR = 'Or ';
+$lang->datepicker->dpText->TEXT_PREV_YEAR = 'Last year';
+$lang->datepicker->dpText->TEXT_PREV_MONTH = 'Last month';
+$lang->datepicker->dpText->TEXT_PREV_WEEK = 'Last week';
+$lang->datepicker->dpText->TEXT_YESTERDAY = 'Yesterday';
+$lang->datepicker->dpText->TEXT_THIS_MONTH = 'This month';
+$lang->datepicker->dpText->TEXT_THIS_WEEK = 'This week';
+$lang->datepicker->dpText->TEXT_TODAY = 'Today';
+$lang->datepicker->dpText->TEXT_NEXT_YEAR = 'Next year';
+$lang->datepicker->dpText->TEXT_NEXT_MONTH = 'Next month';
+$lang->datepicker->dpText->TEXT_CLOSE = 'Close';
+$lang->datepicker->dpText->TEXT_DATE = 'Please select date range';
+$lang->datepicker->dpText->TEXT_CHOOSE_DATE = 'Choose date';
+
+$lang->datepicker->dayNames = array('Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday');
+$lang->datepicker->abbrDayNames = array('Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat');
+$lang->datepicker->monthNames = array('January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December');
+
+include (dirname(__FILE__) . '/menuOrder.php');
diff --git a/module/common/lang/zh-cn.php b/module/common/lang/zh-cn.php
index 37474d3c0c..e3ff4a42bd 100644
--- a/module/common/lang/zh-cn.php
+++ b/module/common/lang/zh-cn.php
@@ -1,395 +1,395 @@
-
- * @package ZenTaoPMS
- * @version $Id$
- * @link http://www.zentao.net
- */
-$lang->arrow = ' ';
-$lang->colon = '::';
-$lang->comma = ',';
-$lang->dot = '。';
-$lang->at = ' 于 ';
-$lang->downArrow = '↓';
-
-$lang->ZenTaoPMS = '禅道管理';
-$lang->welcome = "欢迎使用『%s』{$lang->colon} {$lang->ZenTaoPMS}";
-$lang->myControl = "我的地盘";
-$lang->currentPos = '当前位置:';
-$lang->logout = '退出';
-$lang->login = '登录';
-$lang->aboutZenTao = '关于';
-$lang->todayIs = '今天是%s,';
-$lang->runInfo = "时间: %s 毫秒, 内存: %s KB, 查询: %s.
";
-
-$lang->reset = '重填';
-$lang->edit = '编辑';
-$lang->copy = '复制';
-$lang->delete = '删除';
-$lang->close = '关闭';
-$lang->link = '关联';
-$lang->unlink = '移除';
-$lang->import = '导入';
-$lang->export = '导出';
-$lang->exportType = '导出类型';
-$lang->setFileName = '文件名:';
-$lang->activate = '激活';
-$lang->submitting = '稍候...';
-$lang->save = '保存';
-$lang->confirm = '确认';
-$lang->preview = '查看';
-$lang->goback = '返回';
-$lang->go = 'GO';
-$lang->more = '更多';
-
-$lang->actions = '操作';
-$lang->comment = '备注';
-$lang->history = '历史记录';
-$lang->attatch = '附件';
-$lang->reverse = '切换顺序';
-$lang->switchDisplay= '切换显示';
-$lang->switchHelp = '切换帮助';
-$lang->addFiles = '上传了附件 ';
-$lang->files = '附件 ';
-$lang->unfold = '+';
-$lang->fold = '-';
-
-$lang->selectAll = '全选';
-$lang->selectReverse = '反选';
-$lang->notFound = '抱歉,您访问的对象并不存在!';
-$lang->showAll = '++ 全部显示 ++';
-$lang->hideClosed = '-- 显示进行中 --';
-
-$lang->future = '未来';
-$lang->year = '年';
-$lang->workingHour = '工时';
-
-$lang->idAB = 'ID';
-$lang->priAB = 'P';
-$lang->statusAB = '状态';
-$lang->openedByAB = '创建';
-$lang->assignedToAB = '指派';
-$lang->typeAB = '类型';
-
-$lang->common = new stdclass();
-$lang->common->common = '公有模块';
-
-/* 主导航菜单。*/
-$lang->menu = new stdclass();
-$lang->menu->my = ' 我的地盘|my|index';
-$lang->menu->product = '产品|product|index';
-$lang->menu->project = '项目|project|index';
-$lang->menu->qa = '测试|qa|index';
-$lang->menu->doc = '文档|doc|index';
-$lang->menu->report = '统计|report|index';
-$lang->menu->webapp = '应用|webapp|index';
-$lang->menu->company = '组织|company|index';
-$lang->menu->admin = '后台|admin|index';
-
-/* 查询条中可以选择的对象列表。*/
-$lang->searchObjects['bug'] = 'B:Bug';
-$lang->searchObjects['story'] = 'S:需求';
-$lang->searchObjects['task'] = 'T:任务';
-$lang->searchObjects['testcase'] = 'C:用例';
-$lang->searchObjects['project'] = 'P:项目';
-$lang->searchObjects['product'] = 'P:产品';
-$lang->searchObjects['user'] = 'U:用户';
-$lang->searchObjects['build'] = 'B:版本';
-$lang->searchObjects['release'] = 'R:发布';
-$lang->searchObjects['productplan'] = 'P:产品计划';
-$lang->searchObjects['testtask'] = 'T:测试任务';
-$lang->searchObjects['doc'] = 'D:文档';
-$lang->searchTips = '编号(ctrl+g)';
-
-/* 导入支持的编码格式。*/
-$lang->importEncodeList['gbk'] = 'GBK';
-$lang->importEncodeList['big5'] = 'BIG5';
-$lang->importEncodeList['utf-8'] = 'UTF-8';
-
-/* 导出文件的类型列表。*/
-$lang->exportFileTypeList['csv'] = 'csv';
-$lang->exportFileTypeList['xml'] = 'xml';
-$lang->exportFileTypeList['html'] = 'html';
-
-$lang->exportTypeList['all'] = '导出全部';
-$lang->exportTypeList['selected'] = '导出选中';
-
-/* 支持的编码格式。*/
-$lang->exportEncodeList['gbk'] = 'GBK';
-$lang->exportEncodeList['big5'] = 'BIG5';
-$lang->exportEncodeList['utf-8'] = 'UTF-8';
-
-/* 风格列表。*/
-$lang->themes['default'] = '默认';
-$lang->themes['green'] = '绿色';
-$lang->themes['red'] = '红色';
-$lang->themes['classblue'] = '经典蓝';
-
-/* 首页菜单设置。*/
-$lang->index = new stdclass();
-$lang->index->menu = new stdclass();
-
-$lang->index->menu->product = '浏览产品|product|browse';
-$lang->index->menu->project = '浏览项目|project|browse';
-
-/* 我的地盘菜单设置。*/
-$lang->my = new stdclass();
-$lang->my->menu = new stdclass();
-
-$lang->my->menu->account = ' %s' . $lang->arrow;
-$lang->my->menu->index = '首页|my|index';
-$lang->my->menu->todo = array('link' => '待办|my|todo|', 'subModule' => 'todo');
-$lang->my->menu->task = '任务|my|task|';
-$lang->my->menu->bug = 'Bug|my|bug|';
-$lang->my->menu->testtask = array('link' => '测试|my|testtask|', 'alias' => 'testcase');
-$lang->my->menu->story = '需求|my|story|';
-$lang->my->menu->myProject = '项目|my|project|';
-$lang->my->menu->dynamic = '动态|my|dynamic|';
-$lang->my->menu->profile = array('link' => '档案|my|profile|', 'alias' => 'editprofile');
-$lang->my->menu->changePassword = '密码|my|changepassword|';
-
-$lang->todo = new stdclass();
-$lang->todo->menu = $lang->my->menu;
-
-/* 产品视图设置。*/
-$lang->product = new stdclass();
-$lang->product->menu = new stdclass();
-
-$lang->product->menu->list = '%s';
-$lang->product->menu->story = array('link' => '需求|product|browse|productID=%s', 'alias' => 'batchedit', 'subModule' => 'story');
-$lang->product->menu->dynamic = '动态|product|dynamic|productID=%s';
-$lang->product->menu->plan = array('link' => '计划|productplan|browse|productID=%s', 'subModule' => 'productplan');
-$lang->product->menu->release = array('link' => '发布|release|browse|productID=%s', 'subModule' => 'release');
-$lang->product->menu->roadmap = '路线图|product|roadmap|productID=%s';
-$lang->product->menu->doc = array('link' => '文档|product|doc|productID=%s', 'subModule' => 'doc');
-$lang->product->menu->view = array('link' => '维护|product|view|productID=%s', 'alias' => 'edit');
-$lang->product->menu->module = '模块|tree|browse|productID=%s&view=story';
-$lang->product->menu->project = '项目|product|project|status=all&productID=%s';
-$lang->product->menu->order = '排序|product|order|productID=%s';
-$lang->product->menu->create = array('link' => ' 添加产品|product|create', 'float' => 'right');
-$lang->product->menu->all = array('link' => ' 所有产品|product|index|locate=no&productID=%s', 'float' => 'right');
-
-$lang->story = new stdclass();
-$lang->productplan = new stdclass();
-$lang->release = new stdclass();
-
-$lang->story->menu = $lang->product->menu;
-$lang->productplan->menu = $lang->product->menu;
-$lang->release->menu = $lang->product->menu;
-
-/* 项目视图菜单设置。*/
-$lang->project = new stdclass();
-$lang->project->menu = new stdclass();
-
-$lang->project->menu->list = '%s';
-$lang->project->menu->task = array('link' => '任务|project|task|projectID=%s', 'subModule' => 'task', 'alias' => 'grouptask,importtask,burn,importbug');
-$lang->project->menu->story = array('link' => '需求|project|story|projectID=%s', 'subModule' => 'story', 'alias' => 'linkstory');
-$lang->project->menu->bug = 'Bug|project|bug|projectID=%s';
-$lang->project->menu->dynamic = '动态|project|dynamic|projectID=%s';
-$lang->project->menu->build = array('link' => '版本|project|build|projectID=%s', 'subModule' => 'build');
-$lang->project->menu->testtask = '测试|project|testtask|projectID=%s';
-$lang->project->menu->team = array('link' => '团队|project|team|projectID=%s', 'alias' => 'managemembers');
-$lang->project->menu->doc = array('link' => '文档|project|doc|porjectID=%s', 'subModule' => 'doc');
-$lang->project->menu->product = '产品|project|manageproducts|projectID=%s';
-$lang->project->menu->view = array('link' => '维护|project|view|projectID=%s', 'alias' => 'edit,start,suspend,delay,close');
-$lang->project->menu->order = '排序|project|order|projectID=%s';
-$lang->project->menu->create = array('link' => ' 添加项目|project|create', 'float' => 'right');
-$lang->project->menu->all = array('link' => ' 所有项目|project|index|locate=no&status=all&projectID=%s', 'float' => 'right');
-
-$lang->task = new stdclass();
-$lang->build = new stdclass();
-$lang->task->menu = $lang->project->menu;
-$lang->build->menu = $lang->project->menu;
-
-/* QA视图菜单设置。*/
-$lang->bug = new stdclass();
-$lang->bug->menu = new stdclass();
-
-$lang->bug->menu->product = '%s';
-$lang->bug->menu->bug = array('link' => 'Bug|bug|browse|productID=%s', 'alias' => 'view,create,edit,resolve,close,activate,report,batchedit,confirmbug,assignto', 'subModule' => 'tree');
-$lang->bug->menu->testcase = array('link' => '用例|testcase|browse|productID=%s', 'alias' => 'view,create,edit');
-$lang->bug->menu->testtask = array('link' => '测试任务|testtask|browse|productID=%s');
-
-$lang->testcase = new stdclass();
-$lang->testcase->menu = new stdclass();
-
-$lang->testcase->menu->product = '%s';
-$lang->testcase->menu->bug = array('link' => 'Bug|bug|browse|productID=%s');
-$lang->testcase->menu->testcase = array('link' => '用例|testcase|browse|productID=%s', 'alias' => 'view,create,batchcreate,edit,batchedit', 'subModule' => 'tree');
-$lang->testcase->menu->testtask = array('link' => '测试任务|testtask|browse|productID=%s', 'alias' => 'view,create,edit,linkcase,cases');
-
-$lang->testtask = new stdclass();
-$lang->testtask->menu = $lang->testcase->menu;
-
-/* 文档视图菜单设置。*/
-$lang->doc = new stdclass();
-$lang->doc->menu = new stdclass();
-
-$lang->doc->menu->list = '%s';
-$lang->doc->menu->browse = array('link' => '文档|doc|browse|libID=%s', 'alias' => 'view,create,edit');
-$lang->doc->menu->edit = '编辑|doc|editLib|libID=%s';
-$lang->doc->menu->module = '分类|tree|browse|libID=%s&viewType=doc';
-$lang->doc->menu->delete = array('link' => '删除|doc|deleteLib|libID=%s', 'target' => 'hiddenwin');
-$lang->doc->menu->create = array('link' => ' 添加文档库|doc|createLib', 'float' => 'right');
-
-/* 统计视图菜单设置。*/
-$lang->report = new stdclass();
-$lang->report->menu = new stdclass();
-
-$lang->report->menu->product = array('link' => '产品|report|productinfo');
-$lang->report->menu->prj = array('link' => '项目|report|projectdeviation');
-$lang->report->menu->test = array('link' => '测试|report|bugsummary', 'alias' => 'bugassign');
-$lang->report->menu->staff = array('link' => '组织|report|workload');
-
-/* 资源视图菜单设置。*/
-$lang->webapp = new stdclass();
-$lang->webapp->menu = new stdclass();
-$lang->webapp->menu->obtain = array('link' => '应用商店|webapp|obtain', 'float' => 'right');
-
-/* 组织结构视图菜单设置。*/
-$lang->company = new stdclass();
-$lang->company->menu = new stdclass();
-$lang->company->menu->name = '%s' . $lang->arrow;
-$lang->company->menu->browseUser = array('link' => '用户|company|browse', 'subModule' => 'user');
-$lang->company->menu->dept = array('link' => '部门|dept|browse', 'subModule' => 'dept');
-$lang->company->menu->browseGroup = array('link' => '权限|group|browse', 'subModule' => 'group');
-$lang->company->menu->edit = array('link' => '公司|company|edit');
-$lang->company->menu->dynamic = '动态|company|dynamic|';
-$lang->company->menu->addGroup = array('link' => ' 添加分组|group|create', 'float' => 'right');
-$lang->company->menu->batchAddUser = array('link' => ' 批量添加|user|batchCreate', 'subModule' => 'user', 'float' => 'right');
-$lang->company->menu->addUser = array('link' => ' 添加用户|user|create|dept=%s', 'subModule' => 'user', 'float' => 'right');
-
-$lang->dept = new stdclass();
-$lang->group = new stdclass();
-$lang->user = new stdclass();
-
-$lang->dept->menu = $lang->company->menu;
-$lang->group->menu = $lang->company->menu;
-$lang->user->menu = $lang->company->menu;
-
-/* 后台管理菜单设置。*/
-$lang->admin = new stdclass();
-$lang->admin->menu = new stdclass();
-$lang->admin->menu->index = array('link' => '首页|admin|index');
-$lang->admin->menu->extension = array('link' => '插件|extension|browse', 'subModule' => 'extension');
-$lang->admin->menu->editor = array('link' => '扩展编辑器|editor|index', 'subModule' => 'editor');
-$lang->admin->menu->mail = array('link' => '发信|mail|index', 'subModule' => 'mail');
-$lang->admin->menu->convert = array('link' => '导入|convert|index', 'subModule' => 'convert');
-$lang->admin->menu->trashes = array('link' => '回收站|action|trash', 'subModule' => 'action');
-
-$lang->convert = new stdclass();
-$lang->upgrade = new stdclass();
-$lang->action = new stdclass();
-$lang->extension = new stdclass();
-$lang->editor = new stdclass();
-$lang->mail = new stdclass();
-
-$lang->convert->menu = $lang->admin->menu;
-$lang->upgrade->menu = $lang->admin->menu;
-$lang->action->menu = $lang->admin->menu;
-$lang->extension->menu = $lang->admin->menu;
-$lang->editor->menu = $lang->admin->menu;
-$lang->mail->menu = $lang->admin->menu;
-
-/* 菜单分组。*/
-$lang->menugroup = new stdclass();
-$lang->menugroup->release = 'product';
-$lang->menugroup->story = 'product';
-$lang->menugroup->productplan = 'product';
-$lang->menugroup->task = 'project';
-$lang->menugroup->build = 'project';
-$lang->menugroup->convert = 'admin';
-$lang->menugroup->upgrade = 'admin';
-$lang->menugroup->user = 'company';
-$lang->menugroup->group = 'company';
-$lang->menugroup->bug = 'qa';
-$lang->menugroup->testcase = 'qa';
-$lang->menugroup->testtask = 'qa';
-$lang->menugroup->people = 'company';
-$lang->menugroup->dept = 'company';
-$lang->menugroup->todo = 'my';
-$lang->menugroup->action = 'admin';
-$lang->menugroup->extension = 'admin';
-$lang->menugroup->editor = 'admin';
-$lang->menugroup->mail = 'admin';
-
-/* 错误提示信息。*/
-$lang->error = new stdclass();
-$lang->error->companyNotFound = "您访问的域名 %s 没有对应的公司。";
-$lang->error->length = array("『%s』长度错误,应当为『%s』", "『%s』长度应当不超过『%s』,且不小于『%s』。");
-$lang->error->reg = "『%s』不符合格式,应当为:『%s』。";
-$lang->error->unique = "『%s』已经有『%s』这条记录了。如果您确定该记录已删除,请到后台管理-回收站还原。。";
-$lang->error->gt = "『%s』应当大于『%s』。";
-$lang->error->ge = "『%s』应当不小于『%s』。";
-$lang->error->notempty = "『%s』不能为空。";
-$lang->error->empty = "『%s』必须为空。";
-$lang->error->equal = "『%s』必须为『%s』。";
-$lang->error->int = array("『%s』应当是数字。", "『%s』应当介于『%s-%s』之间。");
-$lang->error->float = "『%s』应当是数字,可以是小数。";
-$lang->error->email = "『%s』应当为合法的EMAIL。";
-$lang->error->date = "『%s』应当为合法的日期。";
-$lang->error->account = "『%s』应当为合法的用户名。";
-$lang->error->passwordsame = "两次密码应当相等。";
-$lang->error->passwordrule = "密码应该符合规则,长度至少为六位。";
-$lang->error->accessDenied = '您没有访问权限';
-
-/* 分页信息。*/
-$lang->pager = new stdclass();
-$lang->pager->noRecord = "暂时没有记录";
-$lang->pager->digest = "共%s 条记录,每页 %s 条,%s/%s ";
-$lang->pager->first = "首页";
-$lang->pager->pre = "上页";
-$lang->pager->next = "下页";
-$lang->pager->last = "末页";
-$lang->pager->locate = "GO!";
-
-$lang->zentaoSite = "官方网站";
-$lang->chinaScrum = "Scrum社区 ";
-$lang->agileTraining = "培训 ";
-$lang->donate = "捐赠 ";
-$lang->proVersion = "购买专业版(特惠)! ";
-$lang->downNotify = "下载桌面提醒";
-
-$lang->suhosinInfo = "警告:数据太多,请在php.ini中修改sohusin.post.max_vars 和sohusin.request.max_vars (设置更大的数)。 保存并重新启动apache,否则会造成部分数据无法保存。";
-
-$lang->noResultsMatch = "没有匹配结果";
-
-/* 时间格式设置。*/
-define('DT_DATETIME1', 'Y-m-d H:i:s');
-define('DT_DATETIME2', 'y-m-d H:i');
-define('DT_MONTHTIME1', 'n/d H:i');
-define('DT_MONTHTIME2', 'n月d日 H:i');
-define('DT_DATE1', 'Y-m-d');
-define('DT_DATE2', 'Ymd');
-define('DT_DATE3', 'Y年m月d日');
-define('DT_DATE4', 'n月j日');
-define('DT_TIME1', 'H:i:s');
-define('DT_TIME2', 'H:i');
-
-/* datepicker 时间*/
-$lang->datepicker = new stdclass();
-
-$lang->datepicker->dpText = new stdclass();
-$lang->datepicker->dpText->TEXT_OR = '或 ';
-$lang->datepicker->dpText->TEXT_PREV_YEAR = '去年';
-$lang->datepicker->dpText->TEXT_PREV_MONTH = '上月';
-$lang->datepicker->dpText->TEXT_PREV_WEEK = '上周';
-$lang->datepicker->dpText->TEXT_YESTERDAY = '昨天';
-$lang->datepicker->dpText->TEXT_THIS_MONTH = '本月';
-$lang->datepicker->dpText->TEXT_THIS_WEEK = '本周';
-$lang->datepicker->dpText->TEXT_TODAY = '今天';
-$lang->datepicker->dpText->TEXT_NEXT_YEAR = '明年';
-$lang->datepicker->dpText->TEXT_NEXT_MONTH = '下月';
-$lang->datepicker->dpText->TEXT_CLOSE = '关闭';
-$lang->datepicker->dpText->TEXT_DATE = '选择时间段';
-$lang->datepicker->dpText->TEXT_CHOOSE_DATE = '选择日期';
-
-$lang->datepicker->dayNames = array('日', '一', '二', '三', '四', '五', '六');
-$lang->datepicker->abbrDayNames = array('日', '一', '二', '三', '四', '五', '六');
-$lang->datepicker->monthNames = array('一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月');
-
-include (dirname(__FILE__) . '/menuOrder.php');
+
+ * @package ZenTaoPMS
+ * @version $Id$
+ * @link http://www.zentao.net
+ */
+$lang->arrow = ' ';
+$lang->colon = '::';
+$lang->comma = ',';
+$lang->dot = '。';
+$lang->at = ' 于 ';
+$lang->downArrow = '↓';
+
+$lang->ZenTaoPMS = '禅道管理';
+$lang->welcome = "欢迎使用『%s』{$lang->colon} {$lang->ZenTaoPMS}";
+$lang->myControl = "我的地盘";
+$lang->currentPos = '当前位置:';
+$lang->logout = '退出';
+$lang->login = '登录';
+$lang->aboutZenTao = '关于';
+$lang->todayIs = '今天是%s,';
+$lang->runInfo = "时间: %s 毫秒, 内存: %s KB, 查询: %s.
";
+
+$lang->reset = '重填';
+$lang->edit = '编辑';
+$lang->copy = '复制';
+$lang->delete = '删除';
+$lang->close = '关闭';
+$lang->link = '关联';
+$lang->unlink = '移除';
+$lang->import = '导入';
+$lang->export = '导出';
+$lang->exportType = '导出类型';
+$lang->setFileName = '文件名:';
+$lang->activate = '激活';
+$lang->submitting = '稍候...';
+$lang->save = '保存';
+$lang->confirm = '确认';
+$lang->preview = '查看';
+$lang->goback = '返回';
+$lang->go = 'GO';
+$lang->more = '更多';
+
+$lang->actions = '操作';
+$lang->comment = '备注';
+$lang->history = '历史记录';
+$lang->attatch = '附件';
+$lang->reverse = '切换顺序';
+$lang->switchDisplay= '切换显示';
+$lang->switchHelp = '切换帮助';
+$lang->addFiles = '上传了附件 ';
+$lang->files = '附件 ';
+$lang->unfold = '+';
+$lang->fold = '-';
+
+$lang->selectAll = '全选';
+$lang->selectReverse = '反选';
+$lang->notFound = '抱歉,您访问的对象并不存在!';
+$lang->showAll = '++ 全部显示 ++';
+$lang->hideClosed = '-- 显示进行中 --';
+
+$lang->future = '未来';
+$lang->year = '年';
+$lang->workingHour = '工时';
+
+$lang->idAB = 'ID';
+$lang->priAB = 'P';
+$lang->statusAB = '状态';
+$lang->openedByAB = '创建';
+$lang->assignedToAB = '指派';
+$lang->typeAB = '类型';
+
+$lang->common = new stdclass();
+$lang->common->common = '公有模块';
+
+/* 主导航菜单。*/
+$lang->menu = new stdclass();
+$lang->menu->my = ' 我的地盘|my|index';
+$lang->menu->product = '产品|product|index';
+$lang->menu->project = '项目|project|index';
+$lang->menu->qa = '测试|qa|index';
+$lang->menu->doc = '文档|doc|index';
+$lang->menu->report = '统计|report|index';
+$lang->menu->webapp = '应用|webapp|index';
+$lang->menu->company = '组织|company|index';
+$lang->menu->admin = '后台|admin|index';
+
+/* 查询条中可以选择的对象列表。*/
+$lang->searchObjects['bug'] = 'B:Bug';
+$lang->searchObjects['story'] = 'S:需求';
+$lang->searchObjects['task'] = 'T:任务';
+$lang->searchObjects['testcase'] = 'C:用例';
+$lang->searchObjects['project'] = 'P:项目';
+$lang->searchObjects['product'] = 'P:产品';
+$lang->searchObjects['user'] = 'U:用户';
+$lang->searchObjects['build'] = 'B:版本';
+$lang->searchObjects['release'] = 'R:发布';
+$lang->searchObjects['productplan'] = 'P:产品计划';
+$lang->searchObjects['testtask'] = 'T:测试任务';
+$lang->searchObjects['doc'] = 'D:文档';
+$lang->searchTips = '编号(ctrl+g)';
+
+/* 导入支持的编码格式。*/
+$lang->importEncodeList['gbk'] = 'GBK';
+$lang->importEncodeList['big5'] = 'BIG5';
+$lang->importEncodeList['utf-8'] = 'UTF-8';
+
+/* 导出文件的类型列表。*/
+$lang->exportFileTypeList['csv'] = 'csv';
+$lang->exportFileTypeList['xml'] = 'xml';
+$lang->exportFileTypeList['html'] = 'html';
+
+$lang->exportTypeList['all'] = '导出全部';
+$lang->exportTypeList['selected'] = '导出选中';
+
+/* 支持的编码格式。*/
+$lang->exportEncodeList['gbk'] = 'GBK';
+$lang->exportEncodeList['big5'] = 'BIG5';
+$lang->exportEncodeList['utf-8'] = 'UTF-8';
+
+/* 风格列表。*/
+$lang->themes['default'] = '默认';
+$lang->themes['green'] = '绿色';
+$lang->themes['red'] = '红色';
+$lang->themes['classblue'] = '经典蓝';
+
+/* 首页菜单设置。*/
+$lang->index = new stdclass();
+$lang->index->menu = new stdclass();
+
+$lang->index->menu->product = '浏览产品|product|browse';
+$lang->index->menu->project = '浏览项目|project|browse';
+
+/* 我的地盘菜单设置。*/
+$lang->my = new stdclass();
+$lang->my->menu = new stdclass();
+
+$lang->my->menu->account = ' %s' . $lang->arrow;
+$lang->my->menu->index = '首页|my|index';
+$lang->my->menu->todo = array('link' => '待办|my|todo|', 'subModule' => 'todo');
+$lang->my->menu->task = '任务|my|task|';
+$lang->my->menu->bug = 'Bug|my|bug|';
+$lang->my->menu->testtask = array('link' => '测试|my|testtask|', 'alias' => 'testcase');
+$lang->my->menu->story = '需求|my|story|';
+$lang->my->menu->myProject = '项目|my|project|';
+$lang->my->menu->dynamic = '动态|my|dynamic|';
+$lang->my->menu->profile = array('link' => '档案|my|profile|', 'alias' => 'editprofile');
+$lang->my->menu->changePassword = '密码|my|changepassword|';
+
+$lang->todo = new stdclass();
+$lang->todo->menu = $lang->my->menu;
+
+/* 产品视图设置。*/
+$lang->product = new stdclass();
+$lang->product->menu = new stdclass();
+
+$lang->product->menu->list = '%s';
+$lang->product->menu->story = array('link' => '需求|product|browse|productID=%s', 'alias' => 'batchedit', 'subModule' => 'story');
+$lang->product->menu->dynamic = '动态|product|dynamic|productID=%s';
+$lang->product->menu->plan = array('link' => '计划|productplan|browse|productID=%s', 'subModule' => 'productplan');
+$lang->product->menu->release = array('link' => '发布|release|browse|productID=%s', 'subModule' => 'release');
+$lang->product->menu->roadmap = '路线图|product|roadmap|productID=%s';
+$lang->product->menu->doc = array('link' => '文档|product|doc|productID=%s', 'subModule' => 'doc');
+$lang->product->menu->view = array('link' => '维护|product|view|productID=%s', 'alias' => 'edit');
+$lang->product->menu->module = '模块|tree|browse|productID=%s&view=story';
+$lang->product->menu->project = '项目|product|project|status=all&productID=%s';
+$lang->product->menu->order = '排序|product|order|productID=%s';
+$lang->product->menu->create = array('link' => ' 添加产品|product|create', 'float' => 'right');
+$lang->product->menu->all = array('link' => ' 所有产品|product|index|locate=no&productID=%s', 'float' => 'right');
+
+$lang->story = new stdclass();
+$lang->productplan = new stdclass();
+$lang->release = new stdclass();
+
+$lang->story->menu = $lang->product->menu;
+$lang->productplan->menu = $lang->product->menu;
+$lang->release->menu = $lang->product->menu;
+
+/* 项目视图菜单设置。*/
+$lang->project = new stdclass();
+$lang->project->menu = new stdclass();
+
+$lang->project->menu->list = '%s';
+$lang->project->menu->task = array('link' => '任务|project|task|projectID=%s', 'subModule' => 'task', 'alias' => 'grouptask,importtask,burn,importbug');
+$lang->project->menu->story = array('link' => '需求|project|story|projectID=%s', 'subModule' => 'story', 'alias' => 'linkstory');
+$lang->project->menu->bug = 'Bug|project|bug|projectID=%s';
+$lang->project->menu->dynamic = '动态|project|dynamic|projectID=%s';
+$lang->project->menu->build = array('link' => '版本|project|build|projectID=%s', 'subModule' => 'build');
+$lang->project->menu->testtask = '测试|project|testtask|projectID=%s';
+$lang->project->menu->team = array('link' => '团队|project|team|projectID=%s', 'alias' => 'managemembers');
+$lang->project->menu->doc = array('link' => '文档|project|doc|porjectID=%s', 'subModule' => 'doc');
+$lang->project->menu->product = '产品|project|manageproducts|projectID=%s';
+$lang->project->menu->view = array('link' => '维护|project|view|projectID=%s', 'alias' => 'edit,start,suspend,delay,close');
+$lang->project->menu->order = '排序|project|order|projectID=%s';
+$lang->project->menu->create = array('link' => ' 添加项目|project|create', 'float' => 'right');
+$lang->project->menu->all = array('link' => ' 所有项目|project|index|locate=no&status=all&projectID=%s', 'float' => 'right');
+
+$lang->task = new stdclass();
+$lang->build = new stdclass();
+$lang->task->menu = $lang->project->menu;
+$lang->build->menu = $lang->project->menu;
+
+/* QA视图菜单设置。*/
+$lang->bug = new stdclass();
+$lang->bug->menu = new stdclass();
+
+$lang->bug->menu->product = '%s';
+$lang->bug->menu->bug = array('link' => 'Bug|bug|browse|productID=%s', 'alias' => 'view,create,edit,resolve,close,activate,report,batchedit,confirmbug,assignto', 'subModule' => 'tree');
+$lang->bug->menu->testcase = array('link' => '用例|testcase|browse|productID=%s', 'alias' => 'view,create,edit');
+$lang->bug->menu->testtask = array('link' => '测试任务|testtask|browse|productID=%s');
+
+$lang->testcase = new stdclass();
+$lang->testcase->menu = new stdclass();
+
+$lang->testcase->menu->product = '%s';
+$lang->testcase->menu->bug = array('link' => 'Bug|bug|browse|productID=%s');
+$lang->testcase->menu->testcase = array('link' => '用例|testcase|browse|productID=%s', 'alias' => 'view,create,batchcreate,edit,batchedit', 'subModule' => 'tree');
+$lang->testcase->menu->testtask = array('link' => '测试任务|testtask|browse|productID=%s', 'alias' => 'view,create,edit,linkcase,cases');
+
+$lang->testtask = new stdclass();
+$lang->testtask->menu = $lang->testcase->menu;
+
+/* 文档视图菜单设置。*/
+$lang->doc = new stdclass();
+$lang->doc->menu = new stdclass();
+
+$lang->doc->menu->list = '%s';
+$lang->doc->menu->browse = array('link' => '文档|doc|browse|libID=%s', 'alias' => 'view,create,edit');
+$lang->doc->menu->edit = '编辑|doc|editLib|libID=%s';
+$lang->doc->menu->module = '分类|tree|browse|libID=%s&viewType=doc';
+$lang->doc->menu->delete = array('link' => '删除|doc|deleteLib|libID=%s', 'target' => 'hiddenwin');
+$lang->doc->menu->create = array('link' => ' 添加文档库|doc|createLib', 'float' => 'right');
+
+/* 统计视图菜单设置。*/
+$lang->report = new stdclass();
+$lang->report->menu = new stdclass();
+
+$lang->report->menu->product = array('link' => '产品|report|productinfo');
+$lang->report->menu->prj = array('link' => '项目|report|projectdeviation');
+$lang->report->menu->test = array('link' => '测试|report|bugsummary', 'alias' => 'bugassign');
+$lang->report->menu->staff = array('link' => '组织|report|workload');
+
+/* 资源视图菜单设置。*/
+$lang->webapp = new stdclass();
+$lang->webapp->menu = new stdclass();
+$lang->webapp->menu->obtain = array('link' => '应用商店|webapp|obtain', 'float' => 'right');
+
+/* 组织结构视图菜单设置。*/
+$lang->company = new stdclass();
+$lang->company->menu = new stdclass();
+$lang->company->menu->name = '%s' . $lang->arrow;
+$lang->company->menu->browseUser = array('link' => '用户|company|browse', 'subModule' => 'user');
+$lang->company->menu->dept = array('link' => '部门|dept|browse', 'subModule' => 'dept');
+$lang->company->menu->browseGroup = array('link' => '权限|group|browse', 'subModule' => 'group');
+$lang->company->menu->edit = array('link' => '公司|company|edit');
+$lang->company->menu->dynamic = '动态|company|dynamic|';
+$lang->company->menu->addGroup = array('link' => ' 添加分组|group|create', 'float' => 'right');
+$lang->company->menu->batchAddUser = array('link' => ' 批量添加|user|batchCreate', 'subModule' => 'user', 'float' => 'right');
+$lang->company->menu->addUser = array('link' => ' 添加用户|user|create|dept=%s', 'subModule' => 'user', 'float' => 'right');
+
+$lang->dept = new stdclass();
+$lang->group = new stdclass();
+$lang->user = new stdclass();
+
+$lang->dept->menu = $lang->company->menu;
+$lang->group->menu = $lang->company->menu;
+$lang->user->menu = $lang->company->menu;
+
+/* 后台管理菜单设置。*/
+$lang->admin = new stdclass();
+$lang->admin->menu = new stdclass();
+$lang->admin->menu->index = array('link' => '首页|admin|index');
+$lang->admin->menu->extension = array('link' => '插件|extension|browse', 'subModule' => 'extension');
+$lang->admin->menu->editor = array('link' => '扩展编辑器|editor|index', 'subModule' => 'editor');
+$lang->admin->menu->mail = array('link' => '发信|mail|index', 'subModule' => 'mail');
+$lang->admin->menu->convert = array('link' => '导入|convert|index', 'subModule' => 'convert');
+$lang->admin->menu->trashes = array('link' => '回收站|action|trash', 'subModule' => 'action');
+
+$lang->convert = new stdclass();
+$lang->upgrade = new stdclass();
+$lang->action = new stdclass();
+$lang->extension = new stdclass();
+$lang->editor = new stdclass();
+$lang->mail = new stdclass();
+
+$lang->convert->menu = $lang->admin->menu;
+$lang->upgrade->menu = $lang->admin->menu;
+$lang->action->menu = $lang->admin->menu;
+$lang->extension->menu = $lang->admin->menu;
+$lang->editor->menu = $lang->admin->menu;
+$lang->mail->menu = $lang->admin->menu;
+
+/* 菜单分组。*/
+$lang->menugroup = new stdclass();
+$lang->menugroup->release = 'product';
+$lang->menugroup->story = 'product';
+$lang->menugroup->productplan = 'product';
+$lang->menugroup->task = 'project';
+$lang->menugroup->build = 'project';
+$lang->menugroup->convert = 'admin';
+$lang->menugroup->upgrade = 'admin';
+$lang->menugroup->user = 'company';
+$lang->menugroup->group = 'company';
+$lang->menugroup->bug = 'qa';
+$lang->menugroup->testcase = 'qa';
+$lang->menugroup->testtask = 'qa';
+$lang->menugroup->people = 'company';
+$lang->menugroup->dept = 'company';
+$lang->menugroup->todo = 'my';
+$lang->menugroup->action = 'admin';
+$lang->menugroup->extension = 'admin';
+$lang->menugroup->editor = 'admin';
+$lang->menugroup->mail = 'admin';
+
+/* 错误提示信息。*/
+$lang->error = new stdclass();
+$lang->error->companyNotFound = "您访问的域名 %s 没有对应的公司。";
+$lang->error->length = array("『%s』长度错误,应当为『%s』", "『%s』长度应当不超过『%s』,且不小于『%s』。");
+$lang->error->reg = "『%s』不符合格式,应当为:『%s』。";
+$lang->error->unique = "『%s』已经有『%s』这条记录了。如果您确定该记录已删除,请到后台管理-回收站还原。。";
+$lang->error->gt = "『%s』应当大于『%s』。";
+$lang->error->ge = "『%s』应当不小于『%s』。";
+$lang->error->notempty = "『%s』不能为空。";
+$lang->error->empty = "『%s』必须为空。";
+$lang->error->equal = "『%s』必须为『%s』。";
+$lang->error->int = array("『%s』应当是数字。", "『%s』应当介于『%s-%s』之间。");
+$lang->error->float = "『%s』应当是数字,可以是小数。";
+$lang->error->email = "『%s』应当为合法的EMAIL。";
+$lang->error->date = "『%s』应当为合法的日期。";
+$lang->error->account = "『%s』应当为合法的用户名。";
+$lang->error->passwordsame = "两次密码应当相等。";
+$lang->error->passwordrule = "密码应该符合规则,长度至少为六位。";
+$lang->error->accessDenied = '您没有访问权限';
+
+/* 分页信息。*/
+$lang->pager = new stdclass();
+$lang->pager->noRecord = "暂时没有记录";
+$lang->pager->digest = "共%s 条记录,每页 %s 条,%s/%s ";
+$lang->pager->first = "首页";
+$lang->pager->pre = "上页";
+$lang->pager->next = "下页";
+$lang->pager->last = "末页";
+$lang->pager->locate = "GO!";
+
+$lang->zentaoSite = "官方网站";
+$lang->chinaScrum = "Scrum社区 ";
+$lang->agileTraining = "培训 ";
+$lang->donate = "捐赠 ";
+$lang->proVersion = "购买专业版(特惠)! ";
+$lang->downNotify = "下载桌面提醒";
+
+$lang->suhosinInfo = "警告:数据太多,请在php.ini中修改sohusin.post.max_vars 和sohusin.request.max_vars (设置更大的数)。 保存并重新启动apache,否则会造成部分数据无法保存。";
+
+$lang->noResultsMatch = "没有匹配结果";
+
+/* 时间格式设置。*/
+define('DT_DATETIME1', 'Y-m-d H:i:s');
+define('DT_DATETIME2', 'y-m-d H:i');
+define('DT_MONTHTIME1', 'n/d H:i');
+define('DT_MONTHTIME2', 'n月d日 H:i');
+define('DT_DATE1', 'Y-m-d');
+define('DT_DATE2', 'Ymd');
+define('DT_DATE3', 'Y年m月d日');
+define('DT_DATE4', 'n月j日');
+define('DT_TIME1', 'H:i:s');
+define('DT_TIME2', 'H:i');
+
+/* datepicker 时间*/
+$lang->datepicker = new stdclass();
+
+$lang->datepicker->dpText = new stdclass();
+$lang->datepicker->dpText->TEXT_OR = '或 ';
+$lang->datepicker->dpText->TEXT_PREV_YEAR = '去年';
+$lang->datepicker->dpText->TEXT_PREV_MONTH = '上月';
+$lang->datepicker->dpText->TEXT_PREV_WEEK = '上周';
+$lang->datepicker->dpText->TEXT_YESTERDAY = '昨天';
+$lang->datepicker->dpText->TEXT_THIS_MONTH = '本月';
+$lang->datepicker->dpText->TEXT_THIS_WEEK = '本周';
+$lang->datepicker->dpText->TEXT_TODAY = '今天';
+$lang->datepicker->dpText->TEXT_NEXT_YEAR = '明年';
+$lang->datepicker->dpText->TEXT_NEXT_MONTH = '下月';
+$lang->datepicker->dpText->TEXT_CLOSE = '关闭';
+$lang->datepicker->dpText->TEXT_DATE = '选择时间段';
+$lang->datepicker->dpText->TEXT_CHOOSE_DATE = '选择日期';
+
+$lang->datepicker->dayNames = array('日', '一', '二', '三', '四', '五', '六');
+$lang->datepicker->abbrDayNames = array('日', '一', '二', '三', '四', '五', '六');
+$lang->datepicker->monthNames = array('一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月');
+
+include (dirname(__FILE__) . '/menuOrder.php');
diff --git a/module/common/lang/zh-tw.php b/module/common/lang/zh-tw.php
index e18080cfc1..8deed1300f 100644
--- a/module/common/lang/zh-tw.php
+++ b/module/common/lang/zh-tw.php
@@ -1,396 +1,396 @@
-
- * @package ZenTaoPMS
- * @version $Id: zh-tw.php 3864 2012-12-20 08:00:07Z wyd621@gmail.com $
- * @link http://www.zentao.net
- */
-$lang->arrow = ' ';
-$lang->colon = '::';
-$lang->comma = ',';
-$lang->dot = '。';
-$lang->at = ' 于 ';
-$lang->downArrow = '↓';
-
-$lang->ZenTaoPMS = '禪道管理';
-$lang->welcome = "歡迎使用『%s』{$lang->colon} {$lang->ZenTaoPMS}";
-$lang->myControl = "我的地盤";
-$lang->currentPos = '當前位置:';
-$lang->logout = '退出';
-$lang->login = '登錄';
-$lang->aboutZenTao = '關於';
-$lang->todayIs = '今天是%s,';
-$lang->runInfo = "時間: %s 毫秒, 內存: %s KB, 查詢: %s.
";
-
-$lang->reset = '重填';
-$lang->edit = '編輯';
-$lang->copy = '複製';
-$lang->delete = '刪除';
-$lang->close = '關閉';
-$lang->link = '關聯';
-$lang->unlink = '移除';
-$lang->import = '導入';
-$lang->export = '導出';
-$lang->exportType = '導出類型';
-$lang->setFileName = '檔案名:';
-$lang->activate = '激活';
-$lang->submitting = '稍候...';
-$lang->save = '保存';
-$lang->confirm = '確認';
-$lang->preview = '查看';
-$lang->goback = '返回';
-$lang->go = 'GO';
-$lang->more = '更多';
-
-$lang->actions = '操作';
-$lang->comment = '備註';
-$lang->history = '歷史記錄';
-$lang->attatch = '附件';
-$lang->reverse = '切換順序';
-$lang->switchDisplay= '切換顯示';
-$lang->switchHelp = '切換幫助';
-$lang->addFiles = '上傳了附件 ';
-$lang->files = '附件 ';
-$lang->unfold = '+';
-$lang->fold = '-';
-
-$lang->selectAll = '全選';
-$lang->selectReverse = '反選';
-$lang->notFound = '抱歉,您訪問的對象並不存在!';
-$lang->showAll = '++ 全部顯示 ++';
-$lang->hideClosed = '-- 隱藏已結束 --';
-
-$lang->future = '未來';
-$lang->year = '年';
-$lang->workingHour = '工時';
-
-$lang->idAB = 'ID';
-$lang->priAB = 'P';
-$lang->statusAB = '狀態';
-$lang->openedByAB = '創建';
-$lang->assignedToAB = '指派';
-$lang->typeAB = '類型';
-
-$lang->common = new stdclass();
-$lang->common->common = '公有模組';
-
-/* 主導航菜單。*/
-$lang->menu = new stdclass();
-$lang->menu->my = ' 我的地盤|my|index';
-$lang->menu->product = '產品|product|index';
-$lang->menu->project = '項目|project|index';
-$lang->menu->qa = '測試|qa|index';
-$lang->menu->doc = '文檔|doc|index';
-$lang->menu->report = '統計|report|index';
-//$lang->menu->webapp = '應用中心|webapp|index';
-$lang->menu->company = '組織|company|index';
-$lang->menu->admin = '管理|admin|index';
-
-/* 查詢條中可以選擇的對象列表。*/
-$lang->searchObjects['bug'] = 'B:Bug';
-$lang->searchObjects['story'] = 'S:需求';
-$lang->searchObjects['task'] = 'T:任務';
-$lang->searchObjects['testcase'] = 'C:用例';
-$lang->searchObjects['project'] = 'P:項目';
-$lang->searchObjects['product'] = 'P:產品';
-$lang->searchObjects['user'] = 'U:用戶';
-$lang->searchObjects['build'] = 'B:版本';
-$lang->searchObjects['release'] = 'R:發佈';
-$lang->searchObjects['productplan'] = 'P:產品計劃';
-$lang->searchObjects['testtask'] = 'T:測試任務';
-$lang->searchObjects['doc'] = 'D:文檔';
-$lang->searchTips = '編號(ctrl+g)';
-
-/* 導入支持的編碼格式。*/
-$lang->importEncodeList['gbk'] = 'GBK';
-$lang->importEncodeList['big5'] = 'BIG5';
-$lang->importEncodeList['utf-8'] = 'UTF-8';
-
-/* 導出檔案的類型列表。*/
-$lang->exportFileTypeList['csv'] = 'csv';
-$lang->exportFileTypeList['xml'] = 'xml';
-$lang->exportFileTypeList['html'] = 'html';
-
-$lang->exportTypeList['all'] = '導出全部';
-$lang->exportTypeList['selected'] = '導出選中';
-
-/* 支持的編碼格式。*/
-$lang->exportEncodeList['gbk'] = 'GBK';
-$lang->exportEncodeList['big5'] = 'BIG5';
-$lang->exportEncodeList['utf-8'] = 'UTF-8';
-
-/* 風格列表。*/
-$lang->themes['default'] = '預設';
-$lang->themes['green'] = '綠色';
-$lang->themes['red'] = '紅色';
-$lang->themes['classblue'] = '經典藍';
-
-/* 首頁菜單設置。*/
-$lang->index = new stdclass();
-$lang->index->menu = new stdclass();
-
-$lang->index->menu->product = '瀏覽產品|product|browse';
-$lang->index->menu->project = '瀏覽項目|project|browse';
-
-/* 我的地盤菜單設置。*/
-$lang->my = new stdclass();
-$lang->my->menu = new stdclass();
-
-$lang->my->menu->account = ' %s' . $lang->arrow;
-$lang->my->menu->index = '首頁|my|index';
-$lang->my->menu->todo = array('link' => '待辦|my|todo|', 'subModule' => 'todo');
-$lang->my->menu->task = '任務|my|task|';
-$lang->my->menu->bug = '缺陷|my|bug|';
-$lang->my->menu->testtask = array('link' => '測試|my|testtask|', 'alias' => 'testcase');
-$lang->my->menu->story = '需求|my|story|';
-$lang->my->menu->myProject = '項目|my|project|';
-$lang->my->menu->dynamic = '動態|my|dynamic|';
-$lang->my->menu->profile = array('link' => '檔案|my|profile|', 'alias' => 'editprofile');
-$lang->my->menu->changePassword = '密碼|my|changepassword|';
-
-$lang->todo = new stdclass();
-$lang->todo->menu = $lang->my->menu;
-
-/* 產品視圖設置。*/
-$lang->product = new stdclass();
-$lang->product->menu = new stdclass();
-
-$lang->product->menu->list = '%s';
-$lang->product->menu->story = array('link' => '需求|product|browse|productID=%s', 'alias' => 'batchedit', 'subModule' => 'story');
-$lang->product->menu->dynamic = '動態|product|dynamic|productID=%s';
-$lang->product->menu->plan = array('link' => '計劃|productplan|browse|productID=%s', 'subModule' => 'productplan');
-$lang->product->menu->release = array('link' => '發佈|release|browse|productID=%s', 'subModule' => 'release');
-$lang->product->menu->roadmap = '路線圖|product|roadmap|productID=%s';
-$lang->product->menu->doc = array('link' => '文檔|product|doc|productID=%s', 'subModule' => 'doc');
-$lang->product->menu->view = array('link' => '維護|product|view|productID=%s', 'alias' => 'edit');
-$lang->product->menu->module = '模組|tree|browse|productID=%s&view=story';
-$lang->product->menu->project = '項目|product|project|status=all&productID=%s';
-$lang->product->menu->order = '排序|product|order|productID=%s';
-$lang->product->menu->create = array('link' => ' 新增產品|product|create', 'float' => 'right');
-$lang->product->menu->all = array('link' => ' 所有產品|product|index|locate=no&productID=%s', 'float' => 'right');
-
-$lang->story = new stdclass();
-$lang->productplan = new stdclass();
-$lang->release = new stdclass();
-
-$lang->story->menu = $lang->product->menu;
-$lang->productplan->menu = $lang->product->menu;
-$lang->release->menu = $lang->product->menu;
-
-/* 項目視圖菜單設置。*/
-$lang->project = new stdclass();
-$lang->project->menu = new stdclass();
-
-$lang->project->menu->list = '%s';
-$lang->project->menu->task = array('link' => '任務|project|task|projectID=%s', 'subModule' => 'task', 'alias' => 'grouptask,importtask,burn,importbug');
-$lang->project->menu->story = array('link' => '需求|project|story|projectID=%s', 'subModule' => 'story', 'alias' => 'linkstory');
-$lang->project->menu->bug = 'Bug|project|bug|projectID=%s';
-$lang->project->menu->dynamic = '動態|project|dynamic|projectID=%s';
-$lang->project->menu->build = array('link' => '版本|project|build|projectID=%s', 'subModule' => 'build');
-$lang->project->menu->testtask = '測試|project|testtask|projectID=%s';
-$lang->project->menu->team = array('link' => '團隊|project|team|projectID=%s', 'alias' => 'managemembers');
-$lang->project->menu->doc = array('link' => '文檔|project|doc|porjectID=%s', 'subModule' => 'doc');
-$lang->project->menu->product = '產品|project|manageproducts|projectID=%s';
-$lang->project->menu->view = array('link' => '維護|project|view|projectID=%s', 'alias' => 'edit');
-$lang->project->menu->order = '排序|project|order|projectID=%s';
-$lang->project->menu->create = array('link' => ' 新增項目|project|create', 'float' => 'right');
-$lang->project->menu->all = array('link' => ' 所有項目|project|index|locate=no&status=undone&projectID=%s', 'float' => 'right');
-
-$lang->task = new stdclass();
-$lang->build = new stdclass();
-$lang->task->menu = $lang->project->menu;
-$lang->build->menu = $lang->project->menu;
-
-/* QA視圖菜單設置。*/
-$lang->bug = new stdclass();
-$lang->bug->menu = new stdclass();
-
-$lang->bug->menu->product = '%s';
-$lang->bug->menu->bug = array('link' => '缺陷管理|bug|browse|productID=%s', 'alias' => 'view,create,edit,resolve,close,activate,report,batchedit', 'subModule' => 'tree');
-$lang->bug->menu->testcase = array('link' => '用例管理|testcase|browse|productID=%s', 'alias' => 'view,create,edit');
-$lang->bug->menu->testtask = array('link' => '測試任務|testtask|browse|productID=%s');
-
-$lang->testcase = new stdclass();
-$lang->testcase->menu = new stdclass();
-
-$lang->testcase->menu->product = '%s';
-$lang->testcase->menu->bug = array('link' => '缺陷管理|bug|browse|productID=%s');
-$lang->testcase->menu->testcase = array('link' => '用例管理|testcase|browse|productID=%s', 'alias' => 'view,create,batchcreate,edit,batchedit', 'subModule' => 'tree');
-$lang->testcase->menu->testtask = array('link' => '測試任務|testtask|browse|productID=%s', 'alias' => 'view,create,edit,linkcase,cases');
-
-$lang->testtask = new stdclass();
-$lang->testtask->menu = $lang->testcase->menu;
-
-/* 文檔視圖菜單設置。*/
-$lang->doc = new stdclass();
-$lang->doc->menu = new stdclass();
-
-$lang->doc->menu->list = '%s';
-$lang->doc->menu->browse = array('link' => '文檔列表|doc|browse|libID=%s', 'alias' => 'view,create,edit');
-$lang->doc->menu->edit = '編輯文檔庫|doc|editLib|libID=%s';
-$lang->doc->menu->module = '維護模組|tree|browse|libID=%s&viewType=doc';
-$lang->doc->menu->delete = array('link' => '刪除文檔庫|doc|deleteLib|libID=%s', 'target' => 'hiddenwin');
-$lang->doc->menu->create = array('link' => ' 新增文檔庫|doc|createLib', 'float' => 'right');
-
-/* 統計視圖菜單設置。*/
-$lang->report = new stdclass();
-$lang->report->menu = new stdclass();
-
-$lang->report->menu->product = array('link' => '產品|report|productinfo');
-$lang->report->menu->prj = array('link' => '項目|report|projectdeviation');
-$lang->report->menu->test = array('link' => '測試|report|bugsummary', 'alias' => 'bugassign');
-$lang->report->menu->staff = array('link' => '組織|report|workload');
-
-/* 資源視圖菜單設置。*/
-$lang->webapp = new stdclass();
-$lang->webapp->menu = new stdclass();
-//$lang->webapp->menu->obtain = array('link' => '應用商店|webapp|obtain', 'float' => 'right');
-
-/* 組織結構視圖菜單設置。*/
-$lang->company = new stdclass();
-$lang->company->menu = new stdclass();
-$lang->company->menu->name = '%s' . $lang->arrow;
-$lang->company->menu->browseUser = array('link' => '用戶|company|browse', 'subModule' => 'user');
-$lang->company->menu->dept = array('link' => '部門|dept|browse', 'subModule' => 'dept');
-$lang->company->menu->browseGroup = array('link' => '權限|group|browse', 'subModule' => 'group');
-$lang->company->menu->edit = array('link' => '公司|company|edit');
-$lang->company->menu->dynamic = '動態|company|dynamic|';
-$lang->company->menu->addGroup = array('link' => ' 添加分組|group|create', 'float' => 'right');
-$lang->company->menu->batchAddUser = array('link' => ' 批量添加|user|batchCreate', 'subModule' => 'user', 'float' => 'right');
-$lang->company->menu->addUser = array('link' => ' 添加用戶|user|create|dept=%s', 'subModule' => 'user', 'float' => 'right');
-
-$lang->dept = new stdclass();
-$lang->group = new stdclass();
-$lang->user = new stdclass();
-
-$lang->dept->menu = $lang->company->menu;
-$lang->group->menu = $lang->company->menu;
-$lang->user->menu = $lang->company->menu;
-
-/* 後台管理菜單設置。*/
-$lang->admin = new stdclass();
-$lang->admin->menu = new stdclass();
-$lang->admin->menu->index = array('link' => '首頁|admin|index');
-$lang->admin->menu->extension = array('link' => '插件|extension|browse', 'subModule' => 'extension');
-$lang->admin->menu->editor = array('link' => '擴展編輯器|editor|index', 'subModule' => 'editor');
-$lang->admin->menu->mail = array('link' => '發信|mail|index', 'subModule' => 'mail');
-$lang->admin->menu->clearData = array('link' => '重置|admin|cleardata');
-$lang->admin->menu->convert = array('link' => '導入|convert|index', 'subModule' => 'convert');
-$lang->admin->menu->trashes = array('link' => '資源回收筒|action|trash', 'subModule' => 'action');
-
-$lang->convert = new stdclass();
-$lang->upgrade = new stdclass();
-$lang->action = new stdclass();
-$lang->extension = new stdclass();
-$lang->editor = new stdclass();
-$lang->mail = new stdclass();
-
-$lang->convert->menu = $lang->admin->menu;
-$lang->upgrade->menu = $lang->admin->menu;
-$lang->action->menu = $lang->admin->menu;
-$lang->extension->menu = $lang->admin->menu;
-$lang->editor->menu = $lang->admin->menu;
-$lang->mail->menu = $lang->admin->menu;
-
-/* 菜單分組。*/
-$lang->menugroup = new stdclass();
-$lang->menugroup->release = 'product';
-$lang->menugroup->story = 'product';
-$lang->menugroup->productplan = 'product';
-$lang->menugroup->task = 'project';
-$lang->menugroup->build = 'project';
-$lang->menugroup->convert = 'admin';
-$lang->menugroup->upgrade = 'admin';
-$lang->menugroup->user = 'company';
-$lang->menugroup->group = 'company';
-$lang->menugroup->bug = 'qa';
-$lang->menugroup->testcase = 'qa';
-$lang->menugroup->testtask = 'qa';
-$lang->menugroup->people = 'company';
-$lang->menugroup->dept = 'company';
-$lang->menugroup->todo = 'my';
-$lang->menugroup->action = 'admin';
-$lang->menugroup->extension = 'admin';
-$lang->menugroup->editor = 'admin';
-$lang->menugroup->mail = 'admin';
-
-/* 錯誤提示信息。*/
-$lang->error = new stdclass();
-$lang->error->companyNotFound = "您訪問的域名 %s 沒有對應的公司。";
-$lang->error->length = array("『%s』長度錯誤,應當為『%s』", "『%s』長度應當不超過『%s』,且不小於『%s』。");
-$lang->error->reg = "『%s』不符合格式,應當為:『%s』。";
-$lang->error->unique = "『%s』已經有『%s』這條記錄了。如果您確定該記錄已刪除,請到後台管理-資源回收筒還原。。";
-$lang->error->gt = "『%s』應當大於『%s』。";
-$lang->error->ge = "『%s』應當不小於『%s』。";
-$lang->error->notempty = "『%s』不能為空。";
-$lang->error->empty = "『%s』必須為空。";
-$lang->error->equal = "『%s』必須為『%s』。";
-$lang->error->int = array("『%s』應當是數字。", "『%s』應當介於『%s-%s』之間。");
-$lang->error->float = "『%s』應當是數字,可以是小數。";
-$lang->error->email = "『%s』應當為合法的EMAIL。";
-$lang->error->date = "『%s』應當為合法的日期。";
-$lang->error->account = "『%s』應當為合法的用戶名。";
-$lang->error->passwordsame = "兩次密碼應當相等。";
-$lang->error->passwordrule = "密碼應該符合規則,長度至少為六位。";
-$lang->error->accessDenied = '您沒有訪問權限';
-
-/* 分頁信息。*/
-$lang->pager = new stdclass();
-$lang->pager->noRecord = "暫時沒有記錄";
-$lang->pager->digest = "共%s 條記錄,每頁 %s 條,%s/%s ";
-$lang->pager->first = "首頁";
-$lang->pager->pre = "上頁";
-$lang->pager->next = "下頁";
-$lang->pager->last = "末頁";
-$lang->pager->locate = "GO!";
-
-$lang->zentaoSite = "官方網站";
-$lang->chinaScrum = "Scrum社區 ";
-$lang->agileTraining = "培訓 ";
-$lang->donate = "捐贈 ";
-$lang->proVersion = "購買專業版(特惠)! ";
-$lang->downNotify = "下載桌面提醒";
-
-$lang->suhosinInfo = "警告:數據太多,請在php.ini中修改sohusin.post.max_vars 和sohusin.request.max_vars (設置更大的數)。 保存並重新啟動apache,否則會造成部分數據無法保存。";
-
-$lang->noResultsMatch = "沒有匹配結果";
-
-/* 時間格式設置。*/
-define('DT_DATETIME1', 'Y-m-d H:i:s');
-define('DT_DATETIME2', 'y-m-d H:i');
-define('DT_MONTHTIME1', 'n/d H:i');
-define('DT_MONTHTIME2', 'n月d日 H:i');
-define('DT_DATE1', 'Y-m-d');
-define('DT_DATE2', 'Ymd');
-define('DT_DATE3', 'Y年m月d日');
-define('DT_DATE4', 'n月j日');
-define('DT_TIME1', 'H:i:s');
-define('DT_TIME2', 'H:i');
-
-/* datepicker 時間*/
-$lang->datepicker = new stdclass();
-
-$lang->datepicker->dpText = new stdclass();
-$lang->datepicker->dpText->TEXT_OR = '或 ';
-$lang->datepicker->dpText->TEXT_PREV_YEAR = '去年';
-$lang->datepicker->dpText->TEXT_PREV_MONTH = '上月';
-$lang->datepicker->dpText->TEXT_PREV_WEEK = '上周';
-$lang->datepicker->dpText->TEXT_YESTERDAY = '昨天';
-$lang->datepicker->dpText->TEXT_THIS_MONTH = '本月';
-$lang->datepicker->dpText->TEXT_THIS_WEEK = '本週';
-$lang->datepicker->dpText->TEXT_TODAY = '今天';
-$lang->datepicker->dpText->TEXT_NEXT_YEAR = '明年';
-$lang->datepicker->dpText->TEXT_NEXT_MONTH = '下月';
-$lang->datepicker->dpText->TEXT_CLOSE = '關閉';
-$lang->datepicker->dpText->TEXT_DATE = '選擇時間段';
-$lang->datepicker->dpText->TEXT_CHOOSE_DATE = '選擇日期';
-
-$lang->datepicker->dayNames = array('日', '一', '二', '三', '四', '五', '六');
-$lang->datepicker->abbrDayNames = array('日', '一', '二', '三', '四', '五', '六');
-$lang->datepicker->monthNames = array('一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月');
-
-include (dirname(__FILE__) . '/menuOrder.php');
+
+ * @package ZenTaoPMS
+ * @version $Id: zh-tw.php 3864 2012-12-20 08:00:07Z wyd621@gmail.com $
+ * @link http://www.zentao.net
+ */
+$lang->arrow = ' ';
+$lang->colon = '::';
+$lang->comma = ',';
+$lang->dot = '。';
+$lang->at = ' 于 ';
+$lang->downArrow = '↓';
+
+$lang->ZenTaoPMS = '禪道管理';
+$lang->welcome = "歡迎使用『%s』{$lang->colon} {$lang->ZenTaoPMS}";
+$lang->myControl = "我的地盤";
+$lang->currentPos = '當前位置:';
+$lang->logout = '退出';
+$lang->login = '登錄';
+$lang->aboutZenTao = '關於';
+$lang->todayIs = '今天是%s,';
+$lang->runInfo = "時間: %s 毫秒, 內存: %s KB, 查詢: %s.
";
+
+$lang->reset = '重填';
+$lang->edit = '編輯';
+$lang->copy = '複製';
+$lang->delete = '刪除';
+$lang->close = '關閉';
+$lang->link = '關聯';
+$lang->unlink = '移除';
+$lang->import = '導入';
+$lang->export = '導出';
+$lang->exportType = '導出類型';
+$lang->setFileName = '檔案名:';
+$lang->activate = '激活';
+$lang->submitting = '稍候...';
+$lang->save = '保存';
+$lang->confirm = '確認';
+$lang->preview = '查看';
+$lang->goback = '返回';
+$lang->go = 'GO';
+$lang->more = '更多';
+
+$lang->actions = '操作';
+$lang->comment = '備註';
+$lang->history = '歷史記錄';
+$lang->attatch = '附件';
+$lang->reverse = '切換順序';
+$lang->switchDisplay= '切換顯示';
+$lang->switchHelp = '切換幫助';
+$lang->addFiles = '上傳了附件 ';
+$lang->files = '附件 ';
+$lang->unfold = '+';
+$lang->fold = '-';
+
+$lang->selectAll = '全選';
+$lang->selectReverse = '反選';
+$lang->notFound = '抱歉,您訪問的對象並不存在!';
+$lang->showAll = '++ 全部顯示 ++';
+$lang->hideClosed = '-- 隱藏已結束 --';
+
+$lang->future = '未來';
+$lang->year = '年';
+$lang->workingHour = '工時';
+
+$lang->idAB = 'ID';
+$lang->priAB = 'P';
+$lang->statusAB = '狀態';
+$lang->openedByAB = '創建';
+$lang->assignedToAB = '指派';
+$lang->typeAB = '類型';
+
+$lang->common = new stdclass();
+$lang->common->common = '公有模組';
+
+/* 主導航菜單。*/
+$lang->menu = new stdclass();
+$lang->menu->my = ' 我的地盤|my|index';
+$lang->menu->product = '產品|product|index';
+$lang->menu->project = '項目|project|index';
+$lang->menu->qa = '測試|qa|index';
+$lang->menu->doc = '文檔|doc|index';
+$lang->menu->report = '統計|report|index';
+//$lang->menu->webapp = '應用中心|webapp|index';
+$lang->menu->company = '組織|company|index';
+$lang->menu->admin = '管理|admin|index';
+
+/* 查詢條中可以選擇的對象列表。*/
+$lang->searchObjects['bug'] = 'B:Bug';
+$lang->searchObjects['story'] = 'S:需求';
+$lang->searchObjects['task'] = 'T:任務';
+$lang->searchObjects['testcase'] = 'C:用例';
+$lang->searchObjects['project'] = 'P:項目';
+$lang->searchObjects['product'] = 'P:產品';
+$lang->searchObjects['user'] = 'U:用戶';
+$lang->searchObjects['build'] = 'B:版本';
+$lang->searchObjects['release'] = 'R:發佈';
+$lang->searchObjects['productplan'] = 'P:產品計劃';
+$lang->searchObjects['testtask'] = 'T:測試任務';
+$lang->searchObjects['doc'] = 'D:文檔';
+$lang->searchTips = '編號(ctrl+g)';
+
+/* 導入支持的編碼格式。*/
+$lang->importEncodeList['gbk'] = 'GBK';
+$lang->importEncodeList['big5'] = 'BIG5';
+$lang->importEncodeList['utf-8'] = 'UTF-8';
+
+/* 導出檔案的類型列表。*/
+$lang->exportFileTypeList['csv'] = 'csv';
+$lang->exportFileTypeList['xml'] = 'xml';
+$lang->exportFileTypeList['html'] = 'html';
+
+$lang->exportTypeList['all'] = '導出全部';
+$lang->exportTypeList['selected'] = '導出選中';
+
+/* 支持的編碼格式。*/
+$lang->exportEncodeList['gbk'] = 'GBK';
+$lang->exportEncodeList['big5'] = 'BIG5';
+$lang->exportEncodeList['utf-8'] = 'UTF-8';
+
+/* 風格列表。*/
+$lang->themes['default'] = '預設';
+$lang->themes['green'] = '綠色';
+$lang->themes['red'] = '紅色';
+$lang->themes['classblue'] = '經典藍';
+
+/* 首頁菜單設置。*/
+$lang->index = new stdclass();
+$lang->index->menu = new stdclass();
+
+$lang->index->menu->product = '瀏覽產品|product|browse';
+$lang->index->menu->project = '瀏覽項目|project|browse';
+
+/* 我的地盤菜單設置。*/
+$lang->my = new stdclass();
+$lang->my->menu = new stdclass();
+
+$lang->my->menu->account = ' %s' . $lang->arrow;
+$lang->my->menu->index = '首頁|my|index';
+$lang->my->menu->todo = array('link' => '待辦|my|todo|', 'subModule' => 'todo');
+$lang->my->menu->task = '任務|my|task|';
+$lang->my->menu->bug = '缺陷|my|bug|';
+$lang->my->menu->testtask = array('link' => '測試|my|testtask|', 'alias' => 'testcase');
+$lang->my->menu->story = '需求|my|story|';
+$lang->my->menu->myProject = '項目|my|project|';
+$lang->my->menu->dynamic = '動態|my|dynamic|';
+$lang->my->menu->profile = array('link' => '檔案|my|profile|', 'alias' => 'editprofile');
+$lang->my->menu->changePassword = '密碼|my|changepassword|';
+
+$lang->todo = new stdclass();
+$lang->todo->menu = $lang->my->menu;
+
+/* 產品視圖設置。*/
+$lang->product = new stdclass();
+$lang->product->menu = new stdclass();
+
+$lang->product->menu->list = '%s';
+$lang->product->menu->story = array('link' => '需求|product|browse|productID=%s', 'alias' => 'batchedit', 'subModule' => 'story');
+$lang->product->menu->dynamic = '動態|product|dynamic|productID=%s';
+$lang->product->menu->plan = array('link' => '計劃|productplan|browse|productID=%s', 'subModule' => 'productplan');
+$lang->product->menu->release = array('link' => '發佈|release|browse|productID=%s', 'subModule' => 'release');
+$lang->product->menu->roadmap = '路線圖|product|roadmap|productID=%s';
+$lang->product->menu->doc = array('link' => '文檔|product|doc|productID=%s', 'subModule' => 'doc');
+$lang->product->menu->view = array('link' => '維護|product|view|productID=%s', 'alias' => 'edit');
+$lang->product->menu->module = '模組|tree|browse|productID=%s&view=story';
+$lang->product->menu->project = '項目|product|project|status=all&productID=%s';
+$lang->product->menu->order = '排序|product|order|productID=%s';
+$lang->product->menu->create = array('link' => ' 新增產品|product|create', 'float' => 'right');
+$lang->product->menu->all = array('link' => ' 所有產品|product|index|locate=no&productID=%s', 'float' => 'right');
+
+$lang->story = new stdclass();
+$lang->productplan = new stdclass();
+$lang->release = new stdclass();
+
+$lang->story->menu = $lang->product->menu;
+$lang->productplan->menu = $lang->product->menu;
+$lang->release->menu = $lang->product->menu;
+
+/* 項目視圖菜單設置。*/
+$lang->project = new stdclass();
+$lang->project->menu = new stdclass();
+
+$lang->project->menu->list = '%s';
+$lang->project->menu->task = array('link' => '任務|project|task|projectID=%s', 'subModule' => 'task', 'alias' => 'grouptask,importtask,burn,importbug');
+$lang->project->menu->story = array('link' => '需求|project|story|projectID=%s', 'subModule' => 'story', 'alias' => 'linkstory');
+$lang->project->menu->bug = 'Bug|project|bug|projectID=%s';
+$lang->project->menu->dynamic = '動態|project|dynamic|projectID=%s';
+$lang->project->menu->build = array('link' => '版本|project|build|projectID=%s', 'subModule' => 'build');
+$lang->project->menu->testtask = '測試|project|testtask|projectID=%s';
+$lang->project->menu->team = array('link' => '團隊|project|team|projectID=%s', 'alias' => 'managemembers');
+$lang->project->menu->doc = array('link' => '文檔|project|doc|porjectID=%s', 'subModule' => 'doc');
+$lang->project->menu->product = '產品|project|manageproducts|projectID=%s';
+$lang->project->menu->view = array('link' => '維護|project|view|projectID=%s', 'alias' => 'edit');
+$lang->project->menu->order = '排序|project|order|projectID=%s';
+$lang->project->menu->create = array('link' => ' 新增項目|project|create', 'float' => 'right');
+$lang->project->menu->all = array('link' => ' 所有項目|project|index|locate=no&status=undone&projectID=%s', 'float' => 'right');
+
+$lang->task = new stdclass();
+$lang->build = new stdclass();
+$lang->task->menu = $lang->project->menu;
+$lang->build->menu = $lang->project->menu;
+
+/* QA視圖菜單設置。*/
+$lang->bug = new stdclass();
+$lang->bug->menu = new stdclass();
+
+$lang->bug->menu->product = '%s';
+$lang->bug->menu->bug = array('link' => '缺陷管理|bug|browse|productID=%s', 'alias' => 'view,create,edit,resolve,close,activate,report,batchedit', 'subModule' => 'tree');
+$lang->bug->menu->testcase = array('link' => '用例管理|testcase|browse|productID=%s', 'alias' => 'view,create,edit');
+$lang->bug->menu->testtask = array('link' => '測試任務|testtask|browse|productID=%s');
+
+$lang->testcase = new stdclass();
+$lang->testcase->menu = new stdclass();
+
+$lang->testcase->menu->product = '%s';
+$lang->testcase->menu->bug = array('link' => '缺陷管理|bug|browse|productID=%s');
+$lang->testcase->menu->testcase = array('link' => '用例管理|testcase|browse|productID=%s', 'alias' => 'view,create,batchcreate,edit,batchedit', 'subModule' => 'tree');
+$lang->testcase->menu->testtask = array('link' => '測試任務|testtask|browse|productID=%s', 'alias' => 'view,create,edit,linkcase,cases');
+
+$lang->testtask = new stdclass();
+$lang->testtask->menu = $lang->testcase->menu;
+
+/* 文檔視圖菜單設置。*/
+$lang->doc = new stdclass();
+$lang->doc->menu = new stdclass();
+
+$lang->doc->menu->list = '%s';
+$lang->doc->menu->browse = array('link' => '文檔列表|doc|browse|libID=%s', 'alias' => 'view,create,edit');
+$lang->doc->menu->edit = '編輯文檔庫|doc|editLib|libID=%s';
+$lang->doc->menu->module = '維護模組|tree|browse|libID=%s&viewType=doc';
+$lang->doc->menu->delete = array('link' => '刪除文檔庫|doc|deleteLib|libID=%s', 'target' => 'hiddenwin');
+$lang->doc->menu->create = array('link' => ' 新增文檔庫|doc|createLib', 'float' => 'right');
+
+/* 統計視圖菜單設置。*/
+$lang->report = new stdclass();
+$lang->report->menu = new stdclass();
+
+$lang->report->menu->product = array('link' => '產品|report|productinfo');
+$lang->report->menu->prj = array('link' => '項目|report|projectdeviation');
+$lang->report->menu->test = array('link' => '測試|report|bugsummary', 'alias' => 'bugassign');
+$lang->report->menu->staff = array('link' => '組織|report|workload');
+
+/* 資源視圖菜單設置。*/
+$lang->webapp = new stdclass();
+$lang->webapp->menu = new stdclass();
+//$lang->webapp->menu->obtain = array('link' => '應用商店|webapp|obtain', 'float' => 'right');
+
+/* 組織結構視圖菜單設置。*/
+$lang->company = new stdclass();
+$lang->company->menu = new stdclass();
+$lang->company->menu->name = '%s' . $lang->arrow;
+$lang->company->menu->browseUser = array('link' => '用戶|company|browse', 'subModule' => 'user');
+$lang->company->menu->dept = array('link' => '部門|dept|browse', 'subModule' => 'dept');
+$lang->company->menu->browseGroup = array('link' => '權限|group|browse', 'subModule' => 'group');
+$lang->company->menu->edit = array('link' => '公司|company|edit');
+$lang->company->menu->dynamic = '動態|company|dynamic|';
+$lang->company->menu->addGroup = array('link' => ' 添加分組|group|create', 'float' => 'right');
+$lang->company->menu->batchAddUser = array('link' => ' 批量添加|user|batchCreate', 'subModule' => 'user', 'float' => 'right');
+$lang->company->menu->addUser = array('link' => ' 添加用戶|user|create|dept=%s', 'subModule' => 'user', 'float' => 'right');
+
+$lang->dept = new stdclass();
+$lang->group = new stdclass();
+$lang->user = new stdclass();
+
+$lang->dept->menu = $lang->company->menu;
+$lang->group->menu = $lang->company->menu;
+$lang->user->menu = $lang->company->menu;
+
+/* 後台管理菜單設置。*/
+$lang->admin = new stdclass();
+$lang->admin->menu = new stdclass();
+$lang->admin->menu->index = array('link' => '首頁|admin|index');
+$lang->admin->menu->extension = array('link' => '插件|extension|browse', 'subModule' => 'extension');
+$lang->admin->menu->editor = array('link' => '擴展編輯器|editor|index', 'subModule' => 'editor');
+$lang->admin->menu->mail = array('link' => '發信|mail|index', 'subModule' => 'mail');
+$lang->admin->menu->clearData = array('link' => '重置|admin|cleardata');
+$lang->admin->menu->convert = array('link' => '導入|convert|index', 'subModule' => 'convert');
+$lang->admin->menu->trashes = array('link' => '資源回收筒|action|trash', 'subModule' => 'action');
+
+$lang->convert = new stdclass();
+$lang->upgrade = new stdclass();
+$lang->action = new stdclass();
+$lang->extension = new stdclass();
+$lang->editor = new stdclass();
+$lang->mail = new stdclass();
+
+$lang->convert->menu = $lang->admin->menu;
+$lang->upgrade->menu = $lang->admin->menu;
+$lang->action->menu = $lang->admin->menu;
+$lang->extension->menu = $lang->admin->menu;
+$lang->editor->menu = $lang->admin->menu;
+$lang->mail->menu = $lang->admin->menu;
+
+/* 菜單分組。*/
+$lang->menugroup = new stdclass();
+$lang->menugroup->release = 'product';
+$lang->menugroup->story = 'product';
+$lang->menugroup->productplan = 'product';
+$lang->menugroup->task = 'project';
+$lang->menugroup->build = 'project';
+$lang->menugroup->convert = 'admin';
+$lang->menugroup->upgrade = 'admin';
+$lang->menugroup->user = 'company';
+$lang->menugroup->group = 'company';
+$lang->menugroup->bug = 'qa';
+$lang->menugroup->testcase = 'qa';
+$lang->menugroup->testtask = 'qa';
+$lang->menugroup->people = 'company';
+$lang->menugroup->dept = 'company';
+$lang->menugroup->todo = 'my';
+$lang->menugroup->action = 'admin';
+$lang->menugroup->extension = 'admin';
+$lang->menugroup->editor = 'admin';
+$lang->menugroup->mail = 'admin';
+
+/* 錯誤提示信息。*/
+$lang->error = new stdclass();
+$lang->error->companyNotFound = "您訪問的域名 %s 沒有對應的公司。";
+$lang->error->length = array("『%s』長度錯誤,應當為『%s』", "『%s』長度應當不超過『%s』,且不小於『%s』。");
+$lang->error->reg = "『%s』不符合格式,應當為:『%s』。";
+$lang->error->unique = "『%s』已經有『%s』這條記錄了。如果您確定該記錄已刪除,請到後台管理-資源回收筒還原。。";
+$lang->error->gt = "『%s』應當大於『%s』。";
+$lang->error->ge = "『%s』應當不小於『%s』。";
+$lang->error->notempty = "『%s』不能為空。";
+$lang->error->empty = "『%s』必須為空。";
+$lang->error->equal = "『%s』必須為『%s』。";
+$lang->error->int = array("『%s』應當是數字。", "『%s』應當介於『%s-%s』之間。");
+$lang->error->float = "『%s』應當是數字,可以是小數。";
+$lang->error->email = "『%s』應當為合法的EMAIL。";
+$lang->error->date = "『%s』應當為合法的日期。";
+$lang->error->account = "『%s』應當為合法的用戶名。";
+$lang->error->passwordsame = "兩次密碼應當相等。";
+$lang->error->passwordrule = "密碼應該符合規則,長度至少為六位。";
+$lang->error->accessDenied = '您沒有訪問權限';
+
+/* 分頁信息。*/
+$lang->pager = new stdclass();
+$lang->pager->noRecord = "暫時沒有記錄";
+$lang->pager->digest = "共%s 條記錄,每頁 %s 條,%s/%s ";
+$lang->pager->first = "首頁";
+$lang->pager->pre = "上頁";
+$lang->pager->next = "下頁";
+$lang->pager->last = "末頁";
+$lang->pager->locate = "GO!";
+
+$lang->zentaoSite = "官方網站";
+$lang->chinaScrum = "Scrum社區 ";
+$lang->agileTraining = "培訓 ";
+$lang->donate = "捐贈 ";
+$lang->proVersion = "購買專業版(特惠)! ";
+$lang->downNotify = "下載桌面提醒";
+
+$lang->suhosinInfo = "警告:數據太多,請在php.ini中修改sohusin.post.max_vars 和sohusin.request.max_vars (設置更大的數)。 保存並重新啟動apache,否則會造成部分數據無法保存。";
+
+$lang->noResultsMatch = "沒有匹配結果";
+
+/* 時間格式設置。*/
+define('DT_DATETIME1', 'Y-m-d H:i:s');
+define('DT_DATETIME2', 'y-m-d H:i');
+define('DT_MONTHTIME1', 'n/d H:i');
+define('DT_MONTHTIME2', 'n月d日 H:i');
+define('DT_DATE1', 'Y-m-d');
+define('DT_DATE2', 'Ymd');
+define('DT_DATE3', 'Y年m月d日');
+define('DT_DATE4', 'n月j日');
+define('DT_TIME1', 'H:i:s');
+define('DT_TIME2', 'H:i');
+
+/* datepicker 時間*/
+$lang->datepicker = new stdclass();
+
+$lang->datepicker->dpText = new stdclass();
+$lang->datepicker->dpText->TEXT_OR = '或 ';
+$lang->datepicker->dpText->TEXT_PREV_YEAR = '去年';
+$lang->datepicker->dpText->TEXT_PREV_MONTH = '上月';
+$lang->datepicker->dpText->TEXT_PREV_WEEK = '上周';
+$lang->datepicker->dpText->TEXT_YESTERDAY = '昨天';
+$lang->datepicker->dpText->TEXT_THIS_MONTH = '本月';
+$lang->datepicker->dpText->TEXT_THIS_WEEK = '本週';
+$lang->datepicker->dpText->TEXT_TODAY = '今天';
+$lang->datepicker->dpText->TEXT_NEXT_YEAR = '明年';
+$lang->datepicker->dpText->TEXT_NEXT_MONTH = '下月';
+$lang->datepicker->dpText->TEXT_CLOSE = '關閉';
+$lang->datepicker->dpText->TEXT_DATE = '選擇時間段';
+$lang->datepicker->dpText->TEXT_CHOOSE_DATE = '選擇日期';
+
+$lang->datepicker->dayNames = array('日', '一', '二', '三', '四', '五', '六');
+$lang->datepicker->abbrDayNames = array('日', '一', '二', '三', '四', '五', '六');
+$lang->datepicker->monthNames = array('一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月');
+
+include (dirname(__FILE__) . '/menuOrder.php');
diff --git a/module/common/model.php b/module/common/model.php
index 84f902590c..e97ff2b958 100644
--- a/module/common/model.php
+++ b/module/common/model.php
@@ -1,620 +1,620 @@
-
- * @package common
- * @version $Id$
- * @link http://www.zentao.net
- */
-class commonModel extends model
-{
- /**
- * Start the session.
- *
- * @access public
- * @return void
- */
- public function startSession()
- {
- session_name($this->config->sessionVar);
- if(isset($_GET[$this->config->sessionVar])) session_id($_GET[$this->config->sessionVar]);
- session_start();
- }
-
- /**
- * Set the header info.
- *
- * @access public
- * @return void
- */
- public function sendHeader()
- {
- header("Content-Type: text/html; Language={$this->config->encoding}");
- header("Cache-control: private");
- }
-
- /**
- * Set the commpany.
- *
- * First, search company by the http host. If not found, search by the default domain. Last, use the first as the default.
- * After get the company, save it to session.
- * @access public
- * @return void
- */
- public function setCompany()
- {
- $httpHost = $this->server->http_host;
- if(strpos($httpHost, ":"))
- {
- $httpHost = explode(":", $httpHost);
- $httpHost = $httpHost[0];
- }
-
- if($this->session->company and $this->session->company->pms == $httpHost)
- {
- $this->app->company = $this->session->company;
- }
- else
- {
- $company = $this->loadModel('company')->getByDomain();
- if(!$company and isset($this->config->default->domain)) $company = $this->company->getByDomain($this->config->default->domain);
- if(!$company) $company = $this->company->getFirst();
- if(!$company) $this->app->error(sprintf($this->lang->error->companyNotFound, $httpHost), __FILE__, __LINE__, $exit = true);
- $this->session->set('company', $company);
- $this->app->company = $company;
- }
- }
-
- /**
- * Set the user info.
- *
- * @access public
- * @return void
- */
- public function setUser()
- {
- if($this->session->user)
- {
- $this->app->user = $this->session->user;
- }
- elseif($this->app->company->guest)
- {
- $user = new stdClass();
- $user->id = 0;
- $user->account = 'guest';
- $user->realname = 'guest';
- $user->role = 'guest';
- $user->rights = $this->loadModel('user')->authorize('guest');
- $this->session->set('user', $user);
- $this->app->user = $this->session->user;
- }
- }
-
- /**
- * Load configs from database and save it to config->system and config->personal.
- *
- * @access public
- * @return void
- */
- public function loadConfigFromDB()
- {
- /* Get configs of system and current user. */
- $account = isset($this->app->user->account) ? $this->app->user->account : '';
- $config = $this->loadModel('setting')->getSysAndPersonalConfig($account);
- $this->config->system = isset($config['system']) ? $config['system'] : array();
- $this->config->personal = isset($config[$account]) ? $config[$account] : array();
-
- /* Overide the items defined in config/config.php and config/my.php. */
- if(isset($this->config->system->common))
- {
- foreach($this->config->system->common as $record)
- {
- if($record->section)
- {
- if(!isset($this->config->{$record->section})) $this->config->{$record->section} = new stdclass();
- $this->config->{$record->section}->{$record->key} = $record->value;
- }
- else
- {
- if(!$record->section) $this->config->{$record->key} = $record->value;
- }
- }
- }
- }
-
- /**
- * Juage a method of one module is open or not?
- *
- * @param string $module
- * @param string $method
- * @access public
- * @return bool
- */
- public function isOpenMethod($module, $method)
- {
- if($module == 'user' and strpos('login|logout|deny', $method) !== false) return true;
- if($module == 'api' and $method == 'getsessionid') return true;
-
- if($this->loadModel('user')->isLogon())
- {
- if(stripos($method, 'ajax') !== false) return true;
- if(stripos($method, 'downnotify') !== false) return true;
- }
-
- if($module == 'misc' and $method == 'about') return true;
- if($module == 'misc' and $method == 'checkupdate') return true;
- if($module == 'help' and $method == 'field') return true;
- return false;
- }
-
- /**
- * Deny access.
- *
- * @access public
- * @return void
- */
- public function deny($module, $method)
- {
- $vars = "module=$module&method=$method";
- if(isset($this->server->http_referer))
- {
- $referer = helper::safe64Encode($this->server->http_referer);
- $vars .= "&referer=$referer";
- }
- $denyLink = helper::createLink('user', 'deny', $vars);
-
- /* Fix the bug of IE: use js locate, can't get the referer. */
- if(strpos($this->server->http_user_agent, 'MSIE') !== false)
- {
- echo "deny ";
- echo "";
- }
- else
- {
- echo js::locate($denyLink);
- }
- exit;
- }
-
- /**
- * Get the run info.
- *
- * @param mixed $startTime the start time of this execution
- * @access public
- * @return array the run info array.
- */
- public function getRunInfo($startTime)
- {
- $info['timeUsed'] = round(getTime() - $startTime, 4) * 1000;
- $info['memory'] = round(memory_get_peak_usage() / 1024, 1);
- $info['querys'] = count(dao::$querys);
- return $info;
- }
-
- /**
- * Print top bar.
- *
- * @static
- * @access public
- * @return void
- */
- public static function printTopBar()
- {
- global $lang, $app;
-
- printf($lang->todayIs, date(DT_DATE4));
- if(isset($app->user)) echo $app->user->realname . ' ';
- if(isset($app->user) and $app->user->account != 'guest')
- {
- echo html::a(helper::createLink('user', 'logout'), $lang->logout);
- }
- else
- {
- echo html::a(helper::createLink('user', 'login'), $lang->login);
- }
-
- echo ' | ';
- echo html::a(helper::createLink('misc', 'about'), $lang->aboutZenTao, '', "class='about'");
- echo $lang->agileTraining;
- echo $lang->donate;
-
- echo ' | ';
- echo html::select('', $app->config->langs, $app->cookie->lang, 'onchange="selectLang(this.value)"');
- echo html::select('', $app->lang->themes, $app->cookie->theme, 'onchange="selectTheme(this.value)"');
- }
-
- /**
- * Print the main menu.
- *
- * @param string $moduleName
- * @static
- * @access public
- * @return void
- */
- public static function printMainmenu($moduleName)
- {
- global $app, $lang;
- echo "\n";
-
- /* Set the main main menu. */
- $mainMenu = $moduleName;
- if(isset($lang->menugroup->$moduleName)) $mainMenu = $lang->menugroup->$moduleName;
-
- /* Sort menu according to menuOrder. */
- if(isset($lang->menuOrder))
- {
- $menus = $lang->menu;
- $lang->menu = new stdclass();
-
- ksort($lang->menuOrder, SORT_ASC);
- foreach($lang->menuOrder as $key)
- {
- $menu = $menus->$key;
- unset($menus->$key);
- $lang->menu->$key = $menu;
- }
- foreach($menus as $key => $menu)
- {
- $lang->menu->$key = $menu;
- }
- }
-
- /* Print all main menus. */
- foreach($lang->menu as $menuKey => $menu)
- {
- $active = $menuKey == $mainMenu ? "class='active'" : '';
- list($menuLabel, $module, $method) = explode('|', $menu);
-
- if(common::hasPriv($module, $method))
- {
- $link = helper::createLink($module, $method);
- echo " \n";
- }
- }
-
- }
-
- /**
- * Print the search box.
- *
- * @static
- * @access public
- * @return void
- */
- public static function printSearchBox()
- {
- global $app, $lang;
- $moduleName = $app->getModuleName();
- $methodName = $app->getMethodName();
- $searchObject = $moduleName;
-
- if($moduleName == 'product')
- {
- if($methodName == 'browse') $searchObject = 'story';
- }
- elseif($moduleName == 'project')
- {
- if(strpos('task|story|bug|build', $methodName) !== false) $searchObject = $methodName;
- }
- elseif($moduleName == 'my' or $moduleName == 'user')
- {
- $searchObject = $methodName;
- }
-
- echo "";
- echo html::select('searchType', $lang->searchObjects, $searchObject);
- echo html::input('searchQuery', $lang->searchTips, "onclick=this.value='' onkeydown='if(event.keyCode==13) shortcut()' class='w-80px'");
- echo " ";
- echo " ";
- echo " \n";
- }
-
- /**
- * Print the module menu.
- *
- * @param string $moduleName
- * @static
- * @access public
- * @return void
- */
- public static function printModuleMenu($moduleName)
- {
- global $lang, $app;
-
- if(!isset($lang->$moduleName->menu)) {echo ""; return;}
-
- /* Get the sub menus of the module, and get current module and method. */
- $submenus = $lang->$moduleName->menu;
- $currentModule = $app->getModuleName();
- $currentMethod = $app->getMethodName();
-
- /* Sort the subMenu according to menuOrder. */
- if(isset($lang->$moduleName->menuOrder))
- {
- $menus = $submenus;
- $submenus = new stdclass();
-
- ksort($lang->$moduleName->menuOrder, SORT_ASC);
- if(isset($menus->list))
- {
- $submenus->list = $menus->list;
- unset($menus->list);
- }
- foreach($lang->$moduleName->menuOrder as $order)
- {
- if(($order != 'list') && isset($menus->$order))
- {
- $subOrder = $menus->$order;
- unset($menus->$order);
- $submenus->$order = $subOrder;
- }
- }
- foreach($menus as $key => $menu)
- {
- $submenus->$key = $menu;
- }
- }
-
- /* The beginning of the menu. */
- echo "\n";
-
- /* Cycling to print every sub menus. */
- foreach($submenus as $subMenuKey => $submenu)
- {
- /* Init the these vars. */
- $link = $submenu;
- $subModule = '';
- $alias = '';
- $float = '';
- $active = '';
- $target = '';
-
- if(is_array($submenu)) extract($submenu); // If the sub menu is an array, extract it.
-
- /* Print the menu. */
- if(strpos($link, '|') === false)
- {
- echo "$link \n";
- }
- else
- {
- $link = explode('|', $link);
- list($label, $module, $method) = $link;
- $vars = isset($link[3]) ? $link[3] : '';
- if(common::hasPriv($module, $method))
- {
- /* Is the currentModule active? */
- if($currentModule == $subModule and $float != 'right') $active = 'active';
- if($module == $currentModule and ($method == $currentMethod or strpos(",$alias,", ",$currentMethod,") !== false) and $float != 'right') $active = 'active';
- echo "" . html::a(helper::createLink($module, $method, $vars), $label, $target, "id=submenu$subMenuKey") . " \n";
- }
- }
- }
- echo " \n";
- }
-
- /**
- * Print the bread menu.
- *
- * @param string $moduleName
- * @param string $position
- * @static
- * @access public
- * @return void
- */
- public static function printBreadMenu($moduleName, $position)
- {
- global $lang;
- $mainMenu = $moduleName;
- if(isset($lang->menugroup->$moduleName)) $mainMenu = $lang->menugroup->$moduleName;
- echo html::a(helper::createLink('my', 'index'), $lang->ZenTaoPMS) . $lang->arrow;
- if($moduleName != 'index')
- {
- list($menuLabel, $module, $method) = explode('|', $lang->menu->$mainMenu);
- echo html::a(helper::createLink($module, $method), $menuLabel);
- }
- else
- {
- echo $lang->index->common;
- }
- if(empty($position)) return;
- echo $lang->arrow;
- foreach($position as $key => $link)
- {
- echo $link;
- if(isset($position[$key + 1])) echo $lang->arrow;
- }
- }
-
- /**
- * Print the link for notify file.
- *
- * @static
- * @access public
- * @return void
- */
- public static function printNotifyLink()
- {
- if(strpos(strtolower($_SERVER['HTTP_USER_AGENT']), 'windows') !== false)
- {
- global $app, $lang;
- $notifyFile = $app->getBasePath() . 'www/data/notify/notify.zip';
-
- if(!file_exists($notifyFile)) return false;
- echo html::a(helper::createLink('misc', 'downNotify'), $lang->downNotify);
- }
- }
-
- /**
- * Diff two string. (see phpt)
- *
- * @param string $text1
- * @param string $text2
- * @static
- * @access public
- * @return string
- */
- public static function diff($text1, $text2)
- {
- $text1 = str_replace(' ', '', trim($text1));
- $text2 = str_replace(' ', '', trim($text2));
- $w = explode("\n", $text1);
- $o = explode("\n", $text2);
- $w1 = array_diff_assoc($w,$o);
- $o1 = array_diff_assoc($o,$w);
- $w2 = array();
- $o2 = array();
- foreach($w1 as $idx => $val) $w2[sprintf("%03d<",$idx)] = sprintf("%03d- ", $idx+1) . "" . trim($val) . "";
- foreach($o1 as $idx => $val) $o2[sprintf("%03d>",$idx)] = sprintf("%03d+ ", $idx+1) . "" . trim($val) . " ";
- $diff = array_merge($w2, $o2);
- ksort($diff);
- return implode("\n", $diff);
- }
-
- /**
- * Judge Suhosin Setting whether the actual size of post data is large than the setting size.
- *
- * @param int $numberOfItems
- * @param int $columns
- * @access public
- * @return void
- */
- public function judgeSuhosinSetting($numberOfItems, $columns)
- {
- if(extension_loaded('suhosin'))
- {
- $maxPostVars = ini_get('suhosin.post.max_vars');
- $maxRequestVars = ini_get('suhosin.request.max_vars');
- if($numberOfItems * $columns > $maxPostVars or $numberOfItems * $columns > $maxRequestVars) return true;
- }
-
- return false;
- }
-
- /**
- * Get the previous and next object.
- *
- * @param string $type story|task|bug|case
- * @param string $objectIDs
- * @param string $objectID
- * @access public
- * @return void
- */
- public function getPreAndNextObject($type, $objectID)
- {
- $preAndNextObject = new stdClass();
-
- if(strpos('story, task, bug, testcase, doc', $type) === false) return $preAndNextObject;
- $table = $this->config->objectTables[$type];
-
- $typeIDs = $type . 'IDs';
- if($this->session->$typeIDs and strpos($this->session->$typeIDs, ',' . $objectID . ',') !== false)
- {
- $objectIDs = $this->session->$typeIDs;
- $this->session->set($typeIDs, '');
- }
- else
- {
- /* Get objectIDs. */
- $queryCondition = $type . 'QueryCondition';
- $typeOnlyCondition = $type . 'OnlyCondition';
- $queryCondition = $this->session->$queryCondition;
- $orderBy = $type . 'OrderBy';
- $orderBy = $this->session->$orderBy;
- $orderBy = str_replace('`left`', 'left', $orderBy); // process the `left` to left.
-
- if(empty($queryCondition) or $this->session->$typeOnlyCondition)
- {
- $objects = $this->dao->select('*')->from($table)
- ->beginIF($queryCondition != false)->where($queryCondition)->fi()
- ->beginIF($orderBy != false)->orderBy($orderBy)->fi()
- ->fetchAll();
- }
- else
- {
- $objects = $this->dbh->query($queryCondition . " ORDER BY $orderBy")->fetchAll();
- }
-
- $tmpObjectIDs = array();
- foreach($objects as $object) $tmpObjectIDs[$object->id] = (!$this->session->$typeOnlyCondition and $type == 'testcase' and isset($object->case)) ? $object->case : $object->id;
- $objectIDs = ',' . implode(',', $tmpObjectIDs) . ',';
- $this->session->set($type . 'IDs', $objectIDs);
- }
-
- /* Current object. */
- $currentStart = strpos($objectIDs, ',' . $objectID . ',') + 1;
- $currentEnd = $currentStart + strlen($objectID) - 1;
-
- /* Get the previous object. */
- $tmp = substr($objectIDs, 0, $currentStart - 1);
- $preStart = strrpos($tmp, ',', 0) + 1;
- $preEnd = $currentStart - 2;
- if($preEnd - $preStart < 0)
- {
- $preAndNextObject->pre = '';
- }
- else
- {
- $preID = substr($objectIDs, $preStart, $preEnd - $preStart + 1);
- $preAndNextObject->pre = $this->dao->select('*')->from($table)->where('id')->eq($preID)->fetch();
- }
-
- /* Get the next object. */
- $nextStart = $currentEnd + 2;
- $nextEnd = strlen($objectIDs) > $nextStart ? strpos($objectIDs, ',', $nextStart) - 1 : 0;
- if($nextEnd - $nextStart < 0)
- {
- $preAndNextObject->next = '';
- }
- else
- {
- $nextID = substr($objectIDs, $nextStart, $nextEnd - $nextStart + 1);
- $preAndNextObject->next = $this->dao->select('*')->from($table)->where('id')->eq($nextID)->fetch();
- }
-
- return $preAndNextObject;
- }
-
- /**
- * Save one executed query.
- *
- * @param string $sql
- * @param string $objectType story|task|bug|testcase
- * @access public
- * @return void
- */
- public function saveQueryCondition($sql, $objectType, $onlyCondition = true)
- {
- /* Set the query condition session. */
- if($onlyCondition)
- {
- $queryCondition = explode('WHERE', $sql);
- $queryCondition = explode('ORDER', $queryCondition[1]);
- $queryCondition = str_replace('t1.', '', $queryCondition[0]);
- }
- else
- {
- $queryCondition = explode('ORDER', $sql);
- $queryCondition = $queryCondition[0];
- }
-
- $this->session->set($objectType . 'QueryCondition', $queryCondition);
- $this->session->set($objectType . 'OnlyCondition', $onlyCondition);
-
- /* Set the query condition session. */
- $orderBy = explode('ORDER BY', $sql);
- if(isset($orderBy[1]))
- {
- $orderBy = explode('limit', $orderBy[1]);
- $orderBy = str_replace('t1.', '', $orderBy[0]);
- $this->session->set($objectType . 'OrderBy', $orderBy);
- }
- else
- {
- $this->session->set($objectType . 'OrderBy', '');
- }
- }
-}
+
+ * @package common
+ * @version $Id$
+ * @link http://www.zentao.net
+ */
+class commonModel extends model
+{
+ /**
+ * Start the session.
+ *
+ * @access public
+ * @return void
+ */
+ public function startSession()
+ {
+ session_name($this->config->sessionVar);
+ if(isset($_GET[$this->config->sessionVar])) session_id($_GET[$this->config->sessionVar]);
+ session_start();
+ }
+
+ /**
+ * Set the header info.
+ *
+ * @access public
+ * @return void
+ */
+ public function sendHeader()
+ {
+ header("Content-Type: text/html; Language={$this->config->encoding}");
+ header("Cache-control: private");
+ }
+
+ /**
+ * Set the commpany.
+ *
+ * First, search company by the http host. If not found, search by the default domain. Last, use the first as the default.
+ * After get the company, save it to session.
+ * @access public
+ * @return void
+ */
+ public function setCompany()
+ {
+ $httpHost = $this->server->http_host;
+ if(strpos($httpHost, ":"))
+ {
+ $httpHost = explode(":", $httpHost);
+ $httpHost = $httpHost[0];
+ }
+
+ if($this->session->company and $this->session->company->pms == $httpHost)
+ {
+ $this->app->company = $this->session->company;
+ }
+ else
+ {
+ $company = $this->loadModel('company')->getByDomain();
+ if(!$company and isset($this->config->default->domain)) $company = $this->company->getByDomain($this->config->default->domain);
+ if(!$company) $company = $this->company->getFirst();
+ if(!$company) $this->app->error(sprintf($this->lang->error->companyNotFound, $httpHost), __FILE__, __LINE__, $exit = true);
+ $this->session->set('company', $company);
+ $this->app->company = $company;
+ }
+ }
+
+ /**
+ * Set the user info.
+ *
+ * @access public
+ * @return void
+ */
+ public function setUser()
+ {
+ if($this->session->user)
+ {
+ $this->app->user = $this->session->user;
+ }
+ elseif($this->app->company->guest)
+ {
+ $user = new stdClass();
+ $user->id = 0;
+ $user->account = 'guest';
+ $user->realname = 'guest';
+ $user->role = 'guest';
+ $user->rights = $this->loadModel('user')->authorize('guest');
+ $this->session->set('user', $user);
+ $this->app->user = $this->session->user;
+ }
+ }
+
+ /**
+ * Load configs from database and save it to config->system and config->personal.
+ *
+ * @access public
+ * @return void
+ */
+ public function loadConfigFromDB()
+ {
+ /* Get configs of system and current user. */
+ $account = isset($this->app->user->account) ? $this->app->user->account : '';
+ $config = $this->loadModel('setting')->getSysAndPersonalConfig($account);
+ $this->config->system = isset($config['system']) ? $config['system'] : array();
+ $this->config->personal = isset($config[$account]) ? $config[$account] : array();
+
+ /* Overide the items defined in config/config.php and config/my.php. */
+ if(isset($this->config->system->common))
+ {
+ foreach($this->config->system->common as $record)
+ {
+ if($record->section)
+ {
+ if(!isset($this->config->{$record->section})) $this->config->{$record->section} = new stdclass();
+ $this->config->{$record->section}->{$record->key} = $record->value;
+ }
+ else
+ {
+ if(!$record->section) $this->config->{$record->key} = $record->value;
+ }
+ }
+ }
+ }
+
+ /**
+ * Juage a method of one module is open or not?
+ *
+ * @param string $module
+ * @param string $method
+ * @access public
+ * @return bool
+ */
+ public function isOpenMethod($module, $method)
+ {
+ if($module == 'user' and strpos('login|logout|deny', $method) !== false) return true;
+ if($module == 'api' and $method == 'getsessionid') return true;
+
+ if($this->loadModel('user')->isLogon())
+ {
+ if(stripos($method, 'ajax') !== false) return true;
+ if(stripos($method, 'downnotify') !== false) return true;
+ }
+
+ if($module == 'misc' and $method == 'about') return true;
+ if($module == 'misc' and $method == 'checkupdate') return true;
+ if($module == 'help' and $method == 'field') return true;
+ return false;
+ }
+
+ /**
+ * Deny access.
+ *
+ * @access public
+ * @return void
+ */
+ public function deny($module, $method)
+ {
+ $vars = "module=$module&method=$method";
+ if(isset($this->server->http_referer))
+ {
+ $referer = helper::safe64Encode($this->server->http_referer);
+ $vars .= "&referer=$referer";
+ }
+ $denyLink = helper::createLink('user', 'deny', $vars);
+
+ /* Fix the bug of IE: use js locate, can't get the referer. */
+ if(strpos($this->server->http_user_agent, 'MSIE') !== false)
+ {
+ echo "deny ";
+ echo "";
+ }
+ else
+ {
+ echo js::locate($denyLink);
+ }
+ exit;
+ }
+
+ /**
+ * Get the run info.
+ *
+ * @param mixed $startTime the start time of this execution
+ * @access public
+ * @return array the run info array.
+ */
+ public function getRunInfo($startTime)
+ {
+ $info['timeUsed'] = round(getTime() - $startTime, 4) * 1000;
+ $info['memory'] = round(memory_get_peak_usage() / 1024, 1);
+ $info['querys'] = count(dao::$querys);
+ return $info;
+ }
+
+ /**
+ * Print top bar.
+ *
+ * @static
+ * @access public
+ * @return void
+ */
+ public static function printTopBar()
+ {
+ global $lang, $app;
+
+ printf($lang->todayIs, date(DT_DATE4));
+ if(isset($app->user)) echo $app->user->realname . ' ';
+ if(isset($app->user) and $app->user->account != 'guest')
+ {
+ echo html::a(helper::createLink('user', 'logout'), $lang->logout);
+ }
+ else
+ {
+ echo html::a(helper::createLink('user', 'login'), $lang->login);
+ }
+
+ echo ' | ';
+ echo html::a(helper::createLink('misc', 'about'), $lang->aboutZenTao, '', "class='about'");
+ echo $lang->agileTraining;
+ echo $lang->donate;
+
+ echo ' | ';
+ echo html::select('', $app->config->langs, $app->cookie->lang, 'onchange="selectLang(this.value)"');
+ echo html::select('', $app->lang->themes, $app->cookie->theme, 'onchange="selectTheme(this.value)"');
+ }
+
+ /**
+ * Print the main menu.
+ *
+ * @param string $moduleName
+ * @static
+ * @access public
+ * @return void
+ */
+ public static function printMainmenu($moduleName)
+ {
+ global $app, $lang;
+ echo "\n";
+
+ /* Set the main main menu. */
+ $mainMenu = $moduleName;
+ if(isset($lang->menugroup->$moduleName)) $mainMenu = $lang->menugroup->$moduleName;
+
+ /* Sort menu according to menuOrder. */
+ if(isset($lang->menuOrder))
+ {
+ $menus = $lang->menu;
+ $lang->menu = new stdclass();
+
+ ksort($lang->menuOrder, SORT_ASC);
+ foreach($lang->menuOrder as $key)
+ {
+ $menu = $menus->$key;
+ unset($menus->$key);
+ $lang->menu->$key = $menu;
+ }
+ foreach($menus as $key => $menu)
+ {
+ $lang->menu->$key = $menu;
+ }
+ }
+
+ /* Print all main menus. */
+ foreach($lang->menu as $menuKey => $menu)
+ {
+ $active = $menuKey == $mainMenu ? "class='active'" : '';
+ list($menuLabel, $module, $method) = explode('|', $menu);
+
+ if(common::hasPriv($module, $method))
+ {
+ $link = helper::createLink($module, $method);
+ echo " \n";
+ }
+ }
+
+ }
+
+ /**
+ * Print the search box.
+ *
+ * @static
+ * @access public
+ * @return void
+ */
+ public static function printSearchBox()
+ {
+ global $app, $lang;
+ $moduleName = $app->getModuleName();
+ $methodName = $app->getMethodName();
+ $searchObject = $moduleName;
+
+ if($moduleName == 'product')
+ {
+ if($methodName == 'browse') $searchObject = 'story';
+ }
+ elseif($moduleName == 'project')
+ {
+ if(strpos('task|story|bug|build', $methodName) !== false) $searchObject = $methodName;
+ }
+ elseif($moduleName == 'my' or $moduleName == 'user')
+ {
+ $searchObject = $methodName;
+ }
+
+ echo "";
+ echo html::select('searchType', $lang->searchObjects, $searchObject);
+ echo html::input('searchQuery', $lang->searchTips, "onclick=this.value='' onkeydown='if(event.keyCode==13) shortcut()' class='w-80px'");
+ echo " ";
+ echo " ";
+ echo " \n";
+ }
+
+ /**
+ * Print the module menu.
+ *
+ * @param string $moduleName
+ * @static
+ * @access public
+ * @return void
+ */
+ public static function printModuleMenu($moduleName)
+ {
+ global $lang, $app;
+
+ if(!isset($lang->$moduleName->menu)) {echo ""; return;}
+
+ /* Get the sub menus of the module, and get current module and method. */
+ $submenus = $lang->$moduleName->menu;
+ $currentModule = $app->getModuleName();
+ $currentMethod = $app->getMethodName();
+
+ /* Sort the subMenu according to menuOrder. */
+ if(isset($lang->$moduleName->menuOrder))
+ {
+ $menus = $submenus;
+ $submenus = new stdclass();
+
+ ksort($lang->$moduleName->menuOrder, SORT_ASC);
+ if(isset($menus->list))
+ {
+ $submenus->list = $menus->list;
+ unset($menus->list);
+ }
+ foreach($lang->$moduleName->menuOrder as $order)
+ {
+ if(($order != 'list') && isset($menus->$order))
+ {
+ $subOrder = $menus->$order;
+ unset($menus->$order);
+ $submenus->$order = $subOrder;
+ }
+ }
+ foreach($menus as $key => $menu)
+ {
+ $submenus->$key = $menu;
+ }
+ }
+
+ /* The beginning of the menu. */
+ echo "\n";
+
+ /* Cycling to print every sub menus. */
+ foreach($submenus as $subMenuKey => $submenu)
+ {
+ /* Init the these vars. */
+ $link = $submenu;
+ $subModule = '';
+ $alias = '';
+ $float = '';
+ $active = '';
+ $target = '';
+
+ if(is_array($submenu)) extract($submenu); // If the sub menu is an array, extract it.
+
+ /* Print the menu. */
+ if(strpos($link, '|') === false)
+ {
+ echo "$link \n";
+ }
+ else
+ {
+ $link = explode('|', $link);
+ list($label, $module, $method) = $link;
+ $vars = isset($link[3]) ? $link[3] : '';
+ if(common::hasPriv($module, $method))
+ {
+ /* Is the currentModule active? */
+ if($currentModule == $subModule and $float != 'right') $active = 'active';
+ if($module == $currentModule and ($method == $currentMethod or strpos(",$alias,", ",$currentMethod,") !== false) and $float != 'right') $active = 'active';
+ echo "" . html::a(helper::createLink($module, $method, $vars), $label, $target, "id=submenu$subMenuKey") . " \n";
+ }
+ }
+ }
+ echo " \n";
+ }
+
+ /**
+ * Print the bread menu.
+ *
+ * @param string $moduleName
+ * @param string $position
+ * @static
+ * @access public
+ * @return void
+ */
+ public static function printBreadMenu($moduleName, $position)
+ {
+ global $lang;
+ $mainMenu = $moduleName;
+ if(isset($lang->menugroup->$moduleName)) $mainMenu = $lang->menugroup->$moduleName;
+ echo html::a(helper::createLink('my', 'index'), $lang->ZenTaoPMS) . $lang->arrow;
+ if($moduleName != 'index')
+ {
+ list($menuLabel, $module, $method) = explode('|', $lang->menu->$mainMenu);
+ echo html::a(helper::createLink($module, $method), $menuLabel);
+ }
+ else
+ {
+ echo $lang->index->common;
+ }
+ if(empty($position)) return;
+ echo $lang->arrow;
+ foreach($position as $key => $link)
+ {
+ echo $link;
+ if(isset($position[$key + 1])) echo $lang->arrow;
+ }
+ }
+
+ /**
+ * Print the link for notify file.
+ *
+ * @static
+ * @access public
+ * @return void
+ */
+ public static function printNotifyLink()
+ {
+ if(strpos(strtolower($_SERVER['HTTP_USER_AGENT']), 'windows') !== false)
+ {
+ global $app, $lang;
+ $notifyFile = $app->getBasePath() . 'www/data/notify/notify.zip';
+
+ if(!file_exists($notifyFile)) return false;
+ echo html::a(helper::createLink('misc', 'downNotify'), $lang->downNotify);
+ }
+ }
+
+ /**
+ * Diff two string. (see phpt)
+ *
+ * @param string $text1
+ * @param string $text2
+ * @static
+ * @access public
+ * @return string
+ */
+ public static function diff($text1, $text2)
+ {
+ $text1 = str_replace(' ', '', trim($text1));
+ $text2 = str_replace(' ', '', trim($text2));
+ $w = explode("\n", $text1);
+ $o = explode("\n", $text2);
+ $w1 = array_diff_assoc($w,$o);
+ $o1 = array_diff_assoc($o,$w);
+ $w2 = array();
+ $o2 = array();
+ foreach($w1 as $idx => $val) $w2[sprintf("%03d<",$idx)] = sprintf("%03d- ", $idx+1) . "" . trim($val) . "";
+ foreach($o1 as $idx => $val) $o2[sprintf("%03d>",$idx)] = sprintf("%03d+ ", $idx+1) . "" . trim($val) . " ";
+ $diff = array_merge($w2, $o2);
+ ksort($diff);
+ return implode("\n", $diff);
+ }
+
+ /**
+ * Judge Suhosin Setting whether the actual size of post data is large than the setting size.
+ *
+ * @param int $numberOfItems
+ * @param int $columns
+ * @access public
+ * @return void
+ */
+ public function judgeSuhosinSetting($numberOfItems, $columns)
+ {
+ if(extension_loaded('suhosin'))
+ {
+ $maxPostVars = ini_get('suhosin.post.max_vars');
+ $maxRequestVars = ini_get('suhosin.request.max_vars');
+ if($numberOfItems * $columns > $maxPostVars or $numberOfItems * $columns > $maxRequestVars) return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Get the previous and next object.
+ *
+ * @param string $type story|task|bug|case
+ * @param string $objectIDs
+ * @param string $objectID
+ * @access public
+ * @return void
+ */
+ public function getPreAndNextObject($type, $objectID)
+ {
+ $preAndNextObject = new stdClass();
+
+ if(strpos('story, task, bug, testcase, doc', $type) === false) return $preAndNextObject;
+ $table = $this->config->objectTables[$type];
+
+ $typeIDs = $type . 'IDs';
+ if($this->session->$typeIDs and strpos($this->session->$typeIDs, ',' . $objectID . ',') !== false)
+ {
+ $objectIDs = $this->session->$typeIDs;
+ $this->session->set($typeIDs, '');
+ }
+ else
+ {
+ /* Get objectIDs. */
+ $queryCondition = $type . 'QueryCondition';
+ $typeOnlyCondition = $type . 'OnlyCondition';
+ $queryCondition = $this->session->$queryCondition;
+ $orderBy = $type . 'OrderBy';
+ $orderBy = $this->session->$orderBy;
+ $orderBy = str_replace('`left`', 'left', $orderBy); // process the `left` to left.
+
+ if(empty($queryCondition) or $this->session->$typeOnlyCondition)
+ {
+ $objects = $this->dao->select('*')->from($table)
+ ->beginIF($queryCondition != false)->where($queryCondition)->fi()
+ ->beginIF($orderBy != false)->orderBy($orderBy)->fi()
+ ->fetchAll();
+ }
+ else
+ {
+ $objects = $this->dbh->query($queryCondition . " ORDER BY $orderBy")->fetchAll();
+ }
+
+ $tmpObjectIDs = array();
+ foreach($objects as $object) $tmpObjectIDs[$object->id] = (!$this->session->$typeOnlyCondition and $type == 'testcase' and isset($object->case)) ? $object->case : $object->id;
+ $objectIDs = ',' . implode(',', $tmpObjectIDs) . ',';
+ $this->session->set($type . 'IDs', $objectIDs);
+ }
+
+ /* Current object. */
+ $currentStart = strpos($objectIDs, ',' . $objectID . ',') + 1;
+ $currentEnd = $currentStart + strlen($objectID) - 1;
+
+ /* Get the previous object. */
+ $tmp = substr($objectIDs, 0, $currentStart - 1);
+ $preStart = strrpos($tmp, ',', 0) + 1;
+ $preEnd = $currentStart - 2;
+ if($preEnd - $preStart < 0)
+ {
+ $preAndNextObject->pre = '';
+ }
+ else
+ {
+ $preID = substr($objectIDs, $preStart, $preEnd - $preStart + 1);
+ $preAndNextObject->pre = $this->dao->select('*')->from($table)->where('id')->eq($preID)->fetch();
+ }
+
+ /* Get the next object. */
+ $nextStart = $currentEnd + 2;
+ $nextEnd = strlen($objectIDs) > $nextStart ? strpos($objectIDs, ',', $nextStart) - 1 : 0;
+ if($nextEnd - $nextStart < 0)
+ {
+ $preAndNextObject->next = '';
+ }
+ else
+ {
+ $nextID = substr($objectIDs, $nextStart, $nextEnd - $nextStart + 1);
+ $preAndNextObject->next = $this->dao->select('*')->from($table)->where('id')->eq($nextID)->fetch();
+ }
+
+ return $preAndNextObject;
+ }
+
+ /**
+ * Save one executed query.
+ *
+ * @param string $sql
+ * @param string $objectType story|task|bug|testcase
+ * @access public
+ * @return void
+ */
+ public function saveQueryCondition($sql, $objectType, $onlyCondition = true)
+ {
+ /* Set the query condition session. */
+ if($onlyCondition)
+ {
+ $queryCondition = explode('WHERE', $sql);
+ $queryCondition = explode('ORDER', $queryCondition[1]);
+ $queryCondition = str_replace('t1.', '', $queryCondition[0]);
+ }
+ else
+ {
+ $queryCondition = explode('ORDER', $sql);
+ $queryCondition = $queryCondition[0];
+ }
+
+ $this->session->set($objectType . 'QueryCondition', $queryCondition);
+ $this->session->set($objectType . 'OnlyCondition', $onlyCondition);
+
+ /* Set the query condition session. */
+ $orderBy = explode('ORDER BY', $sql);
+ if(isset($orderBy[1]))
+ {
+ $orderBy = explode('limit', $orderBy[1]);
+ $orderBy = str_replace('t1.', '', $orderBy[0]);
+ $this->session->set($objectType . 'OrderBy', $orderBy);
+ }
+ else
+ {
+ $this->session->set($objectType . 'OrderBy', '');
+ }
+ }
+}
diff --git a/module/company/control.php b/module/company/control.php
index 1a87a91b2e..91f580d589 100644
--- a/module/company/control.php
+++ b/module/company/control.php
@@ -1,280 +1,280 @@
-
- * @package company
- * @version $Id$
- * @link http://www.zentao.net
- */
-class company extends control
-{
- /**
- * Construct function, load dept and user models auto.
- *
- * @access public
- * @return void
- */
- public function __construct()
- {
- parent::__construct();
- $this->loadModel('dept');
- $this->company->setMenu();
- }
-
- /**
- * Index page, header to browse.
- *
- * @access public
- * @return void
- */
- public function index()
- {
- $this->locate($this->createLink('company', 'browse'));
- }
-
- /**
- * Browse departments and users of a company.
- *
- * @param int $deptID
- * @access public
- * @return void
- */
- public function browse($param = 0, $type = 'bydept', $orderBy = 'id', $recTotal = 0, $recPerPage = 20, $pageID = 1)
- {
- $this->loadModel('search');
- $this->lang->set('menugroup.company', 'company');
-
- $deptID = $type == 'bydept' ? (int)$param : 0;
- $this->company->setMenu($deptID);
-
- /* Set the pager. */
- $this->app->loadClass('pager', $static = true);
- $pager = pager::init($recTotal, $recPerPage, $pageID);
-
- /* Build the search form. */
- $queryID = $type == 'bydept' ? 0 : (int)$param;
- $this->config->company->browse->search['actionURL'] = $this->createLink('company', 'browse', "param=myQueryID&type=bysearch");
- $this->config->company->browse->search['queryID'] = $queryID;
- $this->config->company->browse->search['params']['dept']['values'] = array('' => '') + $this->dept->getOptionMenu();
-
- $header['title'] = $this->lang->company->index . $this->lang->colon . $this->lang->dept->common;
- $position[] = $this->lang->dept->common;
-
- if($type == 'bydept')
- {
- $childDeptIds = $this->dept->getAllChildID($deptID);
- $users = $this->dept->getUsers($childDeptIds, $pager, $orderBy);
- }
- else
- {
- if($queryID)
- {
- $query = $this->search->getQuery($queryID);
- if($query)
- {
- $this->session->set('userQuery', $query->sql);
- $this->session->set('userForm', $query->form);
- }
- else
- {
- $this->session->set('userQuery', ' 1 = 1');
- }
- }
- $users = $this->loadModel('user')->getByQuery($this->session->userQuery, $pager, $orderBy);
- }
-
- $this->view->header = $header;
- $this->view->position = $position;
- $this->view->users = $users;
- $this->view->searchForm = $this->fetch('search', 'buildForm', $this->config->company->browse->search);
- $this->view->deptTree = $this->dept->getTreeMenu($rooteDeptID = 0, array('deptModel', 'createMemberLink'));
- $this->view->parentDepts = $this->dept->getParents($deptID);
- $this->view->orderBy = $orderBy;
- $this->view->deptID = $deptID;
- $this->view->pager = $pager;
- $this->view->param = $param;
- $this->view->type = $type;
-
- $this->display();
- }
-
- /**
- * Create a company.
- *
- * @access public
- * @return void
- */
- public function create()
- {
- if(!empty($_POST))
- {
- $this->company->create();
- if(dao::isError()) die(js::error(dao::getError()));
- die(js::locate($this->createLink('admin', 'browsecompany'), 'parent'));
- }
-
- $this->lang->set('menugroup.company', 'admin');
- $this->lang->company->menu = $this->lang->admin->menu;
- $this->lang->company->menuOrder = $this->lang->admin->menuOrder;
-
- $header['title'] = $this->lang->admin->common . $this->lang->colon . $this->lang->company->create;
- $position[] = html::a($this->createLink('admin', 'browsecompany'), $this->lang->admin->company);
- $position[] = $this->lang->company->create;
- $this->view->header = $header;
- $this->view->position = $position;
-
- $this->display();
- }
-
- /**
- * Edit a company.
- *
- * @access public
- * @return void
- */
- public function edit()
- {
- if(!empty($_POST))
- {
- $this->company->update();
- if(dao::isError()) die(js::error(dao::getError()));
-
- /* reset company in session. */
- $company = $this->loadModel('company')->getByDomain();
- $this->session->set('company', $company);
-
- die(js::alert($this->lang->company->successSaved));
- }
-
- $header['title'] = $this->lang->company->common . $this->lang->colon . $this->lang->company->edit;
- $position[] = $this->lang->company->edit;
- $this->view->header = $header;
- $this->view->position = $position;
- $this->view->company = $this->company->getById($this->app->company->id);
-
- $this->display();
- }
-
- /**
- * Delete a company.
- *
- * @param int $companyID
- * @param string $confirm yes|no
- * @access public
- * @return void
- */
- public function delete($companyID, $confirm = 'no')
- {
- if($confirm == 'no')
- {
- echo js::confirm($this->lang->company->confirmDelete, $this->createLink('company', 'delete', "companyID=$companyID&confirm=yes"));
- exit;
- }
- else
- {
- $this->company->delete($companyID);
- echo js::locate($this->createLink('admin', 'browseCompany'), 'parent');
- exit;
- }
- }
-
- /**
- * Company dynamic.
- *
- * @param string $browseType
- * @param string $orderBy
- * @param int $recTotal
- * @param int $recPerPage
- * @param int $pageID
- * @access public
- * @return void
- */
- public function dynamic($browseType = 'today', $param = '', $orderBy = 'date_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1)
- {
- $this->app->loadLang('user');
- $this->app->loadLang('project');
- $this->loadModel('action');
-
- /* Save session. */
- $uri = $this->app->getURI(true);
- $this->session->set('productList', $uri);
- $this->session->set('productPlanList', $uri);
- $this->session->set('releaseList', $uri);
- $this->session->set('storyList', $uri);
- $this->session->set('projectList', $uri);
- $this->session->set('taskList', $uri);
- $this->session->set('buildList', $uri);
- $this->session->set('bugList', $uri);
- $this->session->set('caseList', $uri);
- $this->session->set('testtaskList', $uri);
-
- /* Set the pager. */
- $this->app->loadClass('pager', $static = true);
- $pager = pager::init($recTotal, $recPerPage, $pageID);
- $this->view->orderBy = $orderBy;
- $this->view->pager = $pager;
-
- /* Set the user and type. */
- $account = $browseType == 'account' ? $param : 'all';
- $product = $browseType == 'product' ? $param : 'all';
- $project = $browseType == 'project' ? $param : 'all';
- $period = ($browseType == 'account' or $browseType == 'product' or $browseType == 'project') ? 'all' : $browseType;
- $queryID = ($browseType == 'bysearch') ? (int)$param : 0;
-
- /* Get products' list.*/
- $products = $this->loadModel('product')->getPairs();
- $products = array($this->lang->product->select) + $products;
- $this->view->products = $products;
-
- /* Get projects' list.*/
- $projects = $this->loadModel('project')->getPairs();
- $projects = array($this->lang->project->select) + $projects;
- $this->view->projects = $projects;
-
- /* Get users.*/
- $users = $this->loadModel('user')->getPairs('nodeleted|noclosed');
- $users[''] = $this->lang->user->select;
- $this->view->users = $users;
-
- /* The header and position. */
- $this->view->header->title = $this->lang->company->common . $this->lang->colon . $this->lang->company->dynamic;
- $this->view->position[] = $this->lang->company->dynamic;
-
- /* Get actions. */
- if($browseType != 'bysearch')
- {
- $actions = $this->action->getDynamic($account, $period, $orderBy, $pager, $product, $project);
- }
- else
- {
- $actions = $this->action->getDynamicBySearch($products, $projects, $queryID, $orderBy, $pager);
- }
-
- /* Build search form. */
- $projects[0] = '';
- $products[0] = '';
- $users[''] = '';
- ksort($projects);
- ksort($products);
- $projects['all'] = $this->lang->project->allProject;
- $products['all'] = $this->lang->product->allProduct;
- $this->config->company->dynamic->search['actionURL'] = $this->createLink('company', 'dynamic', "browseType=bysearch¶m=myQueryID");
- $this->config->company->dynamic->search['queryID'] = $queryID;
- $this->config->company->dynamic->search['params']['project']['values'] = $projects;
- $this->config->company->dynamic->search['params']['product']['values'] = $products;
- $this->config->company->dynamic->search['params']['actor']['values'] = $users;
- $this->loadModel('search')->setSearchParams($this->config->company->dynamic->search);
-
- /* Assign. */
- $this->view->browseType = $browseType;
- $this->view->account = $account;
- $this->view->product = $product;
- $this->view->project = $project;
- $this->view->queryID = $queryID;
- $this->view->actions = $actions;
- $this->display();
- }
-}
+
+ * @package company
+ * @version $Id$
+ * @link http://www.zentao.net
+ */
+class company extends control
+{
+ /**
+ * Construct function, load dept and user models auto.
+ *
+ * @access public
+ * @return void
+ */
+ public function __construct()
+ {
+ parent::__construct();
+ $this->loadModel('dept');
+ $this->company->setMenu();
+ }
+
+ /**
+ * Index page, header to browse.
+ *
+ * @access public
+ * @return void
+ */
+ public function index()
+ {
+ $this->locate($this->createLink('company', 'browse'));
+ }
+
+ /**
+ * Browse departments and users of a company.
+ *
+ * @param int $deptID
+ * @access public
+ * @return void
+ */
+ public function browse($param = 0, $type = 'bydept', $orderBy = 'id', $recTotal = 0, $recPerPage = 20, $pageID = 1)
+ {
+ $this->loadModel('search');
+ $this->lang->set('menugroup.company', 'company');
+
+ $deptID = $type == 'bydept' ? (int)$param : 0;
+ $this->company->setMenu($deptID);
+
+ /* Set the pager. */
+ $this->app->loadClass('pager', $static = true);
+ $pager = pager::init($recTotal, $recPerPage, $pageID);
+
+ /* Build the search form. */
+ $queryID = $type == 'bydept' ? 0 : (int)$param;
+ $this->config->company->browse->search['actionURL'] = $this->createLink('company', 'browse', "param=myQueryID&type=bysearch");
+ $this->config->company->browse->search['queryID'] = $queryID;
+ $this->config->company->browse->search['params']['dept']['values'] = array('' => '') + $this->dept->getOptionMenu();
+
+ $header['title'] = $this->lang->company->index . $this->lang->colon . $this->lang->dept->common;
+ $position[] = $this->lang->dept->common;
+
+ if($type == 'bydept')
+ {
+ $childDeptIds = $this->dept->getAllChildID($deptID);
+ $users = $this->dept->getUsers($childDeptIds, $pager, $orderBy);
+ }
+ else
+ {
+ if($queryID)
+ {
+ $query = $this->search->getQuery($queryID);
+ if($query)
+ {
+ $this->session->set('userQuery', $query->sql);
+ $this->session->set('userForm', $query->form);
+ }
+ else
+ {
+ $this->session->set('userQuery', ' 1 = 1');
+ }
+ }
+ $users = $this->loadModel('user')->getByQuery($this->session->userQuery, $pager, $orderBy);
+ }
+
+ $this->view->header = $header;
+ $this->view->position = $position;
+ $this->view->users = $users;
+ $this->view->searchForm = $this->fetch('search', 'buildForm', $this->config->company->browse->search);
+ $this->view->deptTree = $this->dept->getTreeMenu($rooteDeptID = 0, array('deptModel', 'createMemberLink'));
+ $this->view->parentDepts = $this->dept->getParents($deptID);
+ $this->view->orderBy = $orderBy;
+ $this->view->deptID = $deptID;
+ $this->view->pager = $pager;
+ $this->view->param = $param;
+ $this->view->type = $type;
+
+ $this->display();
+ }
+
+ /**
+ * Create a company.
+ *
+ * @access public
+ * @return void
+ */
+ public function create()
+ {
+ if(!empty($_POST))
+ {
+ $this->company->create();
+ if(dao::isError()) die(js::error(dao::getError()));
+ die(js::locate($this->createLink('admin', 'browsecompany'), 'parent'));
+ }
+
+ $this->lang->set('menugroup.company', 'admin');
+ $this->lang->company->menu = $this->lang->admin->menu;
+ $this->lang->company->menuOrder = $this->lang->admin->menuOrder;
+
+ $header['title'] = $this->lang->admin->common . $this->lang->colon . $this->lang->company->create;
+ $position[] = html::a($this->createLink('admin', 'browsecompany'), $this->lang->admin->company);
+ $position[] = $this->lang->company->create;
+ $this->view->header = $header;
+ $this->view->position = $position;
+
+ $this->display();
+ }
+
+ /**
+ * Edit a company.
+ *
+ * @access public
+ * @return void
+ */
+ public function edit()
+ {
+ if(!empty($_POST))
+ {
+ $this->company->update();
+ if(dao::isError()) die(js::error(dao::getError()));
+
+ /* reset company in session. */
+ $company = $this->loadModel('company')->getByDomain();
+ $this->session->set('company', $company);
+
+ die(js::alert($this->lang->company->successSaved));
+ }
+
+ $header['title'] = $this->lang->company->common . $this->lang->colon . $this->lang->company->edit;
+ $position[] = $this->lang->company->edit;
+ $this->view->header = $header;
+ $this->view->position = $position;
+ $this->view->company = $this->company->getById($this->app->company->id);
+
+ $this->display();
+ }
+
+ /**
+ * Delete a company.
+ *
+ * @param int $companyID
+ * @param string $confirm yes|no
+ * @access public
+ * @return void
+ */
+ public function delete($companyID, $confirm = 'no')
+ {
+ if($confirm == 'no')
+ {
+ echo js::confirm($this->lang->company->confirmDelete, $this->createLink('company', 'delete', "companyID=$companyID&confirm=yes"));
+ exit;
+ }
+ else
+ {
+ $this->company->delete($companyID);
+ echo js::locate($this->createLink('admin', 'browseCompany'), 'parent');
+ exit;
+ }
+ }
+
+ /**
+ * Company dynamic.
+ *
+ * @param string $browseType
+ * @param string $orderBy
+ * @param int $recTotal
+ * @param int $recPerPage
+ * @param int $pageID
+ * @access public
+ * @return void
+ */
+ public function dynamic($browseType = 'today', $param = '', $orderBy = 'date_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1)
+ {
+ $this->app->loadLang('user');
+ $this->app->loadLang('project');
+ $this->loadModel('action');
+
+ /* Save session. */
+ $uri = $this->app->getURI(true);
+ $this->session->set('productList', $uri);
+ $this->session->set('productPlanList', $uri);
+ $this->session->set('releaseList', $uri);
+ $this->session->set('storyList', $uri);
+ $this->session->set('projectList', $uri);
+ $this->session->set('taskList', $uri);
+ $this->session->set('buildList', $uri);
+ $this->session->set('bugList', $uri);
+ $this->session->set('caseList', $uri);
+ $this->session->set('testtaskList', $uri);
+
+ /* Set the pager. */
+ $this->app->loadClass('pager', $static = true);
+ $pager = pager::init($recTotal, $recPerPage, $pageID);
+ $this->view->orderBy = $orderBy;
+ $this->view->pager = $pager;
+
+ /* Set the user and type. */
+ $account = $browseType == 'account' ? $param : 'all';
+ $product = $browseType == 'product' ? $param : 'all';
+ $project = $browseType == 'project' ? $param : 'all';
+ $period = ($browseType == 'account' or $browseType == 'product' or $browseType == 'project') ? 'all' : $browseType;
+ $queryID = ($browseType == 'bysearch') ? (int)$param : 0;
+
+ /* Get products' list.*/
+ $products = $this->loadModel('product')->getPairs();
+ $products = array($this->lang->product->select) + $products;
+ $this->view->products = $products;
+
+ /* Get projects' list.*/
+ $projects = $this->loadModel('project')->getPairs();
+ $projects = array($this->lang->project->select) + $projects;
+ $this->view->projects = $projects;
+
+ /* Get users.*/
+ $users = $this->loadModel('user')->getPairs('nodeleted|noclosed');
+ $users[''] = $this->lang->user->select;
+ $this->view->users = $users;
+
+ /* The header and position. */
+ $this->view->header->title = $this->lang->company->common . $this->lang->colon . $this->lang->company->dynamic;
+ $this->view->position[] = $this->lang->company->dynamic;
+
+ /* Get actions. */
+ if($browseType != 'bysearch')
+ {
+ $actions = $this->action->getDynamic($account, $period, $orderBy, $pager, $product, $project);
+ }
+ else
+ {
+ $actions = $this->action->getDynamicBySearch($products, $projects, $queryID, $orderBy, $pager);
+ }
+
+ /* Build search form. */
+ $projects[0] = '';
+ $products[0] = '';
+ $users[''] = '';
+ ksort($projects);
+ ksort($products);
+ $projects['all'] = $this->lang->project->allProject;
+ $products['all'] = $this->lang->product->allProduct;
+ $this->config->company->dynamic->search['actionURL'] = $this->createLink('company', 'dynamic', "browseType=bysearch¶m=myQueryID");
+ $this->config->company->dynamic->search['queryID'] = $queryID;
+ $this->config->company->dynamic->search['params']['project']['values'] = $projects;
+ $this->config->company->dynamic->search['params']['product']['values'] = $products;
+ $this->config->company->dynamic->search['params']['actor']['values'] = $users;
+ $this->loadModel('search')->setSearchParams($this->config->company->dynamic->search);
+
+ /* Assign. */
+ $this->view->browseType = $browseType;
+ $this->view->account = $account;
+ $this->view->product = $product;
+ $this->view->project = $project;
+ $this->view->queryID = $queryID;
+ $this->view->actions = $actions;
+ $this->display();
+ }
+}
diff --git a/module/company/lang/en.php b/module/company/lang/en.php
index 667deabd55..21fcc0c3d7 100644
--- a/module/company/lang/en.php
+++ b/module/company/lang/en.php
@@ -1,39 +1,39 @@
-
- * @package company
- * @version $Id$
- * @link http://www.zentao.net
- */
-$lang->company->common = 'Company';
-$lang->company->index = "Index";
-$lang->company->create = "Create";
-$lang->company->edit = "Edit";
-$lang->company->read = "Info";
-$lang->company->update = "Update";
-$lang->company->delete = "Delete";
-$lang->company->browse = "User";
-$lang->company->dynamic = "Dynamic";
-$lang->company->depts = "Dept";
-$lang->company->orgView = 'Company';
-
-$lang->company->confirmDelete = "Are you sure to delete this company?";
-$lang->company->successSaved = "Success saved";
-
-$lang->company->id = 'ID';
-$lang->company->name = 'Name';
-$lang->company->phone = 'Phone';
-$lang->company->fax = 'Fax';
-$lang->company->address = 'Address';
-$lang->company->zipcode = 'Zipcode';
-$lang->company->website = 'Web site';
-$lang->company->backyard = 'Internal Site';
-$lang->company->pms = 'ZenTaoPMS Site';
-$lang->company->guest = 'Guest visit';
-
-$lang->company->guestList[0] = 'Deny';
-$lang->company->guestList[1] = 'Allow';
+
+ * @package company
+ * @version $Id$
+ * @link http://www.zentao.net
+ */
+$lang->company->common = 'Company';
+$lang->company->index = "Index";
+$lang->company->create = "Create";
+$lang->company->edit = "Edit";
+$lang->company->read = "Info";
+$lang->company->update = "Update";
+$lang->company->delete = "Delete";
+$lang->company->browse = "User";
+$lang->company->dynamic = "Dynamic";
+$lang->company->depts = "Dept";
+$lang->company->orgView = 'Company';
+
+$lang->company->confirmDelete = "Are you sure to delete this company?";
+$lang->company->successSaved = "Success saved";
+
+$lang->company->id = 'ID';
+$lang->company->name = 'Name';
+$lang->company->phone = 'Phone';
+$lang->company->fax = 'Fax';
+$lang->company->address = 'Address';
+$lang->company->zipcode = 'Zipcode';
+$lang->company->website = 'Web site';
+$lang->company->backyard = 'Internal Site';
+$lang->company->pms = 'ZenTaoPMS Site';
+$lang->company->guest = 'Guest visit';
+
+$lang->company->guestList[0] = 'Deny';
+$lang->company->guestList[1] = 'Allow';
diff --git a/module/company/lang/zh-cn.php b/module/company/lang/zh-cn.php
index 40bc8e8001..f5b2621ba0 100644
--- a/module/company/lang/zh-cn.php
+++ b/module/company/lang/zh-cn.php
@@ -1,39 +1,39 @@
-
- * @package company
- * @version $Id$
- * @link http://www.zentao.net
- */
-$lang->company->common = '组织视图';
-$lang->company->index = "组织视图首页";
-$lang->company->create = "新增公司";
-$lang->company->edit = "编辑公司";
-$lang->company->read = "公司信息";
-$lang->company->update = "更新公司";
-$lang->company->delete = "删除公司";
-$lang->company->browse = "用户列表";
-$lang->company->dynamic = "组织动态";
-$lang->company->depts = "部门列表";
-$lang->company->orgView = '组织视图';
-
-$lang->company->confirmDelete = "您确定删除该公司吗?";
-$lang->company->successSaved = "成功保存";
-
-$lang->company->id = '编号';
-$lang->company->name = '公司名称';
-$lang->company->phone = '联系电话';
-$lang->company->fax = '传真';
-$lang->company->address = '通讯地址';
-$lang->company->zipcode = '邮政编码';
-$lang->company->website = '公司官网';
-$lang->company->backyard = '公司内网';
-$lang->company->pms = 'PMS网站';
-$lang->company->guest = '匿名登录';
-
-$lang->company->guestList[0] = '不允许';
-$lang->company->guestList[1] = '允许';
+
+ * @package company
+ * @version $Id$
+ * @link http://www.zentao.net
+ */
+$lang->company->common = '组织视图';
+$lang->company->index = "组织视图首页";
+$lang->company->create = "新增公司";
+$lang->company->edit = "编辑公司";
+$lang->company->read = "公司信息";
+$lang->company->update = "更新公司";
+$lang->company->delete = "删除公司";
+$lang->company->browse = "用户列表";
+$lang->company->dynamic = "组织动态";
+$lang->company->depts = "部门列表";
+$lang->company->orgView = '组织视图';
+
+$lang->company->confirmDelete = "您确定删除该公司吗?";
+$lang->company->successSaved = "成功保存";
+
+$lang->company->id = '编号';
+$lang->company->name = '公司名称';
+$lang->company->phone = '联系电话';
+$lang->company->fax = '传真';
+$lang->company->address = '通讯地址';
+$lang->company->zipcode = '邮政编码';
+$lang->company->website = '公司官网';
+$lang->company->backyard = '公司内网';
+$lang->company->pms = 'PMS网站';
+$lang->company->guest = '匿名登录';
+
+$lang->company->guestList[0] = '不允许';
+$lang->company->guestList[1] = '允许';
diff --git a/module/company/lang/zh-tw.php b/module/company/lang/zh-tw.php
index 07cce8067a..ef8b8a4c09 100644
--- a/module/company/lang/zh-tw.php
+++ b/module/company/lang/zh-tw.php
@@ -1,40 +1,40 @@
-
- * @package company
- * @version $Id: zh-tw.php 3536 2012-09-21 03:09:38Z zhujinyonging@gmail.com $
- * @link http://www.zentao.net
- */
-$lang->company->common = '組織視圖';
-$lang->company->index = "組織視圖首頁";
-$lang->company->create = "新增公司";
-$lang->company->edit = "編輯公司";
-$lang->company->read = "公司信息";
-$lang->company->update = "更新公司";
-$lang->company->delete = "刪除公司";
-$lang->company->browse = "用戶列表";
-$lang->company->dynamic = "組織動態";
-$lang->company->depts = "部門列表";
-$lang->company->orgView = '組織視圖';
-
-$lang->company->confirmDelete = "您確定刪除該公司嗎?";
-$lang->company->successSaved = "成功保存";
-
-$lang->company->id = '編號';
-$lang->company->name = '公司名稱';
-$lang->company->phone = '聯繫電話';
-$lang->company->fax = '傳真';
-$lang->company->address = '通訊地址';
-$lang->company->zipcode = '郵政編碼';
-$lang->company->website = '公司官網';
-$lang->company->backyard = '公司內網';
-$lang->company->pms = 'PMS網站';
-$lang->company->guest = '匿名登錄';
-$lang->company->unlock = '解鎖';
-
-$lang->company->guestList[0] = '不允許';
-$lang->company->guestList[1] = '允許';
+
+ * @package company
+ * @version $Id: zh-tw.php 3536 2012-09-21 03:09:38Z zhujinyonging@gmail.com $
+ * @link http://www.zentao.net
+ */
+$lang->company->common = '組織視圖';
+$lang->company->index = "組織視圖首頁";
+$lang->company->create = "新增公司";
+$lang->company->edit = "編輯公司";
+$lang->company->read = "公司信息";
+$lang->company->update = "更新公司";
+$lang->company->delete = "刪除公司";
+$lang->company->browse = "用戶列表";
+$lang->company->dynamic = "組織動態";
+$lang->company->depts = "部門列表";
+$lang->company->orgView = '組織視圖';
+
+$lang->company->confirmDelete = "您確定刪除該公司嗎?";
+$lang->company->successSaved = "成功保存";
+
+$lang->company->id = '編號';
+$lang->company->name = '公司名稱';
+$lang->company->phone = '聯繫電話';
+$lang->company->fax = '傳真';
+$lang->company->address = '通訊地址';
+$lang->company->zipcode = '郵政編碼';
+$lang->company->website = '公司官網';
+$lang->company->backyard = '公司內網';
+$lang->company->pms = 'PMS網站';
+$lang->company->guest = '匿名登錄';
+$lang->company->unlock = '解鎖';
+
+$lang->company->guestList[0] = '不允許';
+$lang->company->guestList[1] = '允許';
diff --git a/module/company/model.php b/module/company/model.php
index c7a0df4d20..0b285a9094 100644
--- a/module/company/model.php
+++ b/module/company/model.php
@@ -1,123 +1,123 @@
-
- * @package company
- * @version $Id$
- * @link http://www.zentao.net
- */
-?>
-lang->company->menu, 'name', array($this->app->company->name));
- common::setMenuVars($this->lang->company->menu, 'addUser', array($dept));
- }
-
- /**
- * Get company list.
- *
- * @access public
- * @return void
- */
- public function getList()
- {
- return $this->dao->select('*')->from(TABLE_COMPANY)->fetchAll();
- }
-
- /**
- * Get the first company.
- *
- * @access public
- * @return void
- */
- public function getFirst()
- {
- return $this->dao->select('*')->from(TABLE_COMPANY)->orderBy('id')->limit(1)->fetch();
- }
-
- /**
- * get company by domain.
- *
- * @param string $domain if empty, use current HTTP_HOST.
- * @access public
- * @return object
- */
- public function getByDomain($domain = '')
- {
- if(empty($domain)) $domain = $this->server->http_host;
- return $this->dao->findByPMS($domain)->from(TABLE_COMPANY)->fetch();
- }
-
- /**
- * Get company info by id.
- *
- * @param int $companyID
- * @access public
- * @return object
- */
- public function getByID($companyID = '')
- {
- return $this->dao->findById((int)$companyID)->from(TABLE_COMPANY)->fetch();
- }
-
- /**
- * Create a company.
- *
- * @access public
- * @return void
- */
- public function create()
- {
- $company = fixer::input('post')->get();
- $this->dao->insert(TABLE_COMPANY)
- ->data($company)
- ->autoCheck()
- ->batchCheck($this->config->company->create->requiredFields, 'notempty')
- ->batchCheck('name,pms', 'unique')
- ->exec();
- }
-
- /**
- * Update a company.
- *
- * @access public
- * @return void
- */
- public function update()
- {
- $company = fixer::input('post')->stripTags('name')->get();
- $companyID = $this->app->company->id;
- $this->dao->update(TABLE_COMPANY)
- ->data($company)
- ->autoCheck()
- ->batchCheck($this->config->company->edit->requiredFields, 'notempty')
- ->batchCheck('name,pms', 'unique', "id != '$companyID'")
- ->where('id')->eq($companyID)
- ->exec();
- }
-
- /**
- * Delete a company.
- *
- * @param int $companyID
- * @access public
- * @return void
- */
- public function delete($companyID)
- {
- return $this->dao->delete()->from(TABLE_COMPANY)->where('id')->eq((int)$companyID)->limit(1)->exec();
- }
-}
+
+ * @package company
+ * @version $Id$
+ * @link http://www.zentao.net
+ */
+?>
+lang->company->menu, 'name', array($this->app->company->name));
+ common::setMenuVars($this->lang->company->menu, 'addUser', array($dept));
+ }
+
+ /**
+ * Get company list.
+ *
+ * @access public
+ * @return void
+ */
+ public function getList()
+ {
+ return $this->dao->select('*')->from(TABLE_COMPANY)->fetchAll();
+ }
+
+ /**
+ * Get the first company.
+ *
+ * @access public
+ * @return void
+ */
+ public function getFirst()
+ {
+ return $this->dao->select('*')->from(TABLE_COMPANY)->orderBy('id')->limit(1)->fetch();
+ }
+
+ /**
+ * get company by domain.
+ *
+ * @param string $domain if empty, use current HTTP_HOST.
+ * @access public
+ * @return object
+ */
+ public function getByDomain($domain = '')
+ {
+ if(empty($domain)) $domain = $this->server->http_host;
+ return $this->dao->findByPMS($domain)->from(TABLE_COMPANY)->fetch();
+ }
+
+ /**
+ * Get company info by id.
+ *
+ * @param int $companyID
+ * @access public
+ * @return object
+ */
+ public function getByID($companyID = '')
+ {
+ return $this->dao->findById((int)$companyID)->from(TABLE_COMPANY)->fetch();
+ }
+
+ /**
+ * Create a company.
+ *
+ * @access public
+ * @return void
+ */
+ public function create()
+ {
+ $company = fixer::input('post')->get();
+ $this->dao->insert(TABLE_COMPANY)
+ ->data($company)
+ ->autoCheck()
+ ->batchCheck($this->config->company->create->requiredFields, 'notempty')
+ ->batchCheck('name,pms', 'unique')
+ ->exec();
+ }
+
+ /**
+ * Update a company.
+ *
+ * @access public
+ * @return void
+ */
+ public function update()
+ {
+ $company = fixer::input('post')->stripTags('name')->get();
+ $companyID = $this->app->company->id;
+ $this->dao->update(TABLE_COMPANY)
+ ->data($company)
+ ->autoCheck()
+ ->batchCheck($this->config->company->edit->requiredFields, 'notempty')
+ ->batchCheck('name,pms', 'unique', "id != '$companyID'")
+ ->where('id')->eq($companyID)
+ ->exec();
+ }
+
+ /**
+ * Delete a company.
+ *
+ * @param int $companyID
+ * @access public
+ * @return void
+ */
+ public function delete($companyID)
+ {
+ return $this->dao->delete()->from(TABLE_COMPANY)->where('id')->eq((int)$companyID)->limit(1)->exec();
+ }
+}
diff --git a/module/company/view/browse.html.php b/module/company/view/browse.html.php
index bc11e58240..9136945e65 100644
--- a/module/company/view/browse.html.php
+++ b/module/company/view/browse.html.php
@@ -1,92 +1,92 @@
-
- * @package product
- * @version $Id$
- * @link http://www.zentao.net
- */
-?>
-
-
-
-
-
- dept->common;?>
-
-
-
-
-
-
-
- recTotal}&recPerPage={$pager->recPerPage}";?>
- idAB);?>
- user->realname);?>
- user->account);?>
- user->role);?>
- user->email);?>
- user->gender);?>
- user->phone);?>
- user->join);?>
- user->last);?>
- user->visits);?>
- actions;?>
-
-
-
- ' method='post' id='userListForm'>
-
-
- account'> "; printf('%03d', $user->id);?>
- account", $user->realname)) echo $user->realname;?>
- account;?>
- user->roleList[$user->role];?>
- email);?>
- user->genderList[$user->gender])) echo $lang->user->genderList[$user->gender];?>
- phone;?>
- join;?>
- last);?>
- visits;?>
-
- id&from=company", '', 'list');
- common::printIcon('user', 'delete', "userID=$user->id", '', 'list', '', "hiddenwin");
- if((strtotime(date('Y-m-d H:i:s')) - strtotime($user->locked)) < $this->config->user->lockMinutes * 60)
- {
- common::printIcon('user', 'unlock', "userID=$user->account", '', 'list', '', "hiddenwin");
- }
- ?>
-
-
-
-
-
-
-
- user->batchEdit, 'onclick=batchEdit()');
- echo html::submitButton($lang->user->contacts->manage, 'onclick=manageContacts()');
- $pager->show();
- ?>
-
-
-
-
-
-
-
-
-
+
+ * @package product
+ * @version $Id$
+ * @link http://www.zentao.net
+ */
+?>
+
+
+
+
+
+ dept->common;?>
+
+
+
+
+
+
+
+ recTotal}&recPerPage={$pager->recPerPage}";?>
+ idAB);?>
+ user->realname);?>
+ user->account);?>
+ user->role);?>
+ user->email);?>
+ user->gender);?>
+ user->phone);?>
+ user->join);?>
+ user->last);?>
+ user->visits);?>
+ actions;?>
+
+
+
+ ' method='post' id='userListForm'>
+
+
+ account'> "; printf('%03d', $user->id);?>
+ account", $user->realname)) echo $user->realname;?>
+ account;?>
+ user->roleList[$user->role];?>
+ email);?>
+ user->genderList[$user->gender])) echo $lang->user->genderList[$user->gender];?>
+ phone;?>
+ join;?>
+ last);?>
+ visits;?>
+
+ id&from=company", '', 'list');
+ common::printIcon('user', 'delete', "userID=$user->id", '', 'list', '', "hiddenwin");
+ if((strtotime(date('Y-m-d H:i:s')) - strtotime($user->locked)) < $this->config->user->lockMinutes * 60)
+ {
+ common::printIcon('user', 'unlock', "userID=$user->account", '', 'list', '', "hiddenwin");
+ }
+ ?>
+
+
+
+
+
+
+
+ user->batchEdit, 'onclick=batchEdit()');
+ echo html::submitButton($lang->user->contacts->manage, 'onclick=manageContacts()');
+ $pager->show();
+ ?>
+
+
+
+
+
+
+
+
+
diff --git a/module/company/view/create.html.php b/module/company/view/create.html.php
index dd5fa42dd1..a6621f3e9b 100644
--- a/module/company/view/create.html.php
+++ b/module/company/view/create.html.php
@@ -1,56 +1,56 @@
-
- * @package company
- * @version $Id$
- * @link http://www.zentao.net
- */
-?>
-
-
-
- company->create;?>
-
- company->name;?>
-
-
-
- company->phone;?>
-
-
-
- company->fax;?>
-
-
-
- company->address;?>
-
-
-
- company->zipcode;?>
-
-
-
- company->website;?>
-
-
-
- company->backyard;?>
-
-
-
- company->pms;?>
-
-
-
- company->guest;?>
- company->guestList);?>
-
-
-
-
-
+
+ * @package company
+ * @version $Id$
+ * @link http://www.zentao.net
+ */
+?>
+
+
+
+ company->create;?>
+
+ company->name;?>
+
+
+
+ company->phone;?>
+
+
+
+ company->fax;?>
+
+
+
+ company->address;?>
+
+
+
+ company->zipcode;?>
+
+
+
+ company->website;?>
+
+
+
+ company->backyard;?>
+
+
+
+ company->pms;?>
+
+
+
+ company->guest;?>
+ company->guestList);?>
+
+
+
+
+
diff --git a/module/company/view/dynamic.html.php b/module/company/view/dynamic.html.php
index 77404a24f3..9cf4eaaf86 100644
--- a/module/company/view/dynamic.html.php
+++ b/module/company/view/dynamic.html.php
@@ -1,62 +1,62 @@
-dynamic view file of dashboard module of ZenTaoPMS.
- *
- * @copyright Copyright 2009-2012 青岛易软天创网络科技有限公司 (QingDao Nature Easy Soft Network Technology Co,LTD www.cnezsoft.com)
- * @license LGPL (http://www.gnu.org/licenses/lgpl.html)
- * @author Chunsheng Wang
- * @package dashboard
- * @version $Id: action->dynamic.html.php 1477 2011-03-01 15:25:50Z wwccss $
- * @link http://www.zentao.net
- */
-?>
-
-
-
-
- ' . html::a(inlink('dynamic', "browseType=today"), $lang->action->dynamic->today) . '';
- echo '' . html::a(inlink('dynamic', "browseType=yesterday"), $lang->action->dynamic->yesterday) . ' ';
- echo '' . html::a(inlink('dynamic', "browseType=twodaysago"), $lang->action->dynamic->twoDaysAgo) . ' ';
- echo '' . html::a(inlink('dynamic', "browseType=thisweek"), $lang->action->dynamic->thisWeek) . ' ';
- echo '' . html::a(inlink('dynamic', "browseType=lastweek"), $lang->action->dynamic->lastWeek) . ' ';
- echo '' . html::a(inlink('dynamic', "browseType=thismonth"), $lang->action->dynamic->thisMonth) . ' ';
- echo '' . html::a(inlink('dynamic', "browseType=lastmonth"), $lang->action->dynamic->lastMonth) . ' ';
- echo '' . html::a(inlink('dynamic', "browseType=all"), $lang->action->dynamic->all) . ' ';
- echo "" . html::select('account', $users, $account, 'onchange=changeUser(this.value)') . ' ';
- echo "" . html::select('product', $products, $product, 'onchange=changeProduct(this.value)') . ' ';
- echo "" . html::select('project', $projects, $project, 'onchange=changeProject(this.value)') . ' ';
- echo "" . html::a('#', ' ' . $lang->action->dynamic->search) . " ";
- ?>
-
-'>
-
-
-
- action->date;?>
- action->actor;?>
- action->action;?>
- action->objectType;?>
- idAB;?>
- action->objectName;?>
-
-
-
-
- objectType == 'case' ? 'testcase' : $action->objectType;?>
-
- date;?>
- actor]) ? $users[$action->actor] : $action->actor, 2);?>
- actionLabel;?>
- action->objectTypes[$action->objectType];?>
- objectID;?>
- objectLink, $action->objectName);?>
-
-
-
- show();?>
-
-
-
+dynamic view file of dashboard module of ZenTaoPMS.
+ *
+ * @copyright Copyright 2009-2013 青岛易软天创网络科技有限公司 (QingDao Nature Easy Soft Network Technology Co,LTD www.cnezsoft.com)
+ * @license LGPL (http://www.gnu.org/licenses/lgpl.html)
+ * @author Chunsheng Wang
+ * @package dashboard
+ * @version $Id: action->dynamic.html.php 1477 2011-03-01 15:25:50Z wwccss $
+ * @link http://www.zentao.net
+ */
+?>
+
+
+
+
+ ' . html::a(inlink('dynamic', "browseType=today"), $lang->action->dynamic->today) . '';
+ echo '' . html::a(inlink('dynamic', "browseType=yesterday"), $lang->action->dynamic->yesterday) . ' ';
+ echo '' . html::a(inlink('dynamic', "browseType=twodaysago"), $lang->action->dynamic->twoDaysAgo) . ' ';
+ echo '' . html::a(inlink('dynamic', "browseType=thisweek"), $lang->action->dynamic->thisWeek) . ' ';
+ echo '' . html::a(inlink('dynamic', "browseType=lastweek"), $lang->action->dynamic->lastWeek) . ' ';
+ echo '' . html::a(inlink('dynamic', "browseType=thismonth"), $lang->action->dynamic->thisMonth) . ' ';
+ echo '' . html::a(inlink('dynamic', "browseType=lastmonth"), $lang->action->dynamic->lastMonth) . ' ';
+ echo '' . html::a(inlink('dynamic', "browseType=all"), $lang->action->dynamic->all) . ' ';
+ echo "" . html::select('account', $users, $account, 'onchange=changeUser(this.value)') . ' ';
+ echo "" . html::select('product', $products, $product, 'onchange=changeProduct(this.value)') . ' ';
+ echo "" . html::select('project', $projects, $project, 'onchange=changeProject(this.value)') . ' ';
+ echo "" . html::a('#', ' ' . $lang->action->dynamic->search) . " ";
+ ?>
+
+'>
+
+
+
+ action->date;?>
+ action->actor;?>
+ action->action;?>
+ action->objectType;?>
+ idAB;?>
+ action->objectName;?>
+
+
+
+
+ objectType == 'case' ? 'testcase' : $action->objectType;?>
+
+ date;?>
+ actor]) ? $users[$action->actor] : $action->actor, 2);?>
+ actionLabel;?>
+ action->objectTypes[$action->objectType];?>
+ objectID;?>
+ objectLink, $action->objectName);?>
+
+
+
+ show();?>
+
+
+
diff --git a/module/company/view/edit.html.php b/module/company/view/edit.html.php
index d55865af17..320abe51e3 100644
--- a/module/company/view/edit.html.php
+++ b/module/company/view/edit.html.php
@@ -1,56 +1,56 @@
-
- * @package company
- * @version $Id$
- * @link http://www.zentao.net
- */
-?>
-
-
-
- company->edit;?>
-
- company->name;?>
- name, "class='text-1'");?>
-
-
- company->phone;?>
- phone, "class='text-1'");?>
-
-
- company->fax;?>
- fax, "class='text-1'");?>
-
-
- company->address;?>
- address, "class='text-1'");?>
-
-
- company->zipcode;?>
- zipcode, "class='text-1'");?>
-
-
- company->website;?>
- website, "class='text-1'");?>
-
-
- company->backyard;?>
- backyard, "class='text-1'");?>
-
-
- company->pms;?>
- pms, "class='text-1'");?>
-
-
- company->guest;?>
- company->guestList, $company->guest);?>
-
-
-
-
-
+
+ * @package company
+ * @version $Id$
+ * @link http://www.zentao.net
+ */
+?>
+
+
+
+ company->edit;?>
+
+ company->name;?>
+ name, "class='text-1'");?>
+
+
+ company->phone;?>
+ phone, "class='text-1'");?>
+
+
+ company->fax;?>
+ fax, "class='text-1'");?>
+
+
+ company->address;?>
+ address, "class='text-1'");?>
+
+
+ company->zipcode;?>
+ zipcode, "class='text-1'");?>
+
+
+ company->website;?>
+ website, "class='text-1'");?>
+
+
+ company->backyard;?>
+ backyard, "class='text-1'");?>
+
+
+ company->pms;?>
+ pms, "class='text-1'");?>
+
+
+ company->guest;?>
+ company->guestList, $company->guest);?>
+
+
+
+
+
diff --git a/module/convert/control.php b/module/convert/control.php
index f2194a82f3..9425e893ba 100644
--- a/module/convert/control.php
+++ b/module/convert/control.php
@@ -1,240 +1,240 @@
-
- * @package convert
- * @version $Id$
- * @link http://www.zentao.net
- */
-class convert extends control
-{
- /**
- * Index page of convert.
- *
- * @access public
- * @return void
- */
- public function index()
- {
- $this->convert->saveState();
- $this->view->header->title = $this->lang->convert->common;
- $this->display();
- }
-
- /**
- * Select the source system.
- *
- * @access public
- * @return void
- */
- public function selectSource()
- {
- $this->view->header->title = $this->lang->convert->common . $this->lang->colon;
- $this->display();
- }
-
- /**
- * Set configs of converter.
- *
- * This is the extrance of every system. It will call the set function of corresponding module.
- *
- * @access public
- * @return void
- */
- public function setConfig()
- {
- if(!$this->post->source)
- {
- echo js::alert($this->lang->convert->mustSelectSource);
- die(js::locate('back'));
- }
- list($sourceName, $version) = explode('_', $this->post->source);
- $setFunc = "set$sourceName";
- $this->view->header->title = $this->lang->convert->setting;
- $this->view->source = $sourceName;
- $this->view->version = $version;
- $this->view->setting = $this->fetch('convert', $setFunc, "version=$version");
- $this->display();
- }
-
- /**
- * The setting page of bugfree.
- *
- * @param string $version
- * @access public
- * @return void
- */
- public function setBugFree($version)
- {
- $this->view->source = 'BugFree';
- $this->view->version = $version;
- $this->view->tablePrefix = $version > 1 ? 'bf_' : '';
- $this->view->dbName = $version > 1 ? 'bugfree2' : 'BugFree';
- $this->view->dbCharset = 'utf8';
- $this->display();
- }
-
- /**
- * The setting page of Redmine.
- *
- * @param string $version
- * @access public
- * @return void
- */
- public function setRedmine($version)
- {
- $this->view->source = 'Redmine';
- $this->view->version = $version;
- $this->view->dbName = 'redmine';
- $this->view->dbCharset = 'utf8';
- $this->display();
- }
-
- /**
- * Check config. Same as setConfig.
- *
- * @access public
- * @return void
- */
- public function checkConfig()
- {
- $checkFunc = 'check' . $this->post->source;
- $this->view->header->title = $this->lang->convert->checkConfig;
- $this->view->source = $this->post->source;
- $this->view->checkResult = $this->fetch('convert', $checkFunc, "version={$this->post->version}");
- $this->display();
- }
-
- /**
- * Check settings of bugfree.
- *
- * @param int $version
- * @access public
- * @return void
- */
- public function checkBugFree($version)
- {
- helper::import('./converter/bugfree.php');
- $converter = new bugfreeConvertModel();
-
- /* Check it. */
- $checkInfo['db'] = $converter->connectDB();
- //if(is_object($checkInfo['db'])) $checkInfo['table'] = $converter->checkTables();
- $checkInfo['path'] = $converter->checkPath();
-
- /* Compute the checking result. */
- $result = 'pass';
- if(!is_object($checkInfo['db']) or !$checkInfo['path']) $result = 'fail';
-
- /* Assign. */
- $this->view->version = $version;
- $this->view->source = 'bugfree';
- $this->view->result = $result;
- $this->view->checkInfo = $checkInfo;
- $this->display();
- }
-
- /**
- * Check settings of Redmine.
- *
- * @param int $version
- * @access public
- * @return void
- */
- public function checkRedmine($version)
- {
- helper::import('./converter/redmine.php');
- $converter = new redmineConvertModel();
-
- /* Check it. */
- $checkInfo['db'] = $converter->connectDB();
- $checkInfo['path'] = $converter->checkPath();
-
- $this->view->trackers = $this->dao->dbh($converter->sourceDBH)->select('id, name')->from('trackers')->fetchAll('id', $autoCompany = false);
- $this->view->statuses = $this->dao->dbh($converter->sourceDBH)->select('id, name')->from('issue_statuses')->fetchAll('id', $autoCompany = false);
- $this->view->pries = $this->dao->dbh($converter->sourceDBH)->select('id, name')->from('enumerations')->where('type')->eq('IssuePriority')->fetchAll('id', $autoCompany = false);
- /* Compute the checking result. */
- $result = 'pass';
- if(!is_object($checkInfo['db']) or !$checkInfo['path']) $result = 'fail';
-
- $this->app->loadLang('bug');
- $this->app->loadLang('story');
- $this->app->loadLang('task');
- $this->view->aimTypeList['bug'] = 'bug';
- $this->view->aimTypeList['task'] = 'task';
- $this->view->aimTypeList['story'] = 'story';
-
- /* Assign. */
- $this->view->version = $version;
- $this->view->source = 'Redmine';
- $this->view->result = $result;
- $this->view->checkInfo = $checkInfo;
- $this->display();
- }
-
- /**
- * Execute the converting.
- *
- * @access public
- * @return void
- */
- public function execute()
- {
- $convertFunc = 'convert' . $this->post->source;
- $this->view->header->title = $this->lang->convert->execute;
- $this->view->source = $this->post->source;
- $this->view->version = $this->post->version;
-
- $this->view->executeResult = $this->fetch('convert', $convertFunc, "version={$this->post->version}");
- $this->display();
- }
-
- /**
- * Convert bugfree.
- *
- * @param int $version
- * @access public
- * @return void
- */
- public function convertBugFree($version)
- {
- helper::import('./converter/bugfree.php');
- helper::import("./converter/bugfree$version.php");
- $className = "bugfree{$version}ConvertModel";
- $converter = new $className();
- $this->view->version = $version;
- $this->view->result = $converter->execute($version);
- $this->view->info = bugfreeConvertModel::$info;
- $this->display();
- }
-
- /**
- * convert redmine
- *
- * @param int $version
- * @access public
- * @return void
- */
- public function convertRedmine($version)
- {
- helper::import('./converter/redmine.php');
- helper::import("./converter/redmine$version.php");
- $className = "redmine11ConvertModel";
- $redmine->aimTypes = $this->post->aimTypes;
- $redmine->statusTypes['bug'] = $this->post->statusTypesOfBug;
- $redmine->statusTypes['story'] = $this->post->statusTypesOfStory;
- $redmine->statusTypes['task'] = $this->post->statusTypesOfTask;
- $redmine->priTypes['bug'] = $this->post->priTypesOfBug;
- $redmine->priTypes['story'] = $this->post->priTypesOfStory;
- $redmine->priTypes['task'] = $this->post->priTypesOfTask;
-
- $converter = new $className($redmine);
- $this->view->version = $version;
- $this->view->result = $converter->execute($version);
- $this->view->info = redmineConvertModel::$info;
- $this->display();
- }
-}
+
+ * @package convert
+ * @version $Id$
+ * @link http://www.zentao.net
+ */
+class convert extends control
+{
+ /**
+ * Index page of convert.
+ *
+ * @access public
+ * @return void
+ */
+ public function index()
+ {
+ $this->convert->saveState();
+ $this->view->header->title = $this->lang->convert->common;
+ $this->display();
+ }
+
+ /**
+ * Select the source system.
+ *
+ * @access public
+ * @return void
+ */
+ public function selectSource()
+ {
+ $this->view->header->title = $this->lang->convert->common . $this->lang->colon;
+ $this->display();
+ }
+
+ /**
+ * Set configs of converter.
+ *
+ * This is the extrance of every system. It will call the set function of corresponding module.
+ *
+ * @access public
+ * @return void
+ */
+ public function setConfig()
+ {
+ if(!$this->post->source)
+ {
+ echo js::alert($this->lang->convert->mustSelectSource);
+ die(js::locate('back'));
+ }
+ list($sourceName, $version) = explode('_', $this->post->source);
+ $setFunc = "set$sourceName";
+ $this->view->header->title = $this->lang->convert->setting;
+ $this->view->source = $sourceName;
+ $this->view->version = $version;
+ $this->view->setting = $this->fetch('convert', $setFunc, "version=$version");
+ $this->display();
+ }
+
+ /**
+ * The setting page of bugfree.
+ *
+ * @param string $version
+ * @access public
+ * @return void
+ */
+ public function setBugFree($version)
+ {
+ $this->view->source = 'BugFree';
+ $this->view->version = $version;
+ $this->view->tablePrefix = $version > 1 ? 'bf_' : '';
+ $this->view->dbName = $version > 1 ? 'bugfree2' : 'BugFree';
+ $this->view->dbCharset = 'utf8';
+ $this->display();
+ }
+
+ /**
+ * The setting page of Redmine.
+ *
+ * @param string $version
+ * @access public
+ * @return void
+ */
+ public function setRedmine($version)
+ {
+ $this->view->source = 'Redmine';
+ $this->view->version = $version;
+ $this->view->dbName = 'redmine';
+ $this->view->dbCharset = 'utf8';
+ $this->display();
+ }
+
+ /**
+ * Check config. Same as setConfig.
+ *
+ * @access public
+ * @return void
+ */
+ public function checkConfig()
+ {
+ $checkFunc = 'check' . $this->post->source;
+ $this->view->header->title = $this->lang->convert->checkConfig;
+ $this->view->source = $this->post->source;
+ $this->view->checkResult = $this->fetch('convert', $checkFunc, "version={$this->post->version}");
+ $this->display();
+ }
+
+ /**
+ * Check settings of bugfree.
+ *
+ * @param int $version
+ * @access public
+ * @return void
+ */
+ public function checkBugFree($version)
+ {
+ helper::import('./converter/bugfree.php');
+ $converter = new bugfreeConvertModel();
+
+ /* Check it. */
+ $checkInfo['db'] = $converter->connectDB();
+ //if(is_object($checkInfo['db'])) $checkInfo['table'] = $converter->checkTables();
+ $checkInfo['path'] = $converter->checkPath();
+
+ /* Compute the checking result. */
+ $result = 'pass';
+ if(!is_object($checkInfo['db']) or !$checkInfo['path']) $result = 'fail';
+
+ /* Assign. */
+ $this->view->version = $version;
+ $this->view->source = 'bugfree';
+ $this->view->result = $result;
+ $this->view->checkInfo = $checkInfo;
+ $this->display();
+ }
+
+ /**
+ * Check settings of Redmine.
+ *
+ * @param int $version
+ * @access public
+ * @return void
+ */
+ public function checkRedmine($version)
+ {
+ helper::import('./converter/redmine.php');
+ $converter = new redmineConvertModel();
+
+ /* Check it. */
+ $checkInfo['db'] = $converter->connectDB();
+ $checkInfo['path'] = $converter->checkPath();
+
+ $this->view->trackers = $this->dao->dbh($converter->sourceDBH)->select('id, name')->from('trackers')->fetchAll('id', $autoCompany = false);
+ $this->view->statuses = $this->dao->dbh($converter->sourceDBH)->select('id, name')->from('issue_statuses')->fetchAll('id', $autoCompany = false);
+ $this->view->pries = $this->dao->dbh($converter->sourceDBH)->select('id, name')->from('enumerations')->where('type')->eq('IssuePriority')->fetchAll('id', $autoCompany = false);
+ /* Compute the checking result. */
+ $result = 'pass';
+ if(!is_object($checkInfo['db']) or !$checkInfo['path']) $result = 'fail';
+
+ $this->app->loadLang('bug');
+ $this->app->loadLang('story');
+ $this->app->loadLang('task');
+ $this->view->aimTypeList['bug'] = 'bug';
+ $this->view->aimTypeList['task'] = 'task';
+ $this->view->aimTypeList['story'] = 'story';
+
+ /* Assign. */
+ $this->view->version = $version;
+ $this->view->source = 'Redmine';
+ $this->view->result = $result;
+ $this->view->checkInfo = $checkInfo;
+ $this->display();
+ }
+
+ /**
+ * Execute the converting.
+ *
+ * @access public
+ * @return void
+ */
+ public function execute()
+ {
+ $convertFunc = 'convert' . $this->post->source;
+ $this->view->header->title = $this->lang->convert->execute;
+ $this->view->source = $this->post->source;
+ $this->view->version = $this->post->version;
+
+ $this->view->executeResult = $this->fetch('convert', $convertFunc, "version={$this->post->version}");
+ $this->display();
+ }
+
+ /**
+ * Convert bugfree.
+ *
+ * @param int $version
+ * @access public
+ * @return void
+ */
+ public function convertBugFree($version)
+ {
+ helper::import('./converter/bugfree.php');
+ helper::import("./converter/bugfree$version.php");
+ $className = "bugfree{$version}ConvertModel";
+ $converter = new $className();
+ $this->view->version = $version;
+ $this->view->result = $converter->execute($version);
+ $this->view->info = bugfreeConvertModel::$info;
+ $this->display();
+ }
+
+ /**
+ * convert redmine
+ *
+ * @param int $version
+ * @access public
+ * @return void
+ */
+ public function convertRedmine($version)
+ {
+ helper::import('./converter/redmine.php');
+ helper::import("./converter/redmine$version.php");
+ $className = "redmine11ConvertModel";
+ $redmine->aimTypes = $this->post->aimTypes;
+ $redmine->statusTypes['bug'] = $this->post->statusTypesOfBug;
+ $redmine->statusTypes['story'] = $this->post->statusTypesOfStory;
+ $redmine->statusTypes['task'] = $this->post->statusTypesOfTask;
+ $redmine->priTypes['bug'] = $this->post->priTypesOfBug;
+ $redmine->priTypes['story'] = $this->post->priTypesOfStory;
+ $redmine->priTypes['task'] = $this->post->priTypesOfTask;
+
+ $converter = new $className($redmine);
+ $this->view->version = $version;
+ $this->view->result = $converter->execute($version);
+ $this->view->info = redmineConvertModel::$info;
+ $this->display();
+ }
+}
diff --git a/module/convert/converter/bugfree.php b/module/convert/converter/bugfree.php
index e829fc4e80..f722f51a76 100644
--- a/module/convert/converter/bugfree.php
+++ b/module/convert/converter/bugfree.php
@@ -1,88 +1,88 @@
-
- * @package convert
- * @version $Id$
- * @link http://www.zentao.net
- */
-class bugfreeConvertModel extends convertModel
-{
- public $map = array();
- public $filePath = '';
- static public $info = array();
-
- /**
- * Connect to db auto.
- *
- * @access public
- * @return void
- */
- public function __construct()
- {
- parent::__construct();
- parent::connectDB();
- }
-
- /**
- * Check table.
- *
- * @access public
- * @return bool
- */
- public function checkTables()
- {
- return true;
- }
-
- /**
- * Check the install path.
- *
- * @access public
- * @return bool
- */
- public function checkPath()
- {
- $this->setPath();
- return file_exists($this->filePath);
- }
-
- /**
- * Set the path of attachments.
- *
- * @access public
- * @return bool
- */
- public function setPath()
- {
- $this->filePath = realpath($this->post->installPath) . $this->app->getPathFix() . 'BugFile' . $this->app->getPathFix();
- }
-
- /**
- * Excute the convert.
- *
- * @param int $version
- * @access public
- * @return void
- */
- public function execute($version)
- {
- }
-
- /**
- * Clear rows added in converting.
- *
- * @access public
- * @return void
- */
- public function clear()
- {
- foreach($this->session->state as $table => $maxID)
- {
- $this->dao->dbh($this->dbh)->delete()->from($table)->where('id')->gt($maxID)->exec();
- }
- }
-}
+
+ * @package convert
+ * @version $Id$
+ * @link http://www.zentao.net
+ */
+class bugfreeConvertModel extends convertModel
+{
+ public $map = array();
+ public $filePath = '';
+ static public $info = array();
+
+ /**
+ * Connect to db auto.
+ *
+ * @access public
+ * @return void
+ */
+ public function __construct()
+ {
+ parent::__construct();
+ parent::connectDB();
+ }
+
+ /**
+ * Check table.
+ *
+ * @access public
+ * @return bool
+ */
+ public function checkTables()
+ {
+ return true;
+ }
+
+ /**
+ * Check the install path.
+ *
+ * @access public
+ * @return bool
+ */
+ public function checkPath()
+ {
+ $this->setPath();
+ return file_exists($this->filePath);
+ }
+
+ /**
+ * Set the path of attachments.
+ *
+ * @access public
+ * @return bool
+ */
+ public function setPath()
+ {
+ $this->filePath = realpath($this->post->installPath) . $this->app->getPathFix() . 'BugFile' . $this->app->getPathFix();
+ }
+
+ /**
+ * Excute the convert.
+ *
+ * @param int $version
+ * @access public
+ * @return void
+ */
+ public function execute($version)
+ {
+ }
+
+ /**
+ * Clear rows added in converting.
+ *
+ * @access public
+ * @return void
+ */
+ public function clear()
+ {
+ foreach($this->session->state as $table => $maxID)
+ {
+ $this->dao->dbh($this->dbh)->delete()->from($table)->where('id')->gt($maxID)->exec();
+ }
+ }
+}
diff --git a/module/convert/converter/bugfree1.php b/module/convert/converter/bugfree1.php
index 2e60b09fab..536f36bc35 100644
--- a/module/convert/converter/bugfree1.php
+++ b/module/convert/converter/bugfree1.php
@@ -1,318 +1,318 @@
-
- * @package convert
- * @version $Id$
- * @link http://www.zentao.net
- */
-class bugfree1ConvertModel extends bugfreeConvertModel
-{
- /**
- * Execute the convert.
- *
- * @access public
- * @return array
- */
- public function execute()
- {
- $this->clear();
- $this->convertGroup();
- $result['users'] = $this->convertUser();
- $result['projects'] = $this->convertProject();
- $result['modules'] = $this->convertModule();
- $result['bugs'] = $this->convertBug();
- $result['actions'] = $this->convertAction();
- $result['files'] = $this->convertFile();
- $this->dao->dbh($this->dbh);
- $this->loadModel('tree')->fixModulePath();
- return $result;
- }
-
- /**
- * Convert groups.
- *
- * @access public
- * @return void
- */
- public function convertGroup()
- {
- $groups = $this->dao->dbh($this->sourceDBH)
- ->select("groupID AS id, groupName AS name, groupUser AS users")
- ->from('BugGroup')
- ->fetchAll('id', $autoCompany = false);
- foreach($groups as $groupID => $group)
- {
- /* Explode into array. */
- $groupUsers = explode(',', $group->users);
- unset($group->id);
- unset($group->users);
-
- /* Insert the group. */
- $this->dao->dbh($this->dbh)->insert(TABLE_GROUP)->data($group)->exec();
- $zentaoGroupID = $this->dao->lastInsertId();
-
- /* Insert account. */
- foreach($groupUsers as $account)
- {
- if(empty($account)) continue;
- $this->dao->dbh($this->dbh)->insert(TABLE_USERGROUP)->set('`group`')->eq($zentaoGroupID)->set('account')->eq($account)->exec();
- }
- }
- }
-
- /**
- * Convert user.
- *
- * @access public
- * @return int converted user count
- */
- public function convertUser()
- {
- /* Get users exist in the system. */
- $activeUsers = $this->dao
- ->dbh($this->sourceDBH)
- ->select("username AS account, userpassword AS password, realname, email")
- ->from('BugUser')
- ->orderBy('userID ASC')
- ->fetchAll('account', $autoCompany = false);
-
- /* Get users in histories. */
- $allUsers = $this->dao->select("distinct(username) AS account")->from('BugHistory')->fetchPairs('', '', $autoCompany = false);
-
- /* Merge them. */
- foreach($allUsers as $key => $account)
- {
- if(isset($activeUsers[$account]))
- {
- $allUsers[$key] = $activeUsers[$account];
- }
- else
- {
- $allUsers[$key] = array('account' => $account, 'realname' => $account, 'deleted' => '1');
- }
- }
- foreach($activeUsers as $account => $user) if(!isset($allUsers[$account])) $allUsers[$account] = $user;
-
- /* Insert into zentao. */
- $convertCount = 0;
- foreach($allUsers as $account => $user)
- {
- if(!$this->dao->dbh($this->dbh)->findByAccount($account)->from(TABLE_USER)->fetch('account'))
- {
- $this->dao->dbh($this->dbh)->insert(TABLE_USER)->data($user)->exec();
- $convertCount ++;
- }
- else
- {
- self::$info['users'][] = sprintf($this->lang->convert->errorUserExists, $account);
- }
- }
- return $convertCount;
- }
-
- /**
- * Convert project in bugfree to product in zentao.
- *
- * @access public
- * @return int converted project count
- */
- public function convertProject()
- {
- $projects = $this->dao->dbh($this->sourceDBH)->select("projectID AS id, projectName AS name")->from('BugProject')->fetchAll('id', $autoCompany = false);
- foreach($projects as $projectID => $project)
- {
- unset($project->id);
- $this->dao->dbh($this->dbh)->insert(TABLE_PRODUCT)->data($project)->exec();
- $this->map['product'][$projectID] = $this->dao->lastInsertID();
- }
- return count($projects);
- }
-
- /**
- * Convert modules.
- *
- * @access public
- * @return int converted modules count
- */
- public function convertModule()
- {
- $this->map['module'][0] = 0;
- $modules = $this->dao
- ->dbh($this->sourceDBH)
- ->select(
- 'moduleID AS id,
- projectID AS root,
- moduleName AS name,
- moduleGrade AS grade,
- parentID AS parent,
- "bug" AS type')
- ->from('BugModule')
- ->orderBy('id ASC')
- ->fetchAll('id', $autoCompany = false);
- foreach($modules as $moduleID => $module)
- {
- $module->root = $this->map['product'][$module->root];
- unset($module->id);
- $this->dao->dbh($this->dbh)->insert(TABLE_MODULE)->data($module)->exec();
- $this->map['module'][$moduleID] = $this->dao->lastInsertID();
- }
-
- /* Update parents. */
- foreach($modules as $oldModuleID => $module)
- {
- $newModuleID = $this->map['module'][$oldModuleID];
- $newParentID = $this->map['module'][$module->parent];
- $this->dao->dbh($this->dbh)->update(TABLE_MODULE)->set('parent')->eq($newParentID)->where('id')->eq($newModuleID)->exec();
- }
- return count($modules);
- }
-
- /**
- * Convert bugs.
- *
- * @access public
- * @return int converted bugs count.
- */
- public function convertBug()
- {
- $bugs = $this->dao
- ->dbh($this->sourceDBH)
- ->select('
- bugID AS id,
- projectID AS product,
- moduleID AS module,
- bugTitle AS title,
- bugSeverity AS severity,
- bugType AS type,
- bugOS AS os,
- bugStatus AS status,
- mailto,
- openedBy, openedDate, openedBuild,
- assignedTo, assignedDate,
- resolvedBy, resolution, resolvedBuild, resolvedDate,
- closedBy, closedDate,
- lastEditedBy, lastEditedDate,
- linkID as duplicateBug
- ')
- ->from('BugInfo')
- ->orderBy('bugID')
- ->fetchAll('id', $autoCompany = false);
- foreach($bugs as $bugID => $bug)
- {
- /* Adjust some fields of bug. */
- $bugID = (int)$bugID;
- unset($bug->id);
- if($bug->assignedTo == 'Closed') $bug->assignedTo = 'closed';
- $bug->type = strtolower($bug->type);
- $bug->os = strtolower($bug->os);
- $bug->browser = 'all';
- $bug->resolution = str_replace(' ','', strtolower($bug->resolution));
- $bug->product = $this->map['product'][$bug->product];
- $bug->module = $this->map['module'][$bug->module];
- $this->dao->dbh($this->dbh)->insert(TABLE_BUG)->data($bug)->exec();
- $this->map['bug'][$bugID] = $this->dao->lastInsertID();
- }
-
- /* Update duplicated bugs. */
- foreach($this->map['bug'] as $oldBugID => $newBugID)
- {
- $this->dao->dbh($this->dbh)->update(TABLE_BUG)->set('duplicateBug')->eq($newBugID)->where('duplicateBug')->eq($oldBugID)->exec();
- }
- return count($bugs);
- }
-
- /**
- * Convert actions.
- *
- * @access public
- * @return int converted actions count.
- */
- public function convertAction()
- {
- $actions = $this->dao
- ->dbh($this->sourceDBH)
- ->select("
- 'bug' AS objectType,
- bugID AS objectID,
- userName AS actor,
- action,
- fullInfo AS comment,
- actionDate AS date")
- ->from('BugHistory')
- ->orderBy('bugID, historyID')
- ->fetchGroup('objectID', '', $autoCompany = false);
- $convertCount = 0;
- foreach($actions as $bugID => $bugActions)
- {
- /* Get the related bugID. */
- $bugID = (int)$bugID;
- $zentaoBugID = $this->map['bug'][$bugID];
-
- /* Process actions. */
- foreach($bugActions as $key => $action)
- {
- $action->objectID = $zentaoBugID;
- if($key == 0)
- {
- $this->dao->dbh($this->dbh)->update(TABLE_BUG)->set('steps')->eq(nl2br($action->comment))->where('id')->eq($zentaoBugID)->exec();
- $action->comment = '';
- }
- $this->dao->dbh($this->dbh)->insert(TABLE_ACTION)->data($action)->exec();
- $convertCount ++;
- }
- }
- return $convertCount;
- }
-
- /**
- * Convert files.
- *
- * @access public
- * @return int converted files count.
- */
- public function convertFile()
- {
- $this->setPath();
- $files = $this->dao->dbh($this->sourceDBH)
- ->select("
- fileName AS pathname,
- fileTitle AS title,
- fileType AS extension,
- fileSize AS size,
- 'bug' AS objectType,
- bugID AS objectID,
- addUser AS addedBy,
- addDate AS addedDate
- ")
- ->from('BugFile')
- ->orderBy('fileID')
- ->fetchAll('', $autoCompany = false);
- foreach($files as $file)
- {
- $file->objectID = $this->map['bug'][(int)$file->objectID];
- if(strpos($file->size, 'KB')) $file->size = (int)(str_replace('KB', '', $file->size) * 1024);
- if(strpos($file->size, 'MB')) $file->size = (int)(str_replace('MB', '', $file->size) * 1024 * 1024);
- $this->dao->dbh($this->dbh)->insert(TABLE_FILE)->data($file)->exec();
-
- /* Copy files. */
- $soureFile = $this->filePath . $file->pathname;
- if(!file_exists($soureFile))
- {
- self::$info['files'][] = sprintf($this->lang->convert->errorFileNotExits, $soureFile);
- continue;
- }
- $targetFile = $this->app->getAppRoot() . "www/data/upload/{$this->app->company->id}/" . $file->pathname;
- $targetPath = dirname($targetFile);
- if(!is_dir($targetPath)) mkdir($targetPath, 0777, true);
- if(!copy($soureFile, $targetFile))
- {
- self::$info['files'][] = sprintf($this->lang->convert->errorCopyFailed, $targetFile);
- }
- }
- return count($files);
- }
-}
+
+ * @package convert
+ * @version $Id$
+ * @link http://www.zentao.net
+ */
+class bugfree1ConvertModel extends bugfreeConvertModel
+{
+ /**
+ * Execute the convert.
+ *
+ * @access public
+ * @return array
+ */
+ public function execute()
+ {
+ $this->clear();
+ $this->convertGroup();
+ $result['users'] = $this->convertUser();
+ $result['projects'] = $this->convertProject();
+ $result['modules'] = $this->convertModule();
+ $result['bugs'] = $this->convertBug();
+ $result['actions'] = $this->convertAction();
+ $result['files'] = $this->convertFile();
+ $this->dao->dbh($this->dbh);
+ $this->loadModel('tree')->fixModulePath();
+ return $result;
+ }
+
+ /**
+ * Convert groups.
+ *
+ * @access public
+ * @return void
+ */
+ public function convertGroup()
+ {
+ $groups = $this->dao->dbh($this->sourceDBH)
+ ->select("groupID AS id, groupName AS name, groupUser AS users")
+ ->from('BugGroup')
+ ->fetchAll('id', $autoCompany = false);
+ foreach($groups as $groupID => $group)
+ {
+ /* Explode into array. */
+ $groupUsers = explode(',', $group->users);
+ unset($group->id);
+ unset($group->users);
+
+ /* Insert the group. */
+ $this->dao->dbh($this->dbh)->insert(TABLE_GROUP)->data($group)->exec();
+ $zentaoGroupID = $this->dao->lastInsertId();
+
+ /* Insert account. */
+ foreach($groupUsers as $account)
+ {
+ if(empty($account)) continue;
+ $this->dao->dbh($this->dbh)->insert(TABLE_USERGROUP)->set('`group`')->eq($zentaoGroupID)->set('account')->eq($account)->exec();
+ }
+ }
+ }
+
+ /**
+ * Convert user.
+ *
+ * @access public
+ * @return int converted user count
+ */
+ public function convertUser()
+ {
+ /* Get users exist in the system. */
+ $activeUsers = $this->dao
+ ->dbh($this->sourceDBH)
+ ->select("username AS account, userpassword AS password, realname, email")
+ ->from('BugUser')
+ ->orderBy('userID ASC')
+ ->fetchAll('account', $autoCompany = false);
+
+ /* Get users in histories. */
+ $allUsers = $this->dao->select("distinct(username) AS account")->from('BugHistory')->fetchPairs('', '', $autoCompany = false);
+
+ /* Merge them. */
+ foreach($allUsers as $key => $account)
+ {
+ if(isset($activeUsers[$account]))
+ {
+ $allUsers[$key] = $activeUsers[$account];
+ }
+ else
+ {
+ $allUsers[$key] = array('account' => $account, 'realname' => $account, 'deleted' => '1');
+ }
+ }
+ foreach($activeUsers as $account => $user) if(!isset($allUsers[$account])) $allUsers[$account] = $user;
+
+ /* Insert into zentao. */
+ $convertCount = 0;
+ foreach($allUsers as $account => $user)
+ {
+ if(!$this->dao->dbh($this->dbh)->findByAccount($account)->from(TABLE_USER)->fetch('account'))
+ {
+ $this->dao->dbh($this->dbh)->insert(TABLE_USER)->data($user)->exec();
+ $convertCount ++;
+ }
+ else
+ {
+ self::$info['users'][] = sprintf($this->lang->convert->errorUserExists, $account);
+ }
+ }
+ return $convertCount;
+ }
+
+ /**
+ * Convert project in bugfree to product in zentao.
+ *
+ * @access public
+ * @return int converted project count
+ */
+ public function convertProject()
+ {
+ $projects = $this->dao->dbh($this->sourceDBH)->select("projectID AS id, projectName AS name")->from('BugProject')->fetchAll('id', $autoCompany = false);
+ foreach($projects as $projectID => $project)
+ {
+ unset($project->id);
+ $this->dao->dbh($this->dbh)->insert(TABLE_PRODUCT)->data($project)->exec();
+ $this->map['product'][$projectID] = $this->dao->lastInsertID();
+ }
+ return count($projects);
+ }
+
+ /**
+ * Convert modules.
+ *
+ * @access public
+ * @return int converted modules count
+ */
+ public function convertModule()
+ {
+ $this->map['module'][0] = 0;
+ $modules = $this->dao
+ ->dbh($this->sourceDBH)
+ ->select(
+ 'moduleID AS id,
+ projectID AS root,
+ moduleName AS name,
+ moduleGrade AS grade,
+ parentID AS parent,
+ "bug" AS type')
+ ->from('BugModule')
+ ->orderBy('id ASC')
+ ->fetchAll('id', $autoCompany = false);
+ foreach($modules as $moduleID => $module)
+ {
+ $module->root = $this->map['product'][$module->root];
+ unset($module->id);
+ $this->dao->dbh($this->dbh)->insert(TABLE_MODULE)->data($module)->exec();
+ $this->map['module'][$moduleID] = $this->dao->lastInsertID();
+ }
+
+ /* Update parents. */
+ foreach($modules as $oldModuleID => $module)
+ {
+ $newModuleID = $this->map['module'][$oldModuleID];
+ $newParentID = $this->map['module'][$module->parent];
+ $this->dao->dbh($this->dbh)->update(TABLE_MODULE)->set('parent')->eq($newParentID)->where('id')->eq($newModuleID)->exec();
+ }
+ return count($modules);
+ }
+
+ /**
+ * Convert bugs.
+ *
+ * @access public
+ * @return int converted bugs count.
+ */
+ public function convertBug()
+ {
+ $bugs = $this->dao
+ ->dbh($this->sourceDBH)
+ ->select('
+ bugID AS id,
+ projectID AS product,
+ moduleID AS module,
+ bugTitle AS title,
+ bugSeverity AS severity,
+ bugType AS type,
+ bugOS AS os,
+ bugStatus AS status,
+ mailto,
+ openedBy, openedDate, openedBuild,
+ assignedTo, assignedDate,
+ resolvedBy, resolution, resolvedBuild, resolvedDate,
+ closedBy, closedDate,
+ lastEditedBy, lastEditedDate,
+ linkID as duplicateBug
+ ')
+ ->from('BugInfo')
+ ->orderBy('bugID')
+ ->fetchAll('id', $autoCompany = false);
+ foreach($bugs as $bugID => $bug)
+ {
+ /* Adjust some fields of bug. */
+ $bugID = (int)$bugID;
+ unset($bug->id);
+ if($bug->assignedTo == 'Closed') $bug->assignedTo = 'closed';
+ $bug->type = strtolower($bug->type);
+ $bug->os = strtolower($bug->os);
+ $bug->browser = 'all';
+ $bug->resolution = str_replace(' ','', strtolower($bug->resolution));
+ $bug->product = $this->map['product'][$bug->product];
+ $bug->module = $this->map['module'][$bug->module];
+ $this->dao->dbh($this->dbh)->insert(TABLE_BUG)->data($bug)->exec();
+ $this->map['bug'][$bugID] = $this->dao->lastInsertID();
+ }
+
+ /* Update duplicated bugs. */
+ foreach($this->map['bug'] as $oldBugID => $newBugID)
+ {
+ $this->dao->dbh($this->dbh)->update(TABLE_BUG)->set('duplicateBug')->eq($newBugID)->where('duplicateBug')->eq($oldBugID)->exec();
+ }
+ return count($bugs);
+ }
+
+ /**
+ * Convert actions.
+ *
+ * @access public
+ * @return int converted actions count.
+ */
+ public function convertAction()
+ {
+ $actions = $this->dao
+ ->dbh($this->sourceDBH)
+ ->select("
+ 'bug' AS objectType,
+ bugID AS objectID,
+ userName AS actor,
+ action,
+ fullInfo AS comment,
+ actionDate AS date")
+ ->from('BugHistory')
+ ->orderBy('bugID, historyID')
+ ->fetchGroup('objectID', '', $autoCompany = false);
+ $convertCount = 0;
+ foreach($actions as $bugID => $bugActions)
+ {
+ /* Get the related bugID. */
+ $bugID = (int)$bugID;
+ $zentaoBugID = $this->map['bug'][$bugID];
+
+ /* Process actions. */
+ foreach($bugActions as $key => $action)
+ {
+ $action->objectID = $zentaoBugID;
+ if($key == 0)
+ {
+ $this->dao->dbh($this->dbh)->update(TABLE_BUG)->set('steps')->eq(nl2br($action->comment))->where('id')->eq($zentaoBugID)->exec();
+ $action->comment = '';
+ }
+ $this->dao->dbh($this->dbh)->insert(TABLE_ACTION)->data($action)->exec();
+ $convertCount ++;
+ }
+ }
+ return $convertCount;
+ }
+
+ /**
+ * Convert files.
+ *
+ * @access public
+ * @return int converted files count.
+ */
+ public function convertFile()
+ {
+ $this->setPath();
+ $files = $this->dao->dbh($this->sourceDBH)
+ ->select("
+ fileName AS pathname,
+ fileTitle AS title,
+ fileType AS extension,
+ fileSize AS size,
+ 'bug' AS objectType,
+ bugID AS objectID,
+ addUser AS addedBy,
+ addDate AS addedDate
+ ")
+ ->from('BugFile')
+ ->orderBy('fileID')
+ ->fetchAll('', $autoCompany = false);
+ foreach($files as $file)
+ {
+ $file->objectID = $this->map['bug'][(int)$file->objectID];
+ if(strpos($file->size, 'KB')) $file->size = (int)(str_replace('KB', '', $file->size) * 1024);
+ if(strpos($file->size, 'MB')) $file->size = (int)(str_replace('MB', '', $file->size) * 1024 * 1024);
+ $this->dao->dbh($this->dbh)->insert(TABLE_FILE)->data($file)->exec();
+
+ /* Copy files. */
+ $soureFile = $this->filePath . $file->pathname;
+ if(!file_exists($soureFile))
+ {
+ self::$info['files'][] = sprintf($this->lang->convert->errorFileNotExits, $soureFile);
+ continue;
+ }
+ $targetFile = $this->app->getAppRoot() . "www/data/upload/{$this->app->company->id}/" . $file->pathname;
+ $targetPath = dirname($targetFile);
+ if(!is_dir($targetPath)) mkdir($targetPath, 0777, true);
+ if(!copy($soureFile, $targetFile))
+ {
+ self::$info['files'][] = sprintf($this->lang->convert->errorCopyFailed, $targetFile);
+ }
+ }
+ return count($files);
+ }
+}
diff --git a/module/convert/converter/bugfree2.php b/module/convert/converter/bugfree2.php
index acac3ab1c1..00abb21e44 100644
--- a/module/convert/converter/bugfree2.php
+++ b/module/convert/converter/bugfree2.php
@@ -1,530 +1,530 @@
-
- * @package convert
- * @version $Id$
- * @link http://www.zentao.net
- */
-class bugfree2ConvertModel extends bugfreeConvertModel
-{
- /**
- * Execute the converter.
- *
- * @access public
- * @return array
- */
- public function execute()
- {
- $this->clear();
- $this->setTable();
- $this->convertGroup();
- $result['users'] = $this->convertUser();
- $result['projects'] = $this->convertProject();
- $result['modules'] = $this->convertModule();
- $result['bugs'] = $this->convertBug();
- $result['cases'] = $this->convertCase();
- $result['results'] = $this->convertResult();
- $result['actions'] = $this->convertAction();
- $result['files'] = $this->convertFile();
- $this->dao->dbh($this->dbh);
- $this->loadModel('tree')->fixModulePath();
- return $result;
- }
-
- /**
- * Set table names.
- *
- * @access public
- * @return void
- */
- public function setTable()
- {
- $dbPrefix = $this->post->dbPrefix;
- define('BUGFREE_TABLE_OPTION', $dbPrefix . 'TestOptions');
- define('BUGFREE_TABLE_USER', $dbPrefix . 'TestUser');
- define('BUGFREE_TABLE_PROJECT', $dbPrefix . 'TestProject');
- define('BUGFREE_TABLE_MODULE', $dbPrefix . 'TestModule');
- define('BUGFREE_TABLE_BUGINFO', $dbPrefix . 'BugInfo');
- define('BUGFREE_TABLE_CASEINFO', $dbPrefix . 'CaseInfo');
- define('BUGFREE_TABLE_RESULTINFO', $dbPrefix . 'ResultInfo');
- define('BUGFREE_TABLE_ACTION', $dbPrefix . 'TestAction');
- define('BUGFREE_TABLE_FILE', $dbPrefix . 'TestFile');
- define('BUGFREE_TABLE_HISTORY', $dbPrefix . 'TestHistory');
- define('BUGFREE_TABLE_GROUP', $dbPrefix . 'TestGroup');
- }
-
- /**
- * Get the version of bugfree2.x.
- *
- * @access public
- * @return int
- */
- public function getBugFreeVersion()
- {
- return $this->dao->dbh($this->sourceDBH)
- ->select("optionValue as version")->from(BUGFREE_TABLE_OPTION)
- ->where('OptionName')->eq('dbVersion')
- ->fetch('version', $autoCompany = false);
-
- }
-
- /**
- * Convert user.
- *
- * @access public
- * @return int converted user count
- */
- public function convertUser()
- {
- /* Get all user list. */
- $users = $this->dao
- ->dbh($this->sourceDBH)
- ->select("username AS account, userpassword AS password, realname, email, isDroped AS deleted")
- ->from(BUGFREE_TABLE_USER)
- ->orderBy('userID ASC')
- ->fetchAll('account', $autoCompany = false);
-
- /* Insert into zentao. */
- $convertCount = 0;
- foreach($users as $account => $user)
- {
- if(!$this->dao->dbh($this->dbh)->findByAccount($account)->from(TABLE_USER)->fetch('account'))
- {
- $this->dao->dbh($this->dbh)->insert(TABLE_USER)->data($user)->exec();
- $convertCount ++;
- }
- else
- {
- self::$info['users'][] = sprintf($this->lang->convert->errorUserExists, $account);
- }
- }
- return $convertCount;
- }
-
- /**
- * Convert groups.
- *
- * @access public
- * @return void converted group count.
- */
- public function convertGroup()
- {
- if(!$this->tableExists(BUGFREE_TABLE_GROUP)) return false;
- $groups = $this->dao->dbh($this->sourceDBH)
- ->select("groupID AS id, groupName AS name, groupUser AS users")
- ->from(BUGFREE_TABLE_GROUP)
- ->fetchAll('id', $autoCompany = false);
- foreach($groups as $groupID => $group)
- {
- /* Fix the group data. */
- if($group->name == '[All Users]') continue;
- $groupUsers = explode(',', $group->users);
- unset($group->id);
- unset($group->users);
-
- /* Insert into zentao's group table. */
- $this->dao->dbh($this->dbh)->insert(TABLE_GROUP)->data($group)->exec();
- $zentaoGroupID = $this->dao->lastInsertId();
-
- /* Insert into zentao's usergroup table. */
- foreach($groupUsers as $account)
- {
- if(empty($account)) continue;
- $this->dao->dbh($this->dbh)->insert(TABLE_USERGROUP)
- ->set('`group`')->eq($zentaoGroupID)
- ->set('account')->eq($account)
- ->exec();
- }
- }
- }
-
- /**
- * Convert projects.
- *
- * @access public
- * @return int converted projects count.
- */
- public function convertProject()
- {
- $projects = $this->dao->dbh($this->sourceDBH)
- ->select("projectID AS id, projectName AS name, isDroped AS deleted")
- ->from(BUGFREE_TABLE_PROJECT)
- ->fetchAll('id', $autoComapny = false);
- foreach($projects as $projectID => $project)
- {
- unset($project->id);
- $this->dao->dbh($this->dbh)->insert(TABLE_PRODUCT)->data($project)->exec();
- $this->map['product'][$projectID] = $this->dao->lastInsertID();
- }
- return count($projects);
- }
-
- /**
- * Convert modules.
- *
- * @access public
- * @return int converted modules count.
- */
- public function convertModule()
- {
- $this->map['module'][0] = 0;
- $modules = $this->dao
- ->dbh($this->sourceDBH)
- ->select(
- 'moduleID AS id,
- moduleType as type,
- projectID AS root,
- moduleName AS name,
- moduleGrade AS grade,
- parentID AS parent,
- displayOrder AS `order`')
- ->from(BUGFREE_TABLE_MODULE)
- ->orderBy('id ASC')
- ->fetchAll('id', $autoCompany = false);
- foreach($modules as $moduleID => $module)
- {
- $module->root = $this->map['product'][$module->root];
- $module->type = strtolower($module->type);
- unset($module->id);
- $this->dao->dbh($this->dbh)->insert(TABLE_MODULE)->data($module)->exec();
- $this->map['module'][$moduleID] = $this->dao->lastInsertID();
- }
-
- /* Update parent. */
- foreach($modules as $oldModuleID => $module)
- {
- $newModuleID = $this->map['module'][$oldModuleID];
- $newParentID = $this->map['module'][$module->parent];
- $this->dao->dbh($this->dbh)->update(TABLE_MODULE)->set('parent')->eq($newParentID)->where('id')->eq($newModuleID)->exec();
- }
- return count($modules);
- }
-
- /**
- * Convert bugs.
- *
- * @access public
- * @return int converted bugs count.
- */
- public function convertBug()
- {
- $bugs = $this->dao
- ->dbh($this->sourceDBH)
- ->select('
- bugID AS id,
- projectID AS product,
- moduleID AS module,
- bugTitle AS title,
- bugSeverity AS severity,
- bugPriority AS pri,
- bugType AS type,
- bugOS AS os,
- bugBrowser AS browser,
- bugMachine AS hardware,
- howFound AS found,
- reproSteps AS steps,
- bugStatus AS status,
- linkID AS linkBug,
- duplicateID AS duplicateBug,
- caseID AS `case`,
- 1 AS caseVersion,
- resultID AS result,
- mailto,
- openedBy, openedDate, openedBuild,
- assignedTo, assignedDate,
- resolvedBy, resolution, resolvedBuild, resolvedDate,
- closedBy, closedDate,
- lastEditedBy, lastEditedDate,
- bugKeyword AS keywords
- ')
- ->from(BUGFREE_TABLE_BUGINFO)
- ->where('isDroped')->eq(0)
- ->orderBy('bugID')
- ->fetchAll('id', $autoCompany = false);
- foreach($bugs as $bugID => $bug)
- {
- /* Fix some fileds of bug. */
- $bugID = (int)$bugID;
- unset($bug->id);
-
- if($bug->assignedTo == 'Closed') $bug->assignedTo = 'closed';
- if($bug->assignedTo == 'Active') $bug->assignedTo = '';
-
- $bug->type = strtolower($bug->type);
- $bug->found = strtolower($bug->found);
- $bug->status = strtolower($bug->status);
- $bug->os = strtolower($bug->os);
- $bug->browser= strtolower($bug->browser);
- $bug->steps = nl2br($bug->steps);
-
- if($bug->os == 'winvista') $bug->os = 'vista';
- if($bug->browser == 'firefox3.0') $bug->browser = 'firefox3';
- if($bug->browser == 'firefox2.0') $bug->browser = 'firefox2';
- if($bug->openedBuild == 'N/A') $bug->openedBuild = '';
- if(!$bug->case) $bug->caseVersion = 0;
-
- $bug->resolution = str_replace(' ', '', strtolower($bug->resolution));
- $bug->product = $this->map['product'][$bug->product];
- $bug->module = $this->map['module'][$bug->module];
- $this->dao->dbh($this->dbh)->insert(TABLE_BUG)->data($bug)->exec();
- $this->map['bug'][$bugID] = $this->dao->lastInsertID();
- }
-
- /* Update duplicated bugs. */
- foreach($this->map['bug'] as $oldBugID => $newBugID)
- {
- $this->dao->dbh($this->dbh)->update(TABLE_BUG)->set('duplicateBug')->eq($newBugID)->where('duplicateBug')->eq($oldBugID)->exec();
- }
- return count($bugs);
- }
-
- /**
- * Convert cases.
- *
- * @access public
- * @return int converted cases count.
- */
- public function convertCase()
- {
- $cases = $this->dao
- ->dbh($this->sourceDBH)
- ->select('
- caseID AS id,
- projectID AS product,
- moduleID AS module,
- caseTitle AS title,
- caseSteps AS step,
- casePriority AS pri,
- caseType AS type,
- caseStatus AS status,
- caseMethod AS howRun,
- casePlan AS stage,
- openedBy, openedDate,
- lastEditedBy, lastEditedDate,
- scriptedBy, scriptedDate, scriptStatus, scriptLocation,
- linkID AS linkCase,
- casekeyword AS keywords,
- 1 AS version,
- bugID
- ')
- ->from(BUGFREE_TABLE_CASEINFO)
- ->where('isDroped')->eq(0)
- ->orderBy('caseID')
- ->fetchAll('id', $autoCompany = false);
- foreach($cases as $caseID => $case)
- {
- /* Fix fields of case. */
- $caseID = (int)$caseID;
- $step = $case->step;
- $bugs = explode(',', $case->bugID);
- unset($case->id);
- unset($case->step);
- unset($case->bugID);
-
- $case->type = strtolower($case->type);
- $case->status = strtolower($case->status);
- $case->howRun = strtolower($case->howRun);
- $case->stage = strtolower($case->stage);
-
- if($case->type == 'configuration') $case->type = 'config';
- if($case->type == 'setup') $case->type = 'install';
- if($case->type == 'functional') $case->type = 'feature';
- if($case->status == 'active') $case->status = 'normal';
-
- /* Change product and module by zentao's product and module. */
- $case->product = $this->map['product'][$case->product];
- $case->module = $this->map['module'][$case->module];
-
- /* Insert into case table. */
- $this->dao->dbh($this->dbh)->insert(TABLE_CASE)->data($case)->exec();
- $zentaoCaseID = $this->dao->lastInsertID();
- $this->map['case'][$caseID] = $zentaoCaseID;
-
- /* Insert into case step table. */
- $caseStep->case = $zentaoCaseID;
- $caseStep->version = 1;
- $caseStep->desc = $step;
- $this->dao->dbh($this->dbh)->insert(TABLE_CASESTEP)->data($caseStep)->exec();
-
- /* Update related bugs. */
- foreach($bugs as $bugID)
- {
- if(!isset($this->map['bug'][$bugID])) continue;
- $zentaoBugID = $this->map['bug'][$bugID];
- $this->dao->dbh($this->dbh)->update(TABLE_BUG)->set('`case`')->eq($zentaoCaseID)->where('id')->eq($zentaoBugID)->limit(1)->exec();
- }
- }
- return count($cases);
- }
-
- /**
- * Convert results.
- *
- * @access public
- * @return int converted results count.
- */
- public function convertResult()
- {
- $results = $this->dao->dbh($this->sourceDBH)
- ->select('
- resultID AS id,
- caseID AS `case`,
- resultValue AS caseResult,
- 1 AS version,
- openedDate as date,
- bugID
- ')
- ->from(BUGFREE_TABLE_RESULTINFO)
- ->orderBy('id')
- ->fetchAll('id', $autoCompany = false);
- foreach($results as $resultID => $result)
- {
- unset($result->id);
-
- /* The bug id of zentao. */
- $bugID = (int)$result->bugID;
- $zentaoBugID = $this->map['bug'][$bugID];
- unset($result->bugID);
-
- /* Insert into test result table. */
- $this->dao->dbh($this->dbh)->insert(TABLE_TESTRESULT)->data($result)->exec();
- $zentaoResultID = $this->dao->lastInsertId();
- $this->map['result'][$resultID] = $zentaoResultID;
-
- /* Update result table. */
- $this->dao->dbh($this->dbh)->update(TABLE_BUG)->set('result')->eq($zentaoResultID)->where('id')->eq($zentaoBugID)->limit(1)->exec();
- }
- return count($results);
- }
-
- /**
- * Convert actions.
- *
- * @access public
- * @return int converted actions count.
- */
- public function convertAction()
- {
- $actions = $this->dao
- ->dbh($this->sourceDBH)
- ->select("actionID AS id,
- actionTarget AS objectType,
- idValue AS objectID,
- actionUser AS actor,
- actionType AS action,
- actionDate AS date,
- actionNote AS comment
- ")
- ->from(BUGFREE_TABLE_ACTION)
- ->where('actionTarget' != 'Result')
- ->orderBy('actionID')
- ->fetchAll('id', $autoComapny = false);
-
- foreach($actions as $actionID => $action)
- {
- $actionID = (int)$action->id;
- unset($action->id);
- $action->objectType = strtolower($action->objectType);
- $action->action = strtolower($action->action);
- $action->objectID = $this->map[$action->objectType][$action->objectID];
-
- $this->dao->dbh($this->dbh)->insert(TABLE_ACTION)->data($action)->exec();
- $this->map['action'][$actionID] = $this->dao->lastInsertID();
- }
- return count($actions);
- }
-
- /**
- * Convert histories.
- *
- * @access public
- * @return int the converted histories count.
- */
- public function convertHistory()
- {
- $histories = $this->dao->dbh($this->sourceDBH)
- ->select('actioID, actionField AS field, oldValue AS old, newValue AS new')
- ->from(BUGFREE_TABLE_HISTORY)
- ->orderBy('historyID')
- ->fetchAll('', $autoCompany = false);
- foreach($histories as $history)
- {
- $history->actionID = $this->map['action'][$history->actionID];
- $this->dao->dbh($this->dbh)->insert(TABLE_HISTORY)->data($history)->exec();
- }
- }
-
- /**
- * Convert attachments.
- *
- * @access public
- * @return int the converted files count.
- */
- public function convertFile()
- {
- $this->setPath();
- $files = $this->dao->dbh($this->sourceDBH)
- ->select("
- actionID,
- fileName AS pathname,
- fileTitle AS title,
- fileType AS extension,
- fileSize AS size
- ")
- ->from(BUGFREE_TABLE_FILE)
- ->orderBy('fileID')
- ->fetchAll('', $autoCompany = false);
- foreach($files as $file)
- {
- /* Get the actionID in zentao, to get file info. */
- $zentaoActionID = $this->map['action'][$file->actionID];
- $zentaoAction = $this->dao->dbh($this->dbh)->findById($zentaoActionID)->from(TABLE_ACTION)->fetch();
- $file->objectType = $zentaoAction->objectType;
- $file->objectID = $zentaoAction->objectID;
- $file->addedBy = $zentaoAction->actor;
- $file->addedDate = $zentaoAction->date;
- unset($file->actionID);
-
- /* Compute the file size. */
- if(strpos($file->size, 'KB')) $file->size = (int)(str_replace('KB', '', $file->size) * 1024);
- if(strpos($file->size, 'MB')) $file->size = (int)(str_replace('MB', '', $file->size) * 1024 * 1024);
-
- /* Insert into database. */
- $this->dao->dbh($this->dbh)->insert(TABLE_FILE)->data($file)->exec();
-
- /* Copy file. */
- $soureFile = $this->filePath . $file->pathname;
- if(!file_exists($soureFile))
- {
- self::$info['files'][] = sprintf($this->lang->convert->errorFileNotExits, $soureFile);
- continue;
- }
- $targetFile = $this->app->getAppRoot() . "www/data/upload/{$this->app->company->id}/" . $file->pathname;
- $targetPath = dirname($targetFile);
- if(!is_dir($targetPath)) mkdir($targetPath, 0777, true);
- if(!copy($soureFile, $targetFile))
- {
- self::$info['files'][] = sprintf($this->lang->convert->errorCopyFailed, $targetFile);
- }
- }
- return count($files);
- }
-
- /**
- * Clear the converted records.
- *
- * @access public
- * @return void
- */
- public function clear()
- {
- foreach($this->session->state as $table => $maxID)
- {
- $this->dao->dbh($this->dbh)->delete()->from($table)->where('id')->gt($maxID)->exec();
- }
- }
-}
+
+ * @package convert
+ * @version $Id$
+ * @link http://www.zentao.net
+ */
+class bugfree2ConvertModel extends bugfreeConvertModel
+{
+ /**
+ * Execute the converter.
+ *
+ * @access public
+ * @return array
+ */
+ public function execute()
+ {
+ $this->clear();
+ $this->setTable();
+ $this->convertGroup();
+ $result['users'] = $this->convertUser();
+ $result['projects'] = $this->convertProject();
+ $result['modules'] = $this->convertModule();
+ $result['bugs'] = $this->convertBug();
+ $result['cases'] = $this->convertCase();
+ $result['results'] = $this->convertResult();
+ $result['actions'] = $this->convertAction();
+ $result['files'] = $this->convertFile();
+ $this->dao->dbh($this->dbh);
+ $this->loadModel('tree')->fixModulePath();
+ return $result;
+ }
+
+ /**
+ * Set table names.
+ *
+ * @access public
+ * @return void
+ */
+ public function setTable()
+ {
+ $dbPrefix = $this->post->dbPrefix;
+ define('BUGFREE_TABLE_OPTION', $dbPrefix . 'TestOptions');
+ define('BUGFREE_TABLE_USER', $dbPrefix . 'TestUser');
+ define('BUGFREE_TABLE_PROJECT', $dbPrefix . 'TestProject');
+ define('BUGFREE_TABLE_MODULE', $dbPrefix . 'TestModule');
+ define('BUGFREE_TABLE_BUGINFO', $dbPrefix . 'BugInfo');
+ define('BUGFREE_TABLE_CASEINFO', $dbPrefix . 'CaseInfo');
+ define('BUGFREE_TABLE_RESULTINFO', $dbPrefix . 'ResultInfo');
+ define('BUGFREE_TABLE_ACTION', $dbPrefix . 'TestAction');
+ define('BUGFREE_TABLE_FILE', $dbPrefix . 'TestFile');
+ define('BUGFREE_TABLE_HISTORY', $dbPrefix . 'TestHistory');
+ define('BUGFREE_TABLE_GROUP', $dbPrefix . 'TestGroup');
+ }
+
+ /**
+ * Get the version of bugfree2.x.
+ *
+ * @access public
+ * @return int
+ */
+ public function getBugFreeVersion()
+ {
+ return $this->dao->dbh($this->sourceDBH)
+ ->select("optionValue as version")->from(BUGFREE_TABLE_OPTION)
+ ->where('OptionName')->eq('dbVersion')
+ ->fetch('version', $autoCompany = false);
+
+ }
+
+ /**
+ * Convert user.
+ *
+ * @access public
+ * @return int converted user count
+ */
+ public function convertUser()
+ {
+ /* Get all user list. */
+ $users = $this->dao
+ ->dbh($this->sourceDBH)
+ ->select("username AS account, userpassword AS password, realname, email, isDroped AS deleted")
+ ->from(BUGFREE_TABLE_USER)
+ ->orderBy('userID ASC')
+ ->fetchAll('account', $autoCompany = false);
+
+ /* Insert into zentao. */
+ $convertCount = 0;
+ foreach($users as $account => $user)
+ {
+ if(!$this->dao->dbh($this->dbh)->findByAccount($account)->from(TABLE_USER)->fetch('account'))
+ {
+ $this->dao->dbh($this->dbh)->insert(TABLE_USER)->data($user)->exec();
+ $convertCount ++;
+ }
+ else
+ {
+ self::$info['users'][] = sprintf($this->lang->convert->errorUserExists, $account);
+ }
+ }
+ return $convertCount;
+ }
+
+ /**
+ * Convert groups.
+ *
+ * @access public
+ * @return void converted group count.
+ */
+ public function convertGroup()
+ {
+ if(!$this->tableExists(BUGFREE_TABLE_GROUP)) return false;
+ $groups = $this->dao->dbh($this->sourceDBH)
+ ->select("groupID AS id, groupName AS name, groupUser AS users")
+ ->from(BUGFREE_TABLE_GROUP)
+ ->fetchAll('id', $autoCompany = false);
+ foreach($groups as $groupID => $group)
+ {
+ /* Fix the group data. */
+ if($group->name == '[All Users]') continue;
+ $groupUsers = explode(',', $group->users);
+ unset($group->id);
+ unset($group->users);
+
+ /* Insert into zentao's group table. */
+ $this->dao->dbh($this->dbh)->insert(TABLE_GROUP)->data($group)->exec();
+ $zentaoGroupID = $this->dao->lastInsertId();
+
+ /* Insert into zentao's usergroup table. */
+ foreach($groupUsers as $account)
+ {
+ if(empty($account)) continue;
+ $this->dao->dbh($this->dbh)->insert(TABLE_USERGROUP)
+ ->set('`group`')->eq($zentaoGroupID)
+ ->set('account')->eq($account)
+ ->exec();
+ }
+ }
+ }
+
+ /**
+ * Convert projects.
+ *
+ * @access public
+ * @return int converted projects count.
+ */
+ public function convertProject()
+ {
+ $projects = $this->dao->dbh($this->sourceDBH)
+ ->select("projectID AS id, projectName AS name, isDroped AS deleted")
+ ->from(BUGFREE_TABLE_PROJECT)
+ ->fetchAll('id', $autoComapny = false);
+ foreach($projects as $projectID => $project)
+ {
+ unset($project->id);
+ $this->dao->dbh($this->dbh)->insert(TABLE_PRODUCT)->data($project)->exec();
+ $this->map['product'][$projectID] = $this->dao->lastInsertID();
+ }
+ return count($projects);
+ }
+
+ /**
+ * Convert modules.
+ *
+ * @access public
+ * @return int converted modules count.
+ */
+ public function convertModule()
+ {
+ $this->map['module'][0] = 0;
+ $modules = $this->dao
+ ->dbh($this->sourceDBH)
+ ->select(
+ 'moduleID AS id,
+ moduleType as type,
+ projectID AS root,
+ moduleName AS name,
+ moduleGrade AS grade,
+ parentID AS parent,
+ displayOrder AS `order`')
+ ->from(BUGFREE_TABLE_MODULE)
+ ->orderBy('id ASC')
+ ->fetchAll('id', $autoCompany = false);
+ foreach($modules as $moduleID => $module)
+ {
+ $module->root = $this->map['product'][$module->root];
+ $module->type = strtolower($module->type);
+ unset($module->id);
+ $this->dao->dbh($this->dbh)->insert(TABLE_MODULE)->data($module)->exec();
+ $this->map['module'][$moduleID] = $this->dao->lastInsertID();
+ }
+
+ /* Update parent. */
+ foreach($modules as $oldModuleID => $module)
+ {
+ $newModuleID = $this->map['module'][$oldModuleID];
+ $newParentID = $this->map['module'][$module->parent];
+ $this->dao->dbh($this->dbh)->update(TABLE_MODULE)->set('parent')->eq($newParentID)->where('id')->eq($newModuleID)->exec();
+ }
+ return count($modules);
+ }
+
+ /**
+ * Convert bugs.
+ *
+ * @access public
+ * @return int converted bugs count.
+ */
+ public function convertBug()
+ {
+ $bugs = $this->dao
+ ->dbh($this->sourceDBH)
+ ->select('
+ bugID AS id,
+ projectID AS product,
+ moduleID AS module,
+ bugTitle AS title,
+ bugSeverity AS severity,
+ bugPriority AS pri,
+ bugType AS type,
+ bugOS AS os,
+ bugBrowser AS browser,
+ bugMachine AS hardware,
+ howFound AS found,
+ reproSteps AS steps,
+ bugStatus AS status,
+ linkID AS linkBug,
+ duplicateID AS duplicateBug,
+ caseID AS `case`,
+ 1 AS caseVersion,
+ resultID AS result,
+ mailto,
+ openedBy, openedDate, openedBuild,
+ assignedTo, assignedDate,
+ resolvedBy, resolution, resolvedBuild, resolvedDate,
+ closedBy, closedDate,
+ lastEditedBy, lastEditedDate,
+ bugKeyword AS keywords
+ ')
+ ->from(BUGFREE_TABLE_BUGINFO)
+ ->where('isDroped')->eq(0)
+ ->orderBy('bugID')
+ ->fetchAll('id', $autoCompany = false);
+ foreach($bugs as $bugID => $bug)
+ {
+ /* Fix some fileds of bug. */
+ $bugID = (int)$bugID;
+ unset($bug->id);
+
+ if($bug->assignedTo == 'Closed') $bug->assignedTo = 'closed';
+ if($bug->assignedTo == 'Active') $bug->assignedTo = '';
+
+ $bug->type = strtolower($bug->type);
+ $bug->found = strtolower($bug->found);
+ $bug->status = strtolower($bug->status);
+ $bug->os = strtolower($bug->os);
+ $bug->browser= strtolower($bug->browser);
+ $bug->steps = nl2br($bug->steps);
+
+ if($bug->os == 'winvista') $bug->os = 'vista';
+ if($bug->browser == 'firefox3.0') $bug->browser = 'firefox3';
+ if($bug->browser == 'firefox2.0') $bug->browser = 'firefox2';
+ if($bug->openedBuild == 'N/A') $bug->openedBuild = '';
+ if(!$bug->case) $bug->caseVersion = 0;
+
+ $bug->resolution = str_replace(' ', '', strtolower($bug->resolution));
+ $bug->product = $this->map['product'][$bug->product];
+ $bug->module = $this->map['module'][$bug->module];
+ $this->dao->dbh($this->dbh)->insert(TABLE_BUG)->data($bug)->exec();
+ $this->map['bug'][$bugID] = $this->dao->lastInsertID();
+ }
+
+ /* Update duplicated bugs. */
+ foreach($this->map['bug'] as $oldBugID => $newBugID)
+ {
+ $this->dao->dbh($this->dbh)->update(TABLE_BUG)->set('duplicateBug')->eq($newBugID)->where('duplicateBug')->eq($oldBugID)->exec();
+ }
+ return count($bugs);
+ }
+
+ /**
+ * Convert cases.
+ *
+ * @access public
+ * @return int converted cases count.
+ */
+ public function convertCase()
+ {
+ $cases = $this->dao
+ ->dbh($this->sourceDBH)
+ ->select('
+ caseID AS id,
+ projectID AS product,
+ moduleID AS module,
+ caseTitle AS title,
+ caseSteps AS step,
+ casePriority AS pri,
+ caseType AS type,
+ caseStatus AS status,
+ caseMethod AS howRun,
+ casePlan AS stage,
+ openedBy, openedDate,
+ lastEditedBy, lastEditedDate,
+ scriptedBy, scriptedDate, scriptStatus, scriptLocation,
+ linkID AS linkCase,
+ casekeyword AS keywords,
+ 1 AS version,
+ bugID
+ ')
+ ->from(BUGFREE_TABLE_CASEINFO)
+ ->where('isDroped')->eq(0)
+ ->orderBy('caseID')
+ ->fetchAll('id', $autoCompany = false);
+ foreach($cases as $caseID => $case)
+ {
+ /* Fix fields of case. */
+ $caseID = (int)$caseID;
+ $step = $case->step;
+ $bugs = explode(',', $case->bugID);
+ unset($case->id);
+ unset($case->step);
+ unset($case->bugID);
+
+ $case->type = strtolower($case->type);
+ $case->status = strtolower($case->status);
+ $case->howRun = strtolower($case->howRun);
+ $case->stage = strtolower($case->stage);
+
+ if($case->type == 'configuration') $case->type = 'config';
+ if($case->type == 'setup') $case->type = 'install';
+ if($case->type == 'functional') $case->type = 'feature';
+ if($case->status == 'active') $case->status = 'normal';
+
+ /* Change product and module by zentao's product and module. */
+ $case->product = $this->map['product'][$case->product];
+ $case->module = $this->map['module'][$case->module];
+
+ /* Insert into case table. */
+ $this->dao->dbh($this->dbh)->insert(TABLE_CASE)->data($case)->exec();
+ $zentaoCaseID = $this->dao->lastInsertID();
+ $this->map['case'][$caseID] = $zentaoCaseID;
+
+ /* Insert into case step table. */
+ $caseStep->case = $zentaoCaseID;
+ $caseStep->version = 1;
+ $caseStep->desc = $step;
+ $this->dao->dbh($this->dbh)->insert(TABLE_CASESTEP)->data($caseStep)->exec();
+
+ /* Update related bugs. */
+ foreach($bugs as $bugID)
+ {
+ if(!isset($this->map['bug'][$bugID])) continue;
+ $zentaoBugID = $this->map['bug'][$bugID];
+ $this->dao->dbh($this->dbh)->update(TABLE_BUG)->set('`case`')->eq($zentaoCaseID)->where('id')->eq($zentaoBugID)->limit(1)->exec();
+ }
+ }
+ return count($cases);
+ }
+
+ /**
+ * Convert results.
+ *
+ * @access public
+ * @return int converted results count.
+ */
+ public function convertResult()
+ {
+ $results = $this->dao->dbh($this->sourceDBH)
+ ->select('
+ resultID AS id,
+ caseID AS `case`,
+ resultValue AS caseResult,
+ 1 AS version,
+ openedDate as date,
+ bugID
+ ')
+ ->from(BUGFREE_TABLE_RESULTINFO)
+ ->orderBy('id')
+ ->fetchAll('id', $autoCompany = false);
+ foreach($results as $resultID => $result)
+ {
+ unset($result->id);
+
+ /* The bug id of zentao. */
+ $bugID = (int)$result->bugID;
+ $zentaoBugID = $this->map['bug'][$bugID];
+ unset($result->bugID);
+
+ /* Insert into test result table. */
+ $this->dao->dbh($this->dbh)->insert(TABLE_TESTRESULT)->data($result)->exec();
+ $zentaoResultID = $this->dao->lastInsertId();
+ $this->map['result'][$resultID] = $zentaoResultID;
+
+ /* Update result table. */
+ $this->dao->dbh($this->dbh)->update(TABLE_BUG)->set('result')->eq($zentaoResultID)->where('id')->eq($zentaoBugID)->limit(1)->exec();
+ }
+ return count($results);
+ }
+
+ /**
+ * Convert actions.
+ *
+ * @access public
+ * @return int converted actions count.
+ */
+ public function convertAction()
+ {
+ $actions = $this->dao
+ ->dbh($this->sourceDBH)
+ ->select("actionID AS id,
+ actionTarget AS objectType,
+ idValue AS objectID,
+ actionUser AS actor,
+ actionType AS action,
+ actionDate AS date,
+ actionNote AS comment
+ ")
+ ->from(BUGFREE_TABLE_ACTION)
+ ->where('actionTarget' != 'Result')
+ ->orderBy('actionID')
+ ->fetchAll('id', $autoComapny = false);
+
+ foreach($actions as $actionID => $action)
+ {
+ $actionID = (int)$action->id;
+ unset($action->id);
+ $action->objectType = strtolower($action->objectType);
+ $action->action = strtolower($action->action);
+ $action->objectID = $this->map[$action->objectType][$action->objectID];
+
+ $this->dao->dbh($this->dbh)->insert(TABLE_ACTION)->data($action)->exec();
+ $this->map['action'][$actionID] = $this->dao->lastInsertID();
+ }
+ return count($actions);
+ }
+
+ /**
+ * Convert histories.
+ *
+ * @access public
+ * @return int the converted histories count.
+ */
+ public function convertHistory()
+ {
+ $histories = $this->dao->dbh($this->sourceDBH)
+ ->select('actioID, actionField AS field, oldValue AS old, newValue AS new')
+ ->from(BUGFREE_TABLE_HISTORY)
+ ->orderBy('historyID')
+ ->fetchAll('', $autoCompany = false);
+ foreach($histories as $history)
+ {
+ $history->actionID = $this->map['action'][$history->actionID];
+ $this->dao->dbh($this->dbh)->insert(TABLE_HISTORY)->data($history)->exec();
+ }
+ }
+
+ /**
+ * Convert attachments.
+ *
+ * @access public
+ * @return int the converted files count.
+ */
+ public function convertFile()
+ {
+ $this->setPath();
+ $files = $this->dao->dbh($this->sourceDBH)
+ ->select("
+ actionID,
+ fileName AS pathname,
+ fileTitle AS title,
+ fileType AS extension,
+ fileSize AS size
+ ")
+ ->from(BUGFREE_TABLE_FILE)
+ ->orderBy('fileID')
+ ->fetchAll('', $autoCompany = false);
+ foreach($files as $file)
+ {
+ /* Get the actionID in zentao, to get file info. */
+ $zentaoActionID = $this->map['action'][$file->actionID];
+ $zentaoAction = $this->dao->dbh($this->dbh)->findById($zentaoActionID)->from(TABLE_ACTION)->fetch();
+ $file->objectType = $zentaoAction->objectType;
+ $file->objectID = $zentaoAction->objectID;
+ $file->addedBy = $zentaoAction->actor;
+ $file->addedDate = $zentaoAction->date;
+ unset($file->actionID);
+
+ /* Compute the file size. */
+ if(strpos($file->size, 'KB')) $file->size = (int)(str_replace('KB', '', $file->size) * 1024);
+ if(strpos($file->size, 'MB')) $file->size = (int)(str_replace('MB', '', $file->size) * 1024 * 1024);
+
+ /* Insert into database. */
+ $this->dao->dbh($this->dbh)->insert(TABLE_FILE)->data($file)->exec();
+
+ /* Copy file. */
+ $soureFile = $this->filePath . $file->pathname;
+ if(!file_exists($soureFile))
+ {
+ self::$info['files'][] = sprintf($this->lang->convert->errorFileNotExits, $soureFile);
+ continue;
+ }
+ $targetFile = $this->app->getAppRoot() . "www/data/upload/{$this->app->company->id}/" . $file->pathname;
+ $targetPath = dirname($targetFile);
+ if(!is_dir($targetPath)) mkdir($targetPath, 0777, true);
+ if(!copy($soureFile, $targetFile))
+ {
+ self::$info['files'][] = sprintf($this->lang->convert->errorCopyFailed, $targetFile);
+ }
+ }
+ return count($files);
+ }
+
+ /**
+ * Clear the converted records.
+ *
+ * @access public
+ * @return void
+ */
+ public function clear()
+ {
+ foreach($this->session->state as $table => $maxID)
+ {
+ $this->dao->dbh($this->dbh)->delete()->from($table)->where('id')->gt($maxID)->exec();
+ }
+ }
+}
diff --git a/module/convert/converter/redmine.php b/module/convert/converter/redmine.php
index 50c1b0207a..00b4dffe68 100644
--- a/module/convert/converter/redmine.php
+++ b/module/convert/converter/redmine.php
@@ -1,88 +1,88 @@
-
- * @package convert
- * @version $Id $
- * @link http://www.zentao.net
- */
-class redmineConvertModel extends convertModel
-{
- public $map = array();
- public $filePath = '';
- static public $info = array();
-
- /**
- * Connect to db auto.
- *
- * @access public
- * @return void
- */
- public function __construct()
- {
- parent::__construct();
- parent::connectDB();
- }
-
- /**
- * Check table.
- *
- * @access public
- * @return bool
- */
- public function checkTables()
- {
- return true;
- }
-
- /**
- * Check the install path.
- *
- * @access public
- * @return bool
- */
- public function checkPath()
- {
- $this->setPath();
- return file_exists($this->filePath);
- }
-
- /**
- * Set the path of attachments.
- *
- * @access public
- * @return bool
- */
- public function setPath()
- {
- $this->filePath = realpath($this->post->installPath) . $this->app->getPathFix() . 'files' . $this->app->getPathFix();
- }
-
- /**
- * Excute the convert.
- *
- * @param int $version
- * @access public
- * @return void
- */
- public function execute($version)
- {
- }
-
- /**
- * Clear rows added in converting.
- *
- * @access public
- * @return void
- */
- public function clear()
- {
- foreach($this->session->state as $table => $maxID)
- {
- $this->dao->dbh($this->dbh)->delete()->from($table)->where('id')->gt($maxID)->exec();
- }
- }
-}
+
+ * @package convert
+ * @version $Id $
+ * @link http://www.zentao.net
+ */
+class redmineConvertModel extends convertModel
+{
+ public $map = array();
+ public $filePath = '';
+ static public $info = array();
+
+ /**
+ * Connect to db auto.
+ *
+ * @access public
+ * @return void
+ */
+ public function __construct()
+ {
+ parent::__construct();
+ parent::connectDB();
+ }
+
+ /**
+ * Check table.
+ *
+ * @access public
+ * @return bool
+ */
+ public function checkTables()
+ {
+ return true;
+ }
+
+ /**
+ * Check the install path.
+ *
+ * @access public
+ * @return bool
+ */
+ public function checkPath()
+ {
+ $this->setPath();
+ return file_exists($this->filePath);
+ }
+
+ /**
+ * Set the path of attachments.
+ *
+ * @access public
+ * @return bool
+ */
+ public function setPath()
+ {
+ $this->filePath = realpath($this->post->installPath) . $this->app->getPathFix() . 'files' . $this->app->getPathFix();
+ }
+
+ /**
+ * Excute the convert.
+ *
+ * @param int $version
+ * @access public
+ * @return void
+ */
+ public function execute($version)
+ {
+ }
+
+ /**
+ * Clear rows added in converting.
+ *
+ * @access public
+ * @return void
+ */
+ public function clear()
+ {
+ foreach($this->session->state as $table => $maxID)
+ {
+ $this->dao->dbh($this->dbh)->delete()->from($table)->where('id')->gt($maxID)->exec();
+ }
+ }
+}
diff --git a/module/convert/converter/redmine1.1.php b/module/convert/converter/redmine1.1.php
index 87fec9d407..16bc68060e 100644
--- a/module/convert/converter/redmine1.1.php
+++ b/module/convert/converter/redmine1.1.php
@@ -1,822 +1,822 @@
-
- * @package convert
- * @version $Id $
- * @link http://www.zentao.net
- */
-class redmine11ConvertModel extends redmineConvertModel
-{
- static $convertGroupCount = 0;
- static $convertUserCount = 0;
- static $convertProductCount = 0;
- static $convertProjectCount = 0;
- static $convertStoryCount = 0;
- static $convertTaskCount = 0;
- static $convertBugCount = 0;
- static $convertProductPlanCount = 0;
- static $convertTeamCount = 0;
- static $convertReleaseCount = 0;
- static $convertBuildCount = 0;
- static $convertDocLibCount = 0;
- static $convertDocCount = 0;
- static $convertFileCount = 0;
- public $issueType;
-
- public function __construct($issueType)
- {
- parent::__construct();
- $this->issueType = $issueType;
- }
- /**
- * Execute the converter.
- *
- * @access public
- * @return array
- */
- public function execute()
- {
- $this->clear();
- $this->setTable();
- $this->convertGroup();
- $this->convertUser();
- $this->convertUserGroup();
- $this->convertProduct();
- $this->convertProject();
- $this->convertBuildAndRelease();
- $this->convertProductPlan();
- $this->convertProjectProduct();
- $this->convertTeam();
- $this->convertDocLib();
- $this->convertDoc();
- $this->convertNews();
- $this->convertIssue();
- $this->convertFile();
- $this->dao->dbh($this->dbh);
- $this->loadModel('tree')->fixModulePath();
-
- $result['groups'] = self::$convertGroupCount;
- $result['users'] = self::$convertUserCount ;
- $result['products'] = self::$convertProductCount ;
- $result['projects'] = self::$convertProjectCount ;
- $result['stories'] = self::$convertStoryCount;
- $result['tasks'] = self::$convertTaskCount ;
- $result['bugs'] = self::$convertBugCount ;
- $result['productPlans'] = self::$convertProductPlanCount;
- $result['teams'] = self::$convertTeamCount;
- $result['releases'] = self::$convertReleaseCount;
- $result['builds'] = self::$convertBuildCount;
- $result['docLibs'] = self::$convertDocLibCount ;
- $result['docs'] = self::$convertDocCount;
- $result['files'] = self::$convertFileCount;
- return $result;
- }
-
- /**
- * Set table names.
- *
- * @access public
- * @return void
- */
- public function setTable()
- {
- //$dbPrefix = $this->post->dbPrefix;
- $dbPrefix = '';
- define('REDMINE_TABLE_ATTACHMENTS', $dbPrefix . 'attachments');
- define('REDMINE_TABLE_AUTH_SOURCES', $dbPrefix . 'auth_sources');
- define('REDMINE_TABLE_BOARDS', $dbPrefix . 'boards');
- define('REDMINE_TABLE_CHANGES', $dbPrefix . 'changes');
- define('REDMINE_TABLE_CHANGESETS', $dbPrefix . 'changesets');
- define('REDMINE_TABLE_CHANGESETS_ISSUES', $dbPrefix . 'changesets_issues');
- define('REDMINE_TABLE_COMMENTS', $dbPrefix . 'comments');
- define('REDMINE_TABLE_CUSTOM_FIELDS', $dbPrefix . 'custom_fields');
- define('REDMINE_TABLE_CUSTOM_FIELDS_PROJECTS', $dbPrefix . 'custom_fields_projects');
- define('REDMINE_TABLE_CUSTOM_FIELDS_TRACKERS', $dbPrefix . 'custom_fields_trackers');
- define('REDMINE_TABLE_CUSTOM_VALUES', $dbPrefix . 'custom_values');
- define('REDMINE_TABLE_DOCUMENTS', $dbPrefix . 'documents');
- define('REDMINE_TABLE_ENABLED_MODULES', $dbPrefix . 'enabled_modules');
- define('REDMINE_TABLE_ENUMERATIONS', $dbPrefix . 'enumerations');
- define('REDMINE_TABLE_GROUPS_USERS', $dbPrefix . 'groups_users');
- define('REDMINE_TABLE_ISSUES', $dbPrefix . 'issues');
- define('REDMINE_TABLE_ISSUE_CATEGORIES', $dbPrefix . 'issue_categories');
- define('REDMINE_TABLE_ISSUE_RELATIONS', $dbPrefix . 'issue_relations');
- define('REDMINE_TABLE_ISSUE_STATUSES', $dbPrefix . 'issue_statuses');
- define('REDMINE_TABLE_JOURNALS', $dbPrefix . 'journals');
- define('REDMINE_TABLE_JOURNAL_DETAILS', $dbPrefix . 'journal_details');
- define('REDMINE_TABLE_MEMBERS', $dbPrefix . 'members');
- define('REDMINE_TABLE_MEMBER_ROLES', $dbPrefix . 'member_roles');
- define('REDMINE_TABLE_MESSAGES', $dbPrefix . 'messages');
- define('REDMINE_TABLE_NEWS', $dbPrefix . 'news');
- define('REDMINE_TABLE_OPEN_ID_AUTHENTICATION_ASSOCIATIONS', $dbPrefix . 'open_id_authentication_associations');
- define('REDMINE_TABLE_OPEN_ID_AUTHENTICATION_NONCES', $dbPrefix . 'open_id_authentication_nonces');
- define('REDMINE_TABLE_PROJECTS', $dbPrefix . 'projects');
- define('REDMINE_TABLE_PROJECTS_TRACKERS', $dbPrefix . 'projects_trackers');
- define('REDMINE_TABLE_QUERIES', $dbPrefix . 'queries');
- define('REDMINE_TABLE_REPOSITORIES', $dbPrefix . 'repositories');
- define('REDMINE_TABLE_ROLES', $dbPrefix . 'roles');
- define('REDMINE_TABLE_SCHEMA_MIGRATIONS', $dbPrefix . 'schema_migrations');
- define('REDMINE_TABLE_SETTINGS', $dbPrefix . 'settings');
- define('REDMINE_TABLE_TIME_ENTRIES', $dbPrefix . 'time_entries');
- define('REDMINE_TABLE_TOKENS', $dbPrefix . 'tokens');
- define('REDMINE_TABLE_TRACKERS', $dbPrefix . 'trackers');
- define('REDMINE_TABLE_USERS', $dbPrefix . 'users');
- define('REDMINE_TABLE_USER_PREFERENCES', $dbPrefix . 'user_preferences');
- define('REDMINE_TABLE_VERSIONS', $dbPrefix . 'versions');
- define('REDMINE_TABLE_WATCHERS', $dbPrefix . 'watchers');
- define('REDMINE_TABLE_WIKIS', $dbPrefix . 'wikis');
- define('REDMINE_TABLE_WIKI_CONTENTS', $dbPrefix . 'wiki_contents');
- define('REDMINE_TABLE_WIKI_CONTENT_VERSIONS', $dbPrefix . 'wiki_content_versions');
- define('REDMINE_TABLE_WIKI_PAGES', $dbPrefix . 'wiki_pages');
- define('REDMINE_TABLE_WIKI_REDIRECTS', $dbPrefix . 'wiki_redirects');
- define('REDMINE_TABLE_WORKFLOWS', $dbPrefix . 'workflows');
- }
-
- /**
- * Convert groups.
- *
- * @access public
- * @return void
- */
- public function convertGroup()
- {
- /* Get group list */
- $groups = $this->dao->dbh($this->sourceDBH)
- ->select("id, lastName AS name")
- ->from(REDMINE_TABLE_USERS)
- ->where('type')->eq('Group')
- ->fetchAll('id', $autoCompany = false);
-
- $zentaoGroupNames = $this->dao->dbh($this->dbh)->select('id, name')->from(TABLE_GROUP)->fetchPairs();
- $zentaoGroupIDs = $this->dao->dbh($this->dbh)->select('name, id')->from(TABLE_GROUP)->fetchPairs();
-
- /* Insert into zentao */
- $convertCount = 0;
- foreach($groups as $groupID =>$group)
- {
- unset($group->id);
- if(in_array("$group->name", $zentaoGroupNames))
- {
- self::$info['groups'][] = sprintf($this->lang->convert->errorGroupExists, $group->name);
- $this->map['groups'][$groupID] = $zentaoGroupIDs[$group->name];
- }
- else
- {
- $this->dao->dbh($this->dbh)->insert(TABLE_GROUP)
- ->data($group)->exec();
- $this->map['groups'][$groupID] = $this->dao->lastInsertID();
- $convertCount ++;
- }
- }
- self::$convertGroupCount += $convertCount;
- }
-
- /**
- * Convert users.
- *
- * @access public
- * @return void
- */
- public function convertUser()
- {
- /* Get user list. */
- $users = $this->dao->dbh($this->sourceDBH)
- ->select("id, login AS account, firstname, lastname, mail as email")
- ->from(REDMINE_TABLE_USERS)
- ->where('type')->eq('User')
- ->fetchAll('id', $autoCompany = false);
-
- $zentaoUserNames = $this->dao->dbh($this->dbh)->select('id, account')->from(TABLE_USER)->fetchPairs();
- $zentaoUserIDs = $this->dao->dbh($this->dbh)->select('account, id')->from(TABLE_USER)->fetchPairs();
-
- /* Insert into zentao. */
- $convertCount = 0;
- foreach($users as $id => $user)
- {
- if(in_array("$user->account", $zentaoUserNames))
- {
- self::$info['users'][] = sprintf($this->lang->convert->errorUserExists, $user->account);
- $this->map['users'][$id] = $zentaoUserIDs[$user->account];
- }
- else
- {
- $user->password = md5('123456');
- $user->realname = $user->lastname . $user->firstname;
- unset($user->id);
- unset($user->lastname);
- unset($user->firstname);
- $this->dao->dbh($this->dbh)->insert(TABLE_USER)->data($user)->exec();
- $this->map['users'][$id] = $this->dao->lastInsertID();
- $convertCount ++;
- }
- }
- self::$convertUserCount += $convertCount;
- }
-
- /**
- * convert relationship between user and group.
- *
- * @access public
- * @return void
- */
- public function convertUserGroup()
- {
- $this->map['groups'][0] = 0;
- /* Get relation between user and group list. */
- $userGroups = $this->dao->dbh($this->sourceDBH)
- ->select("t1.group_id, t2.login as account")
- ->from(REDMINE_TABLE_GROUPS_USERS)->alias('t1')
- ->leftJoin(REDMINE_TABLE_USERS)->alias('t2')->on('t1.user_id = t2.id')
- ->fetchAll('', $autoCompany = false);
-
- $zentaoUserGroups = $this->dao->dbh($this->dbh)->select('*')->from(TABLE_USERGROUP)->fetchAll();
-
- /* Insert into zentao. */
- $userGroupExist = false;
- foreach($userGroups as $userGroup)
- {
- $userGroup->group = $this->map['groups'][$userGroup->group_id];
- unset($userGroup->group_id);
- foreach($zentaoUserGroups as $zentaoUserGroup)
- {
- if($userGroup->group == $zentaoUserGroup->group and $userGroup->account == $zentaoUserGroup->account)
- {
- $userGroupExist = true;
- }
- }
- if($userGroupExist == false)
- {
- $this->dao->dbh($this->dbh)->insert(TABLE_USERGROUP)->data($userGroup)->exec();
- }
- }
- }
-
- /**
- * convert products.
- *
- * @access public
- * @return void
- */
- public function convertProduct()
- {
- /* Get product list */
- $products = $this->dao->dbh($this->sourceDBH)
- ->select("id, name, description as `desc`, created_on as createdDate")
- ->from(REDMINE_TABLE_PROJECTS)
- ->fetchAll('id', $autoComapny = false);
-
- /* Insert into zentao */
- foreach($products as $productID => $product)
- {
- unset($product->id);
- $this->dao->dbh($this->dbh)->insert(TABLE_PRODUCT)->data($product)->exec();
- $this->map['products'][$productID] = $this->dao->lastInsertID();
- }
- self::$convertProductCount += count($products);
- }
-
- /**
- * Convert projects.
- *
- * @access public
- * @return void
- */
- public function convertProject()
- {
- /* Get project list */
- $projects = $this->dao->dbh($this->sourceDBH)
- ->select("id, name, project_id, description as `desc`, effective_date AS end")
- ->from(REDMINE_TABLE_VERSIONS)
- ->fetchAll('id', $autoComapny = false);
-
- /* Insert into zentao */
- foreach($projects as $projectID => $project)
- {
- $productID = $project->project_id;
- unset($project->id);
- unset($project->project_id);
- $this->dao->dbh($this->dbh)->insert(TABLE_PROJECT)->data($project)->exec();
- $this->map['projects'][$productID][$projectID] = $this->dao->lastInsertID();
- $this->map['project'][$projectID] = $this->map['projects'][$productID][$projectID];
- }
-
- /* Create a same name project with product */
- foreach($this->map['products'] as $productID)
- {
- $project = $this->dao->dbh($this->dbh)->select('name')->from(TABLE_PRODUCT)->where('id')->eq($productID)->fetch();
- $this->dao->dbh($this->dbh)->insert(TABLE_PROJECT)->data($project)->exec();
- $this->map['projectOfProduct'][$productID] = $this->dao->lastinsertID();
- }
- $convertCount = count($projects) + count($this->map['projectOfProduct']);
- self::$convertProjectCount += $convertCount;
- }
-
- /**
- * convert builds and releases
- *
- * @access public
- * @return void
- */
- public function convertBuildAndRelease()
- {
- /* Get build list */
- $buildAndReleases = $this->dao->dbh($this->sourceDBH)
- ->select("id, name, project_id, description as `desc`, effective_date AS date")
- ->from(REDMINE_TABLE_VERSIONS)
- ->fetchAll('id', $autoCompany = false);
-
- /* Insert into zentao */
- $convertBuildsCount = 0;
- $convertReleasesCount = 0;
- $zentaoBuildNames = $this->dao->dbh($this->dbh)->select('id, name')->from(TABLE_BUILD)->fetchPairs();
- $zentaoBuildIDs = $this->dao->dbh($this->dbh)->select('name, id')->from(TABLE_BUILD)->fetchPairs();
- $zentaoReleaseNames = $this->dao->dbh($this->dbh)->select('id, name')->from(TABLE_RELEASE)->fetchPairs();
- $zentaoReleaseIDs = $this->dao->dbh($this->dbh)->select('name, id')->from(TABLE_RELEASE)->fetchPairs();
- foreach($buildAndReleases as $id => $buildAndRelease)
- {
- $buildAndRelease->project = $this->map['project'][$id];
- $buildAndRelease->product = $this->map['products'][$buildAndRelease->project_id];
- unset($buildAndRelease->id);
- unset($buildAndRelease->project_id);
-
- if(in_array($buildAndRelease->name, $zentaoBuildNames))
- {
- self::$info['builds'][] = sprintf($this->lang->convert->errorBuildExists, $buildAndRelease->name);
- $buildAndRelease->build = $zentaoBuildIDs[$buildAndRelease->name];
- }
- else
- {
- $this->dao->dbh($this->dbh)->insert(TABLE_BUILD)->data($buildAndRelease)->exec();
- $buildAndRelease->build = $this->dao->lastInsertID();
- $convertBuildsCount ++;
- }
-
- unset($buildAndRelease->project);
- if(in_array($buildAndRelease->name, $zentaoBuildNames))
- {
- self::$info['releases'][] = sprintf($this->lang->convert->errorReleaseExists, $buildAndRelease->name);
- }
- else
- {
- $this->dao->dbh($this->dbh)->insert(TABLE_RELEASE)->data($buildAndRelease)->exec();
- $convertReleasesCount ++;
- }
- }
- self::$convertBuildCount += $convertBuildsCount;
- self::$convertReleaseCount += $convertReleasesCount;
- }
-
- /**
- * convert productPlans
- *
- * @access public
- * @return void
- */
- public function convertProductPlan()
- {
- /* Get productPlan list */
- $productPlans = $this->dao->dbh($this->sourceDBH)
- ->select("id, name as title, project_id, description as `desc`, effective_date as end, created_on AS begin")
- ->from(REDMINE_TABLE_VERSIONS)
- ->fetchAll('id', $autoCompany = false);
- /* Insert into zentao */
- foreach($productPlans as $id => $productPlan)
- {
- $productPlan->product = $this->map['products'][$productPlan->project_id];
- unset($productPlan->id);
- unset($productPlan->project_id);
- $this->dao->dbh($this->dbh)->insert(TABLE_PRODUCTPLAN)->data($productPlan)->exec();
- }
-
- /* Create a same plan with product */
- foreach($this->map['products'] as $productID)
- {
- $productPlan = $this->dao->dbh($this->dbh)->select("name as title, createdDate as begin")->from(TABLE_PRODUCT)->where('id')->eq($productID)->fetch();
- $productPlan->product = $productID;
- $this->dao->dbh($this->dbh)->insert(TABLE_PRODUCTPLAN)->data($productPlan)->exec();
- $this->map['planOfProduct'][$productID] = $this->dao->lastinsertID();
- }
- $convertCount = count($this->map['products']) + count($productPlans);
- self::$convertProductPlanCount += $convertCount;
- }
-
- /**
- * convert relationship between project and product.
- *
- * @access public
- * @return void
- */
- public function convertProjectProduct()
- {
- foreach($this->map['projects'] as $productID => $projects)
- {
- foreach($projects as $projectID => $project)
- {
- $this->dao->dbh($this->dbh)->insert(TABLE_PROJECTPRODUCT)
- ->set('project')->eq($project)
- ->set('product')->eq($this->map['products'][$productID])
- ->exec();
- }
- }
- }
-
- /**
- * convert teams.
- *
- * @access public
- * @return void
- */
- public function convertTeam()
- {
- /* Get team list */
- $teams = $this->dao->dbh($this->sourceDBH)
- ->select("t2.login as account, t1.project_id, t1.created_on AS joinDate")
- ->from(REDMINE_TABLE_MEMBERS)->alias('t1')
- ->leftJoin(REDMINE_TABLE_USERS)->alias('t2')->on('t1.user_id = t2.id')
- ->where('t2.type')->eq('User')
- ->fetchAll('', $autoCompany = false);
-
- /* Insert into zentao */
- foreach($teams as $team)
- {
- $productID = $team->project_id;
- unset($team->project_id);
- foreach($this->map['projects'][$productID] as $projectID)
- {
- $team->project = $projectID;
- $this->dao->dbh($this->dbh)->insert(TABLE_TEAM)->data($team)->exec();
- }
- }
- self::$convertTeamCount += count($teams);
- }
-
- /**
- * convert docLibs.
- *
- * @access public
- * @return void
- */
- public function convertDocLib()
- {
- /* Get docLib list */
- $docLibs = $this->dao->dbh($this->sourceDBH)
- ->select("id, name")->from(REDMINE_TABLE_ENUMERATIONS)
- ->where('type')->eq('DocumentCategory')
- ->fetchAll('id', $autoCompany = false);
-
- /* Insert into zentao */
- foreach($docLibs as $docLibID => $docLib)
- {
- unset($docLib->id);
- $this->dao->dbh($this->dbh)->insert(TABLE_DOCLIB)->data($docLib)->exec();
- $this->map['docLibs'][$docLibID] = $this->dao->lastInsertID();
- }
- self::$convertDocLibCount += count($docLibs);
- }
-
- /**
- * convert docs.
- *
- * @access public
- * @return void
- */
- public function convertDoc()
- {
- /* Get all docs */
- $docs = $this->dao->dbh($this->sourceDBH)
- ->select("t1.id, t1.project_id AS product, t2.id AS lib, t1.title, t1.description AS content, t1.created_on AS addedDate")
- ->from(REDMINE_TABLE_DOCUMENTS)->alias('t1')
- ->leftjoin(REDMINE_TABLE_ENUMERATIONS)->alias('t2')->on('t1.category_id = t2.id')
- ->fetchAll('id', $autoCompany = false);
-
- /* Insert into zentao */
- foreach($docs as $docID => $doc)
- {
- unset($doc->id);
- $doc->type = 'text';
- $doc->project = 0;
- $doc->product = $this->map['products'][$doc->product];
- $doc->lib = $this->map['docLibs'][$doc->lib];
- $this->dao->dbh($this->dbh)->insert(TABLE_DOC)->data($doc)->exec();
- $this->map['docs'][$docID] = $this->dao->lastInsertID();
- }
- self::$convertDocCount += count($docs);
- }
-
- /**
- * convert news.
- *
- * @access public
- * @return void
- */
- public function convertNews()
- {
- /* Get news from redmine */
- $news = $this->dao->dbh($this->sourceDBH)
- ->select("t1.project_id as product, t1.title, t1.summary as digest, t1.description as content, t2.login as addedBy, t1.created_on as addedDate")
- ->from(REDMINE_TABLE_NEWS)->alias('t1')
- ->leftJoin(REDMINE_TABLE_USERS)->alias('t2')->on('t1.author_id = t2.id')
- ->fetchAll('', $autoCompany = false);
-
- /* Create a news docLib */
- $newLib->name = 'news';
- $this->dao->dbh($this->dbh)->insert(TABLE_DOCLIB)->data($newLib)->exec();
- $this->map['news'] = $this->dao->lastInsertID();
- self::$convertDocLibCount += 1;
-
- /* Insert into zentao */
- foreach($news as $new)
- {
- $new->product = $this->map['products'][$new->product];
- $new->project = 0;
- $new->lib = $this->map['news'];
- $new->type = 'text';
-
- $this->dao->dbh($this->dbh)->insert(TABLE_DOC)->data($new)->exec();
- }
- self::$convertDocCount += count($news);
- }
-
- /**
- * convert issue
- *
- * @param array $aimTypes //aimTypes['issueTypeID'] = aimtype eg. aimTypes[1] = 'bug';
- * @param array $statusTypes //statusTypes['task']['statusTypeID'] = statusType eg. statusTypes['task'][1] = 'wait';
- * //statusTypes['bug']['statusTypeID'] = statusType eg. statusTypes['bug'][1] = 'active';
- * @param array $priTypes //priTypes['task']['priTypeID'] = priType; eg. priTypes['task'][1] = 1;
- * @access public
- * @return void
- */
- public function convertIssue()
- {
- $aimTypes = $this->issueType->aimTypes;
- $statusTypes = $this->issueType->statusTypes;
- $priTypes = $this->issueType->priTypes;
-
- foreach($aimTypes as $issueType => $aimType)
- {
- if('story' == $aimType)
- {
- $this->convertStory($issueType, $statusTypes, $priTypes);
- }
- elseif('task' == $aimType)
- {
- $this->convertTask($issueType, $statusTypes, $priTypes);
- }
- else
- {
- $this->convertBug($issueType, $statusTypes, $priTypes);
- }
- }
- }
-
- /**
- * convert story
- *
- * @param array $issueType
- * @param array $statusTypes
- * @param array $priTypes
- * @access public
- * @return void
- */
- public function convertStory($issueType, $statusTypes, $priTypes)
- {
- /* Get story list*/
- $stories = $this->dao->dbh($this->sourceDBH)
- ->select("t1.id, t1.project_id as product, t1.subject as title, t1.description as spec, t1.status_id as status, t2.login as assignedTo, t1.priority_id as pri, t3.login as openedBy, t1.created_on as openedDate, t1.estimated_hours as estimate, t1.updated_on as lastEditedDate")
- ->from(REDMINE_TABLE_ISSUES)->alias('t1')
- ->leftJoin(REDMINE_TABLE_USERS)->alias('t2')->on('t1.assigned_to_id = t2.id')
- ->leftJoin(REDMINE_TABLE_USERS)->alias('t3')->on('t1.author_id = t3.id')
- ->where('t1.tracker_id')->eq($issueType)
- ->fetchAll('id', $autoCompany = false);
-
- /* Insert into zentao */
- foreach($stories as $issueID => $story)
- {
- $storySpec->title = $story->title;
- $storySpec->spec = $story->spec;
- unset($story->id);
- unset($story->spec);
-
- /* Insert story into table story */
- $story->product = $this->map['products'][$story->product];
- $story->module = 0;
- $story->plan = $this->map['planOfProduct'][$story->product];
- $story->fromBug = 0;
- $story->pri = $priTypes['story'][$story->pri];
- $story->status = $statusTypes['story'][$story->status];
- $story->toBug = 0;
- $story->duplicateStory = 0;
- $this->dao->dbh($this->dbh)->insert(TABLE_STORY)->data($story)->exec();
- $this->map['issueID'][$issueID] = $this->dao->lastInsertID();
- $this->map['issueType'][$issueID] = 'story';
-
- /* Insert data into table storySpec */
- $storySpec->story = $this->map['issueID'][$issueID];
- $storySpec->version = 1;
- $this->dao->dbh($this->dbh)->insert(TABLE_STORYSPEC)->data($storySpec)->exec();
- }
- self::$convertStoryCount += count($stories);
- }
-
- /**
- * convert task
- *
- * @param array $issueType
- * @param array $statusTypes
- * @param array $priTypes
- * @access public
- * @return void
- */
- public function convertTask($issueType, $statusTypes, $priTypes)
- {
- /* Get task list */
- $tasks = $this->dao->dbh($this->sourceDBH)
- ->select("t1.id, t1.project_id as product, t1.fixed_version_id as project, t1.subject as name, t1.description as `desc`, t1.due_date as deadline, t1.status_id as status, t2.login as assignedTo, t1.priority_id as pri, t3.login as openedBy, t1.created_on as openedDate, t1.estimated_hours as estimate, t1.updated_on as lastEditedDate")
- ->from(REDMINE_TABLE_ISSUES)->alias('t1')
- ->leftJoin(REDMINE_TABLE_USERS)->alias('t2')->on('t1.assigned_to_id = t2.id')
- ->leftJoin(REDMINE_TABLE_USERS)->alias('t3')->on('t1.author_id = t3.id')
- ->where('t1.tracker_id')->eq($issueType)
- ->fetchAll('id', $autoCompany = false);
-
- /* Insert into zentao */
- foreach($tasks as $issueID => $task)
- {
- $task->story = 0;
- $task->storyVersion = 0;
- $task->type = 'misc';
- $task->pri = $priTypes['task'][$task->pri];
- $task->status = $statusTypes['task'][$task->status];
- if($task->project == 0)
- {
- $task->project = $this->map['projectOfProduct'][$task->product];
- }
- else
- {
- $task->project = $this->map['project'][$task->project];
- }
- unset($task->id);
- unset($task->product);
- $this->dao->dbh($this->dbh)->insert(TABLE_TASK)->data($task)->exec();
- $this->map['issueID'][$issueID] = $this->dao->lastInsertID();
- $this->map['issueType'][$issueID] = 'task';
- }
- self::$convertTaskCount += count($tasks);
- }
-
- /**
- * convert bug
- *
- * @param array $issueType
- * @param array $statusTypes
- * @param array $priTypes
- * @access public
- * @return void
- */
- public function convertBug($issueType, $statusTypes, $priTypes)
- {
- /* Get bug list */
- $bugs = $this->dao->dbh($this->sourceDBH)
- ->select("t1.id, t1.project_id as product, t1.fixed_version_id project, t1.subject as title, t1.description as steps, t1.status_id as status, t2.login as assignedTo, t1.priority_id as pri, t3.login as openedBy, t1.created_on as openedDate, t1.updated_on as lastEditedDate")
- ->from(REDMINE_TABLE_ISSUES)->alias('t1')
- ->leftJoin(REDMINE_TABLE_USERS)->alias('t2')->on('t1.assigned_to_id = t2.id')
- ->leftJoin(REDMINE_TABLE_USERS)->alias('t3')->on('t1.author_id = t3.id')
- ->where('t1.tracker_id')->eq($issueType)
- ->fetchAll('id', $autoCompany = false);
-
- /* Insert into zentao */
- foreach($bugs as $issueID => $bug)
- {
- $bug->product = $this->map['products'][$bug->product];
- $bug->module = 0;
- $bug->story = 0;
- $bug->storyVersion = 1;
- $bug->task = 0;
- $bug->severity = 3;
- $bug->type = 'others';
- $bug->status = $statusTypes['bug'][$bug->status];
- $bug->openedBuild = 'trunk';
- $bug->duplicateBug = 0;
- $bug->case = 0;
- $bug->caseVersion = 1;
- $bug->result = 0;
- if($bug->project == 0)
- {
- $bug->project = $this->map['projectOfProduct'][$bug->product];
- }
- else
- {
- $bug->project = $this->map['project'][$bug->project];
- }
- unset($bug->id);
- $this->dao->dbh($this->dbh)->insert(TABLE_BUG)->data($bug)->exec();
- $this->map['issueID'][$issueID] = $this->dao->lastInsertID();
- $this->map['issueType'][$issueID] = 'bug';
- }
- self::$convertBugCount += count($bugs);
- }
-
- /**
- * Convert attachments.
- *
- * @access public
- * @return void
- */
- public function convertFile()
- {
- $this->setPath();
-
- /* Get file list */
- $files = $this->dao->dbh($this->sourceDBH)
- ->select('t1.id, t1.container_id as objectID, t1.container_type as objectType, t1.filename as title, t1.disk_filename as pathname, t1.filesize as size, t2.login as addedBy, t1.created_on as addedDate, description')
- ->from(REDMINE_TABLE_ATTACHMENTS)->alias('t1')
- ->leftJoin(REDMINE_TABLE_USERS)->alias('t2')->on('t1.author_id = t2.id')
- ->fetchAll('id', $autoCompany = false);
-
- /* Insert into zentao */
- foreach($files as $fileID => $file)
- {
- if($file->description != '')
- {
- $file->title = $file->description;
- unset($file->description);
- }
- else
- {
- unset($file->description);
- }
-
- /* Transform objectType and objectID */
- if($file->objectType == 'Issue')
- {
- $file->objectType = $this->map['issueType'][$file->objectID];
- $file->objectID = $this->map['issueID'][$file->objectID];
- }
- elseif($file->objectType == 'Document')
- {
- $file->objectType = 'doc' ;
- $file->objectID = $this->map['docs'][$file->objectID];
- }
- elseif($file->objectType == 'WikiPage')
- {
- continue;
- }
- elseif($file->objectType == 'Version')
- {
- $doc->project = $this->map['project'][$file->objectID];
- $doc = $this->dao->dbh($this->dbh)->select('product')->from(TABLE_PROJECTPRODUCT)->where('project')->eq($doc->project)->fetch();
- $doc->lib = 'project';
- $doc->module = 0;
- $doc->title = $file->title;
- $doc->type = 'file';
- $doc->addedBy = $file->addedBy;
- $doc->addedDate = $file->addedDate;
- $this->dao->dbh($this->dbh)->insert(TABLE_DOC)->data($doc)->exec();
- self::$convertDocCount += 1;
-
- $file->objectType = 'doc';
- $file->objectID = $this->dao->lastInsertID();
- }
-
- $pathname = pathinfo($file->pathname);
- $file->extension = $pathname["extension"];
- unset($file->id);
-
- /* Insert into database. */
- $this->dao->dbh($this->dbh)->insert(TABLE_FILE)->data($file)->exec();
-
- /* Copy file. */
- $soureFile = $this->filePath . $file->pathname;
- if(!file_exists($soureFile))
- {
- self::$info['files'][] = sprintf($this->lang->convert->errorFileNotExits, $soureFile);
- continue;
- }
- $targetFile = $this->app->getAppRoot() . "www/data/upload/{$this->app->company->id}/" . $file->pathname;
- $targetPath = dirname($targetFile);
- if(!is_dir($targetPath)) mkdir($targetPath, 0777, true);
- if(!copy($soureFile, $targetFile))
- {
- self::$info['files'][] = sprintf($this->lang->convert->errorCopyFailed, $targetFile);
- }
- }
- self::$convertFileCount += count($files);
- }
-
- /**
- * Clear the converted records.
- *
- * @access public
- * @return void
- */
- public function clear()
- {
- foreach($this->session->state as $table => $maxID)
- {
- $this->dao->dbh($this->dbh)->delete()->from($table)->where('id')->gt($maxID)->exec();
- }
- }
-}
+
+ * @package convert
+ * @version $Id $
+ * @link http://www.zentao.net
+ */
+class redmine11ConvertModel extends redmineConvertModel
+{
+ static $convertGroupCount = 0;
+ static $convertUserCount = 0;
+ static $convertProductCount = 0;
+ static $convertProjectCount = 0;
+ static $convertStoryCount = 0;
+ static $convertTaskCount = 0;
+ static $convertBugCount = 0;
+ static $convertProductPlanCount = 0;
+ static $convertTeamCount = 0;
+ static $convertReleaseCount = 0;
+ static $convertBuildCount = 0;
+ static $convertDocLibCount = 0;
+ static $convertDocCount = 0;
+ static $convertFileCount = 0;
+ public $issueType;
+
+ public function __construct($issueType)
+ {
+ parent::__construct();
+ $this->issueType = $issueType;
+ }
+ /**
+ * Execute the converter.
+ *
+ * @access public
+ * @return array
+ */
+ public function execute()
+ {
+ $this->clear();
+ $this->setTable();
+ $this->convertGroup();
+ $this->convertUser();
+ $this->convertUserGroup();
+ $this->convertProduct();
+ $this->convertProject();
+ $this->convertBuildAndRelease();
+ $this->convertProductPlan();
+ $this->convertProjectProduct();
+ $this->convertTeam();
+ $this->convertDocLib();
+ $this->convertDoc();
+ $this->convertNews();
+ $this->convertIssue();
+ $this->convertFile();
+ $this->dao->dbh($this->dbh);
+ $this->loadModel('tree')->fixModulePath();
+
+ $result['groups'] = self::$convertGroupCount;
+ $result['users'] = self::$convertUserCount ;
+ $result['products'] = self::$convertProductCount ;
+ $result['projects'] = self::$convertProjectCount ;
+ $result['stories'] = self::$convertStoryCount;
+ $result['tasks'] = self::$convertTaskCount ;
+ $result['bugs'] = self::$convertBugCount ;
+ $result['productPlans'] = self::$convertProductPlanCount;
+ $result['teams'] = self::$convertTeamCount;
+ $result['releases'] = self::$convertReleaseCount;
+ $result['builds'] = self::$convertBuildCount;
+ $result['docLibs'] = self::$convertDocLibCount ;
+ $result['docs'] = self::$convertDocCount;
+ $result['files'] = self::$convertFileCount;
+ return $result;
+ }
+
+ /**
+ * Set table names.
+ *
+ * @access public
+ * @return void
+ */
+ public function setTable()
+ {
+ //$dbPrefix = $this->post->dbPrefix;
+ $dbPrefix = '';
+ define('REDMINE_TABLE_ATTACHMENTS', $dbPrefix . 'attachments');
+ define('REDMINE_TABLE_AUTH_SOURCES', $dbPrefix . 'auth_sources');
+ define('REDMINE_TABLE_BOARDS', $dbPrefix . 'boards');
+ define('REDMINE_TABLE_CHANGES', $dbPrefix . 'changes');
+ define('REDMINE_TABLE_CHANGESETS', $dbPrefix . 'changesets');
+ define('REDMINE_TABLE_CHANGESETS_ISSUES', $dbPrefix . 'changesets_issues');
+ define('REDMINE_TABLE_COMMENTS', $dbPrefix . 'comments');
+ define('REDMINE_TABLE_CUSTOM_FIELDS', $dbPrefix . 'custom_fields');
+ define('REDMINE_TABLE_CUSTOM_FIELDS_PROJECTS', $dbPrefix . 'custom_fields_projects');
+ define('REDMINE_TABLE_CUSTOM_FIELDS_TRACKERS', $dbPrefix . 'custom_fields_trackers');
+ define('REDMINE_TABLE_CUSTOM_VALUES', $dbPrefix . 'custom_values');
+ define('REDMINE_TABLE_DOCUMENTS', $dbPrefix . 'documents');
+ define('REDMINE_TABLE_ENABLED_MODULES', $dbPrefix . 'enabled_modules');
+ define('REDMINE_TABLE_ENUMERATIONS', $dbPrefix . 'enumerations');
+ define('REDMINE_TABLE_GROUPS_USERS', $dbPrefix . 'groups_users');
+ define('REDMINE_TABLE_ISSUES', $dbPrefix . 'issues');
+ define('REDMINE_TABLE_ISSUE_CATEGORIES', $dbPrefix . 'issue_categories');
+ define('REDMINE_TABLE_ISSUE_RELATIONS', $dbPrefix . 'issue_relations');
+ define('REDMINE_TABLE_ISSUE_STATUSES', $dbPrefix . 'issue_statuses');
+ define('REDMINE_TABLE_JOURNALS', $dbPrefix . 'journals');
+ define('REDMINE_TABLE_JOURNAL_DETAILS', $dbPrefix . 'journal_details');
+ define('REDMINE_TABLE_MEMBERS', $dbPrefix . 'members');
+ define('REDMINE_TABLE_MEMBER_ROLES', $dbPrefix . 'member_roles');
+ define('REDMINE_TABLE_MESSAGES', $dbPrefix . 'messages');
+ define('REDMINE_TABLE_NEWS', $dbPrefix . 'news');
+ define('REDMINE_TABLE_OPEN_ID_AUTHENTICATION_ASSOCIATIONS', $dbPrefix . 'open_id_authentication_associations');
+ define('REDMINE_TABLE_OPEN_ID_AUTHENTICATION_NONCES', $dbPrefix . 'open_id_authentication_nonces');
+ define('REDMINE_TABLE_PROJECTS', $dbPrefix . 'projects');
+ define('REDMINE_TABLE_PROJECTS_TRACKERS', $dbPrefix . 'projects_trackers');
+ define('REDMINE_TABLE_QUERIES', $dbPrefix . 'queries');
+ define('REDMINE_TABLE_REPOSITORIES', $dbPrefix . 'repositories');
+ define('REDMINE_TABLE_ROLES', $dbPrefix . 'roles');
+ define('REDMINE_TABLE_SCHEMA_MIGRATIONS', $dbPrefix . 'schema_migrations');
+ define('REDMINE_TABLE_SETTINGS', $dbPrefix . 'settings');
+ define('REDMINE_TABLE_TIME_ENTRIES', $dbPrefix . 'time_entries');
+ define('REDMINE_TABLE_TOKENS', $dbPrefix . 'tokens');
+ define('REDMINE_TABLE_TRACKERS', $dbPrefix . 'trackers');
+ define('REDMINE_TABLE_USERS', $dbPrefix . 'users');
+ define('REDMINE_TABLE_USER_PREFERENCES', $dbPrefix . 'user_preferences');
+ define('REDMINE_TABLE_VERSIONS', $dbPrefix . 'versions');
+ define('REDMINE_TABLE_WATCHERS', $dbPrefix . 'watchers');
+ define('REDMINE_TABLE_WIKIS', $dbPrefix . 'wikis');
+ define('REDMINE_TABLE_WIKI_CONTENTS', $dbPrefix . 'wiki_contents');
+ define('REDMINE_TABLE_WIKI_CONTENT_VERSIONS', $dbPrefix . 'wiki_content_versions');
+ define('REDMINE_TABLE_WIKI_PAGES', $dbPrefix . 'wiki_pages');
+ define('REDMINE_TABLE_WIKI_REDIRECTS', $dbPrefix . 'wiki_redirects');
+ define('REDMINE_TABLE_WORKFLOWS', $dbPrefix . 'workflows');
+ }
+
+ /**
+ * Convert groups.
+ *
+ * @access public
+ * @return void
+ */
+ public function convertGroup()
+ {
+ /* Get group list */
+ $groups = $this->dao->dbh($this->sourceDBH)
+ ->select("id, lastName AS name")
+ ->from(REDMINE_TABLE_USERS)
+ ->where('type')->eq('Group')
+ ->fetchAll('id', $autoCompany = false);
+
+ $zentaoGroupNames = $this->dao->dbh($this->dbh)->select('id, name')->from(TABLE_GROUP)->fetchPairs();
+ $zentaoGroupIDs = $this->dao->dbh($this->dbh)->select('name, id')->from(TABLE_GROUP)->fetchPairs();
+
+ /* Insert into zentao */
+ $convertCount = 0;
+ foreach($groups as $groupID =>$group)
+ {
+ unset($group->id);
+ if(in_array("$group->name", $zentaoGroupNames))
+ {
+ self::$info['groups'][] = sprintf($this->lang->convert->errorGroupExists, $group->name);
+ $this->map['groups'][$groupID] = $zentaoGroupIDs[$group->name];
+ }
+ else
+ {
+ $this->dao->dbh($this->dbh)->insert(TABLE_GROUP)
+ ->data($group)->exec();
+ $this->map['groups'][$groupID] = $this->dao->lastInsertID();
+ $convertCount ++;
+ }
+ }
+ self::$convertGroupCount += $convertCount;
+ }
+
+ /**
+ * Convert users.
+ *
+ * @access public
+ * @return void
+ */
+ public function convertUser()
+ {
+ /* Get user list. */
+ $users = $this->dao->dbh($this->sourceDBH)
+ ->select("id, login AS account, firstname, lastname, mail as email")
+ ->from(REDMINE_TABLE_USERS)
+ ->where('type')->eq('User')
+ ->fetchAll('id', $autoCompany = false);
+
+ $zentaoUserNames = $this->dao->dbh($this->dbh)->select('id, account')->from(TABLE_USER)->fetchPairs();
+ $zentaoUserIDs = $this->dao->dbh($this->dbh)->select('account, id')->from(TABLE_USER)->fetchPairs();
+
+ /* Insert into zentao. */
+ $convertCount = 0;
+ foreach($users as $id => $user)
+ {
+ if(in_array("$user->account", $zentaoUserNames))
+ {
+ self::$info['users'][] = sprintf($this->lang->convert->errorUserExists, $user->account);
+ $this->map['users'][$id] = $zentaoUserIDs[$user->account];
+ }
+ else
+ {
+ $user->password = md5('123456');
+ $user->realname = $user->lastname . $user->firstname;
+ unset($user->id);
+ unset($user->lastname);
+ unset($user->firstname);
+ $this->dao->dbh($this->dbh)->insert(TABLE_USER)->data($user)->exec();
+ $this->map['users'][$id] = $this->dao->lastInsertID();
+ $convertCount ++;
+ }
+ }
+ self::$convertUserCount += $convertCount;
+ }
+
+ /**
+ * convert relationship between user and group.
+ *
+ * @access public
+ * @return void
+ */
+ public function convertUserGroup()
+ {
+ $this->map['groups'][0] = 0;
+ /* Get relation between user and group list. */
+ $userGroups = $this->dao->dbh($this->sourceDBH)
+ ->select("t1.group_id, t2.login as account")
+ ->from(REDMINE_TABLE_GROUPS_USERS)->alias('t1')
+ ->leftJoin(REDMINE_TABLE_USERS)->alias('t2')->on('t1.user_id = t2.id')
+ ->fetchAll('', $autoCompany = false);
+
+ $zentaoUserGroups = $this->dao->dbh($this->dbh)->select('*')->from(TABLE_USERGROUP)->fetchAll();
+
+ /* Insert into zentao. */
+ $userGroupExist = false;
+ foreach($userGroups as $userGroup)
+ {
+ $userGroup->group = $this->map['groups'][$userGroup->group_id];
+ unset($userGroup->group_id);
+ foreach($zentaoUserGroups as $zentaoUserGroup)
+ {
+ if($userGroup->group == $zentaoUserGroup->group and $userGroup->account == $zentaoUserGroup->account)
+ {
+ $userGroupExist = true;
+ }
+ }
+ if($userGroupExist == false)
+ {
+ $this->dao->dbh($this->dbh)->insert(TABLE_USERGROUP)->data($userGroup)->exec();
+ }
+ }
+ }
+
+ /**
+ * convert products.
+ *
+ * @access public
+ * @return void
+ */
+ public function convertProduct()
+ {
+ /* Get product list */
+ $products = $this->dao->dbh($this->sourceDBH)
+ ->select("id, name, description as `desc`, created_on as createdDate")
+ ->from(REDMINE_TABLE_PROJECTS)
+ ->fetchAll('id', $autoComapny = false);
+
+ /* Insert into zentao */
+ foreach($products as $productID => $product)
+ {
+ unset($product->id);
+ $this->dao->dbh($this->dbh)->insert(TABLE_PRODUCT)->data($product)->exec();
+ $this->map['products'][$productID] = $this->dao->lastInsertID();
+ }
+ self::$convertProductCount += count($products);
+ }
+
+ /**
+ * Convert projects.
+ *
+ * @access public
+ * @return void
+ */
+ public function convertProject()
+ {
+ /* Get project list */
+ $projects = $this->dao->dbh($this->sourceDBH)
+ ->select("id, name, project_id, description as `desc`, effective_date AS end")
+ ->from(REDMINE_TABLE_VERSIONS)
+ ->fetchAll('id', $autoComapny = false);
+
+ /* Insert into zentao */
+ foreach($projects as $projectID => $project)
+ {
+ $productID = $project->project_id;
+ unset($project->id);
+ unset($project->project_id);
+ $this->dao->dbh($this->dbh)->insert(TABLE_PROJECT)->data($project)->exec();
+ $this->map['projects'][$productID][$projectID] = $this->dao->lastInsertID();
+ $this->map['project'][$projectID] = $this->map['projects'][$productID][$projectID];
+ }
+
+ /* Create a same name project with product */
+ foreach($this->map['products'] as $productID)
+ {
+ $project = $this->dao->dbh($this->dbh)->select('name')->from(TABLE_PRODUCT)->where('id')->eq($productID)->fetch();
+ $this->dao->dbh($this->dbh)->insert(TABLE_PROJECT)->data($project)->exec();
+ $this->map['projectOfProduct'][$productID] = $this->dao->lastinsertID();
+ }
+ $convertCount = count($projects) + count($this->map['projectOfProduct']);
+ self::$convertProjectCount += $convertCount;
+ }
+
+ /**
+ * convert builds and releases
+ *
+ * @access public
+ * @return void
+ */
+ public function convertBuildAndRelease()
+ {
+ /* Get build list */
+ $buildAndReleases = $this->dao->dbh($this->sourceDBH)
+ ->select("id, name, project_id, description as `desc`, effective_date AS date")
+ ->from(REDMINE_TABLE_VERSIONS)
+ ->fetchAll('id', $autoCompany = false);
+
+ /* Insert into zentao */
+ $convertBuildsCount = 0;
+ $convertReleasesCount = 0;
+ $zentaoBuildNames = $this->dao->dbh($this->dbh)->select('id, name')->from(TABLE_BUILD)->fetchPairs();
+ $zentaoBuildIDs = $this->dao->dbh($this->dbh)->select('name, id')->from(TABLE_BUILD)->fetchPairs();
+ $zentaoReleaseNames = $this->dao->dbh($this->dbh)->select('id, name')->from(TABLE_RELEASE)->fetchPairs();
+ $zentaoReleaseIDs = $this->dao->dbh($this->dbh)->select('name, id')->from(TABLE_RELEASE)->fetchPairs();
+ foreach($buildAndReleases as $id => $buildAndRelease)
+ {
+ $buildAndRelease->project = $this->map['project'][$id];
+ $buildAndRelease->product = $this->map['products'][$buildAndRelease->project_id];
+ unset($buildAndRelease->id);
+ unset($buildAndRelease->project_id);
+
+ if(in_array($buildAndRelease->name, $zentaoBuildNames))
+ {
+ self::$info['builds'][] = sprintf($this->lang->convert->errorBuildExists, $buildAndRelease->name);
+ $buildAndRelease->build = $zentaoBuildIDs[$buildAndRelease->name];
+ }
+ else
+ {
+ $this->dao->dbh($this->dbh)->insert(TABLE_BUILD)->data($buildAndRelease)->exec();
+ $buildAndRelease->build = $this->dao->lastInsertID();
+ $convertBuildsCount ++;
+ }
+
+ unset($buildAndRelease->project);
+ if(in_array($buildAndRelease->name, $zentaoBuildNames))
+ {
+ self::$info['releases'][] = sprintf($this->lang->convert->errorReleaseExists, $buildAndRelease->name);
+ }
+ else
+ {
+ $this->dao->dbh($this->dbh)->insert(TABLE_RELEASE)->data($buildAndRelease)->exec();
+ $convertReleasesCount ++;
+ }
+ }
+ self::$convertBuildCount += $convertBuildsCount;
+ self::$convertReleaseCount += $convertReleasesCount;
+ }
+
+ /**
+ * convert productPlans
+ *
+ * @access public
+ * @return void
+ */
+ public function convertProductPlan()
+ {
+ /* Get productPlan list */
+ $productPlans = $this->dao->dbh($this->sourceDBH)
+ ->select("id, name as title, project_id, description as `desc`, effective_date as end, created_on AS begin")
+ ->from(REDMINE_TABLE_VERSIONS)
+ ->fetchAll('id', $autoCompany = false);
+ /* Insert into zentao */
+ foreach($productPlans as $id => $productPlan)
+ {
+ $productPlan->product = $this->map['products'][$productPlan->project_id];
+ unset($productPlan->id);
+ unset($productPlan->project_id);
+ $this->dao->dbh($this->dbh)->insert(TABLE_PRODUCTPLAN)->data($productPlan)->exec();
+ }
+
+ /* Create a same plan with product */
+ foreach($this->map['products'] as $productID)
+ {
+ $productPlan = $this->dao->dbh($this->dbh)->select("name as title, createdDate as begin")->from(TABLE_PRODUCT)->where('id')->eq($productID)->fetch();
+ $productPlan->product = $productID;
+ $this->dao->dbh($this->dbh)->insert(TABLE_PRODUCTPLAN)->data($productPlan)->exec();
+ $this->map['planOfProduct'][$productID] = $this->dao->lastinsertID();
+ }
+ $convertCount = count($this->map['products']) + count($productPlans);
+ self::$convertProductPlanCount += $convertCount;
+ }
+
+ /**
+ * convert relationship between project and product.
+ *
+ * @access public
+ * @return void
+ */
+ public function convertProjectProduct()
+ {
+ foreach($this->map['projects'] as $productID => $projects)
+ {
+ foreach($projects as $projectID => $project)
+ {
+ $this->dao->dbh($this->dbh)->insert(TABLE_PROJECTPRODUCT)
+ ->set('project')->eq($project)
+ ->set('product')->eq($this->map['products'][$productID])
+ ->exec();
+ }
+ }
+ }
+
+ /**
+ * convert teams.
+ *
+ * @access public
+ * @return void
+ */
+ public function convertTeam()
+ {
+ /* Get team list */
+ $teams = $this->dao->dbh($this->sourceDBH)
+ ->select("t2.login as account, t1.project_id, t1.created_on AS joinDate")
+ ->from(REDMINE_TABLE_MEMBERS)->alias('t1')
+ ->leftJoin(REDMINE_TABLE_USERS)->alias('t2')->on('t1.user_id = t2.id')
+ ->where('t2.type')->eq('User')
+ ->fetchAll('', $autoCompany = false);
+
+ /* Insert into zentao */
+ foreach($teams as $team)
+ {
+ $productID = $team->project_id;
+ unset($team->project_id);
+ foreach($this->map['projects'][$productID] as $projectID)
+ {
+ $team->project = $projectID;
+ $this->dao->dbh($this->dbh)->insert(TABLE_TEAM)->data($team)->exec();
+ }
+ }
+ self::$convertTeamCount += count($teams);
+ }
+
+ /**
+ * convert docLibs.
+ *
+ * @access public
+ * @return void
+ */
+ public function convertDocLib()
+ {
+ /* Get docLib list */
+ $docLibs = $this->dao->dbh($this->sourceDBH)
+ ->select("id, name")->from(REDMINE_TABLE_ENUMERATIONS)
+ ->where('type')->eq('DocumentCategory')
+ ->fetchAll('id', $autoCompany = false);
+
+ /* Insert into zentao */
+ foreach($docLibs as $docLibID => $docLib)
+ {
+ unset($docLib->id);
+ $this->dao->dbh($this->dbh)->insert(TABLE_DOCLIB)->data($docLib)->exec();
+ $this->map['docLibs'][$docLibID] = $this->dao->lastInsertID();
+ }
+ self::$convertDocLibCount += count($docLibs);
+ }
+
+ /**
+ * convert docs.
+ *
+ * @access public
+ * @return void
+ */
+ public function convertDoc()
+ {
+ /* Get all docs */
+ $docs = $this->dao->dbh($this->sourceDBH)
+ ->select("t1.id, t1.project_id AS product, t2.id AS lib, t1.title, t1.description AS content, t1.created_on AS addedDate")
+ ->from(REDMINE_TABLE_DOCUMENTS)->alias('t1')
+ ->leftjoin(REDMINE_TABLE_ENUMERATIONS)->alias('t2')->on('t1.category_id = t2.id')
+ ->fetchAll('id', $autoCompany = false);
+
+ /* Insert into zentao */
+ foreach($docs as $docID => $doc)
+ {
+ unset($doc->id);
+ $doc->type = 'text';
+ $doc->project = 0;
+ $doc->product = $this->map['products'][$doc->product];
+ $doc->lib = $this->map['docLibs'][$doc->lib];
+ $this->dao->dbh($this->dbh)->insert(TABLE_DOC)->data($doc)->exec();
+ $this->map['docs'][$docID] = $this->dao->lastInsertID();
+ }
+ self::$convertDocCount += count($docs);
+ }
+
+ /**
+ * convert news.
+ *
+ * @access public
+ * @return void
+ */
+ public function convertNews()
+ {
+ /* Get news from redmine */
+ $news = $this->dao->dbh($this->sourceDBH)
+ ->select("t1.project_id as product, t1.title, t1.summary as digest, t1.description as content, t2.login as addedBy, t1.created_on as addedDate")
+ ->from(REDMINE_TABLE_NEWS)->alias('t1')
+ ->leftJoin(REDMINE_TABLE_USERS)->alias('t2')->on('t1.author_id = t2.id')
+ ->fetchAll('', $autoCompany = false);
+
+ /* Create a news docLib */
+ $newLib->name = 'news';
+ $this->dao->dbh($this->dbh)->insert(TABLE_DOCLIB)->data($newLib)->exec();
+ $this->map['news'] = $this->dao->lastInsertID();
+ self::$convertDocLibCount += 1;
+
+ /* Insert into zentao */
+ foreach($news as $new)
+ {
+ $new->product = $this->map['products'][$new->product];
+ $new->project = 0;
+ $new->lib = $this->map['news'];
+ $new->type = 'text';
+
+ $this->dao->dbh($this->dbh)->insert(TABLE_DOC)->data($new)->exec();
+ }
+ self::$convertDocCount += count($news);
+ }
+
+ /**
+ * convert issue
+ *
+ * @param array $aimTypes //aimTypes['issueTypeID'] = aimtype eg. aimTypes[1] = 'bug';
+ * @param array $statusTypes //statusTypes['task']['statusTypeID'] = statusType eg. statusTypes['task'][1] = 'wait';
+ * //statusTypes['bug']['statusTypeID'] = statusType eg. statusTypes['bug'][1] = 'active';
+ * @param array $priTypes //priTypes['task']['priTypeID'] = priType; eg. priTypes['task'][1] = 1;
+ * @access public
+ * @return void
+ */
+ public function convertIssue()
+ {
+ $aimTypes = $this->issueType->aimTypes;
+ $statusTypes = $this->issueType->statusTypes;
+ $priTypes = $this->issueType->priTypes;
+
+ foreach($aimTypes as $issueType => $aimType)
+ {
+ if('story' == $aimType)
+ {
+ $this->convertStory($issueType, $statusTypes, $priTypes);
+ }
+ elseif('task' == $aimType)
+ {
+ $this->convertTask($issueType, $statusTypes, $priTypes);
+ }
+ else
+ {
+ $this->convertBug($issueType, $statusTypes, $priTypes);
+ }
+ }
+ }
+
+ /**
+ * convert story
+ *
+ * @param array $issueType
+ * @param array $statusTypes
+ * @param array $priTypes
+ * @access public
+ * @return void
+ */
+ public function convertStory($issueType, $statusTypes, $priTypes)
+ {
+ /* Get story list*/
+ $stories = $this->dao->dbh($this->sourceDBH)
+ ->select("t1.id, t1.project_id as product, t1.subject as title, t1.description as spec, t1.status_id as status, t2.login as assignedTo, t1.priority_id as pri, t3.login as openedBy, t1.created_on as openedDate, t1.estimated_hours as estimate, t1.updated_on as lastEditedDate")
+ ->from(REDMINE_TABLE_ISSUES)->alias('t1')
+ ->leftJoin(REDMINE_TABLE_USERS)->alias('t2')->on('t1.assigned_to_id = t2.id')
+ ->leftJoin(REDMINE_TABLE_USERS)->alias('t3')->on('t1.author_id = t3.id')
+ ->where('t1.tracker_id')->eq($issueType)
+ ->fetchAll('id', $autoCompany = false);
+
+ /* Insert into zentao */
+ foreach($stories as $issueID => $story)
+ {
+ $storySpec->title = $story->title;
+ $storySpec->spec = $story->spec;
+ unset($story->id);
+ unset($story->spec);
+
+ /* Insert story into table story */
+ $story->product = $this->map['products'][$story->product];
+ $story->module = 0;
+ $story->plan = $this->map['planOfProduct'][$story->product];
+ $story->fromBug = 0;
+ $story->pri = $priTypes['story'][$story->pri];
+ $story->status = $statusTypes['story'][$story->status];
+ $story->toBug = 0;
+ $story->duplicateStory = 0;
+ $this->dao->dbh($this->dbh)->insert(TABLE_STORY)->data($story)->exec();
+ $this->map['issueID'][$issueID] = $this->dao->lastInsertID();
+ $this->map['issueType'][$issueID] = 'story';
+
+ /* Insert data into table storySpec */
+ $storySpec->story = $this->map['issueID'][$issueID];
+ $storySpec->version = 1;
+ $this->dao->dbh($this->dbh)->insert(TABLE_STORYSPEC)->data($storySpec)->exec();
+ }
+ self::$convertStoryCount += count($stories);
+ }
+
+ /**
+ * convert task
+ *
+ * @param array $issueType
+ * @param array $statusTypes
+ * @param array $priTypes
+ * @access public
+ * @return void
+ */
+ public function convertTask($issueType, $statusTypes, $priTypes)
+ {
+ /* Get task list */
+ $tasks = $this->dao->dbh($this->sourceDBH)
+ ->select("t1.id, t1.project_id as product, t1.fixed_version_id as project, t1.subject as name, t1.description as `desc`, t1.due_date as deadline, t1.status_id as status, t2.login as assignedTo, t1.priority_id as pri, t3.login as openedBy, t1.created_on as openedDate, t1.estimated_hours as estimate, t1.updated_on as lastEditedDate")
+ ->from(REDMINE_TABLE_ISSUES)->alias('t1')
+ ->leftJoin(REDMINE_TABLE_USERS)->alias('t2')->on('t1.assigned_to_id = t2.id')
+ ->leftJoin(REDMINE_TABLE_USERS)->alias('t3')->on('t1.author_id = t3.id')
+ ->where('t1.tracker_id')->eq($issueType)
+ ->fetchAll('id', $autoCompany = false);
+
+ /* Insert into zentao */
+ foreach($tasks as $issueID => $task)
+ {
+ $task->story = 0;
+ $task->storyVersion = 0;
+ $task->type = 'misc';
+ $task->pri = $priTypes['task'][$task->pri];
+ $task->status = $statusTypes['task'][$task->status];
+ if($task->project == 0)
+ {
+ $task->project = $this->map['projectOfProduct'][$task->product];
+ }
+ else
+ {
+ $task->project = $this->map['project'][$task->project];
+ }
+ unset($task->id);
+ unset($task->product);
+ $this->dao->dbh($this->dbh)->insert(TABLE_TASK)->data($task)->exec();
+ $this->map['issueID'][$issueID] = $this->dao->lastInsertID();
+ $this->map['issueType'][$issueID] = 'task';
+ }
+ self::$convertTaskCount += count($tasks);
+ }
+
+ /**
+ * convert bug
+ *
+ * @param array $issueType
+ * @param array $statusTypes
+ * @param array $priTypes
+ * @access public
+ * @return void
+ */
+ public function convertBug($issueType, $statusTypes, $priTypes)
+ {
+ /* Get bug list */
+ $bugs = $this->dao->dbh($this->sourceDBH)
+ ->select("t1.id, t1.project_id as product, t1.fixed_version_id project, t1.subject as title, t1.description as steps, t1.status_id as status, t2.login as assignedTo, t1.priority_id as pri, t3.login as openedBy, t1.created_on as openedDate, t1.updated_on as lastEditedDate")
+ ->from(REDMINE_TABLE_ISSUES)->alias('t1')
+ ->leftJoin(REDMINE_TABLE_USERS)->alias('t2')->on('t1.assigned_to_id = t2.id')
+ ->leftJoin(REDMINE_TABLE_USERS)->alias('t3')->on('t1.author_id = t3.id')
+ ->where('t1.tracker_id')->eq($issueType)
+ ->fetchAll('id', $autoCompany = false);
+
+ /* Insert into zentao */
+ foreach($bugs as $issueID => $bug)
+ {
+ $bug->product = $this->map['products'][$bug->product];
+ $bug->module = 0;
+ $bug->story = 0;
+ $bug->storyVersion = 1;
+ $bug->task = 0;
+ $bug->severity = 3;
+ $bug->type = 'others';
+ $bug->status = $statusTypes['bug'][$bug->status];
+ $bug->openedBuild = 'trunk';
+ $bug->duplicateBug = 0;
+ $bug->case = 0;
+ $bug->caseVersion = 1;
+ $bug->result = 0;
+ if($bug->project == 0)
+ {
+ $bug->project = $this->map['projectOfProduct'][$bug->product];
+ }
+ else
+ {
+ $bug->project = $this->map['project'][$bug->project];
+ }
+ unset($bug->id);
+ $this->dao->dbh($this->dbh)->insert(TABLE_BUG)->data($bug)->exec();
+ $this->map['issueID'][$issueID] = $this->dao->lastInsertID();
+ $this->map['issueType'][$issueID] = 'bug';
+ }
+ self::$convertBugCount += count($bugs);
+ }
+
+ /**
+ * Convert attachments.
+ *
+ * @access public
+ * @return void
+ */
+ public function convertFile()
+ {
+ $this->setPath();
+
+ /* Get file list */
+ $files = $this->dao->dbh($this->sourceDBH)
+ ->select('t1.id, t1.container_id as objectID, t1.container_type as objectType, t1.filename as title, t1.disk_filename as pathname, t1.filesize as size, t2.login as addedBy, t1.created_on as addedDate, description')
+ ->from(REDMINE_TABLE_ATTACHMENTS)->alias('t1')
+ ->leftJoin(REDMINE_TABLE_USERS)->alias('t2')->on('t1.author_id = t2.id')
+ ->fetchAll('id', $autoCompany = false);
+
+ /* Insert into zentao */
+ foreach($files as $fileID => $file)
+ {
+ if($file->description != '')
+ {
+ $file->title = $file->description;
+ unset($file->description);
+ }
+ else
+ {
+ unset($file->description);
+ }
+
+ /* Transform objectType and objectID */
+ if($file->objectType == 'Issue')
+ {
+ $file->objectType = $this->map['issueType'][$file->objectID];
+ $file->objectID = $this->map['issueID'][$file->objectID];
+ }
+ elseif($file->objectType == 'Document')
+ {
+ $file->objectType = 'doc' ;
+ $file->objectID = $this->map['docs'][$file->objectID];
+ }
+ elseif($file->objectType == 'WikiPage')
+ {
+ continue;
+ }
+ elseif($file->objectType == 'Version')
+ {
+ $doc->project = $this->map['project'][$file->objectID];
+ $doc = $this->dao->dbh($this->dbh)->select('product')->from(TABLE_PROJECTPRODUCT)->where('project')->eq($doc->project)->fetch();
+ $doc->lib = 'project';
+ $doc->module = 0;
+ $doc->title = $file->title;
+ $doc->type = 'file';
+ $doc->addedBy = $file->addedBy;
+ $doc->addedDate = $file->addedDate;
+ $this->dao->dbh($this->dbh)->insert(TABLE_DOC)->data($doc)->exec();
+ self::$convertDocCount += 1;
+
+ $file->objectType = 'doc';
+ $file->objectID = $this->dao->lastInsertID();
+ }
+
+ $pathname = pathinfo($file->pathname);
+ $file->extension = $pathname["extension"];
+ unset($file->id);
+
+ /* Insert into database. */
+ $this->dao->dbh($this->dbh)->insert(TABLE_FILE)->data($file)->exec();
+
+ /* Copy file. */
+ $soureFile = $this->filePath . $file->pathname;
+ if(!file_exists($soureFile))
+ {
+ self::$info['files'][] = sprintf($this->lang->convert->errorFileNotExits, $soureFile);
+ continue;
+ }
+ $targetFile = $this->app->getAppRoot() . "www/data/upload/{$this->app->company->id}/" . $file->pathname;
+ $targetPath = dirname($targetFile);
+ if(!is_dir($targetPath)) mkdir($targetPath, 0777, true);
+ if(!copy($soureFile, $targetFile))
+ {
+ self::$info['files'][] = sprintf($this->lang->convert->errorCopyFailed, $targetFile);
+ }
+ }
+ self::$convertFileCount += count($files);
+ }
+
+ /**
+ * Clear the converted records.
+ *
+ * @access public
+ * @return void
+ */
+ public function clear()
+ {
+ foreach($this->session->state as $table => $maxID)
+ {
+ $this->dao->dbh($this->dbh)->delete()->from($table)->where('id')->gt($maxID)->exec();
+ }
+ }
+}
diff --git a/module/convert/lang/en.php b/module/convert/lang/en.php
index 2ec3c9e055..29faed68a4 100644
--- a/module/convert/lang/en.php
+++ b/module/convert/lang/en.php
@@ -1,124 +1,124 @@
-
- * @package convert
- * @version $Id$
- * @link http://www.zentao.net
- */
-$lang->convert->common = 'Import';
-$lang->convert->index = 'Index';
-$lang->convert->next = 'Next';
-$lang->convert->pre = 'Back';
-$lang->convert->reload = 'Reload';
-$lang->convert->error = 'Error ';
-
-$lang->convert->start = 'Begin import';
-$lang->convert->desc = <<Welcome to use this convert wizard which will help you to import other system data to ZenTaoPMS.