diff --git a/db/update16.0.beta1.sql b/db/update16.0.beta1.sql new file mode 100644 index 0000000000..0ad3e88553 --- /dev/null +++ b/db/update16.0.beta1.sql @@ -0,0 +1,9 @@ +ALTER TABLE `zt_task` ADD `repo` mediumint unsigned NOT NULL AFTER `activatedDate`; +ALTER TABLE `zt_task` ADD `entry` varchar(255) NOT NULL AFTER `repo`; +ALTER TABLE `zt_task` ADD `lines` varchar(10) NOT NULL AFTER `entry`; +ALTER TABLE `zt_task` ADD `v1` varchar(40) NOT NULL AFTER `lines`; +ALTER TABLE `zt_task` ADD `v2` varchar(40) NOT NULL AFTER `v1`; +ALTER TABLE `zt_task` ADD `mr` mediumint(8) unsigned NOT NULL AFTER `repo`; +ALTER TABLE `zt_bug` ADD `mr` mediumint(8) unsigned NOT NULL AFTER `repo`; + +UPDATE `zt_grouppriv` SET `method`='addReview' where `module`='mr' and `method`='addBug'; diff --git a/db/zentao.sql b/db/zentao.sql index 69fee8ea81..41ec30e1e5 100644 --- a/db/zentao.sql +++ b/db/zentao.sql @@ -203,6 +203,7 @@ CREATE TABLE IF NOT EXISTS `zt_bug` ( `caseVersion` smallint(6) NOT NULL DEFAULT '1', `result` mediumint(8) unsigned NOT NULL, `repo` mediumint(8) unsigned NOT NULL, + `mr` mediumint(8) unsigned NOT NULL, `entry` varchar(255) NOT NULL, `lines` varchar(10) NOT NULL, `v1` varchar(40) NOT NULL, @@ -1250,6 +1251,12 @@ CREATE TABLE IF NOT EXISTS `zt_task` ( `lastEditedBy` varchar(30) NOT NULL, `lastEditedDate` datetime NOT NULL, `activatedDate` date NOT NULL, + `repo` mediumint(8) unsigned NOT NULL, + `mr` mediumint(8) unsigned NOT NULL, + `entry` varchar(255) NOT NULL, + `lines` varchar(10) NOT NULL, + `v1` varchar(40) NOT NULL, + `v2` varchar(40) NOT NULL, `deleted` enum('0','1') NOT NULL default '0', PRIMARY KEY (`id`), KEY `execution` (`execution`), diff --git a/lib/scm/gitlab.class.php b/lib/scm/gitlab.class.php index 82474eeb3c..6a4fe815c8 100644 --- a/lib/scm/gitlab.class.php +++ b/lib/scm/gitlab.class.php @@ -220,7 +220,10 @@ class gitlab $count = $count == 0 ? '' : "-n $count"; $list = $this->getCommitsByPath($path, $fromRevision, $toRevision); - foreach($list as $commit) $commit->diffs = $this->getFilesByCommit($commit->id); + foreach($list as $commit) + { + if(isset($commit->id)) $commit->diffs = $this->getFilesByCommit($commit->id); + } return $this->parseLog($list); } @@ -656,6 +659,7 @@ class gitlab { $results = $this->fetch($api, $params); $params->page ++; + if(!is_array($results)) $results = array(); $allResults = $allResults + $results; if(count($results) < 100) break; } @@ -751,6 +755,7 @@ class gitlab $i = 0; foreach($logs as $commit) { + if(!isset($commit->id)) continue; $parsedLog = new stdclass(); $parsedLog->revision = $commit->id; $parsedLog->committer = $commit->committer_name; diff --git a/module/action/lang/en.php b/module/action/lang/en.php index d30f55cafa..f0923f5bb5 100755 --- a/module/action/lang/en.php +++ b/module/action/lang/en.php @@ -79,101 +79,104 @@ $lang->action->periods['lastweek'] = $lang->action->dynamic->lastWeek; $lang->action->periods['thismonth'] = $lang->action->dynamic->thisMonth; $lang->action->periods['lastmonth'] = $lang->action->dynamic->lastMonth; -$lang->action->objectTypes['product'] = $lang->productCommon; -$lang->action->objectTypes['branch'] = 'Branch'; -$lang->action->objectTypes['story'] = $lang->SRCommon; -$lang->action->objectTypes['design'] = 'Design'; -$lang->action->objectTypes['productplan'] = 'Plan'; -$lang->action->objectTypes['release'] = 'Release'; -$lang->action->objectTypes['program'] = 'Program'; -$lang->action->objectTypes['project'] = 'Project'; -$lang->action->objectTypes['execution'] = $lang->executionCommon; -$lang->action->objectTypes['task'] = 'Task'; -$lang->action->objectTypes['build'] = 'Build'; -$lang->action->objectTypes['job'] = 'Job'; -$lang->action->objectTypes['bug'] = 'Bug'; -$lang->action->objectTypes['case'] = 'Case'; -$lang->action->objectTypes['caseresult'] = 'Case Result'; -$lang->action->objectTypes['stepresult'] = 'Case Steps'; -$lang->action->objectTypes['caselib'] = 'Library'; -$lang->action->objectTypes['testsuite'] = 'Suite'; -$lang->action->objectTypes['testtask'] = 'Test Build'; -$lang->action->objectTypes['testreport'] = 'Report'; -$lang->action->objectTypes['doc'] = 'Document'; -$lang->action->objectTypes['api'] = 'Interface'; -$lang->action->objectTypes['doclib'] = 'Document Library'; -$lang->action->objectTypes['apistruct'] = 'API struct'; -$lang->action->objectTypes['todo'] = 'Todo'; -$lang->action->objectTypes['risk'] = 'Risk'; -$lang->action->objectTypes['issue'] = 'Issue'; -$lang->action->objectTypes['module'] = 'Module'; -$lang->action->objectTypes['user'] = 'User'; -$lang->action->objectTypes['stakeholder'] = 'Stakeholder'; -$lang->action->objectTypes['budget'] = 'Cost Estimate'; -$lang->action->objectTypes['entry'] = 'Entry'; -$lang->action->objectTypes['webhook'] = 'Webhook'; -$lang->action->objectTypes['team'] = 'Team'; -$lang->action->objectTypes['whitelist'] = 'Whitelist'; -$lang->action->objectTypes['pipeline'] = 'GitLab'; -$lang->action->objectTypes['gitlab'] = 'GitLab'; -$lang->action->objectTypes['jenkins'] = 'Jenkins'; -$lang->action->objectTypes['mr'] = 'Merge Request'; -$lang->action->objectTypes['gitlabproject'] = 'GitLab Project'; -$lang->action->objectTypes['gitlabuser'] = 'GitLab User'; -$lang->action->objectTypes['gitlabgroup'] = 'GitLab Group'; +$lang->action->objectTypes['product'] = $lang->productCommon; +$lang->action->objectTypes['branch'] = 'Branch'; +$lang->action->objectTypes['story'] = $lang->SRCommon; +$lang->action->objectTypes['design'] = 'Design'; +$lang->action->objectTypes['productplan'] = 'Plan'; +$lang->action->objectTypes['release'] = 'Release'; +$lang->action->objectTypes['program'] = 'Program'; +$lang->action->objectTypes['project'] = 'Project'; +$lang->action->objectTypes['execution'] = $lang->executionCommon; +$lang->action->objectTypes['task'] = 'Task'; +$lang->action->objectTypes['build'] = 'Build'; +$lang->action->objectTypes['job'] = 'Job'; +$lang->action->objectTypes['bug'] = 'Bug'; +$lang->action->objectTypes['case'] = 'Case'; +$lang->action->objectTypes['caseresult'] = 'Case Result'; +$lang->action->objectTypes['stepresult'] = 'Case Steps'; +$lang->action->objectTypes['caselib'] = 'Library'; +$lang->action->objectTypes['testsuite'] = 'Suite'; +$lang->action->objectTypes['testtask'] = 'Test Build'; +$lang->action->objectTypes['testreport'] = 'Report'; +$lang->action->objectTypes['doc'] = 'Document'; +$lang->action->objectTypes['api'] = 'Interface'; +$lang->action->objectTypes['doclib'] = 'Document Library'; +$lang->action->objectTypes['apistruct'] = 'API struct'; +$lang->action->objectTypes['todo'] = 'Todo'; +$lang->action->objectTypes['risk'] = 'Risk'; +$lang->action->objectTypes['issue'] = 'Issue'; +$lang->action->objectTypes['module'] = 'Module'; +$lang->action->objectTypes['user'] = 'User'; +$lang->action->objectTypes['stakeholder'] = 'Stakeholder'; +$lang->action->objectTypes['budget'] = 'Cost Estimate'; +$lang->action->objectTypes['entry'] = 'Entry'; +$lang->action->objectTypes['webhook'] = 'Webhook'; +$lang->action->objectTypes['team'] = 'Team'; +$lang->action->objectTypes['whitelist'] = 'Whitelist'; +$lang->action->objectTypes['pipeline'] = 'GitLab'; +$lang->action->objectTypes['gitlab'] = 'GitLab'; +$lang->action->objectTypes['jenkins'] = 'Jenkins'; +$lang->action->objectTypes['mr'] = 'Merge Request'; +$lang->action->objectTypes['gitlabproject'] = 'GitLab Project'; +$lang->action->objectTypes['gitlabuser'] = 'GitLab User'; +$lang->action->objectTypes['gitlabgroup'] = 'GitLab Group'; +$lang->action->objectTypes['gitlabbranch'] = 'GitLab Branch'; +$lang->action->objectTypes['gitlabbranchpriv'] = 'GitLab Protected Branches'; /* Used to describe operation history. */ $lang->action->desc = new stdclass(); -$lang->action->desc->common = '$date, $action by $actor.' . "\n"; -$lang->action->desc->extra = '$date, $action as $extra by $actor.' . "\n"; -$lang->action->desc->opened = '$date, created by $actor .' . "\n"; -$lang->action->desc->openedbysystem = '$date, opened by system.' . "\n"; -$lang->action->desc->created = '$date, created by $actor .' . "\n"; -$lang->action->desc->added = '$date, added by $actor .' . "\n"; -$lang->action->desc->changed = '$date, changed by $actor .' . "\n"; -$lang->action->desc->edited = '$date, edited by $actor .' . "\n"; -$lang->action->desc->assigned = '$date, $actor assigned to $extra.' . "\n"; -$lang->action->desc->closed = '$date, closed by $actor .' . "\n"; -$lang->action->desc->closedbysystem = '$date, closed by system.' . "\n"; -$lang->action->desc->deleted = '$date, deleted by $actor .' . "\n"; -$lang->action->desc->deletedfile = '$date, $actor deleted $extra.' . "\n"; -$lang->action->desc->editfile = '$date, $actor edited $extra.' . "\n"; -$lang->action->desc->erased = '$date, deleted by $actor .' . "\n"; -$lang->action->desc->undeleted = '$date, restored by $actor .' . "\n"; -$lang->action->desc->hidden = '$date, hidden by $actor .' . "\n"; -$lang->action->desc->commented = '$date, added by $actor.' . "\n"; -$lang->action->desc->activated = '$date, activated by $actor .' . "\n"; -$lang->action->desc->blocked = '$date, blocked by $actor .' . "\n"; -$lang->action->desc->moved = '$date, moved by $actor , which was "$extra".' . "\n"; -$lang->action->desc->confirmed = '$date, $actor confirmed the story change. The latest build is #$extra.' . "\n"; -$lang->action->desc->caseconfirmed = '$date, $actor confirmed the case change. The latest build is #$extra' . "\n"; -$lang->action->desc->bugconfirmed = '$date, $actor confirmed Bug.' . "\n"; -$lang->action->desc->frombug = '$date, converted from $actor. Its ID was $extra.'; -$lang->action->desc->started = '$date, started by $actor.' . "\n"; -$lang->action->desc->restarted = '$date, continued by $actor.' . "\n"; -$lang->action->desc->delayed = '$date, postponed by $actor.' . "\n"; -$lang->action->desc->suspended = '$date, suspended by $actor.' . "\n"; -$lang->action->desc->recordestimate = '$date, recorded by $actor and it cost $extra hours.'; -$lang->action->desc->editestimate = '$date, $actor edited Hour.'; -$lang->action->desc->deleteestimate = '$date, $actor deleted Hour.'; -$lang->action->desc->canceled = '$date, cancelled by $actor.' . "\n"; -$lang->action->desc->svncommited = '$date, $actor committed and the build is #$extra.' . "\n"; -$lang->action->desc->gitcommited = '$date, $actor committed and the build is #$extra.' . "\n"; -$lang->action->desc->finished = '$date, finished by $actor.' . "\n"; -$lang->action->desc->paused = '$date, paused by $actor.' . "\n"; -$lang->action->desc->verified = '$date, verified by $actor.' . "\n"; -$lang->action->desc->diff1 = '%s is changed. It was "%s" and it is "%s".
' . "\n"; -$lang->action->desc->diff2 = '%s is changed. The difference is ' . "\n" . "
%s
" . "\n
%s
"; -$lang->action->desc->diff3 = 'File Name %s was changed to %s .' . "\n"; -$lang->action->desc->linked2bug = '$date, linked to $extra by $actor'; -$lang->action->desc->linked2testtask = '$date, linked to $extra by $actor'; -$lang->action->desc->resolved = '$date, resolved by $actor ' . "\n"; -$lang->action->desc->managed = '$date, by $actor managed.' . "\n"; -$lang->action->desc->estimated = '$date, by $actor estimated.' . "\n"; -$lang->action->desc->run = '$date, by $actor executed.' . "\n"; -$lang->action->desc->syncprogram = '$date, started by $actor(starting the project sets the program status as Ongoing).' . "\n"; -$lang->action->desc->syncproject = '$date, starting the execution sets the project status as Ongoing.' . "\n"; -$lang->action->desc->syncexecution = '$date, starting the task sets the execution status as Ongoing.' . "\n"; +$lang->action->desc->common = '$date, $action by $actor.' . "\n"; +$lang->action->desc->extra = '$date, $action as $extra by $actor.' . "\n"; +$lang->action->desc->opened = '$date, created by $actor .' . "\n"; +$lang->action->desc->openedbysystem = '$date, opened by system.' . "\n"; +$lang->action->desc->created = '$date, created by $actor .' . "\n"; +$lang->action->desc->added = '$date, added by $actor .' . "\n"; +$lang->action->desc->changed = '$date, changed by $actor .' . "\n"; +$lang->action->desc->edited = '$date, edited by $actor .' . "\n"; +$lang->action->desc->assigned = '$date, $actor assigned to $extra.' . "\n"; +$lang->action->desc->closed = '$date, closed by $actor .' . "\n"; +$lang->action->desc->closedbysystem = '$date, closed by system.' . "\n"; +$lang->action->desc->deleted = '$date, deleted by $actor .' . "\n"; +$lang->action->desc->deletedfile = '$date, $actor deleted $extra.' . "\n"; +$lang->action->desc->editfile = '$date, $actor edited $extra.' . "\n"; +$lang->action->desc->erased = '$date, deleted by $actor .' . "\n"; +$lang->action->desc->undeleted = '$date, restored by $actor .' . "\n"; +$lang->action->desc->hidden = '$date, hidden by $actor .' . "\n"; +$lang->action->desc->commented = '$date, added by $actor.' . "\n"; +$lang->action->desc->activated = '$date, activated by $actor .' . "\n"; +$lang->action->desc->blocked = '$date, blocked by $actor .' . "\n"; +$lang->action->desc->moved = '$date, moved by $actor , which was "$extra".' . "\n"; +$lang->action->desc->confirmed = '$date, $actor confirmed the story change. The latest build is #$extra.' . "\n"; +$lang->action->desc->caseconfirmed = '$date, $actor confirmed the case change. The latest build is #$extra' . "\n"; +$lang->action->desc->bugconfirmed = '$date, $actor confirmed Bug.' . "\n"; +$lang->action->desc->frombug = '$date, converted from $actor. Its ID was $extra.'; +$lang->action->desc->started = '$date, started by $actor.' . "\n"; +$lang->action->desc->restarted = '$date, continued by $actor.' . "\n"; +$lang->action->desc->delayed = '$date, postponed by $actor.' . "\n"; +$lang->action->desc->suspended = '$date, suspended by $actor.' . "\n"; +$lang->action->desc->recordestimate = '$date, recorded by $actor and it cost $extra hours.'; +$lang->action->desc->editestimate = '$date, $actor edited Hour.'; +$lang->action->desc->deleteestimate = '$date, $actor deleted Hour.'; +$lang->action->desc->canceled = '$date, cancelled by $actor.' . "\n"; +$lang->action->desc->svncommited = '$date, $actor committed and the build is #$extra.' . "\n"; +$lang->action->desc->gitcommited = '$date, $actor committed and the build is #$extra.' . "\n"; +$lang->action->desc->finished = '$date, finished by $actor.' . "\n"; +$lang->action->desc->paused = '$date, paused by $actor.' . "\n"; +$lang->action->desc->verified = '$date, verified by $actor.' . "\n"; +$lang->action->desc->diff1 = '%s is changed. It was "%s" and it is "%s".
' . "\n"; +$lang->action->desc->diff2 = '%s is changed. The difference is ' . "\n" . "
%s
" . "\n
%s
"; +$lang->action->desc->diff3 = 'File Name %s was changed to %s .' . "\n"; +$lang->action->desc->linked2bug = '$date, linked to $extra by $actor'; +$lang->action->desc->linked2testtask = '$date, linked to $extra by $actor'; +$lang->action->desc->resolved = '$date, resolved by $actor ' . "\n"; +$lang->action->desc->managed = '$date, by $actor managed.' . "\n"; +$lang->action->desc->estimated = '$date, by $actor estimated.' . "\n"; +$lang->action->desc->run = '$date, by $actor executed.' . "\n"; +$lang->action->desc->syncprogram = '$date, started by $actor(starting the project sets the program status as Ongoing).' . "\n"; +$lang->action->desc->syncproject = '$date, starting the execution sets the project status as Ongoing.' . "\n"; +$lang->action->desc->syncexecution = '$date, starting the task sets the execution status as Ongoing.' . "\n"; +$lang->action->desc->importfromgitlab = '$date, Issue associate created from gitlab by $actor.' . "\n"; /* Used to describe the history of operations related to parent-child tasks. */ $lang->action->desc->createchildren = '$date, $actor created a child task $extra。' . "\n"; @@ -303,6 +306,7 @@ $lang->action->label->compilefail = 'Compile Fail'; $lang->action->label->reopen = 'Reopen'; $lang->action->label->approve = 'Passed'; $lang->action->label->reject = 'Rejected'; +$lang->action->label->importfromgitlab = 'Issue associate created'; /* Dynamic information is grouped by object. */ $lang->action->dynamicAction = new stdclass; @@ -353,6 +357,7 @@ $lang->action->dynamicAction->release['notified'] = 'Notify Release'; $lang->action->dynamicAction->release['hidden'] = 'Hide Release'; $lang->action->dynamicAction->story['opened'] = 'Create Story'; +$lang->action->dynamicAction->story['importfromgitlab'] = "Issue associate create story"; $lang->action->dynamicAction->story['edited'] = 'Edit Story'; $lang->action->dynamicAction->story['activated'] = 'Activate Story'; $lang->action->dynamicAction->story['reviewed'] = 'Review Story'; @@ -393,6 +398,7 @@ $lang->action->dynamicAction->kanbanlane['moved'] = 'Move Swimlane'; $lang->action->dynamicAction->team['managedTeam'] = 'Manage Team'; $lang->action->dynamicAction->task['opened'] = 'Create Task'; +$lang->action->dynamicAction->task['importfromgitlab'] = "Issue associate create task"; $lang->action->dynamicAction->task['edited'] = 'Edit Task'; $lang->action->dynamicAction->task['commented'] = 'Task Comment'; $lang->action->dynamicAction->task['assigned'] = 'Assign Task'; @@ -426,6 +432,7 @@ $lang->action->dynamicAction->build['edited'] = 'Edit Build'; $lang->action->dynamicAction->build['deleted'] = 'Delete Build'; $lang->action->dynamicAction->bug['opened'] = 'Report Bug'; +$lang->action->dynamicAction->bug['importfromgitlab'] = "Issue associate create bug"; $lang->action->dynamicAction->bug['edited'] = 'Edit Bug'; $lang->action->dynamicAction->bug['activated'] = 'Activate Bug'; $lang->action->dynamicAction->bug['assigned'] = 'Assign Bug'; @@ -614,6 +621,7 @@ $lang->action->search->label['canceled'] = $lang->action->label->ca $lang->action->search->label['finished'] = $lang->action->label->finished; $lang->action->search->label['paused'] = $lang->action->label->paused; $lang->action->search->label['verified'] = $lang->action->label->verified; +$lang->action->search->label['importfromgitlab'] = $lang->action->label->importfromgitlab; $lang->action->search->label['login'] = $lang->action->label->login; $lang->action->search->label['logout'] = $lang->action->label->logout; diff --git a/module/action/lang/zh-cn.php b/module/action/lang/zh-cn.php index c43e723f00..58fc5a8433 100755 --- a/module/action/lang/zh-cn.php +++ b/module/action/lang/zh-cn.php @@ -79,101 +79,104 @@ $lang->action->periods['lastweek'] = $lang->action->dynamic->lastWeek; $lang->action->periods['thismonth'] = $lang->action->dynamic->thisMonth; $lang->action->periods['lastmonth'] = $lang->action->dynamic->lastMonth; -$lang->action->objectTypes['product'] = $lang->productCommon; -$lang->action->objectTypes['branch'] = '分支'; -$lang->action->objectTypes['story'] = $lang->SRCommon; -$lang->action->objectTypes['design'] = '设计'; -$lang->action->objectTypes['productplan'] = '计划'; -$lang->action->objectTypes['release'] = '发布'; -$lang->action->objectTypes['program'] = '项目集'; -$lang->action->objectTypes['project'] = '项目'; -$lang->action->objectTypes['execution'] = $config->systemMode == 'new' ? '执行' : $lang->executionCommon; -$lang->action->objectTypes['task'] = '任务'; -$lang->action->objectTypes['build'] = '版本'; -$lang->action->objectTypes['job'] = '构建'; -$lang->action->objectTypes['bug'] = 'Bug'; -$lang->action->objectTypes['case'] = '用例'; -$lang->action->objectTypes['caseresult'] = '用例结果'; -$lang->action->objectTypes['stepresult'] = '用例步骤'; -$lang->action->objectTypes['caselib'] = '用例库'; -$lang->action->objectTypes['testsuite'] = '套件'; -$lang->action->objectTypes['testtask'] = '测试单'; -$lang->action->objectTypes['testreport'] = '报告'; -$lang->action->objectTypes['doc'] = '文档'; -$lang->action->objectTypes['api'] = '接口'; -$lang->action->objectTypes['doclib'] = '文档库'; -$lang->action->objectTypes['apistruct'] = '数据结构'; -$lang->action->objectTypes['todo'] = '待办'; -$lang->action->objectTypes['risk'] = '风险'; -$lang->action->objectTypes['issue'] = '问题'; -$lang->action->objectTypes['module'] = '模块'; -$lang->action->objectTypes['user'] = '用户'; -$lang->action->objectTypes['stakeholder'] = '干系人'; -$lang->action->objectTypes['budget'] = '费用估算'; -$lang->action->objectTypes['entry'] = '应用'; -$lang->action->objectTypes['webhook'] = 'Webhook'; -$lang->action->objectTypes['team'] = '团队'; -$lang->action->objectTypes['whitelist'] = '白名单'; -$lang->action->objectTypes['pipeline'] = 'GitLab'; -$lang->action->objectTypes['gitlab'] = 'GitLab'; -$lang->action->objectTypes['jenkins'] = 'Jenkins'; -$lang->action->objectTypes['mr'] = '合并请求'; -$lang->action->objectTypes['gitlabproject'] = 'GitLab项目'; -$lang->action->objectTypes['gitlabuser'] = 'GitLab用户'; -$lang->action->objectTypes['gitlabgroup'] = 'GitLab群组'; +$lang->action->objectTypes['product'] = $lang->productCommon; +$lang->action->objectTypes['branch'] = '分支'; +$lang->action->objectTypes['story'] = $lang->SRCommon; +$lang->action->objectTypes['design'] = '设计'; +$lang->action->objectTypes['productplan'] = '计划'; +$lang->action->objectTypes['release'] = '发布'; +$lang->action->objectTypes['program'] = '项目集'; +$lang->action->objectTypes['project'] = '项目'; +$lang->action->objectTypes['execution'] = $config->systemMode == 'new' ? '执行' : $lang->executionCommon; +$lang->action->objectTypes['task'] = '任务'; +$lang->action->objectTypes['build'] = '版本'; +$lang->action->objectTypes['job'] = '构建'; +$lang->action->objectTypes['bug'] = 'Bug'; +$lang->action->objectTypes['case'] = '用例'; +$lang->action->objectTypes['caseresult'] = '用例结果'; +$lang->action->objectTypes['stepresult'] = '用例步骤'; +$lang->action->objectTypes['caselib'] = '用例库'; +$lang->action->objectTypes['testsuite'] = '套件'; +$lang->action->objectTypes['testtask'] = '测试单'; +$lang->action->objectTypes['testreport'] = '报告'; +$lang->action->objectTypes['doc'] = '文档'; +$lang->action->objectTypes['api'] = '接口'; +$lang->action->objectTypes['doclib'] = '文档库'; +$lang->action->objectTypes['apistruct'] = '数据结构'; +$lang->action->objectTypes['todo'] = '待办'; +$lang->action->objectTypes['risk'] = '风险'; +$lang->action->objectTypes['issue'] = '问题'; +$lang->action->objectTypes['module'] = '模块'; +$lang->action->objectTypes['user'] = '用户'; +$lang->action->objectTypes['stakeholder'] = '干系人'; +$lang->action->objectTypes['budget'] = '费用估算'; +$lang->action->objectTypes['entry'] = '应用'; +$lang->action->objectTypes['webhook'] = 'Webhook'; +$lang->action->objectTypes['team'] = '团队'; +$lang->action->objectTypes['whitelist'] = '白名单'; +$lang->action->objectTypes['pipeline'] = 'GitLab'; +$lang->action->objectTypes['gitlab'] = 'GitLab'; +$lang->action->objectTypes['jenkins'] = 'Jenkins'; +$lang->action->objectTypes['mr'] = '合并请求'; +$lang->action->objectTypes['gitlabproject'] = 'GitLab项目'; +$lang->action->objectTypes['gitlabuser'] = 'GitLab用户'; +$lang->action->objectTypes['gitlabgroup'] = 'GitLab群组'; +$lang->action->objectTypes['gitlabbranch'] = 'GitLab分支'; +$lang->action->objectTypes['gitlabbranchpriv'] = 'GitLab保护分支'; /* 用来描述操作历史记录。*/ $lang->action->desc = new stdclass(); -$lang->action->desc->common = '$date, $action by $actor。' . "\n"; -$lang->action->desc->extra = '$date, $action as $extra by $actor。' . "\n"; -$lang->action->desc->opened = '$date, 由 $actor 创建。' . "\n"; -$lang->action->desc->openedbysystem = '$date, 由系统创建。' . "\n"; -$lang->action->desc->created = '$date, 由 $actor 创建。' . "\n"; -$lang->action->desc->added = '$date, 由 $actor 添加。' . "\n"; -$lang->action->desc->changed = '$date, 由 $actor 变更。' . "\n"; -$lang->action->desc->edited = '$date, 由 $actor 编辑。' . "\n"; -$lang->action->desc->assigned = '$date, 由 $actor 指派给 $extra。' . "\n"; -$lang->action->desc->closed = '$date, 由 $actor 关闭。' . "\n"; -$lang->action->desc->closedbysystem = '$date, 由系统关闭。' . "\n"; -$lang->action->desc->deleted = '$date, 由 $actor 删除。' . "\n"; -$lang->action->desc->deletedfile = '$date, 由 $actor 删除了附件:$extra。' . "\n"; -$lang->action->desc->editfile = '$date, 由 $actor 编辑了附件:$extra。' . "\n"; -$lang->action->desc->erased = '$date, 由 $actor 删除。' . "\n"; -$lang->action->desc->undeleted = '$date, 由 $actor 还原。' . "\n"; -$lang->action->desc->hidden = '$date, 由 $actor 隐藏。' . "\n"; -$lang->action->desc->commented = '$date, 由 $actor 添加备注。' . "\n"; -$lang->action->desc->activated = '$date, 由 $actor 激活。' . "\n"; -$lang->action->desc->blocked = '$date, 由 $actor 阻塞。' . "\n"; -$lang->action->desc->moved = '$date, 由 $actor 移动,之前为 "$extra"。' . "\n"; -$lang->action->desc->confirmed = '$date, 由 $actor 确认' . $lang->SRCommon . '变动,最新版本为#$extra。' . "\n"; -$lang->action->desc->caseconfirmed = '$date, 由 $actor 确认用例变动,最新版本为#$extra。' . "\n"; -$lang->action->desc->bugconfirmed = '$date, 由 $actor 确认Bug。' . "\n"; -$lang->action->desc->frombug = '$date, 由 $actor Bug转化而来,Bug编号为 $extra。'; -$lang->action->desc->started = '$date, 由 $actor 启动。' . "\n"; -$lang->action->desc->restarted = '$date, 由 $actor 继续。' . "\n"; -$lang->action->desc->delayed = '$date, 由 $actor 延期。' . "\n"; -$lang->action->desc->suspended = '$date, 由 $actor 挂起。' . "\n"; -$lang->action->desc->recordestimate = '$date, 由 $actor 记录工时,消耗 $extra 小时。'; -$lang->action->desc->editestimate = '$date, 由 $actor 编辑工时。'; -$lang->action->desc->deleteestimate = '$date, 由 $actor 删除工时。'; -$lang->action->desc->canceled = '$date, 由 $actor 取消。' . "\n"; -$lang->action->desc->svncommited = '$date, 由 $actor 提交代码,版本为#$extra。' . "\n"; -$lang->action->desc->gitcommited = '$date, 由 $actor 提交代码,版本为#$extra。' . "\n"; -$lang->action->desc->finished = '$date, 由 $actor 完成。' . "\n"; -$lang->action->desc->paused = '$date, 由 $actor 暂停。' . "\n"; -$lang->action->desc->verified = '$date, 由 $actor 验收。' . "\n"; -$lang->action->desc->diff1 = '修改了 %s,旧值为 "%s",新值为 "%s"。
' . "\n"; -$lang->action->desc->diff2 = '修改了 %s,区别为:' . "\n" . "
%s
" . "\n
%s
"; -$lang->action->desc->diff3 = '将文件名 %s 改为 %s 。' . "\n"; -$lang->action->desc->linked2bug = '$date 由 $actor 关联到版本 $extra'; -$lang->action->desc->linked2testtask = '$date 由 $actor 关联到测试单 $extra'; -$lang->action->desc->resolved = '$date, 由 $actor 解决。' . "\n"; -$lang->action->desc->managed = '$date, 由 $actor 维护。' . "\n"; -$lang->action->desc->estimated = '$date, 由 $actor 估算。' . "\n"; -$lang->action->desc->run = '$date, 由 $actor 执行。' . "\n"; -$lang->action->desc->syncprogram = '$date, 由 $actor 启动(因项目开始而启动项目集)。' . "\n"; -$lang->action->desc->syncproject = '$date, 系统判断由于执行开始,将项目状态置为进行中。' . "\n"; -$lang->action->desc->syncexecution = '$date, 系统判断由于任务开始,将执行状态置为进行中。' . "\n"; +$lang->action->desc->common = '$date, $action by $actor。' . "\n"; +$lang->action->desc->extra = '$date, $action as $extra by $actor。' . "\n"; +$lang->action->desc->opened = '$date, 由 $actor 创建。' . "\n"; +$lang->action->desc->openedbysystem = '$date, 由系统创建。' . "\n"; +$lang->action->desc->created = '$date, 由 $actor 创建。' . "\n"; +$lang->action->desc->added = '$date, 由 $actor 添加。' . "\n"; +$lang->action->desc->changed = '$date, 由 $actor 变更。' . "\n"; +$lang->action->desc->edited = '$date, 由 $actor 编辑。' . "\n"; +$lang->action->desc->assigned = '$date, 由 $actor 指派给 $extra。' . "\n"; +$lang->action->desc->closed = '$date, 由 $actor 关闭。' . "\n"; +$lang->action->desc->closedbysystem = '$date, 由系统关闭。' . "\n"; +$lang->action->desc->deleted = '$date, 由 $actor 删除。' . "\n"; +$lang->action->desc->deletedfile = '$date, 由 $actor 删除了附件:$extra。' . "\n"; +$lang->action->desc->editfile = '$date, 由 $actor 编辑了附件:$extra。' . "\n"; +$lang->action->desc->erased = '$date, 由 $actor 删除。' . "\n"; +$lang->action->desc->undeleted = '$date, 由 $actor 还原。' . "\n"; +$lang->action->desc->hidden = '$date, 由 $actor 隐藏。' . "\n"; +$lang->action->desc->commented = '$date, 由 $actor 添加备注。' . "\n"; +$lang->action->desc->activated = '$date, 由 $actor 激活。' . "\n"; +$lang->action->desc->blocked = '$date, 由 $actor 阻塞。' . "\n"; +$lang->action->desc->moved = '$date, 由 $actor 移动,之前为 "$extra"。' . "\n"; +$lang->action->desc->confirmed = '$date, 由 $actor 确认' . $lang->SRCommon . '变动,最新版本为#$extra。' . "\n"; +$lang->action->desc->caseconfirmed = '$date, 由 $actor 确认用例变动,最新版本为#$extra。' . "\n"; +$lang->action->desc->bugconfirmed = '$date, 由 $actor 确认Bug。' . "\n"; +$lang->action->desc->frombug = '$date, 由 $actor Bug转化而来,Bug编号为 $extra。'; +$lang->action->desc->started = '$date, 由 $actor 启动。' . "\n"; +$lang->action->desc->restarted = '$date, 由 $actor 继续。' . "\n"; +$lang->action->desc->delayed = '$date, 由 $actor 延期。' . "\n"; +$lang->action->desc->suspended = '$date, 由 $actor 挂起。' . "\n"; +$lang->action->desc->recordestimate = '$date, 由 $actor 记录工时,消耗 $extra 小时。'; +$lang->action->desc->editestimate = '$date, 由 $actor 编辑工时。'; +$lang->action->desc->deleteestimate = '$date, 由 $actor 删除工时。'; +$lang->action->desc->canceled = '$date, 由 $actor 取消。' . "\n"; +$lang->action->desc->svncommited = '$date, 由 $actor 提交代码,版本为#$extra。' . "\n"; +$lang->action->desc->gitcommited = '$date, 由 $actor 提交代码,版本为#$extra。' . "\n"; +$lang->action->desc->finished = '$date, 由 $actor 完成。' . "\n"; +$lang->action->desc->paused = '$date, 由 $actor 暂停。' . "\n"; +$lang->action->desc->verified = '$date, 由 $actor 验收。' . "\n"; +$lang->action->desc->diff1 = '修改了 %s,旧值为 "%s",新值为 "%s"。
' . "\n"; +$lang->action->desc->diff2 = '修改了 %s,区别为:' . "\n" . "
%s
" . "\n
%s
"; +$lang->action->desc->diff3 = '将文件名 %s 改为 %s 。' . "\n"; +$lang->action->desc->linked2bug = '$date 由 $actor 关联到版本 $extra'; +$lang->action->desc->linked2testtask = '$date 由 $actor 关联到测试单 $extra'; +$lang->action->desc->resolved = '$date, 由 $actor 解决。' . "\n"; +$lang->action->desc->managed = '$date, 由 $actor 维护。' . "\n"; +$lang->action->desc->estimated = '$date, 由 $actor 估算。' . "\n"; +$lang->action->desc->run = '$date, 由 $actor 执行。' . "\n"; +$lang->action->desc->syncprogram = '$date, 由 $actor 启动(因项目开始而启动项目集)。' . "\n"; +$lang->action->desc->syncproject = '$date, 系统判断由于执行开始,将项目状态置为进行中。' . "\n"; +$lang->action->desc->syncexecution = '$date, 系统判断由于任务开始,将执行状态置为进行中。' . "\n"; +$lang->action->desc->importfromgitlab = '$date, 由 $actor 从Gitlab的Issue关联创建。' . "\n"; /* 用来描述和父子任务相关的操作历史记录。*/ $lang->action->desc->createchildren = '$date, 由 $actor 创建子任务 $extra。' . "\n"; @@ -303,6 +306,7 @@ $lang->action->label->compilefail = '构建失败'; $lang->action->label->reopen = '重新打开'; $lang->action->label->approve = '通过了'; $lang->action->label->reject = '拒绝了'; +$lang->action->label->importfromgitlab = '从Gitlab关联创建了'; /* 动态信息按照对象分组 */ $lang->action->dynamicAction = new stdclass(); @@ -353,6 +357,7 @@ $lang->action->dynamicAction->release['notified'] = '通知发布'; $lang->action->dynamicAction->release['hidden'] = '隐藏发布'; $lang->action->dynamicAction->story['opened'] = "创建{$lang->SRCommon}"; +$lang->action->dynamicAction->story['importfromgitlab'] = "从Gitlab关联创建{$lang->SRCommon}"; $lang->action->dynamicAction->story['edited'] = "编辑{$lang->SRCommon}"; $lang->action->dynamicAction->story['activated'] = "激活{$lang->SRCommon}"; $lang->action->dynamicAction->story['reviewed'] = "评审{$lang->SRCommon}"; @@ -393,6 +398,7 @@ $lang->action->dynamicAction->kanbanlane['moved'] = '移动泳道'; $lang->action->dynamicAction->team['managedTeam'] = '维护团队'; $lang->action->dynamicAction->task['opened'] = '创建任务'; +$lang->action->dynamicAction->task['importfromgitlab'] = "从Gitlab关联创建任务"; $lang->action->dynamicAction->task['edited'] = '编辑任务'; $lang->action->dynamicAction->task['commented'] = '备注任务'; $lang->action->dynamicAction->task['assigned'] = '指派任务'; @@ -426,6 +432,7 @@ $lang->action->dynamicAction->build['edited'] = '编辑版本'; $lang->action->dynamicAction->build['deleted'] = '删除版本'; $lang->action->dynamicAction->bug['opened'] = '创建Bug'; +$lang->action->dynamicAction->bug['importfromgitlab'] = "从Gitlab关联创建Bug"; $lang->action->dynamicAction->bug['edited'] = '编辑Bug'; $lang->action->dynamicAction->bug['activated'] = '激活Bug'; $lang->action->dynamicAction->bug['assigned'] = '指派Bug'; @@ -614,6 +621,7 @@ $lang->action->search->label['canceled'] = $lang->action->label->ca $lang->action->search->label['finished'] = $lang->action->label->finished; $lang->action->search->label['paused'] = $lang->action->label->paused; $lang->action->search->label['verified'] = $lang->action->label->verified; +$lang->action->search->label['importfromgitlab'] = $lang->action->label->importfromgitlab; $lang->action->search->label['login'] = $lang->action->label->login; $lang->action->search->label['logout'] = $lang->action->label->logout; diff --git a/module/block/lang/en.php b/module/block/lang/en.php index ce31de4f53..b0a9a555e3 100644 --- a/module/block/lang/en.php +++ b/module/block/lang/en.php @@ -91,6 +91,7 @@ $lang->block->refresh = 'Refresh'; $lang->block->nbsp = ' '; $lang->block->hidden = 'Hide'; $lang->block->dynamicInfo = "%s %s %s %s %s"; +$lang->block->noLinkDynamic = "%s %s %s %s %s"; $lang->block->cannotPlaceInLeft = 'Cannot place the block at left side.'; $lang->block->cannotPlaceInRight = 'Cannot place the block at right side.'; diff --git a/module/block/lang/zh-cn.php b/module/block/lang/zh-cn.php index ac77206f01..e5d8deface 100644 --- a/module/block/lang/zh-cn.php +++ b/module/block/lang/zh-cn.php @@ -91,6 +91,7 @@ $lang->block->refresh = '刷新'; $lang->block->nbsp = ''; $lang->block->hidden = '隐藏'; $lang->block->dynamicInfo = "%s %s %s %s %s"; +$lang->block->noLinkDynamic = "%s %s %s %s %s"; $lang->block->cannotPlaceInLeft = '此区块无法放置在左侧。'; $lang->block->cannotPlaceInRight = '此区块无法放置在右侧。'; diff --git a/module/block/view/dynamic.html.php b/module/block/view/dynamic.html.php index 2447f62507..215bb804d3 100644 --- a/module/block/view/dynamic.html.php +++ b/module/block/view/dynamic.html.php @@ -15,7 +15,8 @@ if($action->action == 'login' or $action->action == 'logout') $action->objectName = $action->objectLabel = ''; $class = $action->major ? "class='active'" : ''; echo "
  • "; - printf($lang->block->dynamicInfo, $action->date, $user, $action->actionLabel, $action->objectLabel, $action->objectLink, $action->objectName, $action->objectName); + if($action->objectLink) printf($lang->block->dynamicInfo, $action->date, $user, $action->actionLabel, $action->objectLabel, $action->objectLink, $action->objectName, $action->objectName); + if(!$action->objectLink) printf($lang->block->noLinkDynamic, $action->date, $action->objectName, $user, $action->actionLabel, $action->objectLabel, $action->objectName); echo "
  • "; $i++; } diff --git a/module/gitlab/config.php b/module/gitlab/config.php index 5f41d70ceb..d02cf70f27 100644 --- a/module/gitlab/config.php +++ b/module/gitlab/config.php @@ -5,6 +5,12 @@ $config->gitlab->create->requiredFields = 'name,url,token'; $config->gitlab->edit = new stdclass; $config->gitlab->edit->requiredFields = 'name,url,token'; +$config->gitlab->createbranch = new stdclass; +$config->gitlab->createbranch->requiredFields = 'branch,ref'; + +$config->gitlab->createbranchpriv = new stdclass; +$config->gitlab->createbranchpriv->requiredFields = 'name'; + $config->gitlab->labelPattern = new stdclass; $config->gitlab->labelPattern->task = '/^zentao_task\/\d+$/'; $config->gitlab->labelPattern->bug = '/^zentao_bug\/\d+$/'; diff --git a/module/gitlab/control.php b/module/gitlab/control.php index e56cae595d..d6e34fc2c2 100644 --- a/module/gitlab/control.php +++ b/module/gitlab/control.php @@ -712,6 +712,224 @@ class gitlab extends control die(js::alert($reponse->message)); } + /** + * Browse gitlab branch. + * + * @param int $gitlabID + * @param int $projectID + * @param string $orderBy + * @param int $recTotal + * @param int $recPerPage + * @param int $pageID + * @access public + * @return void + */ + public function browseBranch($gitlabID, $projectID, $orderBy = 'name_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1) + { + $this->session->set('gitlabBranchList', $this->app->getURI(true)); + + $branchList = array(); + $result = $this->gitlab->apiGetBranches($gitlabID, $projectID); + foreach($result as $gitlabBranch) + { + $branch = new stdClass(); + $branch->name = $gitlabBranch->name; + $branch->lastCommitter = $gitlabBranch->commit->committer_name; + $branch->lastCommittedDate = date('Y-m-d H:i:s', strtotime($gitlabBranch->commit->committed_date)); + + $branchList[] = $branch; + } + + /* Data sort. */ + list($order, $sort) = explode('_', $orderBy); + $orderList = array(); + foreach($branchList as $branch) + { + $orderList[] = $branch->$order; + } + array_multisort($orderList, $sort == 'desc' ? SORT_DESC : SORT_ASC, $branchList); + + /* Pager. */ + $this->app->loadClass('pager', $static = true); + $recTotal = count($branchList); + $pager = new pager($recTotal, $recPerPage, $pageID); + $branchList = array_chunk($branchList, $pager->recPerPage); + + $this->view->gitlab = $this->gitlab->getByID($gitlabID); + $this->view->pager = $pager; + $this->view->title = $this->lang->gitlab->common . $this->lang->colon . $this->lang->gitlab->browseBranch; + $this->view->gitlabID = $gitlabID; + $this->view->projectID = $projectID; + $this->view->gitlabBranchList = empty($branchList) ? $branchList: $branchList[$pageID - 1]; + $this->view->orderBy = $orderBy; + $this->display(); + } + + /** + * Creat a gitlab branch. + * + * @param int $gitlabID + * @param int $projectID + * @access public + * @return void + */ + public function createBranch($gitlabID, $projectID) + { + if($_POST) + { + $this->gitlab->createBranch($gitlabID, $projectID); + if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError())); + + $locate = $this->session->gitlabBranchList ? $this->session->gitlabBranchList : inlink('browseBranch', "gitlibID=$gitlabID&projectID=$projectID"); + return $this->send(array('result' => 'success', 'message' => $this->lang->gitlab->createSuccess, 'locate' => $locate)); + } + + /* Get branches by api. */ + $branches = $this->gitlab->apiGetBranches($gitlabID, $projectID); + if(!is_array($branches)) $branches= array(); + + $branchPairs = array(); + foreach($branches as $branch) $branchPairs[$branch->name] = $branch->name; + + $this->view->title = $this->lang->gitlab->common . $this->lang->colon . $this->lang->gitlab->createBranch; + $this->view->gitlabID = $gitlabID; + $this->view->projectID = $projectID; + $this->view->branchPairs = $branchPairs; + $this->display(); + } + + /** + * Browse gitlab protect branch. + * + * @param int $gitlabID + * @param int $projectID + * @param string $orderBy + * @param int $recTotal + * @param int $recPerPage + * @param int $pageID + * @access public + * @return void + */ + public function browseBranchPriv($gitlabID, $projectID, $orderBy = 'id_desc', $recTotal = 0, $recPerPage = 15, $pageID = 1) + { + $keyword = fixer::input('post')->setDefault('keyword', '')->get('keyword'); + $branches = $this->gitlab->apiGetBranchPrivs($gitlabID, $projectID, $keyword, $orderBy); + $project = $this->gitlab->apiGetSingleProject($gitlabID, $projectID); + + /* Pager. */ + $this->app->loadClass('pager', $static = true); + $recTotal = count($branches); + $pager = new pager($recTotal, $recPerPage, $pageID); + $branchList = array_chunk($branches, $pager->recPerPage); + + $this->view->keyword = $keyword; + $this->view->pager = $pager; + $this->view->title = $this->lang->gitlab->common . $this->lang->colon . $this->lang->gitlab->browseBranchPriv; + $this->view->levelLang = $this->lang->gitlab->branch->branchCreationLevelList; + $this->view->gitlabID = $gitlabID; + $this->view->projectID = $projectID; + $this->view->project = $project; + $this->view->orderBy = $orderBy; + $this->view->branchList = empty($branchList) ? $branchList: $branchList[$pageID - 1]; + $this->display(); + } + + /** + * Set a gitlab protect branch. + * + * @param int $gitlabID + * @param int $projectID + * @param string $branch + * @access public + * @return void + */ + public function createBranchPriv($gitlabID, $projectID, $branch = '') + { + if($_POST) + { + $this->gitlab->createBranchPriv($gitlabID, $projectID, $branch); + + if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError())); + return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => inlink('browseBranchPriv', "gitlabID=$gitlabID&projectID=$projectID"))); + } + + $branchPriv = new stdClass(); + $branchPriv->name = ''; + $branchPriv->mergeAccessLevel = 40; // Initialize data, and the operation authority is the maintainers by default. + $branchPriv->pushAccessLevel = 40; // Initialize data, and the operation authority is the maintainers by default. + + $gitlab = $this->gitlab->getByID($gitlabID); + $title = $this->lang->gitlab->createBranchPriv; + + if($branch) + { + $title = $this->lang->gitlab->editBranchPriv; + $branchPriv = $this->gitlab->apiGetSingleBranchPriv($gitlabID, $projectID, $branch); + $branchPriv->mergeAccessLevel = $this->gitlab->checkAccessLevel($branchPriv->merge_access_levels); + $branchPriv->pushAccessLevel = $this->gitlab->checkAccessLevel($branchPriv->push_access_levels); + } + + $gitlabBranches = $this->gitlab->apiGetBranches($gitlabID, $projectID); + $protectBranches = $this->gitlab->apiGetBranchPrivs($gitlabID, $projectID, '', 'name_asc'); + $protectNames = array_keys($protectBranches); + + $branches = array(); + foreach($gitlabBranches as $oneBranch) + { + if(!in_array($oneBranch->name, $protectNames) || $oneBranch->name == $branch) $branches[$oneBranch->name] = $oneBranch->name; + } + + $this->view->title = $this->lang->gitlab->common . $this->lang->colon . $title; + $this->view->pageTitle = $title; + $this->view->gitlab = $gitlab; + $this->view->gitlabID = $gitlabID; + $this->view->branch = $branch; + $this->view->projectID = $projectID; + $this->view->branches = $branches; + $this->view->branchPriv = $branchPriv; + $this->display(); + } + + /** + * Edit a gitlab branch protect. + * + * @param int $gitlabID + * @param int $projectID + * @param string $branch + * @access public + * @return void + */ + public function editBranchPriv($gitlabID, $projectID, $branch) + { + echo $this->fetch('gitlab', 'createBranchPriv', "gitlabID=$gitlabID&projectID=$projectID&branch=$branch"); + } + + /** + * Delete a gitlab protect branch. + * + * @param int $gitlabID + * @param int $projectID + * @param string $branch + * @param string $confirm + * @access public + * @return void + */ + public function deleteBranchPriv($gitlabID, $projectID, $branch, $confirm = 'no') + { + if($confirm != 'yes') die(js::confirm($this->lang->gitlab->branch->confirmDelete , inlink('deleteBranchPriv', "gitlabID=$gitlabID&projectID=$projectID&branch=$branch&confirm=yes"))); + + $reponse = $this->gitlab->apiDeleteBranchPriv($gitlabID, $projectID, $branch); + + /* If the status code beginning with 20 is returned or empty is returned, it is successful. */ + if(!$reponse or substr($reponse->message, 0, 2) == '20') + { + $this->loadModel('action')->create('gitlabbranchPriv', $branch, 'deleted', '', $branch); + die(js::reload('parent')); + } + + die(js::alert($reponse->message)); + } + /** * Import gitlab issue to zentaopms. * @@ -730,7 +948,6 @@ class gitlab extends control if($gitlab) $user = $this->gitlab->apiGetCurrentUser($gitlab->url, $gitlab->token); if(empty($user->is_admin)) die(js::alert($this->lang->gitlab->tokenLimit) . js::locate($this->createLink('gitlab', 'edit', array('gitlabID' => $gitlabID)))); - if($_POST) { $executionList = $this->post->executionList; @@ -740,38 +957,40 @@ class gitlab extends control $failedIssues = array(); foreach($executionList as $issueID => $executionID) { - if($executionID) + if(empty($executionID) and $productList[$issueID] != 0) return $this->send(array('result' => 'fail', 'message' => $this->lang->gitlab->importIssueError, 'locate' => $this->server->http_referer)); + } + + foreach($executionList as $issueID => $executionID) + { + if(empty($executionID)) continue; + + $objectType = $objectTypeList[$issueID]; + + $issue = $this->gitlab->apiGetSingleIssue($gitlabID, $projectID, $issueID); + $issue->objectType = $objectType; + $issue->objectID = 0; // Meet the required parameters for issueToZentaoObject. + if(isset($issue->assignee)) $issue->assignee_id = $issue->assignee->id; + $issue->updated_by_id = $issue->author->id; // Here can be replaced by current zentao user. + + $object = $this->gitlab->issueToZentaoObject($issue, $gitlabID); + $object->product = $productList[$issueID]; + $object->execution = $executionID; + $clonedObject = clone $object; + + if($objectType == 'task') $objectID = $this->loadModel('task')->createTaskFromGitlabIssue($clonedObject, $executionID); + if($objectType == 'bug') $objectID = $this->loadModel('bug')->createBugFromGitlabIssue($clonedObject, $executionID); + if($objectType == 'story') $objectID = $this->loadModel('story')->createStoryFromGitlabIssue($clonedObject, $executionID); + + if($objectID) { - $objectType = $objectTypeList[$issueID]; + $this->loadModel('action')->create($objectType, $objectID, 'ImportFromGitlab', '', $issueID); - $issue = $this->gitlab->apiGetSingleIssue($gitlabID, $projectID, $issueID); - $issue->objectType = $objectType; - $issue->objectID = 0; // Meet the required parameters for issueToZentaoObject. - if(isset($issue->assignee)) $issue->assignee_id = $issue->assignee->id; - $issue->updated_by_id = $issue->author->id; // Here can be replaced by current zentao user. - - $object = $this->gitlab->issueToZentaoObject($issue, $gitlabID); - $object->product = $productList[$issueID]; - $object->execution = $executionID; - $clonedObject = clone $object; - - if($objectType == 'task') $objectID = $this->loadModel('task')->createTaskFromGitlabIssue($clonedObject, $executionID); - if($objectType == 'bug') $objectID = $this->loadModel('bug')->createBugFromGitlabIssue($clonedObject, $executionID); - if($objectType == 'story') $objectID = $this->loadModel('story')->createStoryFromGitlabIssue($clonedObject, $executionID); - - if($objectID) - { - $object->id = $objectID; - $this->gitlab->saveImportedIssue($gitlabID, $projectID, $objectType, $objectID, $issue, $object); - } - else - { - $failedIssues[] = $issue->iid; - } + $object->id = $objectID; + $this->gitlab->saveImportedIssue($gitlabID, $projectID, $objectType, $objectID, $issue, $object); } else { - if($productList[$issueID] != 0) return $this->send(array('result' => 'fail', 'message' => $this->lang->gitlab->importIssueError, 'locate' => $this->server->http_referer)); + $failedIssues[] = $issue->iid; } } diff --git a/module/gitlab/css/browsebranchpriv.css b/module/gitlab/css/browsebranchpriv.css new file mode 100644 index 0000000000..d86ca85e6a --- /dev/null +++ b/module/gitlab/css/browsebranchpriv.css @@ -0,0 +1,2 @@ +.text-c-counts > span {margin-left: 5px;} +#mainMenu .pull-left {margin-right: 15px;} diff --git a/module/gitlab/css/createbranchpriv.css b/module/gitlab/css/createbranchpriv.css new file mode 100644 index 0000000000..025aeb5e7f --- /dev/null +++ b/module/gitlab/css/createbranchpriv.css @@ -0,0 +1,2 @@ +.table-form>tbody>tr>th {width: 110px;} +.table-form {width: 50%;} diff --git a/module/gitlab/css/managegroupmembers.css b/module/gitlab/css/managegroupmembers.css index 0d940091ae..16c089036c 100644 --- a/module/gitlab/css/managegroupmembers.css +++ b/module/gitlab/css/managegroupmembers.css @@ -1 +1,3 @@ -.table-form {min-width: 600px;} +.table-form {min-width: 700px;} +.c-levels {width: 150px;} +.c-names {width: 300px;} diff --git a/module/gitlab/css/manageprojectmembers.css b/module/gitlab/css/manageprojectmembers.css index 0d940091ae..16c089036c 100644 --- a/module/gitlab/css/manageprojectmembers.css +++ b/module/gitlab/css/manageprojectmembers.css @@ -1 +1,3 @@ -.table-form {min-width: 600px;} +.table-form {min-width: 700px;} +.c-levels {width: 150px;} +.c-names {width: 300px;} diff --git a/module/gitlab/js/browsebranchpriv.js b/module/gitlab/js/browsebranchpriv.js new file mode 100644 index 0000000000..806b8bc4e1 --- /dev/null +++ b/module/gitlab/js/browsebranchpriv.js @@ -0,0 +1,23 @@ +$(document).ready(function() +{ + $('#branchSearch').click(function() + { + triggerSearch(); + }); + $('#keyword').keypress(function(event) + { + if(event.which == 13) triggerSearch(); + }) + +}); + +/** + * Trigger filtering function. + * + * @access public + * @return void + */ +function triggerSearch() +{ + $("#branchPrivForm").submit(); +} diff --git a/module/gitlab/js/creategroup.js b/module/gitlab/js/creategroup.js new file mode 100644 index 0000000000..6cf1b82249 --- /dev/null +++ b/module/gitlab/js/creategroup.js @@ -0,0 +1 @@ +$("input[type='radio'][value='public']").parent().parent().css("margin-bottom", "0px"); diff --git a/module/gitlab/js/managegroupmembers.js b/module/gitlab/js/managegroupmembers.js index 589e0ffc61..a9391db43b 100644 --- a/module/gitlab/js/managegroupmembers.js +++ b/module/gitlab/js/managegroupmembers.js @@ -41,6 +41,25 @@ function addItem(obj) */ function deleteItem(obj) { - if($('#teamForm .table tbody').children().length < 2) return false; + if($('#teamForm .table-form tbody').children().length < 2) return false; $(obj).closest('tr').remove(); -} \ No newline at end of file +} + +$(document).on('change', '[id^="levels"]', function() +{ + $tr = $(this).closest('tr'); + $next = $(this).closest('td').next() + var ownerLevel = 50; + if($(this).val() == ownerLevel) + { + $next.prepend(''); + $next.find('[id^="expires"]').addClass('hidden'); + $tr.find('a[onclick^="deleteItem"]').addClass('disabled'); + } + else + { + $next.find('[id^="expires"]').removeClass('hidden'); + $next.find('input.disabled').remove(); + $tr.find('a[onclick^="deleteItem"]').removeClass('disabled'); + } +}) diff --git a/module/gitlab/js/manageprojectmembers.js b/module/gitlab/js/manageprojectmembers.js index 589e0ffc61..f67e13d81e 100644 --- a/module/gitlab/js/manageprojectmembers.js +++ b/module/gitlab/js/manageprojectmembers.js @@ -41,6 +41,6 @@ function addItem(obj) */ function deleteItem(obj) { - if($('#teamForm .table tbody').children().length < 2) return false; + if($('#teamForm .table-form tbody').children().length < 2) return false; $(obj).closest('tr').remove(); -} \ No newline at end of file +} diff --git a/module/gitlab/lang/en.php b/module/gitlab/lang/en.php index 07c7ad4e7f..b03cf87c94 100644 --- a/module/gitlab/lang/en.php +++ b/module/gitlab/lang/en.php @@ -30,6 +30,7 @@ $lang->gitlab->gitlabProject = "GitLab Project"; $lang->gitlab->browseProject = "GitLab Project List"; $lang->gitlab->browseUser = "User List"; $lang->gitlab->browseGroup = "Group List"; +$lang->gitlab->browseBranch = "GitLab Branch List"; $lang->gitlab->gitlabIssue = "GitLab Issue"; $lang->gitlab->zentaoProduct = 'Zentao Product'; $lang->gitlab->objectType = 'Type'; // task, bug, story @@ -43,8 +44,13 @@ $lang->gitlab->deleteGroup = 'Delete group'; $lang->gitlab->createUser = 'Create user'; $lang->gitlab->editUser = 'Edit user'; $lang->gitlab->deleteUser = 'Delete user'; +$lang->gitlab->createBranch = 'Add branch'; $lang->gitlab->manageGroupMembers = 'Manage group member'; $lang->gitlab->createWebhook = 'Create Webhook'; +$lang->gitlab->browseBranchPriv = 'Protect branch'; +$lang->gitlab->createBranchPriv = 'Cerate branch protected'; +$lang->gitlab->editBranchPriv = 'Edit branch protected'; +$lang->gitlab->deleteBranchPriv = 'Delete branch protected'; $lang->gitlab->id = 'ID'; $lang->gitlab->name = "GitLab Name"; @@ -53,10 +59,12 @@ $lang->gitlab->token = 'Token'; $lang->gitlab->defaultProject = 'Default Project'; $lang->gitlab->private = 'MD5 Verify'; -$lang->gitlab->lblCreate = 'Create GitLab Server'; -$lang->gitlab->desc = 'Description'; -$lang->gitlab->tokenFirst = 'When the Token is not empty, the Token will be used first'; -$lang->gitlab->tips = 'When using a password, please disable the "Prevent cross-site request forgery" option in the GitLab global security settings.'; +$lang->gitlab->lblCreate = 'Create GitLab Server'; +$lang->gitlab->desc = 'Description'; +$lang->gitlab->tokenFirst = 'When the Token is not empty, the Token will be used first'; +$lang->gitlab->tips = 'When using a password, please disable the "Prevent cross-site request forgery" option in the GitLab global security settings.'; +$lang->gitlab->emptyError = " cannot be empty"; +$lang->gitlab->createSuccess = "Create success"; $lang->gitlab->placeholder = new stdclass; $lang->gitlab->placeholder->name = ''; @@ -82,11 +90,15 @@ $lang->gitlab->apiError[0] = 'internal is not allowed in a private group.'; $lang->gitlab->apiError[1] = 'public is not allowed in a private group.'; $lang->gitlab->apiError[2] = 'is too short (minimum is 8 characters)'; $lang->gitlab->apiError[3] = "can contain only letters, digits, '_', '-' and '.'. Cannot start with '-', end in '.git' or end in '.atom'"; +$lang->gitlab->apiError[4] = 'Branch already exists'; +$lang->gitlab->apiError[5] = 'Failed to save group {:path=>["has already been taken"]}'; $lang->gitlab->errorLang[0] = 'You cannot set Internal as its Visibility Level, if it is private in GitLab.'; $lang->gitlab->errorLang[1] = 'You cannot set Public as its Visibility Level, if it is private in GitLab.'; $lang->gitlab->errorLang[2] = 'Password is too short (minimum is 8 characters)'; $lang->gitlab->errorLang[3] = 'It should contain only letters, digits, underscore, hyphen and period. It should not start with hypen, or end with .git or .atom.'; +$lang->gitlab->errorLang[4] = 'Branch already exists.'; +$lang->gitlab->errorLang[5] = 'Failed to save group, path has already been taken.'; $lang->gitlab->project = new stdclass; $lang->gitlab->project->id = "Project ID"; @@ -122,7 +134,7 @@ $lang->gitlab->user->projectsLimit = "Projects limit"; $lang->gitlab->user->canCreateGroup = "Can create group"; $lang->gitlab->user->external = "External"; $lang->gitlab->user->externalTip = "External users cannot see internal or private projects unless access is explicitly granted. Also, external users cannot create projects, groups, or personal snippets."; -$lang->gitlab->user->bind = "Bind Zentao user"; +$lang->gitlab->user->bind = "Zentao user"; $lang->gitlab->user->avatar = "Avatar"; $lang->gitlab->user->skype = "Skype"; $lang->gitlab->user->linkedin = "Linkedin"; @@ -150,6 +162,7 @@ $lang->gitlab->group->visibility = "Visibility leve $lang->gitlab->group->visibilityList['private'] = "Private(The group and its projects can only be viewed by members)"; $lang->gitlab->group->visibilityList['internal'] = "Internal(The group and any internal projects can be viewed by any logged in user except external users)"; $lang->gitlab->group->visibilityList['public'] = "Public(The group and any public projects can be viewed without any authentication.)"; +$lang->gitlab->group->permission = 'Permission'; $lang->gitlab->group->requestAccessEnabledTip = "Allow users to request access (if visibility is public or internal)"; $lang->gitlab->group->lfsEnabled = 'Large File Storage'; $lang->gitlab->group->lfsEnabledTip = "Allow projects within this group to use Git LFS(This setting can be overridden in each project)"; @@ -171,3 +184,21 @@ $lang->gitlab->group->memberName = 'Account'; $lang->gitlab->group->memberAccessLevel = 'Access Level'; $lang->gitlab->group->memberExpiresAt = 'Expiration time'; $lang->gitlab->group->repeatError = "Group members cannot be added repeatedly"; + +$lang->gitlab->branch = new stdclass(); +$lang->gitlab->branch->name = 'Branch name'; +$lang->gitlab->branch->from = 'Create from'; +$lang->gitlab->branch->create = 'Create'; +$lang->gitlab->branch->lastCommitter = 'Last Committer'; +$lang->gitlab->branch->lastCommittedDate = 'Last Committed Date'; +$lang->gitlab->branch->accessLevel = "Branch protection list"; +$lang->gitlab->branch->mergeAllowed = "Merge Allowed"; +$lang->gitlab->branch->pushAllowed = "Push Allowed"; +$lang->gitlab->branch->placeholderSearch = "Branch name"; +$lang->gitlab->branch->placeholderSelect = "Branch name"; +$lang->gitlab->branch->confirmDelete = 'Branch will be writable for developers. Are you sure?'; +$lang->gitlab->branch->branchCreationLevelList[40] = "Maintainers"; +$lang->gitlab->branch->branchCreationLevelList[30] = "Developers + Maintainers"; +$lang->gitlab->branch->branchCreationLevelList[0] = "No one"; +$lang->gitlab->branch->emptyPrivNameError = "Branch cannot be empty."; +$lang->gitlab->branch->issetPrivNameError = "The protection branch already exists"; diff --git a/module/gitlab/lang/zh-cn.php b/module/gitlab/lang/zh-cn.php index d911572925..658367e491 100644 --- a/module/gitlab/lang/zh-cn.php +++ b/module/gitlab/lang/zh-cn.php @@ -30,6 +30,7 @@ $lang->gitlab->gitlabProject = "{$lang->gitlab->common}项目"; $lang->gitlab->browseProject = "{$lang->gitlab->common}项目列表"; $lang->gitlab->browseUser = "用户列表"; $lang->gitlab->browseGroup = "群组列表"; +$lang->gitlab->browseBranch = "GitLab分支列表"; $lang->gitlab->gitlabIssue = "{$lang->gitlab->common} issue"; $lang->gitlab->zentaoProduct = '禅道产品'; $lang->gitlab->objectType = '类型'; // task, bug, story @@ -43,8 +44,13 @@ $lang->gitlab->deleteGroup = '删除群组'; $lang->gitlab->createUser = '添加用户'; $lang->gitlab->editUser = '编辑用户'; $lang->gitlab->deleteUser = '删除用户'; +$lang->gitlab->createBranch = '添加分支'; $lang->gitlab->manageGroupMembers = '群组成员管理'; $lang->gitlab->createWebhook = '创建Webhook'; +$lang->gitlab->browseBranchPriv = '分支保护管理'; +$lang->gitlab->createBranchPriv = '创建分支保护'; +$lang->gitlab->editBranchPriv = '编辑分支保护'; +$lang->gitlab->deleteBranchPriv = '删除分支保护'; $lang->gitlab->id = 'ID'; $lang->gitlab->name = "{$lang->gitlab->common}名称"; @@ -53,10 +59,12 @@ $lang->gitlab->token = 'Token'; $lang->gitlab->defaultProject = '默认项目'; $lang->gitlab->private = 'MD5验证'; -$lang->gitlab->lblCreate = '添加GitLab服务器'; -$lang->gitlab->desc = '描述'; -$lang->gitlab->tokenFirst = 'Token不为空时,优先使用Token。'; -$lang->gitlab->tips = '使用密码时,请在GitLab全局安全设置中禁用"防止跨站点请求伪造"选项。'; +$lang->gitlab->lblCreate = '添加GitLab服务器'; +$lang->gitlab->desc = '描述'; +$lang->gitlab->tokenFirst = 'Token不为空时,优先使用Token。'; +$lang->gitlab->tips = '使用密码时,请在GitLab全局安全设置中禁用"防止跨站点请求伪造"选项。'; +$lang->gitlab->emptyError = "不能为空"; +$lang->gitlab->createSuccess = "创建成功"; $lang->gitlab->placeholder = new stdclass; $lang->gitlab->placeholder->name = ''; @@ -82,11 +90,15 @@ $lang->gitlab->apiError[0] = 'internal is not allowed in a private group.'; $lang->gitlab->apiError[1] = 'public is not allowed in a private group.'; $lang->gitlab->apiError[2] = 'is too short (minimum is 8 characters)'; $lang->gitlab->apiError[3] = "can contain only letters, digits, '_', '-' and '.'. Cannot start with '-', end in '.git' or end in '.atom'"; +$lang->gitlab->apiError[4] = 'Branch already exists'; +$lang->gitlab->apiError[5] = 'Failed to save group {:path=>["has already been taken"]}'; $lang->gitlab->errorLang[0] = '私有分组的项目,可见性级别不能设为内部。'; $lang->gitlab->errorLang[1] = '私有分组的项目,可见性级别不能设为公开。'; $lang->gitlab->errorLang[2] = '密码太短(最少8个字符)'; $lang->gitlab->errorLang[3] = "只能包含字母、数字、'.'-'和'.'。不能以'-'开头、以'.git'结尾或以'.atom'结尾。"; +$lang->gitlab->errorLang[4] = '分支名已存在。'; +$lang->gitlab->errorLang[5] = '保存失败,群组URL路径已经被使用。'; $lang->gitlab->project = new stdclass; $lang->gitlab->project->id = "项目ID"; @@ -122,7 +134,7 @@ $lang->gitlab->user->projectsLimit = "限制项目"; $lang->gitlab->user->canCreateGroup = "可创建组"; $lang->gitlab->user->external = "外部人员"; $lang->gitlab->user->externalTip = "除非明确授予访问权限,否则外部用户无法查看内部或私有项目。另外,外部用户无法创建项目,群组或个人代码片段。"; -$lang->gitlab->user->bind = "绑定禅道用户"; +$lang->gitlab->user->bind = "禅道用户"; $lang->gitlab->user->avatar = "头像"; $lang->gitlab->user->skype = "Skype"; $lang->gitlab->user->linkedin = "Linkedin"; @@ -150,6 +162,7 @@ $lang->gitlab->group->visibility = "可见性级别 $lang->gitlab->group->visibilityList['private'] = "私有(群组及其项目只能由成员查看)"; $lang->gitlab->group->visibilityList['internal'] = "内部(除外部用户外,任何登录用户均可查看该组和任何内部项目)"; $lang->gitlab->group->visibilityList['public'] = "公开(群组和任何公共项目可以在没有任何身份验证的情况下查看)"; +$lang->gitlab->group->permission = '许可'; $lang->gitlab->group->requestAccessEnabledTip = "允许用户请求访问(如果可见性是公开或内部的)"; $lang->gitlab->group->lfsEnabled = '大文件存储'; $lang->gitlab->group->lfsEnabledTip = "允许该组内的项目使用 Git LFS(可以在每个项目中覆盖此设置)"; @@ -171,3 +184,21 @@ $lang->gitlab->group->memberName = '账号'; $lang->gitlab->group->memberAccessLevel = '角色权限'; $lang->gitlab->group->memberExpiresAt = '过期时间'; $lang->gitlab->group->repeatError = "群组成员不能重复添加"; + +$lang->gitlab->branch = new stdclass(); +$lang->gitlab->branch->name = '分支名'; +$lang->gitlab->branch->from = '创建自'; +$lang->gitlab->branch->create = '创建'; +$lang->gitlab->branch->lastCommitter = '最后提交'; +$lang->gitlab->branch->lastCommittedDate = '最后修改时间'; +$lang->gitlab->branch->accessLevel = "分支保护列表"; +$lang->gitlab->branch->mergeAllowed = "允许合并到"; +$lang->gitlab->branch->pushAllowed = "允许推送到"; +$lang->gitlab->branch->placeholderSearch = "请输入分支名称"; +$lang->gitlab->branch->placeholderSelect = "请选择分支"; +$lang->gitlab->branch->confirmDelete = '确定删除分支保护?'; +$lang->gitlab->branch->branchCreationLevelList[40] = "维护者"; +$lang->gitlab->branch->branchCreationLevelList[30] = "开发者 + 维护者"; +$lang->gitlab->branch->branchCreationLevelList[0] = "禁止"; +$lang->gitlab->branch->emptyPrivNameError = "分支不能为空"; +$lang->gitlab->branch->issetPrivNameError = "已存在该保护分支"; diff --git a/module/gitlab/model.php b/module/gitlab/model.php index b2af4366f7..47cbbd899b 100644 --- a/module/gitlab/model.php +++ b/module/gitlab/model.php @@ -620,7 +620,7 @@ class gitlabModel extends model $order = explode('_', $orderBy); $keyword = urlencode($keyword); - $result = commonModel::httpWithHeader($host . "?private_token={$gitlab->token}&simple=true&&per_page={$pager->recPerPage}&order_by={$order[0]}&sort={$order[1]}&page={$pager->pageID}&search={$keyword}"); + $result = commonModel::httpWithHeader($host . "?private_token={$gitlab->token}&simple=true&&per_page={$pager->recPerPage}&order_by={$order[0]}&sort={$order[1]}&page={$pager->pageID}&search={$keyword}&search_namespaces=true"); $header = $result['header']; $recTotal = $header['X-Total']; @@ -896,6 +896,24 @@ class gitlabModel extends model return json_decode(commonModel::http($url, array(), $options = array(CURLOPT_CUSTOMREQUEST => 'DELETE'))); } + /** + * Create a gitab user by api. + * + * @param int $gitlabID + * @param int $projectID + * @param object $branch + * @access public + * @return object + */ + public function apiCreateBranch($gitlabID, $projectID, $branch) + { + if(empty($branch->branch) or empty($branch->ref)) return false; + + $apiRoot = $this->getApiRoot($gitlabID); + $url = sprintf($apiRoot, "/projects/{$projectID}/repository/branches"); + return json_decode(commonModel::http($url, $branch)); + } + /** * Get single project by API. * @@ -2032,15 +2050,15 @@ class gitlabModel extends model if(empty($project->path)) dao::$errors['path'][] = $this->lang->gitlab->project->emptyPathError; if(dao::isError()) return false; - $reponse = $this->apiCreateProject($gitlabID, $project); + $response = $this->apiCreateProject($gitlabID, $project); - if(!empty($reponse->id)) + if(!empty($response->id)) { - $this->loadModel('action')->create('gitlabproject', $reponse->id, 'created', '', $reponse->name); + $this->loadModel('action')->create('gitlabproject', $response->id, 'created', '', $response->name); return true; } - return $this->apiErrorHandling($reponse); + return $this->apiErrorHandling($response); } /** @@ -2056,15 +2074,15 @@ class gitlabModel extends model if(empty($project->name)) dao::$errors['name'][] = $this->lang->gitlab->project->emptyNameError; if(dao::isError()) return false; - $reponse = $this->apiUpdateProject($gitlabID, $project); + $response = $this->apiUpdateProject($gitlabID, $project); - if(!empty($reponse->id)) + if(!empty($response->id)) { $this->loadModel('action')->create('gitlabproject', $project->id, 'edited', '', $project->name); return true; } - return $this->apiErrorHandling($reponse); + return $this->apiErrorHandling($response); } /** @@ -2101,11 +2119,11 @@ class gitlabModel extends model } } - $reponse = $this->apiCreateUser($gitlabID, $user); + $response = $this->apiCreateUser($gitlabID, $user); - if(!empty($reponse->id)) + if(!empty($response->id)) { - $this->loadModel('action')->create('gitlabuser', $reponse->id, 'created', '', $reponse->name); + $this->loadModel('action')->create('gitlabuser', $response->id, 'created', '', $response->name); /* Bind user. */ if($user->account) @@ -2114,13 +2132,13 @@ class gitlabModel extends model $userBind->providerID = $gitlabID; $userBind->providerType = 'gitlab'; $userBind->account = $user->account; - $userBind->openID = $reponse->id; + $userBind->openID = $response->id; $this->dao->insert(TABLE_OAUTH)->data($userBind)->exec(); } return true; } - return $this->apiErrorHandling($reponse); + return $this->apiErrorHandling($response); } /** @@ -2161,14 +2179,14 @@ class gitlabModel extends model } } - $reponse = $this->apiUpdateUser($gitlabID, $user); + $response = $this->apiUpdateUser($gitlabID, $user); - if(!empty($reponse->id)) + if(!empty($response->id)) { - $this->loadModel('action')->create('gitlabuser', $reponse->id, 'edited', '', $reponse->name); + $this->loadModel('action')->create('gitlabuser', $response->id, 'edited', '', $response->name); /* Delete old bind. */ - $this->dao->delete()->from(TABLE_OAUTH)->where('providerType')->eq('gitlab')->andWhere('providerID')->eq($gitlabID)->andWhere('openID')->eq($reponse->id)->andWhere('account')->ne($user->account)->exec(); + $this->dao->delete()->from(TABLE_OAUTH)->where('providerType')->eq('gitlab')->andWhere('providerID')->eq($gitlabID)->andWhere('openID')->eq($response->id)->andWhere('account')->ne($user->account)->exec(); /* Bind user. */ if($user->account && $changeBind) { @@ -2176,13 +2194,13 @@ class gitlabModel extends model $userBind->providerID = $gitlabID; $userBind->providerType = 'gitlab'; $userBind->account = $user->account; - $userBind->openID = $reponse->id; + $userBind->openID = $response->id; $this->dao->replace(TABLE_OAUTH)->data($userBind)->exec(); } return true; } - return $this->apiErrorHandling($reponse); + return $this->apiErrorHandling($response); } /** @@ -2200,15 +2218,15 @@ class gitlabModel extends model if(empty($group->path)) dao::$errors['path'][] = $this->lang->gitlab->group->path . $this->lang->gitlab->group->emptyError; if(dao::isError()) return false; - $reponse = $this->apiCreateGroup($gitlabID, $group); + $response = $this->apiCreateGroup($gitlabID, $group); - if(!empty($reponse->id)) + if(!empty($response->id)) { - $this->loadModel('action')->create('gitlabgroup', $reponse->id, 'created', '', $reponse->name); + $this->loadModel('action')->create('gitlabgroup', $response->id, 'created', '', $response->name); return true; } - return $this->apiErrorHandling($reponse); + return $this->apiErrorHandling($response); } /** @@ -2225,41 +2243,68 @@ class gitlabModel extends model if(empty($group->name)) dao::$errors['name'][] = $this->lang->gitlab->group->name . $this->lang->gitlab->group->emptyError; if(dao::isError()) return false; - $reponse = $this->apiUpdateGroup($gitlabID, $group); + $response = $this->apiUpdateGroup($gitlabID, $group); - if(!empty($reponse->id)) + if(!empty($response->id)) { - $this->loadModel('action')->create('gitlabgroup', $reponse->id, 'edited', '', $reponse->name); + $this->loadModel('action')->create('gitlabgroup', $response->id, 'edited', '', $response->name); return true; } - return $this->apiErrorHandling($reponse); + return $this->apiErrorHandling($response); + } + + /** + * Create a gitlab branch. + * + * @param int $gitlabID + * @param int $projectID + * @access public + * @return bool + */ + public function createBranch($gitlabID, $projectID) + { + $branch = fixer::input('post')->get(); + + if(empty($branch->branch)) dao::$errors['branch'][] = $this->lang->gitlab->branch->name . $this->lang->gitlab->emptyError; + if(empty($branch->ref)) dao::$errors['ref'][] = $this->lang->gitlab->branch->from . $this->lang->gitlab->emptyError; + if(dao::isError()) return false; + + $response = $this->apiCreateBranch($gitlabID, $projectID, $branch); + + if(!empty($response->name)) + { + $this->loadModel('action')->create('gitlabbranch', 0, 'created', '', $response->name); + return true; + } + + return $this->apiErrorHandling($response); } /** * Api error handling. * - * @param object $reponse + * @param object $response * @access public * @return bool */ - public function apiErrorHandling($reponse) + public function apiErrorHandling($response) { - if(!empty($reponse->error)) + if(!empty($response->error)) { - dao::$errors[] = $reponse->error; + dao::$errors[] = $response->error; return false; } - if(!empty($reponse->message)) + if(!empty($response->message)) { - if(is_string($reponse->message)) + if(is_string($response->message)) { - $errorKey = array_search($reponse->message, $this->lang->gitlab->apiError); - dao::$errors[] = $errorKey === false ? $reponse->message : zget($this->lang->gitlab->errorLang, $errorKey); + $errorKey = array_search($response->message, $this->lang->gitlab->apiError); + dao::$errors[] = $errorKey === false ? $response->message : zget($this->lang->gitlab->errorLang, $errorKey); } else { - foreach($reponse->message as $field => $fieldErrors) + foreach($response->message as $field => $fieldErrors) { foreach($fieldErrors as $error) { @@ -2270,7 +2315,7 @@ class gitlabModel extends model } } - if(!$reponse) dao::$errors[] = false; + if(!$response) dao::$errors[] = false; return false; } @@ -2287,4 +2332,142 @@ class gitlabModel extends model ->andWhere('path')->in($projectIDs) ->fetchPairs('path', 'product'); } + + /** + * Get protect branches of one project. + * + * @param int $gitlabID + * @param int $projectID + * @param string $keyword + * @param string $orderBy + * @access public + * @return array + */ + public function apiGetBranchPrivs($gitlabID, $projectID, $keyword = '', $orderBy = 'id_desc') + { + $keyword = urlencode($keyword); + $url = sprintf($this->getApiRoot($gitlabID), "/projects/$projectID/protected_branches"); + $branches = json_decode(commonModel::http($url)); + + if(!is_array($branches)) return $branches; + /* Parse order string. */ + $order = explode('_', $orderBy); + + $newBranches = array(); + foreach($branches as $branch) + { + if(empty($keyword) || stristr($branch->name, $keyword)) $newBranches[$branch->{$order[0]}] = $branch; + } + + if($order[1] == 'asc') ksort($newBranches); + if($order[1] == 'desc') krsort($newBranches); + + return $newBranches; + } + + /** + * Get single protct branch by API. + * + * @param int $gitlabID + * @param int $projectID + * @param string $branch + * @access public + * @return object + */ + public function apiGetSingleBranchPriv($gitlabID, $projectID, $branch) + { + if(empty($gitlabID)) return false; + $url = sprintf($this->getApiRoot($gitlabID), "/projects/$projectID/protected_branches/$branch"); + return json_decode(commonModel::http($url)); + } + + /** + * Create gitlab potect branch. + * + * @param int $gitlabID + * @param int $projectID + * @param string $branch + * @access public + * @return bool + */ + public function createBranchPriv($gitlabID, $projectID, $branch = '') + { + $priv = fixer::input('post')->get(); + if(empty($priv->name)) dao::$errors['name'][] = $this->lang->gitlab->branch->emptyPrivNameError; + $singleBranch = $this->apiGetSingleBranchPriv($gitlabID, $projectID, $priv->name); + if(empty($branch) && !empty($singleBranch->id)) dao::$errors['name'][] = $this->lang->gitlab->branch->issetPrivNameError; + if(dao::isError()) return false; + if(!empty($branch) && !empty($singleBranch->id)) $this->apiDeleteBranchPriv($gitlabID, $projectID, $branch); + + $response = $this->apiCreateBranchPriv($gitlabID, $projectID, $priv); + + if(!empty($response->id)) + { + $action = empty($branch) ? 'created' : 'edited'; + $this->loadModel('action')->create('gitlabbranchpriv', $response->id, $action, '', $response->name); + return true; + } + + return $this->apiErrorHandling($response); + } + + /** + * Create a gitab protect branch by api. + * + * @param int $gitlabID + * @param int $projectID + * @param object $priv + * @access public + * @return object + */ + public function apiCreateBranchPriv($gitlabID, $projectID, $priv) + { + if(empty($gitlabID)) return false; + if(empty($priv->name)) return false; + $url = sprintf($this->getApiRoot($gitlabID), "/projects/" . $projectID . '/protected_branches'); + return json_decode(commonModel::http($url, $priv)); + } + + /** + * Delete a gitab protect branch by api. + * + * @param int $gitlabID + * @param int $projectID + * @param string $branch + * @access public + * @return object + */ + public function apiDeleteBranchPriv($gitlabID, $projectID, $branch) + { + if(empty($gitlabID)) return false; + $apiRoot = $this->getApiRoot($gitlabID); + $url = sprintf($apiRoot, "/projects/{$projectID}/protected_branches/{$branch}"); + return json_decode(commonModel::http($url, array(), $options = array(CURLOPT_CUSTOMREQUEST => 'DELETE'))); + } + + /** + * Check access level. + * + * @param array $accessLevels + * @access public + * @return int + */ + public function checkAccessLevel($accessLevels) + { + $noAccess = 0; + $developerAccess = 30; + $maintainerAccess = 40; + if(is_array($accessLevels)) + { + $levels = array(); + foreach($accessLevels as $level) + { + if(is_array($level)) $level = (object)$level; + $levels[] = isset($level->access_level) ? (int)$level->access_level : $maintainerAccess; + } + if(in_array($noAccess, $levels)) return $noAccess; + if(in_array($developerAccess, $levels)) return $developerAccess; + } + return $maintainerAccess; + } } diff --git a/module/gitlab/view/binduser.html.php b/module/gitlab/view/binduser.html.php index 107697b1e2..381867a303 100644 --- a/module/gitlab/view/binduser.html.php +++ b/module/gitlab/view/binduser.html.php @@ -21,7 +21,7 @@ gitlab->gitlabAccount;?> - gitlab->zentaoAccount;?> + gitlab->zentaoAccount;?> gitlab->bindingStatus;?> @@ -51,7 +51,8 @@ id]", $userPairs, $gitlabUser->zentaoAccount, "class='form-control select chosen'" );?> zentaoAccount])):?> - zentaoAccount, ''))):?> + zentaoAccount, '');?> + gitlab->binded;?> ' . $lang->gitlab->bindedError . '';?> diff --git a/module/gitlab/view/browse.html.php b/module/gitlab/view/browse.html.php index c32e725dbb..b682227146 100644 --- a/module/gitlab/view/browse.html.php +++ b/module/gitlab/view/browse.html.php @@ -42,16 +42,16 @@ $gitlab): ?> - ">name;?> + ">name;?> url;?> isAdminToken) ? '' : 'disabled'; - common::printLink('gitlab', 'browseProject', "gitlabID=$id", " ", '',"title={$lang->gitlab->browseProject} class='btn btn-primary'"); - common::printLink('gitlab', 'browseGroup', "gitlabID=$id", " ", '', "title={$lang->gitlab->browseGroup} class='btn btn-primary'"); - common::printLink('gitlab', 'edit', "gitlabID=$id", " ", '',"title={$lang->gitlab->edit} class='btn btn-primary'"); - common::printLink('gitlab', 'browseUser', "gitlabID=$id", " ", '', "title={$lang->gitlab->browseUser} class='btn {$disabled}' ,'disabled'"); - common::printLink('gitlab', 'bindUser', "id=$id", " ", '', "title={$lang->gitlab->bindUser} class='btn {$disabled}' ,'disabled'"); + common::printLink('gitlab', 'browseProject', "gitlabID=$id", " ", '',"title='{$lang->gitlab->browseProject}' class='btn btn-primary'"); + common::printLink('gitlab', 'browseGroup', "gitlabID=$id", " ", '', "title='{$lang->gitlab->browseGroup}' class='btn btn-primary'"); + common::printLink('gitlab', 'edit', "gitlabID=$id", " ", '',"title='{$lang->gitlab->edit}' class='btn btn-primary'"); + common::printLink('gitlab', 'browseUser', "gitlabID=$id", " ", '', "title='{$lang->gitlab->browseUser}' class='btn {$disabled}' ,'disabled'"); + common::printLink('gitlab', 'bindUser', "id=$id", " ", '', "title='{$lang->gitlab->bindUser}' class='btn {$disabled}' ,'disabled'"); if(common::hasPriv('gitlab', 'delete')) echo html::a($this->createLink('gitlab', 'delete', "gitlabID=$id"), '', 'hiddenwin', "title='{$lang->gitlab->delete}' class='btn'"); ?> diff --git a/module/gitlab/view/browsebranch.html.php b/module/gitlab/view/browsebranch.html.php new file mode 100644 index 0000000000..dd6448fb4f --- /dev/null +++ b/module/gitlab/view/browsebranch.html.php @@ -0,0 +1,61 @@ + + * @package gitlab + * @version $Id$ + * @link http://www.zentao.net + */ +?> + +recTotal}&recPerPage={$pager->recPerPage}&pageID=1")?> + + + +
    +

    + noData;?> + + createLink('gitlab', 'createBranch', "gitlabID=$gitlabID&projectID=$projectID"), " " . $lang->gitlab->createBranch, '', "class='btn btn-info'");?> + +

    +
    + +
    +
    + + recTotal}&recPerPage={$pager->recPerPage}&pageID={$pager->pageID}";?> + + + + + + + + + $gitlabBranch): ?> + + + + + + + +
    gitlab->branch->name);?>gitlab->branch->lastCommitter;?>gitlab->branch->lastCommittedDate);?>
    name;?>lastCommitter;?>lastCommittedDate?>
    + + + +
    +
    + + diff --git a/module/gitlab/view/browsebranchpriv.html.php b/module/gitlab/view/browsebranchpriv.html.php new file mode 100644 index 0000000000..7023020575 --- /dev/null +++ b/module/gitlab/view/browsebranchpriv.html.php @@ -0,0 +1,79 @@ + + * @package gitlab + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + + +
    +

    + noData;?> + + createLink('gitlab', 'createBranchPriv', "gitlabID=$gitlabID&projectID=$projectID"), " " . $lang->gitlab->createBranchPriv, '', "class='btn btn-info'");?> + +

    +
    + +
    +
    + + recTotal}&recPerPage={$pager->recPerPage}&pageID={$pager->pageID}";?> + + + + + + + + + + $branch): ?> + merge_access_level = $this->gitlab->checkAccessLevel($branch->merge_access_levels); ?> + push_access_level = $this->gitlab->checkAccessLevel($branch->push_access_levels); ?> + + + + + + + + +
    gitlab->branch->name);?>gitlab->branch->mergeAllowed;?>gitlab->branch->pushAllowed;?>actions;?>
    name;?>merge_access_level];?>push_access_level];?> + name", " ", '', "title={$lang->gitlab->editBranchPriv} class='btn btn-primary'"); + if(common::hasPriv('gitlab', 'deleteBranchPriv')) echo html::a($this->createLink('gitlab', 'deleteBranchPriv', "gitlabID=$gitlabID&projectID=$projectID&branch=$branch->name"), '', 'hiddenwin', "title='{$lang->gitlab->deleteBranchPriv}' class='btn'"); + ?> +
    + + + +
    +
    + + diff --git a/module/gitlab/view/browsegroup.html.php b/module/gitlab/view/browsegroup.html.php index 77302dc4a0..30e60c5187 100644 --- a/module/gitlab/view/browsegroup.html.php +++ b/module/gitlab/view/browsegroup.html.php @@ -54,8 +54,8 @@ created_at, 0, 10);?> id", " ", '',"title={$lang->gitlab->group->manageMembers} class='btn btn-primary'"); - common::printLink('gitlab', 'editGroup', "gitlabID=$gitlabID&groupID=$gitlabGroup->id", " ", '', "title={$lang->gitlab->group->edit} class='btn btn-primary'"); + common::printLink('gitlab', 'manageGroupMembers', "gitlabID=$gitlabID&groupID=$gitlabGroup->id", " ", '',"title='{$lang->gitlab->group->manageMembers}' class='btn btn-primary'"); + common::printLink('gitlab', 'editGroup', "gitlabID=$gitlabID&groupID=$gitlabGroup->id", " ", '', "title='{$lang->gitlab->group->edit}' class='btn btn-primary'"); if(common::hasPriv('gitlab', 'delete')) echo html::a($this->createLink('gitlab', 'deleteGroup', "gitlabID=$gitlabID&groupID=$gitlabGroup->id"), '', 'hiddenwin', "title='{$lang->gitlab->deleteGroup}' class='btn'"); ?> diff --git a/module/gitlab/view/browseproject.html.php b/module/gitlab/view/browseproject.html.php index 40eea5877c..ab0bcfadad 100644 --- a/module/gitlab/view/browseproject.html.php +++ b/module/gitlab/view/browseproject.html.php @@ -15,7 +15,7 @@