diff --git a/module/common/lang/en.php b/module/common/lang/en.php index d48b8d0d94..7506af29fe 100644 --- a/module/common/lang/en.php +++ b/module/common/lang/en.php @@ -280,6 +280,8 @@ $lang->admin->data = 'Data'; $lang->admin->cron = 'Cron'; $lang->admin->buildIndex = 'Full Text Search'; +$lang->convert->importJira = 'Import Jira'; + $lang->storyConcept = 'Story Concpet'; $lang->searchTips = ''; diff --git a/module/common/lang/menu.php b/module/common/lang/menu.php index 06031c105c..755a609abf 100644 --- a/module/common/lang/menu.php +++ b/module/common/lang/menu.php @@ -480,7 +480,7 @@ $lang->admin->menu->custom = array('link' => "{$lang->custom->common}|custom| $lang->admin->menu->extension = array('link' => "{$lang->extension->common}|extension|browse", 'subModule' => 'extension'); $lang->admin->menu->dev = array('link' => "$lang->redev|dev|api", 'alias' => 'db', 'subModule' => 'dev,editor,entry'); $lang->admin->menu->message = array('link' => "{$lang->message->common}|message|index", 'subModule' => 'message,mail,webhook'); -$lang->admin->menu->system = array('link' => "{$lang->admin->system}|backup|index", 'subModule' => 'cron,backup,action,admin,search', 'exclude' => 'admin-index,admin-xuanxuan,admin-register,admin-ztcompany'); +$lang->admin->menu->system = array('link' => "{$lang->admin->system}|backup|index", 'subModule' => 'cron,backup,action,admin,search,convert', 'exclude' => 'admin-index,admin-xuanxuan,admin-register,admin-ztcompany'); $lang->admin->menu->model['dropMenu'] = new stdclass(); $lang->admin->menu->model['dropMenu']->allModel = array('link' => "{$lang->globalSetting}|custom|browsestoryconcept|", 'subModule' => 'measurement,report,sqlbuilder,subject,custom,meetingroom,baseline'); @@ -534,12 +534,13 @@ $lang->admin->menu->dev['menuOrder'][10] = 'db'; $lang->admin->menu->dev['menuOrder'][15] = 'editor'; $lang->admin->menu->dev['menuOrder'][20] = 'entry'; -$lang->admin->menu->system['subMenu'] = new stdclass(); -$lang->admin->menu->system['subMenu']->data = array('link' => "{$lang->admin->data}|backup|index", 'subModule' => 'action'); -$lang->admin->menu->system['subMenu']->safe = array('link' => "$lang->security|admin|safe", 'alias' => 'checkweak'); -$lang->admin->menu->system['subMenu']->cron = array('link' => "{$lang->admin->cron}|cron|index", 'subModule' => 'cron'); -$lang->admin->menu->system['subMenu']->timezone = array('link' => "$lang->timezone|custom|timezone"); -$lang->admin->menu->system['subMenu']->buildIndex = array('link' => "{$lang->admin->buildIndex}|search|buildindex|"); +$lang->admin->menu->system['subMenu'] = new stdclass(); +$lang->admin->menu->system['subMenu']->data = array('link' => "{$lang->admin->data}|backup|index", 'subModule' => 'action'); +$lang->admin->menu->system['subMenu']->safe = array('link' => "$lang->security|admin|safe", 'alias' => 'checkweak'); +$lang->admin->menu->system['subMenu']->cron = array('link' => "{$lang->admin->cron}|cron|index", 'subModule' => 'cron'); +$lang->admin->menu->system['subMenu']->timezone = array('link' => "$lang->timezone|custom|timezone"); +$lang->admin->menu->system['subMenu']->buildIndex = array('link' => "{$lang->admin->buildIndex}|search|buildindex|"); +$lang->admin->menu->system['subMenu']->convertJira = array('link' => "{$lang->convert->importJira}|convert|convertjira|", 'subModule' => 'convert'); $lang->admin->dividerMenu = ',company,message,system,'; @@ -660,6 +661,7 @@ $lang->navGroup->dev = 'admin'; $lang->navGroup->entry = 'admin'; $lang->navGroup->extension = 'admin'; $lang->navGroup->action = 'admin'; +$lang->navGroup->convert = 'admin'; $lang->navGroup->search = 'search'; $lang->navGroup->index = 'index'; diff --git a/module/common/lang/zh-cn.php b/module/common/lang/zh-cn.php index c6c8dada3c..b7212e328e 100644 --- a/module/common/lang/zh-cn.php +++ b/module/common/lang/zh-cn.php @@ -280,6 +280,8 @@ $lang->admin->data = '数据'; $lang->admin->cron = '定时'; $lang->admin->buildIndex = '重建索引'; +$lang->convert->importJira = '导入Jira数据'; + $lang->storyConcept = '需求概念'; $lang->searchTips = ''; diff --git a/module/convert/config.php b/module/convert/config.php new file mode 100644 index 0000000000..ee299c8b0e --- /dev/null +++ b/module/convert/config.php @@ -0,0 +1,15 @@ +view->info = redmineConvertModel::$info; $this->display(); } + + /** + * Import jira index. + * + * @access public + * @return void + */ + public function convertJira() + { + $this->view->title = $this->lang->convert->jira->method; + $this->display(); + } + + /** + * Import jira notice. + * + * @param string $type db|file + * @access public + * @return void + */ + public function importNotice($type = 'db') + { + if($_POST) + { + $dbName = $this->post->dbName; + if(!$dbName) + { + $response['result'] = 'fail'; + $response['message'] = $this->lang->convert->jira->dbNameEmpty; + return print($this->send($response)); + } + + if(!$this->convert->dbExists($dbName)) + { + $response['result'] = 'fail'; + $response['message'] = $this->lang->convert->jira->invalidDB; + return print($this->send($response)); + } + + $this->session->set('jiraDB', $dbName); + $response['result'] = 'success'; + $response['message'] = $this->lang->saveSuccess; + $response['locate'] = $this->createLink('convert', 'mapJira2Zentao', "type=db&dbName={$this->post->dbName}"); + return print($this->send($response)); + } + + $this->view->title = $this->lang->convert->jira->method; + $this->view->type = $type; + $this->display(); + } + + /** + * Map jira objects to zentao. + * + * @param string $type db|file + * @param string $dbName + * @access public + * @return void + */ + public function mapJira2Zentao($type = 'db', $dbName = '') + { + $this->app->loadLang('story'); + $this->app->loadLang('bug'); + $this->app->loadLang('task'); + + if($_POST) + { + $this->session->set('jiraRelation', $_POST); + + $response['result'] = 'success'; + $response['message'] = $this->lang->saveSuccess; + $response['locate'] = $this->createLink('convert', 'initJiraUser', "type=$type"); + return print($this->send($response)); + } + + if($type == 'db') + { + $dbh = $this->convert->connectDB($dbName); + + $issueTypePairs = $this->dao->dbh($dbh)->select('ID,pname')->from(JIRA_ISSUETYPE)->fetchPairs(); + $linkTypePairs = $this->dao->dbh($dbh)->select('ID,LINKNAME')->from(JIRA_ISSUELINKTYPE)->fetchPairs(); + $resolutions = $this->dao->dbh($dbh)->select('ID,pname')->from(JIRA_RESOLUTION)->fetchPairs(); + $statusList = $this->dao->dbh($dbh)->select('ID,pname')->from(JIRA_ISSUESTATUS)->fetchPairs(); + } + + $this->view->title = $this->lang->convert->jira->mapJira2Zentao; + $this->view->issueTypePairs = $issueTypePairs; + $this->view->linkTypePairs = $linkTypePairs; + $this->view->resolutions = $resolutions; + $this->view->statusList = $statusList; + $this->display(); + } + + /** + * Init jira user. + * + * @param string $type db|file + * @access public + * @return void + */ + public function initJiraUser($type = 'db') + { + $this->app->loadLang('user'); + + if($_POST) + { + if(!$this->post->password1 || !$this->post->password2) + { + $response['result'] = 'fail'; + $response['message'] = $this->lang->convert->jira->passwordEmpty; + return print($this->send($response)); + } + + if($this->post->password1 != $this->post->password2) + { + $response['result'] = 'fail'; + $response['message'] = $this->lang->convert->jira->passwordDifferent; + return print($this->send($response)); + } + + $jiraUser['password'] = md5($this->post->password1); + $jiraUser['group'] = $this->post->group; + $this->session->set('jiraUser', $jiraUser); + + $response['result'] = 'success'; + $response['message'] = $this->lang->saveSuccess; + $response['locate'] = $this->createLink('convert', 'importJira', "type=$type"); + return print($this->send($response)); + } + + $this->view->title = $this->lang->convert->jira->initJiraUser; + $this->view->groups = $this->loadModel('group')->getPairs(); + $this->display(); + } + + /** + * Import jira main logic. + * + * @param string $method db|file + * @param string $type user|issue|project|attachment + * @param int $lastID + * @access public + * @return void + */ + public function importJira($method = 'db', $type = 'user', $lastID = 0, $createTable = false) + { + set_time_limit(0); + + if($method = 'db') + { + if(helper::isAjaxRequest()) + { + $result = $this->convert->importJiraFromDB($type, $lastID, $createTable); + if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError())); + if(isset($result['finished']) and $result['finished']) + { + return print $this->send(array('result' => 'finished', 'message' => $this->lang->convert->jira->importSuccessfully)); + } + else + { + $type = zget($this->lang->convert->jira->objectList, $result['type'], $result['type']); + + $response['result'] = 'unfinished'; + $response['message'] = sprintf($this->lang->convert->jira->importResult, $type, $type, $result['count']); + $response['type'] = $type; + $response['count'] = $result['count']; + $response['next'] = inlink('importJira', "method=$method&type={$result['type']}&lastID={$result['lastID']}"); + return print $this->send($response); + } + } + } + else + { + //$this->convert->importJiraFromFile(); + } + + $this->view->type = $type; + $this->view->method = $method; + $this->view->title = $this->lang->convert->jira->importJira; + $this->display(); + } } diff --git a/module/convert/lang/en.php b/module/convert/lang/en.php index cf993dbd6f..065d9fda22 100644 --- a/module/convert/lang/en.php +++ b/module/convert/lang/en.php @@ -114,3 +114,6 @@ $lang->convert->issue = new stdclass(); $lang->convert->issue->redmine = 'Redmine'; $lang->convert->issue->zentao = 'ZenTao'; $lang->convert->issue->goto = 'Convert To'; + +$lang->convert->jira = new stdclass(); +$lang->convert->jira->import = 'Import Jira'; diff --git a/module/convert/lang/zh-cn.php b/module/convert/lang/zh-cn.php index 1326aa2751..d3146b2994 100644 --- a/module/convert/lang/zh-cn.php +++ b/module/convert/lang/zh-cn.php @@ -114,3 +114,67 @@ $lang->convert->issue = new stdclass(); $lang->convert->issue->redmine = 'Redmine'; $lang->convert->issue->zentao = '禅道'; $lang->convert->issue->goto = '转换为'; + +$lang->convert->jira = new stdclass(); +$lang->convert->jira->method = '选择导入方式'; +$lang->convert->jira->next = '下一步'; +$lang->convert->jira->importFromDB = '从数据库导入'; +$lang->convert->jira->importFromFile = '从文件导入'; +$lang->convert->jira->mapJira2Zentao = '设置对应关系'; +$lang->convert->jira->dbNameNotice = '请输入Jira数据库名字'; +$lang->convert->jira->importNotice = '注意:导入数据有风险!请务必确保如下操作步骤依次完成,再进行合并。'; +$lang->convert->jira->dbDesc = '

如果您的Jira使用Mysql数据库, 请选择此方式

'; +$lang->convert->jira->fileDesc = '

如果您的Jira使用非Mysql数据库, 请选择此方式

'; +$lang->convert->jira->jiraObject = 'Jira Issues'; +$lang->convert->jira->zentaoObject = '禅道对象'; +$lang->convert->jira->jiraLinkType = 'Jira 关联关系'; +$lang->convert->jira->zentaoLinkType = '禅道关联关系'; +$lang->convert->jira->jiraResolution = 'Jira 解决方案'; +$lang->convert->jira->zentaoResolution = '禅道Bug解决方案'; +$lang->convert->jira->zentaoReason = '禅道需求关闭原因'; +$lang->convert->jira->jiraStatus = 'Jira Issues 状态'; +$lang->convert->jira->storyStatus = '禅道需求状态'; +$lang->convert->jira->storyStage = '禅道需求阶段'; +$lang->convert->jira->bugStatus = '禅道Bug状态'; +$lang->convert->jira->taskStatus = '禅道任务状态'; +$lang->convert->jira->initJiraUser = '设置Jira用户'; +$lang->convert->jira->importJira = '导入Jira'; +$lang->convert->jira->start = '开始导入'; + +$lang->convert->jira->dbNameEmpty = 'Jira数据库名字不能为空!'; +$lang->convert->jira->invalidDB = '无效的数据库名!'; +$lang->convert->jira->passwordNotice = "设置Jira用户导入到禅道后的默认密码,用户后续可以在禅道中自行修改密码。"; +$lang->convert->jira->groupNotice = "设置Jira用户导入到禅道后的默认权限分组。"; +$lang->convert->jira->passwordDifferent = '两次密码不一致!'; +$lang->convert->jira->passwordEmpty = '密码不能为空!'; +$lang->convert->jira->importSuccessfully = 'Jira导入完成!'; +$lang->convert->jira->importResult = "导入 %s 数据, 已处理 %s 条记录;"; + +$lang->convert->jira->zentaoObjectList['task'] = '任务'; +$lang->convert->jira->zentaoObjectList['requirement'] = '用户需求'; +$lang->convert->jira->zentaoObjectList['story'] = '软件需求'; +$lang->convert->jira->zentaoObjectList['bug'] = 'Bug'; + +$lang->convert->jira->zentaoLinkTypeList['subTaskLink'] = '父-子任务'; +$lang->convert->jira->zentaoLinkTypeList['subStoryLink'] = '父-子需求'; +$lang->convert->jira->zentaoLinkTypeList['duplicate'] = '重复对象'; +$lang->convert->jira->zentaoLinkTypeList['relates'] = '互相关联'; + +$lang->convert->jira->importSteps['db'][1] = '备份禅道数据库,备份Jira数据库。'; +$lang->convert->jira->importSteps['db'][2] = '导入数据时使用禅道会给服务器造成性能压力,请尽量保证导入数据时无人使用禅道。'; +$lang->convert->jira->importSteps['db'][3] = '将Jira数据库导入到禅道使用的Mysql中,名字和禅道数据库区别开来。'; +$lang->convert->jira->importSteps['db'][4] = "将Jira附件目录 attachments 放到 %s 下,确保禅道服务器磁盘空间足够。"; +$lang->convert->jira->importSteps['db'][5] = "上述步骤完成后,请输入Jira数据库名字进行下一步。"; +$lang->convert->jira->importSteps['file'][1] = '备份禅道数据库,备份Jira数据库。'; +$lang->convert->jira->importSteps['file'][2] = '导入数据时使用禅道会给服务器造成性能压力,请尽量保证导入数据时无人使用禅道。'; +$lang->convert->jira->importSteps['file'][3] = "将Jira的备份文件 entities.xml 放到 %s 下。"; +$lang->convert->jira->importSteps['file'][4] = "将Jira附件目录 attachments 放到 %s 下,确保禅道服务器磁盘空间足够。"; +$lang->convert->jira->importSteps['file'][5] = "上述步骤完成后,点击下一步。"; + +$lang->convert->jira->objectList['user'] = '用户'; +$lang->convert->jira->objectList['project'] = '项目'; +$lang->convert->jira->objectList['issue'] = 'Issue'; +$lang->convert->jira->objectList['build'] = '版本'; +$lang->convert->jira->objectList['issuelink'] = '关联关系'; +$lang->convert->jira->objectList['action'] = '历史记录'; +$lang->convert->jira->objectList['file'] = '附件'; diff --git a/module/convert/model.php b/module/convert/model.php index 99f357bbd7..e36c70652d 100644 --- a/module/convert/model.php +++ b/module/convert/model.php @@ -19,15 +19,15 @@ class convertModel extends model * @access public * @return void */ - public function connectDB() + public function connectDB($dbName = '') { - $dsn = "mysql:host={$this->post->dbHost}; port={$this->post->dbPort};dbname={$this->post->dbName}"; + $dsn = "mysql:host={$this->config->db->host}; port={$this->config->db->port};dbname={$dbName}"; try { - $dbh = new PDO($dsn, $this->post->dbUser, $this->post->dbPassword); + $dbh = new PDO($dsn, $this->config->db->user, $this->config->db->password); $dbh->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_OBJ); $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); - $dbh->exec("SET NAMES {$this->post->dbCharset}"); + $dbh->exec("SET NAMES {$this->config->db->encoding}"); $this->sourceDBH = $dbh; return $dbh; } @@ -43,9 +43,9 @@ class convertModel extends model * @access public * @return bool */ - public function dbExists() + public function dbExists($dbName = '') { - $sql = "SHOW DATABASES like '{$this->post->db->name}'"; + $sql = "SHOW DATABASES like '{$dbName}'"; return $this->dbh->query($sql)->fetch(); } @@ -93,4 +93,965 @@ class convertModel extends model } $this->session->set('state', $state); } + + /** + * Get jira data. + * + * @param int $module + * @access public + * @return void + */ + public function getJiraData($module = '', $lastID = 0, $limit = 0) + { + $dataList = array(); + if($module == 'user') + { + $dataList = $this->dao->dbh($this->sourceDBH)->select('t1.`ID`, t1.`lower_user_name` as account, t1.`lower_display_name` as realname, t1.`lower_email_address` as email, t1.created_date as `join`, t2.user_key as userCode')->from(JIRA_USERINFO)->alias('t1') + ->leftJoin(JIRA_USER)->alias('t2')->on('t1.`lower_user_name` = t2.`lower_user_name`') + ->where(1) + ->beginIF($lastID)->andWhere('t1.ID')->gt($lastID)->fi() + ->orderBy('t1.ID asc')->limit($limit) + ->fetchAll('ID'); + } + elseif($module == 'project') + { + $dataList = $this->dao->dbh($this->sourceDBH)->select('*')->from(JIRA_PROJECT) + ->where(1) + ->beginIF($lastID)->andWhere('ID')->gt($lastID)->fi() + ->orderBy('ID asc')->limit($limit) + ->fetchAll('ID'); + } + elseif($module == 'issue') + { + $dataList = $this->dao->dbh($this->sourceDBH)->select('*')->from(JIRA_ISSUE) + ->where(1) + ->beginIF($lastID)->andWhere('ID')->gt($lastID)->fi() + ->orderBy('ID asc')->limit($limit) + ->fetchAll('ID'); + } + elseif($module == 'build') + { + $dataList = $this->dao->dbh($this->sourceDBH)->select('*')->from(JIRA_BUILD) + ->where(1) + ->beginIF($lastID)->andWhere('ID')->gt($lastID)->fi() + ->orderBy('ID asc')->limit($limit) + ->fetchAll('ID'); + } + elseif($module == 'issuelink') + { + $dataList = $this->dao->dbh($this->sourceDBH)->select('*')->from(JIRA_ISSUELINK) + ->where(1) + ->beginIF($lastID)->andWhere('ID')->gt($lastID)->fi() + ->orderBy('ID asc')->limit($limit) + ->fetchAll('ID'); + } + elseif($module == 'action') + { + $dataList = $this->dao->dbh($this->sourceDBH)->select('*')->from(JIRA_ACTION) + ->where(1) + ->beginIF($lastID)->andWhere('ID')->gt($lastID)->fi() + ->orderBy('ID asc')->limit($limit) + ->fetchAll('ID'); + } + elseif($module == 'file') + { + $dataList = $this->dao->dbh($this->sourceDBH)->select('*')->from(JIRA_FILE) + ->where(1) + ->beginIF($lastID)->andWhere('ID')->gt($lastID)->fi() + ->orderBy('ID asc')->limit($limit) + ->fetchAll('ID'); + } + + return $dataList; + } + + /** + * Import jira from db. + * + * @param string $type + * @param int $lastID + * @access public + * @return void + */ + public function importJiraFromDB($type = '', $lastID = 0, $createTable = false) + { + if($createTable) $this->createTmpTable4Jira(); + + $this->connectDB($this->session->jiraDB); + + $limit = 1000; + $nextObject = false; + if(empty($type)) $type = key($this->lang->convert->jira->objectList); + + foreach($this->lang->convert->jira->objectList as $module => $moduleName) + { + if($module != $type and !$nextObject) continue; + if($module == $type) $nextObject = true; + + while(true) + { + $dataList = $this->getJiraData($module, $lastID, $limit); + + if(empty($dataList)) + { + $lastID = 0; + break; + } + + if($module == 'user') $this->importJiraUser($dataList); + if($module == 'project') $this->importJiraProject($dataList); + if($module == 'issue') $this->importJiraIssue($dataList); + if($module == 'build') $this->importJiraBuild($dataList); + if($module == 'issuelink') $this->importJiraIssueLink($dataList); + if($module == 'action') $this->importJiraAction($dataList); + if($module == 'file') $this->importJiraFile($dataList); + + return array('type' => $module, 'count' => count($dataList), 'lastID' => max(array_keys($dataList))); + } + } + + /* Set project min start date. */ + $executionProject = $this->dao->dbh($this->dbh)->select('id,project')->from(TABLE_PROJECT)->where('type')->eq('sprint')->andWhere('project')->ne(0)->fetchPairs(); + $minOpenedDateList = $this->dao->dbh($this->dbh)->select('id,execution,min(openedDate) as minOpenedDate')->from(TABLE_TASK)->where('execution')->in(array_keys($executionProject))->groupBy('execution')->fetchPairs('execution', 'minOpenedDate'); + + foreach($minOpenedDateList as $executionID => $minOpenedDate) + { + $projectID = $executionProject[$executionID]; + $this->dao->update(TABLE_PROJECT)->set('begin')->eq($minOpenedDate)->where('id')->eq($projectID)->orWhere('id')->eq($executionID)->exec(); + } + + $this->dbh->exec("DROP TABLE" . JIRA_TMPRELATION); + return array('finished' => true); + } + + /** + * Import jira user. + * + * @param object $dataList + * @access public + * @return void + */ + public function importJiraUser($dataList) + { + $localUsers = $this->dao->dbh($this->dbh)->select('account')->from(TABLE_USER)->where('deleted')->eq('0')->fetchPairs(); + $userConfig = $this->session->jiraUser; + + foreach($dataList as $id => $data) + { + if(isset($localUsers[$data->account])) continue; + + $user = new stdclass(); + $user->account = $data->account; + $user->realname = $data->realname; + $user->password = $userConfig['password']; + $user->group = $userConfig['group']; + $user->email = $data->email; + $user->gender = 'm'; + $user->type = 'inside'; + $user->join = $data->join; + + $this->dao->dbh($this->dbh)->insert(TABLE_USER)->data($user, 'group')->exec(); + + if(!dao::isError()) + { + $data = new stdclass(); + $data->account = $user->account; + $data->group = $user->group; + + $this->dao->dbh($this->dbh)->replace(TABLE_USERGROUP)->set('account')->eq($user->account)->set('`group`')->eq($user->group)->exec(); + } + } + } + + /** + * Import jira project. + * + * @param object $dataList + * @access public + * @return void + */ + public function importJiraProject($dataList) + { + global $app; + $app->loadConfig('execution'); + $app->loadLang('doc'); + $now = helper::now(); + + foreach($dataList as $id => $data) + { + $projectRelation = array(); + $executionRelation = array(); + $productRelation = array(); + + /* Create project. */ + $project = new stdclass(); + $project->name = $data->pname; + $project->code = $data->pkey; + $project->desc = $data->DESCRIPTION; + $project->status = 'wait'; + $project->type = 'project'; + $project->model = 'scrum'; + $project->grade = 1; + $project->acl = 'open'; + $project->end = date('Y-m-d', time() + 24 * 3600); + + $project->PM = $this->getJiraAccount($data->LEAD); + $project->openedBy = $this->getJiraAccount($data->LEAD); + $project->openedDate = $now; + $project->openedVersion = $this->config->version; + + $this->dao->dbh($this->dbh)->insert(TABLE_PROJECT)->data($project)->exec(); + $projectID = $this->dao->dbh($this->dbh)->lastInsertID(); + $this->dao->dbh($this->dbh)->update(TABLE_PROJECT)->set('`order`')->eq($projectID * 5)->set('path')->eq(",$projectID,")->where('id')->eq($projectID)->exec(); + + $member = new stdclass(); + $member->root = $projectID; + $member->account = $project->openedBy; + $member->role = ''; + $member->join = ''; + $member->type = 'project'; + $member->days = 0; + $member->hours = $this->config->execution->defaultWorkhours; + $this->dao->dbh($this->dbh)->insert(TABLE_TEAM)->data($member)->exec(); + + /* Create doc lib. */ + $lib = new stdclass(); + $lib->project = $projectID; + $lib->name = $this->lang->doclib->main['project']; + $lib->type = 'project'; + $lib->main = '1'; + $lib->acl = 'default'; + $this->dao->dbh($this->dbh)->insert(TABLE_DOCLIB)->data($lib)->exec(); + + /* Create execution. */ + $execution = new stdclass(); + $execution->name = $data->pname; + $execution->code = $data->pkey; + $execution->desc = $data->DESCRIPTION; + $execution->status = 'wait'; + $execution->project = $projectID; + $execution->parent = $projectID; + $execution->grade = 1; + $execution->type = 'sprint'; + $execution->acl = 'open'; + $execution->end = date('Y-m-d', time() + 24 * 3600); + + $execution->PM = $project->PM; + $execution->openedBy = $project->openedBy; + $execution->openedDate = $now; + $execution->openedVersion = $this->config->version; + + $this->dao->dbh($this->dbh)->insert(TABLE_PROJECT)->data($execution)->exec(); + $executionID = $this->dao->dbh($this->dbh)->lastInsertID(); + $this->dao->dbh($this->dbh)->update(TABLE_PROJECT)->set('`order`')->eq($executionID * 5)->set('path')->eq(",$projectID,$executionID,")->where('id')->eq($executionID)->exec(); + + $member = new stdclass(); + $member->root = $executionID; + $member->account = $execution->openedBy; + $member->role = ''; + $member->join = ''; + $member->type = 'execution'; + $member->days = 0; + $member->hours = $this->config->execution->defaultWorkhours; + $this->dao->dbh($this->dbh)->insert(TABLE_TEAM)->data($member)->exec(); + + /* Create doc lib. */ + $lib = new stdclass(); + $lib->project = $projectID; + $lib->execution = $executionID; + $lib->name = $this->lang->doclib->main['project']; + $lib->type = 'execution'; + $lib->main = '1'; + $lib->acl = 'default'; + + $this->dao->dbh($this->dbh)->insert(TABLE_DOCLIB)->data($lib)->exec(); + + /* Create product. */ + $product = new stdclass(); + $product->name = $project->name; + $product->code = $project->code; + $product->type = 'normal'; + $product->status = 'normal'; + $product->acl = 'open'; + + $product->createdBy = $project->openedBy; + $product->createdDate = helper::now(); + $product->createdVersion = $this->config->version; + + $this->dao->dbh($this->dbh)->insert(TABLE_PRODUCT)->data($product)->exec(); + $productID = $this->dao->dbh($this->dbh)->lastInsertID(); + + /* Create doc lib. */ + $lib = new stdclass(); + $lib->product = $productID; + $lib->name = $this->lang->doclib->main['product']; + $lib->type = 'product'; + $lib->main = '1'; + $lib->acl = 'default'; + $this->dao->dbh($this->dbh)->insert(TABLE_DOCLIB)->data($lib)->exec(); + + $this->dao->dbh($this->dbh)->update(TABLE_PRODUCT)->set('`order`')->eq($productID * 5)->where('id')->eq($productID)->exec(); + $this->dao->dbh($this->dbh)->replace(TABLE_PROJECTPRODUCT)->set('project')->eq($projectID)->set('product')->eq($productID)->exec(); + $this->dao->dbh($this->dbh)->replace(TABLE_PROJECTPRODUCT)->set('project')->eq($executionID)->set('product')->eq($productID)->exec(); + + $projectRelation['AType'] = 'jproject'; + $projectRelation['BType'] = 'zproject'; + $projectRelation['AID'] = $id; + $projectRelation['BID'] = $projectID; + + $this->dao->dbh($this->dbh)->insert(JIRA_TMPRELATION)->data($projectRelation)->exec(); + + $executionRelation['AType'] = 'jproject'; + $executionRelation['BType'] = 'zexecution'; + $executionRelation['AID'] = $id; + $executionRelation['BID'] = $executionID; + + $this->dao->dbh($this->dbh)->insert(JIRA_TMPRELATION)->data($executionRelation)->exec(); + } + } + + /** + * Import jira issue. + * + * @param object $dataList + * @access public + * @return void + */ + public function importJiraIssue($dataList) + { + $relations = $this->session->jiraRelation; + + $this->app->loadLang('story'); + $this->app->loadLang('task'); + $this->app->loadLang('bug'); + + $projectRelation = $this->dao->dbh($this->dbh)->select('AID,BID')->from(JIRA_TMPRELATION) + ->where('AType')->eq('jproject') + ->andWhere('BType')->eq('zproject') + ->fetchPairs(); + + $projectProduct = $this->dao->dbh($this->dbh)->select('project,product')->from(TABLE_PROJECTPRODUCT) + ->where('project')->in(array_values($projectRelation)) + ->fetchPairs(); + + $projectExecution = $this->dao->dbh($this->dbh)->select('project,id')->from(TABLE_PROJECT) + ->where('project')->in(array_values($projectRelation)) + ->fetchPairs(); + + $issueTypeList = array(); + foreach($relations['jiraObject'] as $id => $jiraCode) + { + $issueTypeList[$jiraCode] = $relations['zentaoObject'][$id]; + } + + $reasonList = array(); + $resolutionList = array(); + foreach($relations['jiraResolution'] as $id => $jiraCode) + { + if(!empty($relations['zentaoReason'][$id])) $reasonList[$jiraCode] = $relations['zentaoReason'][$id]; + if(!empty($relations['zentaoResolution'][$id])) $resolutionList[$jiraCode] = $relations['zentaoResolution'][$id]; + } + + $projectKeys = $this->dao->dbh($this->sourceDBH)->select('ID, ORIGINALKEY as oldKey, pkey as newKey')->from(JIRA_PROJECT)->fetchAll('ID'); + + foreach($dataList as $id => $data) + { + $issueType = isset($issueTypeList[$data->issuetype]) ? $issueTypeList[$data->issuetype] : 'task'; + $issueID = $data->ID; + $issueProject = $data->PROJECT; + + if(!isset($projectRelation[$issueProject])) continue; + + $projectID = $projectRelation[$issueProject]; + $productID = $projectProduct[$projectID]; + $executionID = $projectExecution[$projectID]; + + if($issueType == 'requirement' or $issueType == 'story') + { + $story = new stdclass(); + $story->product = $productID; + $story->title = $data->SUMMARY; + $story->type = $issueType; + $story->pri = $data->PRIORITY; + $story->version = 1; + $story->stage = $this->convertStage($data->issuestatus); + $story->status = $this->convertStatus('story', $data->issuestatus); + $story->openedBy = $this->getJiraAccount($data->CREATOR); + $story->openedDate = substr($data->CREATED, 0, 19); + $story->assignedTo = $this->getJiraAccount($data->ASSIGNEE); + + if($data->RESOLUTION) + { + $story->closedReason = zget($reasonList, $data->RESOLUTION, ''); + if($story->closedReason and !isset($this->lang->story->reasonList[$story->closedReason])) $story->closedReason = 'done'; + } + + $this->dao->dbh($this->dbh)->insert(TABLE_STORY)->data($story)->exec(); + + if(!dao::isError()) + { + $storyID = $this->dao->dbh($this->dbh)->lastInsertID(); + + $storyDesc = new stdclass(); + $storyDesc->story = $storyID; + $storyDesc->version = 1; + $storyDesc->title = $story->title; + $storyDesc->spec = $data->DESCRIPTION; + $this->dao->dbh($this->dbh)->replace(TABLE_STORYSPEC)->data($storyDesc)->exec(); + $this->dao->dbh($this->dbh)->replace(TABLE_PROJECTSTORY)->set('project')->eq($projectID) + ->set('product')->eq($productID) + ->set('story')->eq($storyID) + ->set('version')->eq('1') + ->exec(); + + $this->dao->dbh($this->dbh)->replace(TABLE_PROJECTSTORY)->set('project')->eq($executionID) + ->set('product')->eq($productID) + ->set('story')->eq($storyID) + ->set('version')->eq('1') + ->exec(); + + /* Create opened action from openedDate. */ + $action = new stdclass(); + $action->objectType = 'story'; + $action->objectID = $storyID; + $action->actor = $story->openedBy; + $action->action = 'Opened'; + $action->date = $story->openedDate; + $this->dao->dbh($this->dbh)->insert(TABLE_ACTION)->data($action)->exec(); + + /* Record relation. */ + $storyRelation['AType'] = 'jstory'; + $storyRelation['BType'] = 'zstory'; + $storyRelation['AID'] = $issueID; + $storyRelation['BID'] = $storyID; + $this->dao->dbh($this->dbh)->insert(JIRA_TMPRELATION)->data($storyRelation)->exec(); + + $issueRelation['AType'] = 'jissueid'; + $issueRelation['BType'] = 'zissuetype'; + $issueRelation['AID'] = $issueID; + $issueRelation['extra'] = 'story'; + $this->dao->dbh($this->dbh)->insert(JIRA_TMPRELATION)->data($issueRelation)->exec(); + } + } + elseif($issueType == 'task' or $issueType == 'subTask') + { + $task = new stdclass(); + $task->project = $projectID; + $task->execution = $executionID; + $task->name = $data->SUMMARY; + $task->type = 'devel'; + $task->pri = $data->PRIORITY; + $task->status = $this->convertStatus('task', $data->issuestatus); + $task->desc = $data->DESCRIPTION; + $task->openedBy = $this->getJiraAccount($data->CREATOR); + $task->openedDate = substr($data->CREATED, 0, 19); + $task->assignedTo = $this->getJiraAccount($data->ASSIGNEE); + if($data->RESOLUTION) + { + $task->closedReason = zget($reasonList, $data->RESOLUTION, ''); + if($task->closedReason and !isset($this->lang->task->reasonList[$task->closedReason])) $task->closedReason = 'cancel'; + } + + $this->dao->dbh($this->dbh)->insert(TABLE_TASK)->data($task)->exec(); + $taskID = $this->dao->dbh($this->dbh)->lastInsertID(); + + /* Create opened action from openedDate. */ + $action = new stdclass(); + $action->objectType = 'task'; + $action->objectID = $taskID; + $action->actor = $task->openedBy; + $action->action = 'Opened'; + $action->date = $task->openedDate; + $this->dao->dbh($this->dbh)->insert(TABLE_ACTION)->data($action)->exec(); + + $taskRelation['AType'] = 'jtask'; + $taskRelation['BType'] = 'ztask'; + $taskRelation['AID'] = $issueID; + $taskRelation['BID'] = $taskID; + $this->dao->dbh($this->dbh)->insert(JIRA_TMPRELATION)->data($taskRelation)->exec(); + + $issueRelation['AType'] = 'jissueid'; + $issueRelation['BType'] = 'zissuetype'; + $issueRelation['AID'] = $issueID; + $issueRelation['extra'] = 'task'; + $this->dao->dbh($this->dbh)->insert(JIRA_TMPRELATION)->data($issueRelation)->exec(); + } + elseif($issueType == 'bug') + { + $bug = new stdclass(); + $bug->product = $productID; + $bug->project = $projectID; + $bug->title = $data->SUMMARY; + $bug->pri = $data->PRIORITY; + $bug->status = $this->convertStatus('bug', $data->issuestatus); + $bug->steps = $data->DESCRIPTION; + $bug->openedBy = $this->getJiraAccount($data->CREATOR); + $bug->openedDate = substr($data->CREATED, 0, 19); + $bug->openedBuild = 'trunk'; + $bug->assignedTo = $this->getJiraAccount($data->ASSIGNEE); + + if($data->RESOLUTION) + { + $bug->resolution = zget($resolutionList, $data->RESOLUTION, ''); + if($bug->resolution and !isset($this->lang->bug->resolutionList[$bug->resolution])) $bug->resolution = 'fixed'; + } + + $this->dao->dbh($this->dbh)->insert(TABLE_BUG)->data($bug)->exec(); + $bugID = $this->dao->dbh($this->dbh)->lastInsertID(); + + /* Create opened action from openedDate. */ + $action = new stdclass(); + $action->objectType = 'bug'; + $action->objectID = $bugID; + $action->actor = $bug->openedBy; + $action->action = 'Opened'; + $action->date = $bug->openedDate; + $this->dao->dbh($this->dbh)->insert(TABLE_ACTION)->data($action)->exec(); + + $bugRelation['AType'] = 'jbug'; + $bugRelation['BType'] = 'zbug'; + $bugRelation['AID'] = $issueID; + $bugRelation['BID'] = $bugID; + $this->dao->dbh($this->dbh)->insert(JIRA_TMPRELATION)->data($bugRelation)->exec(); + + $issueRelation['AType'] = 'jissueid'; + $issueRelation['BType'] = 'zissuetype'; + $issueRelation['AID'] = $issueID; + $issueRelation['extra'] = 'bug'; + $this->dao->dbh($this->dbh)->insert(JIRA_TMPRELATION)->data($issueRelation)->exec(); + } + + $oldKey = zget($projectKeys[$issueProject], 'oldKey', ''); + $newKey = zget($projectKeys[$issueProject], 'newKey', ''); + $issueKey = $oldKey ? $oldKey . '-' . $data->issuenum : $newKey . '-' . $data->issuenum; + + $fileRelation['AType'] = 'jissueid'; + $fileRelation['BType'] = 'jfilepath'; + $fileRelation['AID'] = $issueID; + $fileRelation['extra'] = "{$oldKey}/10000/{$issueKey}/"; + + $this->dao->dbh($this->dbh)->insert(JIRA_TMPRELATION)->data($fileRelation)->exec(); + } + } + + /** + * Import jira build. + * + * @param object $dataList + * @access public + * @return void + */ + public function importJiraBuild($dataList) + { + $issueObjectType = $this->dao->dbh($this->dbh)->select('AID,extra')->from(JIRA_TMPRELATION) + ->where('AType')->eq('jissueid') + ->andWhere('BType')->eq('zissuetype') + ->fetchPairs(); + + $issueBugs = $this->dao->dbh($this->dbh)->select('AID,BID')->from(JIRA_TMPRELATION) + ->where('AType')->eq('jbug') + ->andWhere('BType')->eq('zbug') + ->fetchPairs(); + + $issueStories = $this->dao->dbh($this->dbh)->select('AID,BID')->from(JIRA_TMPRELATION) + ->where('AType')->eq('jstory') + ->andWhere('BType')->eq('zstory') + ->fetchPairs(); + + $projectRelation = $this->dao->dbh($this->dbh)->select('AID,BID')->from(JIRA_TMPRELATION) + ->where('AType')->eq('jproject') + ->andWhere('BType')->eq('zproject') + ->fetchPairs(); + + $projectProduct = $this->dao->dbh($this->dbh)->select('project,product')->from(TABLE_PROJECTPRODUCT) + ->where('project')->in(array_values($projectRelation)) + ->fetchPairs(); + + $versionGroup = $this->dao->dbh($this->sourceDBH)->select('SINK_NODE_ID as versionID, SOURCE_NODE_ID as issueID')->from(JIRA_NODEASSOCIATION)->where('SINK_NODE_ENTITY')->eq('Version')->fetchGroup('versionID'); + + foreach($dataList as $data) + { + if(empty($data->RELEASEDATE)) continue; + + $versionID = $data->ID; + $buildProject = $data->PROJECT; + $projectID = $projectRelation[$buildProject]; + $productID = $projectProduct[$projectID]; + + $build = new stdclass(); + $build->product = $productID; + $build->project = $projectID; + $build->name = $data->vname; + $build->date = substr($data->RELEASEDATE, 0, 10); + $build->builder = $this->app->user->account; + + $this->dao->dbh($this->dbh)->insert(TABLE_BUILD)->data($build)->exec(); + $buildID = $this->dao->dbh($this->dbh)->lastInsertID(); + + $release = new stdclass(); + $release->product = $build->product; + $release->build = $buildID; + $release->name = $build->name; + $release->date = $build->date; + $release->desc = $data->DESCRIPTION; + $release->status = 'normal'; + + $this->dao->dbh($this->dbh)->insert(TABLE_RELEASE)->data($release)->exec(); + $releaseID = $this->dao->dbh($this->dbh)->lastInsertID(); + + /* Process release data. */ + if(isset($versionGroup[$versionID])) + { + foreach($versionGroup[$versionID] as $issue) + { + $issueType = zget($issueObjectType, $issue->issueID, ''); + if(!$issueType || ($issueType != 'story' and $issueType != 'bug')) continue; + $objectID = $issueType == 'bug' ? zget($issueBugs, $issue->issueID) : zget($issueStories, $issue->issueID); + + $field = $issueType == 'story' ? 'stories' : 'bugs'; + if($issueType == 'story') + { + $this->dao->dbh($this->dbh)->update(TABLE_RELEASE)->set("stories = CONCAT(stories, ',$objectID')")->where('id')->eq($releaseID)->exec(); + } + else + { + $this->dao->dbh($this->dbh)->update(TABLE_RELEASE)->set("bugs = CONCAT(bugs, ',$objectID')")->where('id')->eq($releaseID)->exec(); + } + } + } + } + } + + /** + * Import jira issue link. + * + * @param object $dataList + * @access public + * @return void + */ + public function importJiraIssueLink($dataList) + { + $issueLinkTypeList = array(); + $relations = $this->session->jiraRelation; + + $issueStories = $this->dao->dbh($this->dbh)->select('AID,BID')->from(JIRA_TMPRELATION) + ->where('AType')->eq('jstory') + ->andWhere('BType')->eq('zstory') + ->fetchPairs(); + + $issueTasks = $this->dao->dbh($this->dbh)->select('AID,BID')->from(JIRA_TMPRELATION) + ->where('AType')->eq('jtask') + ->andWhere('BType')->eq('ztask') + ->fetchPairs(); + + $issueBugs = $this->dao->dbh($this->dbh)->select('AID,BID')->from(JIRA_TMPRELATION) + ->where('AType')->eq('jbug') + ->andWhere('BType')->eq('zbug') + ->fetchPairs(); + + $issueObjectType = $this->dao->dbh($this->dbh)->select('AID,extra')->from(JIRA_TMPRELATION) + ->where('AType')->eq('jissueid') + ->andWhere('BType')->eq('zissuetype') + ->fetchPairs(); + + foreach($relations['jiraLinkType'] as $id => $jiraCode) $issueLinkTypeList[$jiraCode] = $relations['zentaoLinkType'][$id]; + + $storyLink = $taskLink = $duplicateLink = $relatesLink = array(); + foreach($dataList as $issueLink) + { + $linkType = $issueLink->LINKTYPE; + if($issueLinkTypeList[$linkType] == 'subStoryLink') $storyLink[$issueLink->SOURCE][] = $issueLink->DESTINATION; + if($issueLinkTypeList[$linkType] == 'subTaskLink') $taskLink[$issueLink->SOURCE][] = $issueLink->DESTINATION; + if($issueLinkTypeList[$linkType] == 'duplicate') $duplicateLink[$issueLink->SOURCE] = $issueLink->DESTINATION; + if($issueLinkTypeList[$linkType] == 'relates') $relatesLink[$issueLink->SOURCE] = $issueLink->DESTINATION; + } + + foreach($storyLink as $source => $dest) + { + if(!isset($issueStories[$source])) continue; + $parentID = $issueStories[$source]; + $this->dao->dbh($this->dbh)->update(TABLE_STORY)->set('parent')->eq('-1')->where('id')->eq($parentID)->exec(); + foreach($dest as $childID) + { + if(!isset($issueStories[$childID])) continue; + $this->dao->dbh($this->dbh)->update(TABLE_STORY)->set('parent')->eq($parentID)->where('id')->eq($issueStories[$childID])->exec(); + } + } + + foreach($taskLink as $source => $dest) + { + if(!isset($issueTasks[$source])) continue; + $parentID = $issueTasks[$source]; + $this->dao->dbh($this->dbh)->update(TABLE_TASK)->set('parent')->eq('-1')->where('id')->eq($parentID)->exec(); + foreach($dest as $childID) + { + if(!isset($issueTasks[$childID])) continue; + $this->dao->dbh($this->dbh)->update(TABLE_TASK)->set('parent')->eq($parentID)->where('id')->eq($issueTasks[$childID])->exec(); + } + } + + foreach($duplicateLink as $source => $dest) + { + $objectType = $issueObjectType[$source]; + + if($objectType != 'story' and $objectType != 'bug') continue; + if($issueObjectType[$source] != $issueObjectType[$dest]) continue; + + if(!isset($relation[$objectType][$source]) or !isset($relation[$objectType][$dest])) continue; + + if($objectType == 'story') + { + if(empty($issueStories[$dest]) or empty($issueStories[$source])) continue; + $this->dao->dbh($this->dbh)->update(TABLE_STORY)->set('duplicateStory')->eq($$issueStories[$dest])->where('id')->eq($issueStories[$source])->exec(); + } + elseif($objectType == 'bug') + { + if(empty($issueBugs[$dest]) or empty($issueBugs[$source])) continue; + $this->dao->dbh($this->dbh)->update(TABLE_BUG)->set('duplicateBug')->eq($issueBugs[$dest])->where('id')->eq($issueBugs[$source])->exec(); + } + } + + foreach($relatesLink as $source => $dest) + { + if(empty($issueObjectType[$source]) or empty($issueObjectType[$dest])) continue; + + $sourceObjectType = $issueObjectType[$source]; + $destObjectType = $issueObjectType[$dest]; + + if($sourceObjectType == 'task' and $destObjectType == 'story') + { + $this->dao->dbh($this->dbh)->update(TABLE_TASK)->set('story')->eq($issueStories[$dest])->where('id')->eq($issueTasks[$source])->exec(); + } + elseif($sourceObjectType == 'story' and $destObjectType == 'task') + { + $this->dao->dbh($this->dbh)->update(TABLE_TASK)->set('story')->eq($issueStories[$source])->where('id')->eq($issueTasks[$dest])->exec(); + } + elseif($sourceObjectType == 'story' and $destObjectType == 'bug') + { + $this->dao->dbh($this->dbh)->update(TABLE_BUG)->set('story')->eq($issueStories[$source])->set('storyVersion')->eq(1)->where('id')->eq($issueBugs[$dest])->exec(); + } + elseif($sourceObjectType == 'bug' and $destObjectType == 'story') + { + $this->dao->dbh($this->dbh)->update(TABLE_BUG)->set('story')->eq($issueStories[$dest])->set('storyVersion')->eq(1)->where('id')->eq($issueBugs[$source])->exec(); + } + elseif($sourceObjectType == 'story' and $destObjectType == 'story') + { + $this->dao->dbh($this->dbh)->update(TABLE_STORY)->set("linkStories=concat(linkStories, ',{$issueStories[$dest]}')")->where('id')->eq($issueStories[$source])->exec(); + } + elseif($sourceObjectType == 'bug' and $destObjectType == 'bug') + { + $this->dao->dbh($this->dbh)->update(TABLE_BUG)->set("linkBug=concat(linkBug, ',{$issueBugs[$dest]}')")->where('id')->eq($issueBugs[$source])->exec(); + } + } + } + + /** + * Import jira action. + * + * @param object $dataList + * @access public + * @return void + */ + public function importJiraAction($dataList) + { + $issueStories = $this->dao->dbh($this->dbh)->select('AID,BID')->from(JIRA_TMPRELATION) + ->where('AType')->eq('jstory') + ->andWhere('BType')->eq('zstory') + ->fetchPairs(); + + $issueTasks = $this->dao->dbh($this->dbh)->select('AID,BID')->from(JIRA_TMPRELATION) + ->where('AType')->eq('jtask') + ->andWhere('BType')->eq('ztask') + ->fetchPairs(); + + $issueBugs = $this->dao->dbh($this->dbh)->select('AID,BID')->from(JIRA_TMPRELATION) + ->where('AType')->eq('jbug') + ->andWhere('BType')->eq('zbug') + ->fetchPairs(); + + $issueObjectType = $this->dao->dbh($this->dbh)->select('AID,extra')->from(JIRA_TMPRELATION) + ->where('AType')->eq('jissueid') + ->andWhere('BType')->eq('zissuetype') + ->fetchPairs(); + + $projectRelation = $this->dao->dbh($this->dbh)->select('AID,BID')->from(JIRA_TMPRELATION) + ->where('AType')->eq('jproject') + ->andWhere('BType')->eq('zproject') + ->fetchPairs(); + + $projectProduct = $this->dao->dbh($this->dbh)->select('project,product')->from(TABLE_PROJECTPRODUCT) + ->where('project')->in(array_values($projectRelation)) + ->fetchPairs(); + + foreach($dataList as $data) + { + $action = new stdclass(); + + $issueID = $data->issueid; + $comment = $data->actionbody; + if(empty($comment)) continue; + + $objectType = $issueObjectType[$issueID]; + if($objectType == 'task') $objectID = $issueTasks[$issueID]; + if($objectType == 'bug') $objectID = $issueBugs[$issueID]; + if($objectType == 'story') $objectID = $issueStories[$issueID]; + + if(empty($objectID)) continue; + + $action = new stdclass(); + $action->objectType = $objectType; + $action->objectID = $objectID; + $action->actor = $this->getJiraAccount($data->AUTHOR); + $action->action = 'commented'; + $action->date = substr($data->CREATED, 0, 19); + $action->comment = $comment; + $this->dao->dbh($this->dbh)->insert(TABLE_ACTION)->data($action)->exec(); + } + } + + /** + * Import jira file. + * + * @param object $dataList + * @access public + * @return void + */ + public function importJiraFile($dataList) + { + $this->loadModel('file'); + + $issueObjectType = $this->dao->dbh($this->dbh)->select('AID,extra')->from(JIRA_TMPRELATION) + ->where('AType')->eq('jissueid') + ->andWhere('BType')->eq('zissuetype') + ->fetchPairs(); + + $issueStories = $this->dao->dbh($this->dbh)->select('AID,BID')->from(JIRA_TMPRELATION) + ->where('AType')->eq('jstory') + ->andWhere('BType')->eq('zstory') + ->fetchPairs(); + + $issueTasks = $this->dao->dbh($this->dbh)->select('AID,BID')->from(JIRA_TMPRELATION) + ->where('AType')->eq('jtask') + ->andWhere('BType')->eq('ztask') + ->fetchPairs(); + + $issueBugs = $this->dao->dbh($this->dbh)->select('AID,BID')->from(JIRA_TMPRELATION) + ->where('AType')->eq('jbug') + ->andWhere('BType')->eq('zbug') + ->fetchPairs(); + + $filePaths = $this->dao->dbh($this->dbh)->select('AID,extra')->from(JIRA_TMPRELATION) + ->where('AType')->eq('jissueid') + ->andWhere('BType')->eq('jfilepath') + ->fetchPairs(); + + foreach($dataList as $fileAttachment) + { + $issueID = $fileAttachment->issueid; + $objectType = $issueObjectType[$issueID]; + if($objectType != 'bug' and $objectType != 'task' and $objectType != 'story') continue; + + $fileID = $fileAttachment->ID; + $fileName = $fileAttachment->FILENAME; + list($mime, $extension) = explode('/', $fileAttachment->MIMETYPE); + + if($objectType == 'bug') $objectID = $issueBugs[$issueID]; + if($objectType == 'task') $objectID = $issueTasks[$issueID]; + if($objectType == 'story') $objectID = $issueStories[$issueID]; + if(empty($objectID)) continue; + + $file = new stdclass(); + $file->pathname = $this->file->setPathName($fileID, $extension); + $file->title = str_ireplace(".{$extension}", '', $fileName); + $file->extension = $extension; + $file->size = $fileAttachment->FILESIZE; + $file->objectType = $objectType; + $file->objectID = $objectID; + $file->addedBy = $this->getJiraAccount($fileAttachment->AUTHOR); + $file->addedDate = substr($fileAttachment->CREATED, 0, 19); + $this->dao->dbh($this->dbh)->insert(TABLE_FILE)->data($file)->exec(); + + $jiraFile = $this->app->getTmpRoot() . 'attachments/' . $filePaths[$issueID] . $fileID; + if(is_file($jiraFile)) copy($jiraFile, $this->file->savePath . $file->pathname); + } + } + + /** + * Convert jira status. + * + * @param string $objectType + * @param string $jiraStatus + * @access public + * @return void + */ + public function convertStatus($objectType, $jiraStatus) + { + $status = 'active'; + if($objectType == 'task') $status = 'wait'; + $relations = $this->session->jiraRelation; + + $arrayKey = "{$objectType}Status"; + $jiraStatusList = array_flip($relations['jiraStatus']); + $statusID = $jiraStatusList[$jiraStatus]; + + if(!empty($relations[$arrayKey][$statusID])) $status = $relations[$arrayKey][$statusID]; + + return $status; + } + + /** + * Convert stage. + * + * @param string $jiraStatus + * @access public + * @return void + */ + public function convertStage($jiraStatus) + { + $stage = 'wait'; + $relations = $this->session->jiraRelation; + + $jiraStatusList = array_flip($relations['jiraStatus']); + $stageID = $jiraStatusList[$jiraStatus]; + + if(!empty($relations['storyStage'][$stageID])) $stage = $relations['storyStage'][$stageID]; + + return $stage; + } + + /** + * Get jira account. + * + * @param string $userKey + * @access public + * @return void + */ + public function getJiraAccount($userKey) + { + if(strpos($userKey, 'JIRAUSER') === false) return $userKey; + + return $this->dao->dbh($this->sourceDBH)->select('lower_user_name')->from(JIRA_USER)->where('user_key')->eq($userKey)->fetch('lower_user_name'); + } + + public function createTmpTable4Jira() + { +$sql = <<dbh->exec($sql); + } + catch(Exception $e){} + } } diff --git a/module/convert/view/convertjira.html.php b/module/convert/view/convertjira.html.php new file mode 100644 index 0000000000..35d3bcd4b6 --- /dev/null +++ b/module/convert/view/convertjira.html.php @@ -0,0 +1,50 @@ + + * @package convert + * @version $Id: execute.html.php 4129 2013-01-18 01:58:14Z wwccss $ + */ +?> + + +
+
+
+
+

convert->jira->method;?>

+
+
+
+
+
"> +

convert->jira->importFromDB;?>

+ convert->jira->dbDesc;?> +
+
+
+
"> +

convert->jira->importFromFile;?>

+ convert->jira->fileDesc;?> +
+
+
+
+
+ + diff --git a/module/convert/view/importjira.html.php b/module/convert/view/importjira.html.php new file mode 100644 index 0000000000..e764849fd9 --- /dev/null +++ b/module/convert/view/importjira.html.php @@ -0,0 +1,61 @@ + + * @package article + * @version $Id$ + * @link http://www.chanzhi.org + */ +?> + +
+
+

convert->jira->importJira;?>

+
+
+
+
    +
    +
    convert->jira->start, '', "class='btn btn-primary' id='execButton'");?>
    +
    +
    + + diff --git a/module/convert/view/importnotice.html.php b/module/convert/view/importnotice.html.php new file mode 100644 index 0000000000..f76f35ddfd --- /dev/null +++ b/module/convert/view/importnotice.html.php @@ -0,0 +1,49 @@ + + * @package convert + * @version $Id: execute.html.php 4129 2013-01-18 01:58:14Z wwccss $ + */ +?> + + +
    +
    +

    + convert->jira->importFromDB : $lang->convert->jira->importFromFile;?> +

    +
    +
    +
    convert->jira->importNotice;?>
    +
    +
      +
    1. convert->jira->importSteps[$type][1];?>
    2. +
    3. convert->jira->importSteps[$type][2];?>
    4. + +
    5. convert->jira->importSteps[$type][3];?>
    6. + +
    7. convert->jira->importSteps[$type][3], $app->getTmpRoot() . 'jirafile');?>
    8. + +
    9. convert->jira->importSteps[$type][4], $app->getTmpRoot());?>
    10. +
    11. + convert->jira->importSteps[$type][5];?> + + convert->jira->dbNameNotice}");?> + +
    12. +
    +
    +
    + +
    +
    + diff --git a/module/convert/view/initjirauser.html.php b/module/convert/view/initjirauser.html.php new file mode 100644 index 0000000000..98d42a81ad --- /dev/null +++ b/module/convert/view/initjirauser.html.php @@ -0,0 +1,50 @@ + + * @package user + * @version $Id: create.html.php 4728 2013-05-03 06:14:34Z chencongzhi520@gmail.com $ + * @link http://www.zentao.net + */ +?> + +
    +
    +
    +

    convert->jira->initJiraUser;?>

    +
    +
    + + + + + + + + + + + + + + + + + + +
    user->password;?> + + + + + convert->jira->passwordNotice;?>
    user->password2;?>
    user->group;?>convert->jira->groupNotice;?>
    + convert->jira->next);?> +
    +
    +
    +
    + + diff --git a/module/convert/view/mapjira2zentao.html.php b/module/convert/view/mapjira2zentao.html.php new file mode 100644 index 0000000000..7156708bdc --- /dev/null +++ b/module/convert/view/mapjira2zentao.html.php @@ -0,0 +1,101 @@ + + * @package convert + * @version $Id: execute.html.php 4129 2013-01-18 01:58:14Z wwccss $ + */ +?> + +
    +
    +

    + convert->jira->mapJira2Zentao;?> +

    +
    +
    + + + + + + + + + $name):?> + + + + + + +
    convert->jira->jiraObject;?>convert->jira->zentaoObject;?>
    convert->jira->zentaoObjectList, '', "class='form-control chosen'");?>
    +
    + + + + + + + + + $name):?> + + + + + + +
    convert->jira->jiraLinkType;?>convert->jira->zentaoLinkType;?>
    convert->jira->zentaoLinkTypeList, '', "class='form-control chosen'");?>
    +
    + + + + + + + + + + $name):?> + + + + + + + +
    convert->jira->jiraResolution;?>convert->jira->zentaoResolution;?>convert->jira->zentaoReason;?>
    bug->resolutionList, '', "class='form-control chosen'");?>story->reasonList, '', "class='form-control chosen'");?>
    +
    + + + + + + + + + + + + $name):?> + + + + + + + + + + + + + + +
    convert->jira->jiraStatus;?>convert->jira->storyStatus;?>convert->jira->storyStage;?>convert->jira->taskStatus;?>convert->jira->bugStatus;?>
    story->statusList, '', "class='form-control chosen'");?>story->stageList, '', "class='form-control chosen'");?>task->statusList, '', "class='form-control chosen'");?>bug->statusList, '', "class='form-control chosen'");?>
    convert->jira->next);?>
    +
    +