diff --git a/config/zentaopms.php b/config/zentaopms.php index 1c33bb6d96..646f396d0a 100644 --- a/config/zentaopms.php +++ b/config/zentaopms.php @@ -377,6 +377,7 @@ $config->objectTables['gitlab'] = TABLE_PIPELINE; $config->objectTables['jebkins'] = TABLE_PIPELINE; $config->objectTables['stage'] = TABLE_STAGE; $config->objectTables['apistruct'] = TABLE_APISTRUCT; +$config->objectTables['repo'] = TABLE_REPO; $config->newFeatures = array('introduction', 'tutorial', 'youngBlueTheme', 'visions'); @@ -388,3 +389,5 @@ $config->programPriv->scrum = array('story', 'projectstory', 'projectrelease $config->programPriv->waterfall = array_merge($config->programPriv->scrum, array('task', 'workestimation', 'durationestimation', 'budget', 'programplan', 'review', 'reviewissue', 'weekly', 'cm', 'milestone', 'design', 'issue', 'risk', 'opportunity', 'measrecord', 'auditplan', 'trainplan', 'gapanalysis', 'pssp', 'researchplan', 'researchreport')); $config->waterfallModules = array('workestimation', 'durationestimation', 'budget', 'programplan', 'review', 'reviewissue', 'weekly', 'cm', 'milestone', 'design', 'opportunity', 'auditplan', 'trainplan', 'gapanalysis', 'pssp', 'researchplan', 'researchreport'); + +$config->showMainMenu = true; diff --git a/db/update17.3.sql b/db/update17.3.sql new file mode 100644 index 0000000000..a000ab61d5 --- /dev/null +++ b/db/update17.3.sql @@ -0,0 +1,3 @@ +ALTER TABLE `zt_mr` CHANGE COLUMN `gitlabID` `hostID` mediumint(8) UNSIGNED NOT NULL AFTER `id`; +ALTER TABLE `zt_mr` MODIFY COLUMN `sourceProject` varchar(50) NOT NULL AFTER `hostID`; +ALTER TABLE `zt_mr` MODIFY COLUMN `targetProject` varchar(50) NOT NULL AFTER `sourceBranch`; diff --git a/db/zentao.sql b/db/zentao.sql index 808fa6805e..ad5feb37ee 100755 --- a/db/zentao.sql +++ b/db/zentao.sql @@ -955,10 +955,10 @@ CREATE TABLE IF NOT EXISTS `zt_module` ( -- DROP TABLE IF EXISTS `zt_mr`; CREATE TABLE IF NOT EXISTS `zt_mr` ( `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT, - `gitlabID` mediumint(8) unsigned NOT NULL, - `sourceProject` int unsigned NOT NULL, + `hostID` mediumint(8) unsigned NOT NULL, + `sourceProject` varchar(50) NOT NULL, `sourceBranch` varchar(100) NOT NULL, - `targetProject` int unsigned NOT NULL, + `targetProject` varchar(50) NOT NULL, `targetBranch` varchar(100) NOT NULL, `mriid` int unsigned NOT NULL, `title` varchar(255) NOT NULL, diff --git a/framework/base/router.class.php b/framework/base/router.class.php index 039c2edd2a..60ef97b0b1 100644 --- a/framework/base/router.class.php +++ b/framework/base/router.class.php @@ -658,6 +658,20 @@ class baseRouter $_POST = validater::filterSuper($_POST); $_GET = validater::filterSuper($_GET); $_COOKIE = validater::filterSuper($_COOKIE); + + /* Filter common get and cookie vars. */ + if($this->config->framework->filterParam == 2) + { + global $filter; + foreach($filter->default->get as $key => $rules) + { + if(isset($_GET[$key]) and !validater::checkByRule($_GET[$key], $rules)) unset($_GET[$key]); + } + foreach($filter->default->cookie as $key => $rules) + { + if(isset($_COOKIE[$key]) and !validater::checkByRule($_COOKIE[$key], $rules)) unset($_COOKIE[$key]); + } + } } /** diff --git a/lib/scm/gitea.class.php b/lib/scm/gitea.class.php new file mode 100644 index 0000000000..b01638fa87 --- /dev/null +++ b/lib/scm/gitea.class.php @@ -0,0 +1,815 @@ +client = $client; + $this->root = rtrim($root, '/') . '/'; + $this->token = $password; + $this->branch = isset($_COOKIE['repoBranch']) ? $_COOKIE['repoBranch'] : 'HEAD'; + } + + /** + * List files. + * + * @param string $path + * @param string $revision + * @access public + * @return array + */ + public function ls($path, $revision = 'HEAD') + { + if(!scm::checkRevision($revision)) return array(); + $api = "contents"; + $path = ltrim($path, '/'); + if($path) $api .= "/$path"; + + $param = new stdclass(); + $param->ref = $revision; + $param->recursive = 0; + if(!empty($this->branch)) $param->ref = $this->branch; + + $list = $this->fetch($api, $param, true); + if(empty($list)) return array(); + + $infos = array(); + foreach($list as $file) + { + if(!isset($file->type)) continue; + + $info = new stdClass(); + $info->name = $file->name; + $info->kind = $file->type; + + if($file->type == 'file') + { + $file = $this->files($file->path, $this->branch); + + $info->revision = zget($file, 'revision', ''); + $info->comment = zget($file, 'comment', ''); + $info->account = zget($file, 'committer', ''); + $info->date = zget($file, 'date', ''); + $info->size = zget($file, 'size', ''); + } + else + { + $commits = $this->getCommitsByPath($file->path, '', '', 1, 1); + if(empty($commits) or !is_array($commits)) continue; + $commit = $commits[0]; + + $info->revision = $commit->sha; + $info->comment = $commit->commit->message; + $info->account = $commit->commit->author->name; + $info->date = date('Y-m-d H:i:s', strtotime($commit->commit->author->date)); + $info->size = 0; + } + + $infos[] = $info; + unset($info); + } + + /* Sort by kind */ + foreach($infos as $key => $info) $kinds[$key] = $info->kind; + if($infos) array_multisort($kinds, SORT_ASC, $infos); + return $infos; + } + + /** + * Get files info. + * + * The API path requested is: "GET /projects/:id/repository/files/:file_path". + * Known issue of GitLab API: if a '%' in 'file_path', GitLab API will show a error 'file_path should be a valid file path'. + * + * @param string $path + * @param string $ref + * @access public + * @return object + * @doc https://docs.gitea.com/ee/api/repository_files.html + */ + public function files($path, $ref = 'master') + { + $path = urlencode($path); + $api = "contents/$path"; + $file = $this->fetch($api, array('ref' => $ref)); + if(!isset($file->name)) return false; + + $commits = $this->getCommitsByPath($path, '', '', 1, 1); + $file->revision = $file->sha; + $file->size = $this->formatBytes($file->size); + + if(!empty($commits)) + { + $commit = $commits[0]; + + $file->revision = $commit->sha; + $file->committer = $commit->commit->author->name; + $file->comment = $commit->commit->message; + $file->date = date('Y-m-d H:i:s', strtotime($commit->commit->author->date)); + } + + return $file; + } + + /** + * Get tags + * + * @param string $path + * @param string $revision + * @access public + * @return array + */ + public function tags($path, $revision = 'HEAD') + { + $api = "tags"; + $tags = array(); + + $params = array(); + $params['limit'] = $this->pageLimit; + for($page = 1; true; $page ++) + { + $params['page'] = $page; + $list = $this->fetch($api, $params); + if(empty($list) or $list == '[]') break; + + foreach($list as $tag) $tags[] = $tag->name; + if(count($list) < $params['limit']) break; + } + + return $tags; + } + + /** + * Get branches. + * + * @access public + * @return array + */ + public function branch() + { + /* Max size of limit in gitea API is 50. */ + $params = array(); + $params['limit'] = $this->pageLimit; + + /* Get default branch. */ + $project = $this->fetch(''); + $defaultBranch = $project->default_branch; + + $branches = array(); + $default = array(); + for($page = 1; true; $page ++) + { + $params['page'] = $page; + $branchList = $this->fetch("branches", $params); + if(empty($branchList)) break; + + foreach($branchList as $branch) + { + if(!isset($branch->name)) continue; + if($branch->name == $defaultBranch) + { + $default[$branch->name] = $branch->name; + } + else + { + $branches[$branch->name] = $branch->name; + } + } + + /* Last page. */ + if(count($branchList) < $params['limit']) break; + } + + if(empty($branches) and empty($default)) $branches['master'] = 'master'; + asort($branches); + + $branches = $default + $branches; + return $branches; + } + + /** + * Get last log. + * + * @param string $path + * @param int $count + * @access public + * @return array + */ + public function getLastLog($path, $count = 10) + { + return $this->log($path); + } + + /** + * Get logs. + * + * @param string $path + * @param string $fromRevision + * @param string $toRevision + * @param int $count + * @access public + * @return array + */ + public function log($path, $fromRevision = 0, $toRevision = 'HEAD', $count = 0) + { + if(!scm::checkRevision($fromRevision)) return array(); + if(!scm::checkRevision($toRevision)) return array(); + + $path = ltrim($path, DIRECTORY_SEPARATOR); + $count = $count == 0 ? '' : "-n $count"; + $list = $this->getCommitsByPath($path, $fromRevision, $toRevision, 1, 1); + foreach($list as $commit) + { + if(isset($commit->sha)) $commit->diffs = $this->getFilesByCommit($commit->sha); + } + + return $this->parseLog($list); + } + + /** + * Blame file + * + * @param string $path + * @param string $revision + * @access public + * @return array + */ + public function blame($path, $revision) + { + return array(); + } + + /** + * Diff file. + * + * @param string $path + * @param string $fromRevision + * @param string $toRevision + * @param string $fromProject + * @param string $extra + * @access public + * @return array + */ + public function diff($path, $fromRevision, $toRevision, $fromProject = '', $extra = '') + { + if(!scm::checkRevision($fromRevision) and $extra != 'isBranchOrTag') return array(); + if(!scm::checkRevision($toRevision) and $extra != 'isBranchOrTag') return array(); + + $diffApi = "{$this->root}git/commits/$toRevision.diff?token={$this->token}"; + $diffs = commonModel::http($diffApi); + $lines = explode("\n", $diffs); + return $lines; + } + + /** + * Cat file. + * + * @param string $entry + * @param string $revision + * @access public + * @return string + */ + public function cat($entry, $revision = 'HEAD') + { + if(!scm::checkRevision($revision)) return false; + if($revision == 'HEAD' and $this->branch) $revision = $this->branch; + $file = $this->files($entry, $revision); + return base64_decode($file->content); + } + + /** + * Get info. + * + * @param string $entry + * @param string $revision + * @access public + * @return object + */ + public function info($entry, $revision = 'HEAD') + { + if(!scm::checkRevision($revision)) return false; + + $info = new stdclass(); + $info->kind = 'dir'; + $info->path = $entry; + $info->revision = $revision; + $info->root = ''; + if($revision == 'HEAD' and $this->branch) $info->revision = $this->branch; + + if($entry) + { + $parent = dirname($entry); + if($parent == '.') $parent = '/'; + if($parent == '') $parent = '/'; + $list = $this->tree($parent, 0); + $file = new stdclass(); + + foreach($list as $node) if($node->path == $entry) $file = $node; + + $commits = $this->getCommitsByPath($entry); + + if(!empty($commits)) $file->revision = zget($commits[0], 'id', ''); + $info->kind = (isset($file->type) and $file->type == 'tree') ? 'dir' : 'file'; + } + + return $info; + } + + /** + * Exec git cmd. + * + * @param string $cmd + * @access public + * @todo Exec commands by gitea api. + * @return array + */ + public function exec($cmd) + { + return execCmd(escapeCmd("$this->client $cmd"), 'array'); + } + + /** + * Parse diff. + * + * @param array $lines + * @access public + * @return array + */ + public function parseDiff($lines) + { + if(empty($lines)) return array(); + $diffs = array(); + $num = count($lines); + $endLine = end($lines); + if(strpos($endLine, '\ No newline at end of file') === 0) $num -= 1; + + $newFile = false; + $allFiles = array(); + for($i = 0; $i < $num; $i ++) + { + $diffFile = new stdclass(); + if(strpos($lines[$i], "diff --git ") === 0) + { + $fileInfo = explode(' ',$lines[$i]); + $fileName = substr($fileInfo[2], strpos($fileInfo[2], '/') + 1); + + /* Prevent duplicate display of files. */ + if(in_array($fileName, $allFiles)) continue; + $allFiles[] = $fileName; + + $diffFile->fileName = $fileName; + for($i++; $i < $num; $i ++) + { + $diff = new stdclass(); + /* Fix bug #1757. */ + if($lines[$i] == '+++ /dev/null') $newFile = true; + if(strpos($lines[$i], '+++', 0) !== false) continue; + if(strpos($lines[$i], '---', 0) !== false) continue; + if(strpos($lines[$i], '======', 0) !== false) continue; + if(preg_match('/^@@ -(\\d+)(,(\\d+))?\\s+\\+(\\d+)(,(\\d+))?\\s+@@/A', $lines[$i])) + { + $startLines = trim(str_replace(array('@', '+', '-'), '', $lines[$i])); + list($oldStartLine, $newStartLine) = explode(' ', $startLines); + list($diff->oldStartLine) = explode(',', $oldStartLine); + list($diff->newStartLine) = explode(',', $newStartLine); + $oldCurrentLine = $diff->oldStartLine; + $newCurrentLine = $diff->newStartLine; + if($newFile) + { + $oldCurrentLine = $diff->newStartLine; + $newCurrentLine = $diff->oldStartLine; + } + $newLines = array(); + for($i++; $i < $num; $i ++) + { + if(preg_match('/^@@ -(\\d+)(,(\\d+))?\\s+\\+(\\d+)(,(\\d+))?\\s+@@/A', $lines[$i])) + { + $i --; + break; + } + if(strpos($lines[$i], "diff --git ") === 0) break; + + $line = $lines[$i]; + if(strpos($line, '\ No newline at end of file') === 0)continue; + $sign = empty($line) ? '' : $line[0]; + if($sign == '-' and $newFile) $sign = '+'; + $type = $sign != '-' ? $sign == '+' ? 'new' : 'all' : 'old'; + if($sign == '-' || $sign == '+') + { + $line = substr_replace($line, ' ', 1, 0); + if($newFile) $line = preg_replace('/^\-/', '+', $line); + } + + $newLine = new stdclass(); + $newLine->type = $type; + $newLine->oldlc = $type != 'new' ? $oldCurrentLine : ''; + $newLine->newlc = $type != 'old' ? $newCurrentLine : ''; + $newLine->line = htmlSpecialString($line); + + if($type != 'new') $oldCurrentLine++; + if($type != 'old') $newCurrentLine++; + + $newLines[] = $newLine; + } + + $diff->lines = $newLines; + $diffFile->contents[] = $diff; + } + + if(isset($lines[$i]) and strpos($lines[$i], "diff --git ") === 0) + { + $i --; + $newFile = false; + break; + } + } + $diffs[] = $diffFile; + } + } + return $diffs; + } + + /** + * Get commit count. + * + * @param int $commits + * @param string $lastVersion + * @access public + * @return int + */ + public function getCommitCount($commits = 0, $lastVersion = '') + { + if(!scm::checkRevision($lastVersion)) return false; + + chdir($this->root); + $revision = $this->branch ? $this->branch : 'HEAD'; + return execCmd(escapeCmd("$this->client rev-list --count $revision -- ./"), 'string'); + } + + /** + * Get first revision. + * + * @access public + * @return string + */ + public function getFirstRevision() + { + chdir($this->root); + $list = execCmd(escapeCmd("$this->client rev-list --reverse HEAD -- ./"), 'array'); + return $list[0]; + } + + /** + * Get latest revision + * + * @access public + * @return string + */ + public function getLatestRevision() + { + chdir($this->root); + $revision = $this->branch ? $this->branch : 'HEAD'; + $list = execCmd(escapeCmd("$this->client rev-list -1 $revision -- ./"), 'array'); + return $list[0]; + } + + /** + * Get commits. + * + * @param string $version + * @param int $count + * @param string $branch + * @access public + * @return array + */ + public function getCommits($version = '', $count = 0, $branch = '') + { + if(!scm::checkRevision($version)) return array(); + $api = "commits"; + $commits = array(); + $files = array(); + + if(empty($count)) $count = $this->pageLimit; + + if(!empty($version) and $count == 1) + { + $commits = $this->fetch($api, array('limit' => 1, 'sha' => $version)); + $commit = $commits[0]; + if(isset($commit->sha)) + { + $log = new stdclass; + $log->committer = $commit->commit->author->name; + $log->revision = $commit->sha; + $log->comment = $commit->commit->message; + $log->time = date('Y-m-d H:i:s', strtotime($commit->commit->author->date)); + + $commits[$commit->sha] = $log; + $files[$commit->sha] = $this->getFilesByCommit($log->revision); + + return array('commits' => $commits, 'files' => $files); + } + } + + $params['sha'] = $branch; + if($version and $version != 'HEAD') + { + /* Get since param. */ + if(substr($version, 0, 5) == 'since') + { + $since = true; + $version = substr($version, 5); + } + + $committedDate = $this->getCommittedDate($version); + if(!$committedDate) return array('commits' => array(), 'files' => array()); + + if(!empty($since)) + { + $params['since'] = $committedDate; + } + else + { + $params['until'] = $committedDate; + } + } + + $list = $this->fetch($api, $params); + + foreach($list as $commit) + { + if(!isset($commit->commit) or !is_object($commit->commit)) continue; + + $log = new stdclass; + $log->committer = $commit->commit->author->name; + $log->revision = $commit->sha; + $log->comment = $commit->commit->message; + $log->time = date('Y-m-d H:i:s', strtotime($commit->commit->author->date)); + + $commits[$commit->sha] = $log; + $files[$commit->sha] = $this->getFilesByCommit($log->revision); + } + + return array('commits' => $commits, 'files' => $files); + } + + /** + * getCommit + * + * @param int $sha + * @access public + * @return void + */ + public function getCommittedDate($sha) + { + if(!scm::checkRevision($sha)) return null; + if(!$sha or $sha == 'HEAD') return date('c'); + + global $dao; + $time = $dao->select('time')->from(TABLE_REPOHISTORY)->where('revision')->eq($sha)->fetch('time'); + if($time) return date('c', strtotime($time)); + + $params = array(); + $params['sha'] = $sha; + $params['limit'] = 1; + $result = $this->fetch("commits", $params); + return (isset($resulti[0]->created)) ? date('Y-m-d H:i:s', strtotime($result->created)) : false; + } + + /** + * Get commits by path. + * + * @param string $path + * @param string $fromRevision + * @param string $toRevision + * @param int $perPage + * @access public + * @return array + */ + public function getCommitsByPath($path, $fromRevision = '', $toRevision = '', $perPage = 0, $limit = 0) + { + $path = ltrim($path, DIRECTORY_SEPARATOR); + $api = "commits"; + + if(!$limit) $limit = $this->pageLimit; + $param = new stdclass(); + $param->path = urldecode($path); + $param->limit = $limit; + $param->sha = ($toRevision != 'HEAD' and $toRevision) ? $toRevision : $this->branch; + + if($perPage) $param->page = $perPage; + return $this->fetch($api, $param); + } + + /** + * Get diff files by reviesion. + * + * @param int $reviesion + * @access public + * @return array + */ + public function getDiffFiles($revision) + { + $diffApi = "{$this->root}git/commits/$revision.patch?token={$this->token}"; + $diffs = commonModel::http($diffApi); + + $newFiles = array(); + $delFiles = array(); + + if(!empty($diffs)) + { + $diffs = explode("\n", $diffs); + foreach($diffs as $row) + { + preg_match('/^(\s)(create|delete)\smode\s\d+\s(.+)$/', $row, $matches); + if(count($matches) == 4 and !in_array($matches[3], $newFiles) and !in_array($matches[3], $delFiles)) + { + if($matches[2] == 'create') + { + $newFiles[] = $matches[3]; + } + elseif($matches[2] == 'delete') + { + $delFiles[] = $matches[3]; + } + } + } + } + + return array('newFiles' => $newFiles, 'delFiles' => $delFiles); + } + + /** + * Get files by commit. + * + * @param string $commit + * @access public + * @return void + */ + public function getFilesByCommit($revision) + { + if(!scm::checkRevision($revision)) return array(); + $api = "git/commits/$revision"; + $results = $this->fetch($api); + if(empty($results)) return array(); + + $diffFiles = $this->getDiffFiles($revision); + $files = array(); + foreach($results->files as $row) + { + $file = new stdclass(); + $file->revision = $revision; + $file->type = 'file'; + $file->path = '/' . $row->filename; + $file->action = 'M'; + if(in_array($row->filename, $diffFiles['newFiles'])) + { + $file->action = 'A'; + } + elseif(in_array($row->filename, $diffFiles['delFiles'])) + { + $file->action = 'D'; + } + + $files[] = $file; + } + + return $files; + } + + /** + * Repository/tree api. + * + * @param string $path + * @param bool $recursive + * @access public + * @return mixed + */ + public function tree($path, $recursive = 1) + { + $api = "contents"; + + $params = array(); + $params['path'] = ltrim($path, '/'); + $params['ref'] = $this->branch; + $params['recursive'] = (int) $recursive; + return $this->fetch($api, $params); + } + + /** + * Fetch data from gitea api. + * + * @param string $api + * @access public + * @return mixed + */ + public function fetch($api, $params = array(), $needToLoop = false) + { + $params = (array) $params; + $params['token'] = $this->token; + $params['limit'] = isset($params['limit']) ? $params['limit'] : $this->pageLimit; + + $api = ltrim($api, '/'); + $api = $this->root . $api . '?' . http_build_query($params); + if($needToLoop) + { + $allResults = array(); + for($page = 1; true; $page++) + { + $results = json_decode(commonModel::http($api . "&page={$page}")); + if(!is_array($results)) break; + if(!empty($results)) $allResults = array_merge($allResults, $results); + if(count($results) < $this->pageLimit) break; + } + + return $allResults; + } + else + { + $response = commonModel::http($api); + if(!empty(commonModel::$requestErrors)) + { + commonModel::$requestErrors = array(); + return array(); + } + + return json_decode($response); + } + } + + /** + * Format bytes shown. + * + * @param int $size + * @static + * @access public + * @return string + */ + public static function formatBytes($size) + { + if($size < 1024) return $size . 'Bytes'; + if(round($size / (1024 * 1024), 2) > 1) return round($size / (1024 * 1024), 2) . 'G'; + if(round($size / 1024, 2) > 1) return round($size / 1024, 2) . 'M'; + return round($size, 2) . 'KB'; + } + + /** + * Parse log. + * + * @param array $logs + * @access public + * @return array + */ + public function parseLog($logs) + { + $parsedLogs = array(); + $i = 0; + foreach($logs as $commit) + { + if(!isset($commit->sha)) continue; + $parsedLog = new stdclass(); + $parsedLog->revision = $commit->sha; + $parsedLog->committer = $commit->commit->author->name; + $parsedLog->time = date('Y-m-d H:i:s', strtotime($commit->commit->author->date)); + $parsedLog->comment = $commit->commit->message; + $parsedLog->change = array(); + foreach($commit->diffs as $diff) + { + $parsedLog->change[$diff->path] = array(); + $parsedLog->change[$diff->path]['action'] = $diff->action; + $parsedLog->change[$diff->path]['kind'] = $diff->type; + } + $parsedLogs[] = $parsedLog; + } + + return $parsedLogs; + } + + /** + * Get download url. + * + * @param string $branch + * @param string $ext + * @access public + * @return string + */ + public function getDownloadUrl($branch = 'master', $ext = 'zip') + { + $params['token'] = $this->token; + + return "{$this->root}archive/" . urlencode($branch) . ".{$ext}" . '?' . http_build_query($params); + } +} diff --git a/lib/scm/gitlab.class.php b/lib/scm/gitlab.class.php index 324d03a9cc..583b0b1475 100644 --- a/lib/scm/gitlab.class.php +++ b/lib/scm/gitlab.class.php @@ -834,4 +834,21 @@ class gitlab return $parsedLogs; } + + /** + * Get download url. + * + * @param string $branch + * @param string $ext + * @access public + * @return string + */ + public function getDownloadUrl($branch = 'master', $ext = 'zip') + { + $params = (array) $params; + $params['private_token'] = $this->token; + $params['sha'] = $branch; + + return "{$this->root}archive.{$ext}" . '?' . http_build_query($params); + } } diff --git a/lib/scm/scm.class.php b/lib/scm/scm.class.php index 06648998c3..4dc69b4236 100644 --- a/lib/scm/scm.class.php +++ b/lib/scm/scm.class.php @@ -244,6 +244,19 @@ class scm if(preg_match('/[^a-z0-9\-_\.\^\w][\x{4e00}-\x{9fa5}]/ui', $revision)) return false; return true; } + + /** + * Get download url. + * + * @param string $branch + * @param string $ext + * @access public + * @return string + */ + public function getDownloadUrl($branch = '', $ext = 'zip') + { + return $this->engine->getDownloadUrl($branch, $ext); + } } /** diff --git a/module/action/config.php b/module/action/config.php index cc841bc007..000cdcd5cf 100755 --- a/module/action/config.php +++ b/module/action/config.php @@ -46,6 +46,7 @@ $config->action->objectNameFields['gitlab'] = 'name'; $config->action->objectNameFields['gitea'] = 'name'; $config->action->objectNameFields['stage'] = 'name'; $config->action->objectNameFields['apistruct'] = 'name'; +$config->action->objectNameFields['repo'] = 'name'; $config->action->commonImgSize = 870; @@ -61,7 +62,7 @@ $config->action->majorList['execution'] = array('opened', 'edited'); $config->action->needGetProjectType = 'build,task,bug,case,testcase,caselib,testtask,testsuite,testreport,doc,issue,release,risk,design,opportunity,trainplan,gapanalysis,researchplan,researchreport,'; $config->action->needGetRelateField = ',story,productplan,release,task,build,bug,testcase,case,testtask,testreport,doc,doclib,issue,risk,opportunity,trainplan,gapanalysis,team,whitelist,researchplan,researchreport,meeting,kanbanlane,kanbancolumn,module,'; -$config->action->noLinkModules = ',doclib,module,webhook,gitlab,gitea,sonarqube,pipeline,jenkins,kanban,kanbanspace,kanbancolumn,kanbanlane,kanbanregion,kanbancard,execution,project,traincategory,apistruct,program,product,user,entry,'; +$config->action->noLinkModules = ',doclib,module,webhook,gitlab,gitea,sonarqube,pipeline,jenkins,kanban,kanbanspace,kanbancolumn,kanbanlane,kanbanregion,kanbancard,execution,project,traincategory,apistruct,program,product,user,entry,repo,'; $config->action->preferredTypeNum = 10; diff --git a/module/action/lang/de.php b/module/action/lang/de.php index d3f0dbfedd..a98ee3c3c0 100644 --- a/module/action/lang/de.php +++ b/module/action/lang/de.php @@ -133,6 +133,7 @@ $lang->action->objectTypes['gitlabbranch'] = 'GitLab Branch'; $lang->action->objectTypes['gitlabbranchpriv'] = 'GitLab Protected Branches'; $lang->action->objectTypes['gitlabtag'] = 'GitLab Tag'; $lang->action->objectTypes['gitlabtagpriv'] = 'GitLab Tag Protected'; +$lang->action->objectTypes['giteauser'] = 'Gitea User'; $lang->action->objectTypes['kanbanspace'] = 'Kanban Space'; $lang->action->objectTypes['kanban'] = 'Kanban'; $lang->action->objectTypes['kanbanregion'] = 'Kanban Region'; @@ -143,6 +144,7 @@ $lang->action->objectTypes['sonarqube'] = 'SonarQube Server'; $lang->action->objectTypes['sonarqubeproject'] = 'SonarQube Project'; $lang->action->objectTypes['stage'] = 'Stage'; $lang->action->objectTypes['patch'] = 'Patch'; +$lang->action->objectTypes['repo'] = 'Repo'; /* Used to describe operation history. */ $lang->action->desc = new stdclass(); diff --git a/module/action/lang/en.php b/module/action/lang/en.php index 0ab354241a..26fecace0b 100755 --- a/module/action/lang/en.php +++ b/module/action/lang/en.php @@ -133,6 +133,7 @@ $lang->action->objectTypes['gitlabbranch'] = 'GitLab Branch'; $lang->action->objectTypes['gitlabbranchpriv'] = 'GitLab Protected Branches'; $lang->action->objectTypes['gitlabtag'] = 'GitLab Tag'; $lang->action->objectTypes['gitlabtagpriv'] = 'GitLab Tag Protected'; +$lang->action->objectTypes['giteauser'] = 'Gitea User'; $lang->action->objectTypes['kanbanspace'] = 'Kanban Space'; $lang->action->objectTypes['kanban'] = 'Kanban'; $lang->action->objectTypes['kanbanregion'] = 'Kanban Region'; @@ -143,6 +144,7 @@ $lang->action->objectTypes['sonarqube'] = 'SonarQube Server'; $lang->action->objectTypes['sonarqubeproject'] = 'SonarQube Project'; $lang->action->objectTypes['stage'] = 'Stage'; $lang->action->objectTypes['patch'] = 'Patch'; +$lang->action->objectTypes['repo'] = 'Repo'; /* Used to describe operation history. */ $lang->action->desc = new stdclass(); diff --git a/module/action/lang/fr.php b/module/action/lang/fr.php index 01c2a52222..2d4a6ca759 100644 --- a/module/action/lang/fr.php +++ b/module/action/lang/fr.php @@ -133,6 +133,7 @@ $lang->action->objectTypes['gitlabbranch'] = 'GitLab Branch'; $lang->action->objectTypes['gitlabbranchpriv'] = 'GitLab Protected Branches'; $lang->action->objectTypes['gitlabtag'] = 'GitLab Tag'; $lang->action->objectTypes['gitlabtagpriv'] = 'GitLab Tag Protected'; +$lang->action->objectTypes['giteauser'] = 'Gitea User'; $lang->action->objectTypes['kanbanspace'] = 'Kanban Space'; $lang->action->objectTypes['kanban'] = 'Kanban'; $lang->action->objectTypes['kanbanregion'] = 'Kanban Region'; @@ -143,6 +144,7 @@ $lang->action->objectTypes['sonarqube'] = 'SonarQube Server'; $lang->action->objectTypes['sonarqubeproject'] = 'SonarQube Project'; $lang->action->objectTypes['stage'] = 'Stage'; $lang->action->objectTypes['patch'] = 'Patch'; +$lang->action->objectTypes['repo'] = 'Repo'; /* Used to describe operation history. */ $lang->action->desc = new stdclass(); diff --git a/module/action/lang/vi.php b/module/action/lang/vi.php index 681dc1b71f..56a4ac1674 100644 --- a/module/action/lang/vi.php +++ b/module/action/lang/vi.php @@ -111,6 +111,7 @@ $lang->action->objectTypes['gitlabbranch'] = 'GitLab Branch'; $lang->action->objectTypes['gitlabbranchpriv'] = 'GitLab Protected Branches'; $lang->action->objectTypes['gitlabtag'] = 'GitLab Tag'; $lang->action->objectTypes['gitlabtagpriv'] = 'GitLab Tag Protected'; +$lang->action->objectTypes['giteauser'] = 'Gitea User'; $lang->action->objectTypes['kanbanspace'] = 'Kanban Space'; $lang->action->objectTypes['kanban'] = 'Kanban'; $lang->action->objectTypes['kanbanregion'] = 'Kanban Region'; @@ -121,6 +122,7 @@ $lang->action->objectTypes['sonarqube'] = 'SonarQube Server'; $lang->action->objectTypes['sonarqubeproject'] = 'SonarQube Project'; $lang->action->objectTypes['stage'] = 'Stage'; $lang->action->objectTypes['patch'] = 'Patch'; +$lang->action->objectTypes['repo'] = 'Repo'; /* Used to describe operation history. */ $lang->action->desc = new stdclass(); diff --git a/module/action/lang/zh-cn.php b/module/action/lang/zh-cn.php index a9011287c3..8efd487286 100755 --- a/module/action/lang/zh-cn.php +++ b/module/action/lang/zh-cn.php @@ -133,6 +133,7 @@ $lang->action->objectTypes['gitlabbranch'] = 'GitLab分支'; $lang->action->objectTypes['gitlabbranchpriv'] = 'GitLab保护分支'; $lang->action->objectTypes['gitlabtag'] = 'GitLab标签'; $lang->action->objectTypes['gitlabtagpriv'] = 'GitLab标签保护'; +$lang->action->objectTypes['giteauser'] = 'Gitea用户'; $lang->action->objectTypes['kanbanspace'] = '看板空间'; $lang->action->objectTypes['kanban'] = '看板'; $lang->action->objectTypes['kanbanregion'] = '看板区域'; @@ -143,6 +144,7 @@ $lang->action->objectTypes['sonarqube'] = 'SonarQube服务器'; $lang->action->objectTypes['sonarqubeproject'] = 'SonarQube项目'; $lang->action->objectTypes['stage'] = '阶段'; $lang->action->objectTypes['patch'] = '补丁'; +$lang->action->objectTypes['repo'] = '代码库'; /* 用来描述操作历史记录。*/ $lang->action->desc = new stdclass(); diff --git a/module/action/lang/zh-tw.php b/module/action/lang/zh-tw.php index 9a66017d80..dbdac896d3 100755 --- a/module/action/lang/zh-tw.php +++ b/module/action/lang/zh-tw.php @@ -127,12 +127,14 @@ $lang->action->objectTypes['gitlabgroup'] = 'GitLab群組'; $lang->action->objectTypes['gitlabbranch'] = 'GitLab分支'; $lang->action->objectTypes['gitlabbranchpriv'] = 'GitLab保護分支'; $lang->action->objectTypes['gitlabtag'] = 'GitLab標籤'; +$lang->action->objectTypes['giteauser'] = 'Gitea用戶'; $lang->action->objectTypes['kanbanspace'] = '看板空間'; $lang->action->objectTypes['kanban'] = '看板'; $lang->action->objectTypes['kanbanregion'] = '看板區域'; $lang->action->objectTypes['kanbanlane'] = '看板泳道'; $lang->action->objectTypes['kanbancolumn'] = '看板列'; $lang->action->objectTypes['kanbancard'] = '看板卡片'; +$lang->action->objectTypes['repo'] = '代码库'; /* 用來描述操作歷史記錄。*/ $lang->action->desc = new stdclass(); diff --git a/module/action/model.php b/module/action/model.php index 56cbf24af1..8aec1a5db1 100755 --- a/module/action/model.php +++ b/module/action/model.php @@ -984,13 +984,16 @@ class actionModel extends model $executions = array(); if(!$this->app->user->admin) { - if($productID == 'all') $authedProducts = $this->app->user->view->products; - if($projectID == 'all') $authedProjects = $this->app->user->view->projects; - if($executionID == 'all') $authedExecutions = $this->app->user->view->sprints; + $aclViews = isset($this->app->user->rights['acls']['views']) ? $this->app->user->rights['acls']['views'] : array(); + if($productID == 'all') $authedProducts = (empty($aclViews) or (!empty($aclViews) and !empty($aclViews['product']))) ? $this->app->user->view->products : '0'; + if($projectID == 'all') $authedProjects = (empty($aclViews) or (!empty($aclViews) and !empty($aclViews['project']))) ? $this->app->user->view->projects : '0'; + if($executionID == 'all') $authedExecutions = (empty($aclViews) or (!empty($aclViews) and !empty($aclViews['execution']))) ? $this->app->user->view->sprints : '0'; if($productID == 'all' and $projectID == 'all') { - $productCondition = "product " . helper::dbIN($authedProducts); + $productCondition = ''; + foreach(explode(',', $authedProducts) as $product) $productCondition = empty($productCondition) ? "product LIKE '%,$product,%'" : "$productCondition OR product LIKE '%,$product,%'"; + $projectCondition = "project " . helper::dbIN($authedProjects); $executionCondition = isset($authedExecutions) ? "execution " . helper::dbIN($authedExecutions) : ''; } @@ -999,7 +1002,9 @@ class actionModel extends model $products = $this->loadModel('product')->getProductPairsByProject($projectID); $executions = $this->loadModel('execution')->getPairs($projectID) + array(0 => 0); - $productCondition = "product " . helper::dbIN(array_keys($products)); + $productCondition = ''; + foreach(array_keys($products) as $product) $productCondition = empty($productCondition) ? "product LIKE '%,$product,%'" : "$productCondition OR product LIKE '%,$product,%'"; + $projectCondition = "project = $projectID"; $executionCondition = "execution " . helper::dbIN(array_keys($executions)); } @@ -1014,7 +1019,7 @@ class actionModel extends model $executionCondition = "execution " . helper::dbIN(array_keys($executions)); } - $condition = "((product =',0,' or product=0) AND project = '0' AND execution = 0)"; + $condition = "((product =',0,' or product = '0') AND project = '0' AND execution = '0')"; if(!empty($productCondition)) $condition .= ' OR ' . $productCondition; if(!empty($projectCondition)) $condition .= ' OR ' . $projectCondition; if(!empty($executionCondition)) $condition .= ' OR ' . $executionCondition; @@ -1086,6 +1091,7 @@ class actionModel extends model foreach($this->app->user->rights['acls']['actions'] as $moduleName => $actions) { + if(isset($this->lang->mainNav->$moduleName) and !empty($this->app->user->rights['acls']['views']) and !isset($this->app->user->rights['acls']['views'][$moduleName])) continue; $actionCondition .= "(`objectType` = '$moduleName' and `action` " . helper::dbIN($actions) . ") or "; } $actionCondition = trim($actionCondition, 'or '); @@ -1254,15 +1260,11 @@ class actionModel extends model /* If action type is login or logout, needn't link. */ if($actionType == 'svncommited' or $actionType == 'gitcommited') $action->actor = zget($commiters, $action->actor); - /* Get gitlab objectname. */ - if(empty($action->objectName) and substr($objectType, 0, 6) == 'gitlab') $action->objectName = $action->extra; + /* Get gitlab or gitea objectname. */ + if(empty($action->objectName) and (substr($objectType, 0, 6) == 'gitlab' or substr($objectType, 0, 5) == 'gitea')) $action->objectName = $action->extra; /* Other actions, create a link. */ - if(!$this->setObjectLink($action, $deptUsers)) - { - unset($actions[$i]); - continue; - } + $this->setObjectLink($action, $deptUsers); /* Set merge request link. */ if(empty($action->objectName) and $action->objectType == 'mr') $action->objectLink = ''; @@ -1437,7 +1439,6 @@ class actionModel extends model /* Fix bug #2961. */ $isLoginOrLogout = $action->objectType == 'user' and ($action->action == 'login' or $action->action == 'logout'); - if(!common::hasPriv($moduleName, $methodName) and !$isLoginOrLogout) return false; $action->objectLabel = $objectLabel; $action->product = trim($action->product, ','); @@ -1536,6 +1537,7 @@ class actionModel extends model $action->objectLink = !isset($deptUsers[$action->objectID]) ? 'javascript:void(0)' : helper::createLink($moduleName, $methodName, sprintf($vars, $action->objectID)); } } + if(!common::hasPriv($moduleName, $methodName) and !$isLoginOrLogout) $action->objectLink = ''; } elseif($action->objectType == 'team') { diff --git a/module/block/view/dynamic.html.php b/module/block/view/dynamic.html.php index e2e44aac2d..6e0102b36c 100644 --- a/module/block/view/dynamic.html.php +++ b/module/block/view/dynamic.html.php @@ -25,7 +25,7 @@ $class = $action->major ? "class='active'" : ''; echo "
  • "; 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); + if(!$action->objectLink) printf($lang->block->noLinkDynamic, $action->date, $action->objectName, $user, $action->actionLabel, $action->objectLabel, ' ' . $action->objectName); echo "
  • "; $i++; } diff --git a/module/bug/model.php b/module/bug/model.php index a85d73a178..d3ec16ff2c 100644 --- a/module/bug/model.php +++ b/module/bug/model.php @@ -740,6 +740,24 @@ class bugModel extends model $this->linkBugToBuild($bugID, $bug->resolvedBuild); } + $linkBugs = explode(',', $bug->linkBug); + $oldLinkBugs = explode(',', $oldBug->linkBug); + $addBugs = array_diff($linkBugs, $oldLinkBugs); + $removeBugs = array_diff($oldLinkBugs, $linkBugs); + $changeBugs = array_merge($addBugs, $removeBugs); + $changeBugs = $this->dao->select('id,linkbug')->from(TABLE_BUG)->where('id')->in(array_filter($changeBugs))->fetchPairs(); + foreach($changeBugs as $changeBugID => $changeBug) + { + if(in_array($changeBugID, $addBugs) and empty($changeBug)) $this->dao->update(TABLE_BUG)->set('linkBug')->eq($bugID)->where('id')->eq((int)$changeBugID)->exec(); + if(in_array($changeBugID, $addBugs) and !empty($changeBug)) $this->dao->update(TABLE_BUG)->set('linkBug')->eq("$changeBug,$bugID")->where('id')->eq((int)$changeBugID)->exec(); + if(in_array($changeBugID, $removeBugs)) + { + $linkBugs = explode(',', $changeBug); + unset($linkBugs[array_search($bugID, $linkBugs)]); + $this->dao->update(TABLE_BUG)->set('linkBug')->eq(implode(',', $linkBugs))->where('id')->eq((int)$changeBugID)->exec(); + } + } + if(!empty($bug->resolvedBy)) $this->loadModel('score')->create('bug', 'resolve', $bugID); $this->file->updateObjectID($this->post->uid, $bugID, 'bug'); diff --git a/module/ci/model.php b/module/ci/model.php index 2f5bf854b0..0d27513edc 100644 --- a/module/ci/model.php +++ b/module/ci/model.php @@ -26,7 +26,13 @@ class ciModel extends model } common::setMenuVars('devops', $this->session->repoID); - $this->lang->switcherMenu = $this->loadModel('repo')->getSwitcher($this->session->repoID); + if($this->session->repoID) + { + $repo = $this->loadModel('repo')->getRepoByID($this->session->repoID); + if(!in_array(strtolower($repo->SCM), $this->config->repo->gitServiceList)) unset($this->lang->devops->menu->mr); + + $this->lang->switcherMenu = $this->loadModel('repo')->getSwitcher($this->session->repoID); + } } /** diff --git a/module/common/lang/de.php b/module/common/lang/de.php index e9529dc6f5..08c98ec4fd 100644 --- a/module/common/lang/de.php +++ b/module/common/lang/de.php @@ -150,6 +150,7 @@ $lang->openedByAB = 'Ersteller'; $lang->assignedToAB = 'Bearbeiter'; $lang->typeAB = 'Typ'; $lang->nameAB = 'Name'; +$lang->code = 'Code'; $lang->pri = 'Priority'; $lang->delayed = 'Delayed'; diff --git a/module/common/lang/en.php b/module/common/lang/en.php index 16edf7074d..66ec104c45 100644 --- a/module/common/lang/en.php +++ b/module/common/lang/en.php @@ -150,6 +150,7 @@ $lang->openedByAB = 'CreatedBy'; $lang->assignedToAB = 'AssignedTo'; $lang->typeAB = 'Type'; $lang->nameAB = 'Name'; +$lang->code = 'Code'; $lang->pri = 'Priority'; $lang->delayed = 'Delayed'; diff --git a/module/common/lang/fr.php b/module/common/lang/fr.php index d6aad09697..7007d61b66 100644 --- a/module/common/lang/fr.php +++ b/module/common/lang/fr.php @@ -150,6 +150,7 @@ $lang->openedByAB = 'Créé par'; $lang->assignedToAB = 'Affecté à'; $lang->typeAB = 'Type'; $lang->nameAB = 'Name'; +$lang->code = 'Code'; $lang->pri = 'Priority'; $lang->delayed = 'Delayed'; diff --git a/module/common/lang/menu.php b/module/common/lang/menu.php index b7703e2dc1..fc95005d2e 100644 --- a/module/common/lang/menu.php +++ b/module/common/lang/menu.php @@ -488,7 +488,7 @@ $lang->admin->menu = new stdclass(); $lang->admin->menu->index = array('link' => "$lang->indexPage|admin|index", 'alias' => 'register,certifytemail,certifyztmobile,ztcompany'); $lang->admin->menu->company = array('link' => "{$lang->personnel->common}|company|browse|", 'subModule' => ',user,dept,group,'); $lang->admin->menu->model = array('link' => "$lang->model|custom|browsestoryconcept|", 'class' => 'dropdown dropdown-hover', 'exclude' => 'custom-index,custom-set,custom-product,custom-execution,custom-kanban,custom-required,custom-flow,custom-score,custom-feedback,custom-timezone,custom-mode'); -$lang->admin->menu->custom = array('link' => "{$lang->custom->common}|custom|index", 'exclude' => 'custom-browsestoryconcept,custom-timezone,custom-estimate'); +$lang->admin->menu->custom = array('link' => "{$lang->custom->common}|custom|index", 'exclude' => 'custom-browsestoryconcept,custom-timezone,custom-estimate,custom-code'); $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'); @@ -506,7 +506,10 @@ if($config->systemMode == 'new') $lang->admin->menu->allModel['subMenu'] = new stdclass(); $lang->admin->menu->allModel['subMenu']->storyConcept = array('link' => "{$lang->storyConcept}|custom|browsestoryconcept|"); -$lang->admin->menu->allModel['menuOrder'][5] = 'storyConcept'; +$lang->admin->menu->allModel['subMenu']->code = array('link' => "{$lang->code}|custom|code|"); + +$lang->admin->menu->allModel['menuOrder'][5] = 'storyConcept'; +$lang->admin->menu->allModel['menuOrder'][30] = 'code'; $lang->admin->menu->waterfall['subMenu'] = new stdclass(); $lang->admin->menu->waterfall['subMenu']->stage = array('link' => "{$lang->stage->common}|stage|setType|", 'subModule' => 'stage'); diff --git a/module/common/lang/zh-cn.php b/module/common/lang/zh-cn.php index c63345b39f..e303e4b881 100644 --- a/module/common/lang/zh-cn.php +++ b/module/common/lang/zh-cn.php @@ -150,6 +150,7 @@ $lang->openedByAB = '创建'; $lang->assignedToAB = '指派'; $lang->typeAB = '类型'; $lang->nameAB = '名称'; +$lang->code = '代号'; $lang->pri = '优先级'; $lang->delayed = '已延期'; diff --git a/module/common/model.php b/module/common/model.php index bb85ca6c40..4f68d398e7 100644 --- a/module/common/model.php +++ b/module/common/model.php @@ -2379,8 +2379,7 @@ EOD; } $referer = helper::safe64Encode($uri); - print(js::locate(helper::createLink('user', 'login', "referer=$referer"))); - helper::end(); + die(js::locate(helper::createLink('user', 'login', "referer=$referer"))); } } catch(EndResponseException $endResponseException) @@ -3084,11 +3083,13 @@ EOD; * @param string|array $data * @param array $options This is option and value pair, like CURLOPT_HEADER => true. Use curl_setopt function to set options. * @param array $headers Set request headers. + * @param string $dataType + * @param string $method POST|PATCH|PUT * @static * @access public * @return string */ - public static function http($url, $data = null, $options = array(), $headers = array(), $dataType = 'data') + public static function http($url, $data = null, $options = array(), $headers = array(), $dataType = 'data', $method = 'POST') { global $lang, $app; if(!extension_loaded('curl')) @@ -3125,7 +3126,8 @@ EOD; if(!empty($data)) { if(is_object($data)) $data = (array) $data; - curl_setopt($curl, CURLOPT_POST, true); + if($method == 'POST') curl_setopt($curl, CURLOPT_POST, true); + if(in_array($method, array('PATCH', 'PUT'))) curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $method); curl_setopt($curl, CURLOPT_POSTFIELDS, $data); } diff --git a/module/common/view/header.html.php b/module/common/view/header.html.php index 5e3a344972..6d67bb95e8 100755 --- a/module/common/view/header.html.php +++ b/module/common/view/header.html.php @@ -7,6 +7,7 @@ include 'chosen.html.php'; app->loadConfig('sso');?> sso->redirect)) js::set('ssoRedirect', $config->sso->redirect);?> +showMainMenu):?> + + + - - + + - - - -doc->placeholder);?> - -
    -
    -
    -

    doc->create;?>

    -
    - - ' . $lang->doc->createLib, '', 'class="iframe hidden createCustomLib"');?> - -
    - - - - - - - - - - - - - - - - - - - - - doc->types as $typeKey => $typeName) $typeKeyList[$typeKey] = $typeKey; - ?> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    doc->lib;?>
    doc->module;?> - -
    doc->title;?>
    doc->keywords;?>doc->keywordsTips}'");?>
    doc->type;?>doc->types, zget($typeKeyList, $docType, 'text'));?>
    doc->content;?> -
    - - -
    doc->files;?>fetch('file', 'buildform');?>
    doc->mailto;?> -
    - fetch('my', 'buildContactLists'); - ?> -
    -
    doclib->control;?> - acl == 'default' ? 'open' : $lib->acl;?> - type == 'project' and $acl == 'private') ? 'open' : $acl;?> - doc->aclList, $acl, "onchange='toggleAcl(this.value, \"doc\")'");?> - doc->noticeAcl['doc'][$acl];?> -
    - - goback, "data-app='{$app->tab}'");?> - goback, '', "class='btn btn-back btn-wide'");?> -
    -
    -
    -
    - -doc->noticeAcl['doc']);?> - + diff --git a/module/doc/view/createothertype.html.php b/module/doc/view/createothertype.html.php new file mode 100644 index 0000000000..06cb9cc168 --- /dev/null +++ b/module/doc/view/createothertype.html.php @@ -0,0 +1,137 @@ + + * @package doc + * @version $Id: create.html.php 975 2010-07-29 03:30:25Z jajacn@126.com $ + * @link http://www.zentao.net + */ +?> +doc->officeTypes, $docType) !== false):?> + +
    +
    +
    +

    doc->create;?>

    +
    + config->edition != 'open'):?> +
    + doc->notSetOffice, zget($lang->doc->typeList, $docType), common::hasPriv('custom', 'libreoffice') ? $this->createLink('custom', 'libreoffice', '', '', true) : '###');?> +
    + +
    doc->cannotCreateOffice, zget($lang->doc->typeList, $docType));?>
    + +
    +
    + + + + + + + +doc->placeholder);?> + +
    +
    +
    +

    doc->create;?>

    +
    + + ' . $lang->doc->createLib, '', 'class="iframe hidden createCustomLib"');?> + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    doc->lib;?>
    doc->module;?> + +
    doc->title;?>
    doc->keywords;?>doc->keywordsTips}'");?>
    doc->content;?> +
    + + + +
    doc->files;?>fetch('file', 'buildform');?>
    doc->mailto;?> +
    + fetch('my', 'buildContactLists'); + ?> +
    +
    doclib->control;?> + acl == 'default' ? 'open' : $lib->acl;?> + type == 'project' and $acl == 'private') ? 'open' : $acl;?> + doc->aclList, $acl, "onchange='toggleAcl(this.value, \"doc\")'");?> + doc->noticeAcl['doc'][$acl];?> +
    + + goback, "data-app='{$app->tab}'");?> + goback, '', "class='btn btn-back btn-wide'");?> +
    +
    +
    +
    + +doc->noticeAcl['doc']);?> + + diff --git a/module/doc/view/createtexttype.html.php b/module/doc/view/createtexttype.html.php new file mode 100644 index 0000000000..9c97f6d3c5 --- /dev/null +++ b/module/doc/view/createtexttype.html.php @@ -0,0 +1,168 @@ + + * @package doc + * @version $Id: createtext.html.php 975 2022-07-14 13:49:25Z $ + * @link http://www.zentao.net + */ +?> + + + +doc->placeholder);?> + + + + ' . $lang->doc->createLib, '', 'class="iframe hidden createCustomLib"');?> + +
    +
    + + + + + + + + + + +
    doc->titlePlaceholder}' class='form-control' required");?>
    +
    +
    +
    + + + +
    + +
    +
    +
    +
    + + +doc->noticeAcl['doc']);?> + diff --git a/module/doc/view/edit.html.php b/module/doc/view/edit.html.php index 3569041e5c..1f6d3b8382 100644 --- a/module/doc/view/edit.html.php +++ b/module/doc/view/edit.html.php @@ -10,109 +10,8 @@ * @link http://www.zentao.net */ ?> - -contentType == 'html') include '../../common/view/kindeditor.html.php';?> -contentType == 'markdown') include '../../common/view/markdown.html.php';?> -content != $doc->draft);?> -doc->confirmUpdateContent);?> -id);?> -draft);?> -
    -
    -
    -

    - id;?> - createLink('doc', 'view', "docID=$doc->id"), $doc->title, '', "title='$doc->title'");?> - arrow . ' ' . $lang->doc->edit;?> -

    -
    save, '', 'id="top-submit" class="btn btn-primary"');?>
    -
    -
    - - - - - - - - - - - - - - - - - - - - - - type == 'url') echo "class='hidden'"?>> - - - - type != 'url') echo "class='hidden'"?>> - - - - - - - - - - - - - - - - - - - - - - -
    doc->lib;?> lib, "class='form-control chosen' onchange=loadDocModule(this.value)");?>
    doc->module;?> - module, "class='form-control chosen'");?> -
    doc->title;?>title, "class='form-control' required");?>
    doc->keywords;?>keywords, "class='form-control' placeholder='{$lang->doc->keywordsTips}'");?>
    doc->type;?> - doc->types; - if(!isset($lang->doc->types[$doc->type])) $typeList = $lang->doc->typeList; - echo html::radio('type', array($doc->type => zget($typeList, $doc->type)), $doc->type); - ?> -
    doc->content;?>type == 'url' ? '' : htmlSpecialString($doc->content), "style='width:100%; height:200px'") . html::hidden('contentType', $doc->contentType);?>
    doc->url;?>type == 'url' ? $doc->content : '', "class='form-control'");?>
    doc->files;?>fetch('file', 'buildform');?>
    doc->mailto;?> -
    - mailto, "multiple class='form-control picker-select' data-drop-direction='top'"); - echo $this->fetch('my', 'buildContactLists'); - ?> -
    -
    doclib->control;?> - acl == 'private' ? 'private' : $doc->acl;?> - doc->aclList, $acl, "onchange='toggleAcl(this.value, \"doc\")'")?> - doc->noticeAcl['doc'][$acl];?> -
    - editedDate); - echo html::submitButton(); - echo html::backButton($lang->goback, "data-app='{$app->tab}'"); - ?> -
    -
    -
    -
    -doc->noticeAcl['doc']);?> - +type == 'text'):?> + + + + diff --git a/module/doc/view/editothertype.html.php b/module/doc/view/editothertype.html.php new file mode 100644 index 0000000000..3569041e5c --- /dev/null +++ b/module/doc/view/editothertype.html.php @@ -0,0 +1,118 @@ + + * @package doc + * @version $Id: edit.html.php 975 2010-07-29 03:30:25Z jajacn@126.com $ + * @link http://www.zentao.net + */ +?> + +contentType == 'html') include '../../common/view/kindeditor.html.php';?> +contentType == 'markdown') include '../../common/view/markdown.html.php';?> +content != $doc->draft);?> +doc->confirmUpdateContent);?> +id);?> +draft);?> +
    +
    +
    +

    + id;?> + createLink('doc', 'view', "docID=$doc->id"), $doc->title, '', "title='$doc->title'");?> + arrow . ' ' . $lang->doc->edit;?> +

    +
    save, '', 'id="top-submit" class="btn btn-primary"');?>
    +
    +
    + + + + + + + + + + + + + + + + + + + + + + type == 'url') echo "class='hidden'"?>> + + + + type != 'url') echo "class='hidden'"?>> + + + + + + + + + + + + + + + + + + + + + + +
    doc->lib;?> lib, "class='form-control chosen' onchange=loadDocModule(this.value)");?>
    doc->module;?> + module, "class='form-control chosen'");?> +
    doc->title;?>title, "class='form-control' required");?>
    doc->keywords;?>keywords, "class='form-control' placeholder='{$lang->doc->keywordsTips}'");?>
    doc->type;?> + doc->types; + if(!isset($lang->doc->types[$doc->type])) $typeList = $lang->doc->typeList; + echo html::radio('type', array($doc->type => zget($typeList, $doc->type)), $doc->type); + ?> +
    doc->content;?>type == 'url' ? '' : htmlSpecialString($doc->content), "style='width:100%; height:200px'") . html::hidden('contentType', $doc->contentType);?>
    doc->url;?>type == 'url' ? $doc->content : '', "class='form-control'");?>
    doc->files;?>fetch('file', 'buildform');?>
    doc->mailto;?> +
    + mailto, "multiple class='form-control picker-select' data-drop-direction='top'"); + echo $this->fetch('my', 'buildContactLists'); + ?> +
    +
    doclib->control;?> + acl == 'private' ? 'private' : $doc->acl;?> + doc->aclList, $acl, "onchange='toggleAcl(this.value, \"doc\")'")?> + doc->noticeAcl['doc'][$acl];?> +
    + editedDate); + echo html::submitButton(); + echo html::backButton($lang->goback, "data-app='{$app->tab}'"); + ?> +
    +
    +
    +
    +doc->noticeAcl['doc']);?> + diff --git a/module/doc/view/edittexttype.html.php b/module/doc/view/edittexttype.html.php new file mode 100644 index 0000000000..67bf6c18a6 --- /dev/null +++ b/module/doc/view/edittexttype.html.php @@ -0,0 +1,167 @@ + + * @package doc + * @version $Id: create.html.php 975 2010-07-29 03:30:25Z jajacn@126.com $ + * @link http://www.zentao.net + */ +?> + +contentType == 'html') include '../../common/view/kindeditor.html.php';?> +contentType == 'markdown') include '../../common/view/markdown.html.php';?> +content != $doc->draft);?> +doc->confirmUpdateContent);?> +id);?> +draft);?> +doc->placeholder);?> + + +
    +
    + + + + + + + + + + +
    title, "placeholder='{$lang->doc->titlePlaceholder}' class='form-control' required");?>
    +
    +
    +
    content), "style='width:100%;'");?>
    + contentType);?> + + editedDate);?> +
    + +
    +
    +
    +
    + +doc->noticeAcl['doc']);?> + diff --git a/module/doc/view/selectlibtype.html.php b/module/doc/view/selectlibtype.html.php index 8c92315749..aa1057648c 100644 --- a/module/doc/view/selectlibtype.html.php +++ b/module/doc/view/selectlibtype.html.php @@ -21,12 +21,19 @@ - vision == 'lite'):?> - doc->libTypeList;?> - - doc->libTypeList + $lang->doc->libGlobalList;?> - - + + + + + + + + + doc->types as $typeKey => $typeName) $typeKeyList[$typeKey] = $typeKey; + ?> + diff --git a/module/execution/config.php b/module/execution/config.php index 2e46428e5b..a79943e81e 100644 --- a/module/execution/config.php +++ b/module/execution/config.php @@ -139,7 +139,14 @@ $config->execution->gantt->linkType['end']['end'] = 2; $config->execution->gantt->linkType['begin']['end'] = 3; $config->execution->datatable = new stdclass(); -$config->execution->datatable->defaultField = array('id', 'name', 'code', 'project', 'PM', 'status', 'progress', 'percent', 'attribute', 'begin', 'end', 'estimate', 'consumed', 'left', 'burn', 'actions'); +if(!isset($config->setCode) or $config->setCode == 1) +{ + $config->execution->datatable->defaultField = array('id', 'name', 'code', 'project', 'PM', 'status', 'progress', 'percent', 'attribute', 'begin', 'end', 'estimate', 'consumed', 'left', 'burn', 'actions'); +} +else +{ + $config->execution->datatable->defaultField = array('id', 'name', 'project', 'PM', 'status', 'progress', 'percent', 'attribute', 'begin', 'end', 'estimate', 'consumed', 'left', 'burn', 'actions'); +} $config->execution->datatable->fieldList['id']['title'] = 'idAB'; $config->execution->datatable->fieldList['id']['fixed'] = 'left'; @@ -151,10 +158,13 @@ $config->execution->datatable->fieldList['name']['fixed'] = 'left'; $config->execution->datatable->fieldList['name']['width'] = 'auto'; $config->execution->datatable->fieldList['name']['required'] = 'yes'; -$config->execution->datatable->fieldList['code']['title'] = 'code'; -$config->execution->datatable->fieldList['code']['fixed'] = 'no'; -$config->execution->datatable->fieldList['code']['width'] = '95'; -$config->execution->datatable->fieldList['code']['required'] = 'no'; +if(!isset($config->setCode) or $config->setCode == 1) +{ + $config->execution->datatable->fieldList['code']['title'] = 'code'; + $config->execution->datatable->fieldList['code']['fixed'] = 'no'; + $config->execution->datatable->fieldList['code']['width'] = '95'; + $config->execution->datatable->fieldList['code']['required'] = 'no'; +} $config->execution->datatable->fieldList['project']['title'] = 'project'; $config->execution->datatable->fieldList['project']['fixed'] = 'no'; diff --git a/module/execution/model.php b/module/execution/model.php index 355ee67754..6731dc0ddd 100644 --- a/module/execution/model.php +++ b/module/execution/model.php @@ -462,7 +462,7 @@ class executionModel extends model $oldExecution = $this->dao->findById($executionID)->from(TABLE_EXECUTION)->fetch(); /* Judgment of required items. */ - if($oldExecution->type != 'stage' and $this->post->code == '') + if($oldExecution->type != 'stage' and $this->post->code == '' and (!isset($this->config->setCode) or $this->config->setCode == 1)) { dao::$errors['code'] = sprintf($this->lang->error->notempty, $this->lang->execution->code); return false; @@ -660,13 +660,12 @@ class executionModel extends model foreach($data->executionIDList as $executionID) { $executionName = $data->names[$executionID]; - $executionCode = $data->codes[$executionID]; + if(isset($data->codes)) $executionCode = $data->codes[$executionID]; $executionID = (int)$executionID; $executions[$executionID] = new stdClass(); $executions[$executionID]->id = $executionID; $executions[$executionID]->name = $executionName; - $executions[$executionID]->code = $executionCode; $executions[$executionID]->PM = $data->PMs[$executionID]; $executions[$executionID]->PO = $data->POs[$executionID]; $executions[$executionID]->QD = $data->QDs[$executionID]; @@ -680,13 +679,15 @@ class executionModel extends model $executions[$executionID]->days = $data->dayses[$executionID]; $executions[$executionID]->lastEditedBy = $this->app->user->account; $executions[$executionID]->lastEditedDate = helper::now(); + + if(isset($data->codes)) $executions[$executionID]->code = $executionCode; if(isset($data->projects)) $executions[$executionID]->project = zget($data->projects, $executionID, 0); if(isset($data->attributes)) $executions[$executionID]->attribute = zget($data->attributes, $executionID, ''); if($executions[$executionID]->status == 'closed') $executions[$executionID]->closedDate = helper::now(); if($executions[$executionID]->status == 'suspended') $executions[$executionID]->suspendedDate = helper::today(); /* Check unique code for edited executions. */ - if($projectModel == 'scrum' and empty($executionCode)) + if($projectModel == 'scrum' and isset($executionCode) and empty($executionCode)) { dao::$errors['code'][] = 'execution#' . $executionID . sprintf($this->lang->error->notempty, $this->lang->project->code); return false; diff --git a/module/execution/view/batchedit.html.php b/module/execution/view/batchedit.html.php index 260211cd5a..e9a76ecae3 100755 --- a/module/execution/view/batchedit.html.php +++ b/module/execution/view/batchedit.html.php @@ -35,14 +35,12 @@ } } $minWidth = (count($visibleFields) > 5) ? 'w-150px' : ''; - - $name = $from == 'execution' ? 'execName' : 'name'; - $code = $from == 'execution' ? 'execCode' : 'code'; - $PM = $from == 'execution' ? 'execPM' : 'PM'; - $type = $from == 'execution' ? 'execType' : 'type'; - $desc = $from == 'execution' ? 'execDesc' : 'desc'; - $status = $from == 'execution' ? 'execStatus' : 'status'; - + $name = $from == 'execution' ? 'execName' : 'name'; + $code = $from == 'execution' ? 'execCode' : 'code'; + $PM = $from == 'execution' ? 'execPM' : 'PM'; + $type = $from == 'execution' ? 'execType' : 'type'; + $desc = $from == 'execution' ? 'execDesc' : 'desc'; + $status = $from == 'execution' ? 'execStatus' : 'status'; ?> '>
    @@ -54,7 +52,9 @@
    + setCode) and $config->setCode == 1):?> + @@ -86,7 +86,9 @@ - + setCode) and $config->setCode == 1):?> + + diff --git a/module/execution/view/create.html.php b/module/execution/view/create.html.php index 18fff781b3..2d4d4eff1a 100644 --- a/module/execution/view/create.html.php +++ b/module/execution/view/create.html.php @@ -70,10 +70,12 @@ + setCode) or $config->setCode == 1):?> + + setCode) or $config->setCode == 1):?> + diff --git a/module/gitlab/control.php b/module/gitlab/control.php index 5c8074064a..6cd8195de4 100644 --- a/module/gitlab/control.php +++ b/module/gitlab/control.php @@ -47,9 +47,7 @@ class gitlab extends control foreach($gitlabList as $gitlab) { - $token = $this->gitlab->apiGetCurrentUser($gitlab->url, $gitlab->token); - $gitlab->isAdminToken = (isset($token->is_admin) and $token->is_admin); - $gitlab->isBindUser = true; + $gitlab->isBindUser = true; if(!$this->app->user->admin and !isset($myGitLabs[$gitlab->id])) $gitlab->isBindUser = false; } @@ -722,7 +720,7 @@ class gitlab extends control } $gitlab = $this->gitlab->getByID($gitlabID); - $repos = $this->loadModel('repo')->getGitLabRepoList($gitlabID); + $repos = $this->loadModel('repo')->getRepoListByClient($gitlabID); $repoPairs = array(); foreach($repos as $repo) $repoPairs[$repo->path] = $repo->id; @@ -911,176 +909,6 @@ class gitlab extends control $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) - { - $project = $this->gitlab->apiGetSingleProject($gitlabID, $projectID); - - if(!$this->app->user->admin) - { - $openID = $this->gitlab->getUserIDByZentaoAccount($gitlabID, $this->app->user->account); - if(!$openID) return print(js::alert($this->lang->gitlab->mustBindUser) . js::locate($this->createLink('gitlab', 'browse'))); - if(!$this->gitlab->checkUserAccess($gitlabID, $projectID, $project)) return print(js::alert($this->lang->gitlab->noAccess) . js::locate($this->createLink('gitlab', 'browse'))); - } - - $keyword = fixer::input('post')->setDefault('keyword', '')->get('keyword'); - $branches = $this->gitlab->apiGetBranchPrivs($gitlabID, $projectID, $keyword, $orderBy); - - /* 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(!$this->app->user->admin) - { - $openID = $this->gitlab->getUserIDByZentaoAccount($gitlabID, $this->app->user->account); - if(!$openID) return print(js::alert($this->lang->gitlab->mustBindUser) . js::locate($this->createLink('gitlab', 'browse'))); - - $project = $this->gitlab->apiGetSingleProject($gitlabID, $projectID); - if(!$this->gitlab->checkUserAccess($gitlabID, $projectID, $project)) return print(js::alert($this->lang->gitlab->noAccess) . js::locate($this->createLink('gitlab', 'browse'))); - } - - /* Fix error when request type is PATH_INFO and the branch name contains '-'.*/ - if($branch) $branch = urldecode(helper::safe64Decode($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. - - $title = $this->lang->gitlab->createBranchPriv; - - if($branch) - { - $title = $this->lang->gitlab->editBranchPriv; - $branchPriv = $this->gitlab->apiGetSingleBranchPriv($gitlabID, $projectID, $branch); - $branchPriv->name = helper::safe64Encode(urlencode($branchPriv->name)); - $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) - { - $branchName = helper::safe64Encode(urlencode($oneBranch->name)); - $branches[$branchName] = $oneBranch->name; - } - } - - $this->view->title = $this->lang->gitlab->common . $this->lang->colon . $title; - $this->view->pageTitle = $title; - $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(!$this->app->user->admin) - { - $openID = $this->gitlab->getUserIDByZentaoAccount($gitlabID, $this->app->user->account); - if(!$openID) return print(js::alert($this->lang->gitlab->mustBindUser) . js::locate($this->createLink('gitlab', 'browse'))); - - $project = $this->gitlab->apiGetSingleProject($gitlabID, $projectID); - if(!$this->gitlab->checkUserAccess($gitlabID, $projectID, $project)) return print(js::alert($this->lang->gitlab->noAccess) . js::locate($this->createLink('gitlab', 'browse'))); - } - - if($confirm != 'yes') - { - $branch = urlencode($branch); - return print(js::confirm($this->lang->gitlab->branch->confirmDelete , inlink('deleteBranchPriv', "gitlabID=$gitlabID&projectID=$projectID&branch=$branch&confirm=yes"))); - } - - /* Fix error when request type is PATH_INFO and the branch name contains '-'.*/ - $branch = urldecode(helper::safe64Decode($branch)); - $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); - return print(js::reload('parent')); - } - - echo js::alert($reponse->message); - } - /** * Browse gitlab tag. * @@ -1135,206 +963,6 @@ class gitlab extends control $this->display(); } - /** - * Browse gitlab protect tag. - * - * @param int $gitlabID - * @param int $projectID - * @param string $orderBy - * @param int $recTotal - * @param int $recPerPage - * @param int $pageID - * @access public - * @return void - */ - public function browseTagPriv($gitlabID, $projectID, $orderBy = 'name_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1) - { - $project = $this->gitlab->apiGetSingleProject($gitlabID, $projectID); - - if(!$this->app->user->admin) - { - $openID = $this->gitlab->getUserIDByZentaoAccount($gitlabID, $this->app->user->account); - if(!$openID) return print(js::alert($this->lang->gitlab->mustBindUser) . js::locate($this->createLink('gitlab', 'browse'))); - - if(!$this->gitlab->checkUserAccess($gitlabID, $projectID, $project)) return print(js::alert($this->lang->gitlab->noAccess) . js::locate($this->createLink('gitlab', 'browse'))); - } - - $this->session->set('gitlabTagPrivList', $this->app->getURI(true)); - $keyword = fixer::input('post')->setDefault('keyword', '')->get('keyword'); - - $gitlabTags = array(); - $allTags = $this->gitlab->apiGetTags($gitlabID, $projectID); - foreach($allTags as $tag) - { - $gitlabTags[$tag->name] = $tag; - } - - $tagList = array(); - $gitlabProtectTags = $this->gitlab->apiGetTagPrivs($gitlabID, $projectID); - foreach($gitlabProtectTags as $gitlabProtectTag) - { - $tag = new stdClass(); - $tag->name = $gitlabProtectTag->name; - $tag->lastCommitter = isset($gitlabTags[$tag->name]) ? $gitlabTags[$tag->name]->commit->committer_name : ''; - $tag->accessLevels = $gitlabProtectTag->create_access_levels; - - $tagList[] = $tag; - } - - /* Data search. */ - if($keyword) - { - foreach($tagList as $key => $tag) - { - if(strpos($tag->name, $keyword) === false) unset($tagList[$key]); - } - $tagList = array_values($tagList); - } - - /* Data sort. */ - list($order, $sort) = explode('_', $orderBy); - $orderList = array(); - foreach($tagList as $tag) $orderList[] = $tag->$order; - array_multisort($orderList, $sort == 'desc' ? SORT_DESC : SORT_ASC, $tagList); - - /* Pager. */ - $this->app->loadClass('pager', $static = true); - $recTotal = count($tagList); - $pager = new pager($recTotal, $recPerPage, $pageID); - $tagList = array_chunk($tagList, $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->browseTagPriv; - $this->view->gitlabID = $gitlabID; - $this->view->projectID = $projectID; - $this->view->keyword = $keyword; - $this->view->project = $project; - $this->view->gitlabTagList = empty($tagList) ? $tagList: $tagList[$pageID - 1]; - $this->view->orderBy = $orderBy; - $this->display(); - } - - /** - * Set a gitlab protect tag. - * - * @param int $gitlabID - * @param int $projectID - * @access public - * @return void - */ - public function createTagPriv($gitlabID, $projectID) - { - if(!$this->app->user->admin) - { - $openID = $this->gitlab->getUserIDByZentaoAccount($gitlabID, $this->app->user->account); - if(!$openID) return print(js::alert($this->lang->gitlab->mustBindUser) . js::locate($this->createLink('gitlab', 'browse'))); - - $project = $this->gitlab->apiGetSingleProject($gitlabID, $projectID); - if(!$this->gitlab->checkUserAccess($gitlabID, $projectID, $project)) return print(js::alert($this->lang->gitlab->noAccess) . js::locate($this->createLink('gitlab', 'browse'))); - } - - if($_POST) - { - $this->gitlab->createTagPriv($gitlabID, $projectID); - - if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError())); - return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => inlink('browseTagPriv', "gitlabID=$gitlabID&projectID=$projectID"))); - } - - $gitlabTags = $this->gitlab->apiGetTags($gitlabID, $projectID); - $protectTags = $this->gitlab->apiGetTagPrivs($gitlabID, $projectID, '', 'name_asc'); - $protectNames = array_keys($protectTags); - - $tags = array(); - foreach($gitlabTags as $tag) - { - if(!in_array($tag->name, $protectNames)) $tags[$tag->name] = $tag->name; - } - - $this->view->title = $this->lang->gitlab->common . $this->lang->colon . $this->lang->gitlab->createTagPriv; - $this->view->gitlabID = $gitlabID; - $this->view->projectID = $projectID; - $this->view->tags = $tags; - $this->display(); - } - - /** - * Edit a gitlab protect tag. - * - * @param int $gitlabID - * @param int $projectID - * @param string $tag - * @access public - * @return void - */ - public function editTagPriv($gitlabID, $projectID, $tag = '') - { - if(!$this->app->user->admin) - { - $openID = $this->gitlab->getUserIDByZentaoAccount($gitlabID, $this->app->user->account); - if(!$openID) return print(js::alert($this->lang->gitlab->mustBindUser) . js::locate($this->createLink('gitlab', 'browse'))); - - $project = $this->gitlab->apiGetSingleProject($gitlabID, $projectID); - if(!$this->gitlab->checkUserAccess($gitlabID, $projectID, $project)) return print(js::alert($this->lang->gitlab->noAccess) . js::locate($this->createLink('gitlab', 'browse'))); - } - - /* Fix error when request type is PATH_INFO and the tag name contains '-'.*/ - $tag = urldecode(helper::safe64Decode($tag)); - - if($_POST) - { - $this->gitlab->createTagPriv($gitlabID, $projectID, $tag); - - if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError())); - return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => inlink('browseTagPriv', "gitlabID=$gitlabID&projectID=$projectID"))); - } - - $tagPriv = $this->gitlab->apiGetSingleTagPriv($gitlabID, $projectID, $tag); - $tagPriv->createAccessLevel = $this->gitlab->checkAccessLevel($tagPriv->create_access_levels); - - $this->view->title = $this->lang->gitlab->common . $this->lang->colon . $this->lang->gitlab->editTagPriv; - $this->view->gitlabID = $gitlabID; - $this->view->projectID = $projectID; - $this->view->tagPriv = $tagPriv; - $this->view->tag = $tag; - $this->display(); - } - - /** - * Delete a gitlab protect tag. - * - * @param int $gitlabID - * @param int $projectID - * @param string $tag - * @access public - * @return void - */ - public function deleteTagPriv($gitlabID, $projectID, $tag) - { - if(!$this->app->user->admin) - { - $openID = $this->gitlab->getUserIDByZentaoAccount($gitlabID, $this->app->user->account); - if(!$openID) return print(js::alert($this->lang->gitlab->mustBindUser) . js::locate($this->createLink('gitlab', 'browse'))); - - $project = $this->gitlab->apiGetSingleProject($gitlabID, $projectID); - if(!$this->gitlab->checkUserAccess($gitlabID, $projectID, $project)) return print(js::alert($this->lang->gitlab->noAccess) . js::locate($this->createLink('gitlab', 'browse'))); - } - - /* Fix error when request type is PATH_INFO and the tag name contains '-'.*/ - $tag = urldecode(helper::safe64Decode($tag)); - $reponse = $this->gitlab->apiDeleteTagPriv($gitlabID, $projectID, $tag); - - /* 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('gitlabtagpriv', 0, 'deleted', '', $tag); - return print(js::reload('parent')); - } - - echo js::alert($reponse->message); - } - /** * Import gitlab issue to zentaopms. * @@ -1346,7 +974,7 @@ class gitlab extends control { $repo = $this->loadModel('repo')->getRepoByID($repoID); $productIDList = explode(',', $repo->product); - $gitlabID = $repo->gitlab; + $gitlabID = $repo->gitService; $projectID = $repo->project; $gitlab = $this->gitlab->getByID($gitlabID); @@ -1491,7 +1119,7 @@ class gitlab extends control $bindedUsers = $this->dao->select('account,openID') ->from(TABLE_OAUTH) ->where('providerType')->eq('gitlab') - ->andWhere('providerID')->eq($repo->gitlab) + ->andWhere('providerID')->eq($repo->gitService) ->fetchPairs(); if(empty($repo->acl)) @@ -1511,7 +1139,7 @@ class gitlab extends control } } - $gitlabCurrentMembers = $this->gitlab->apiGetProjectMembers($repo->gitlab, $repo->project); + $gitlabCurrentMembers = $this->gitlab->apiGetProjectMembers($repo->gitService, $repo->project); $addedMembers = $updatedMembers = $deletedMembers = array(); /* Get the updated data. */ @@ -1570,17 +1198,17 @@ class gitlab extends control foreach($addedMembers as $addedMember) { - $this->gitlab->apiCreateProjectMember($repo->gitlab, $repo->project, $addedMember); + $this->gitlab->apiCreateProjectMember($repo->gitService, $repo->project, $addedMember); } foreach($updatedMembers as $updatedMember) { - $this->gitlab->apiUpdateProjectMember($repo->gitlab, $repo->project, $updatedMember); + $this->gitlab->apiUpdateProjectMember($repo->gitService, $repo->project, $updatedMember); } foreach($deletedMembers as $deletedMemberID) { - $this->gitlab->apiDeleteProjectMember($repo->gitlab, $repo->project, $deletedMemberID); + $this->gitlab->apiDeleteProjectMember($repo->gitService, $repo->project, $deletedMemberID); } $repo->acl->users = array_values($accounts); @@ -1590,7 +1218,7 @@ class gitlab extends control $repo = $this->loadModel('repo')->getRepoByID($repoID); $users = $this->loadModel('user')->getPairs('noletter|noempty|nodeleted|noclosed'); - $projectMembers = $this->gitlab->apiGetProjectMembers($repo->gitlab, $repo->project); + $projectMembers = $this->gitlab->apiGetProjectMembers($repo->gitService, $repo->project); if(!is_array($projectMembers)) $projectMembers = array(); /* Get users accesslevel. */ @@ -1598,7 +1226,7 @@ class gitlab extends control $bindedUsers = $this->dao->select('openID,account') ->from(TABLE_OAUTH) ->where('providerType')->eq('gitlab') - ->andWhere('providerID')->eq($repo->gitlab) + ->andWhere('providerID')->eq($repo->gitService) ->fetchPairs(); foreach($projectMembers as $projectMember) @@ -1746,4 +1374,99 @@ class gitlab extends control echo js::alert($reponse->message); } + + /** + * Manage a gitlab branch protected. + * + * @param int $repoID + * @param int $projectID + * @access public + * @return void + */ + public function manageBranchPriv($gitlabID, $projectID) + { + if(!$this->app->user->admin) + { + $openID = $this->gitlab->getUserIDByZentaoAccount($gitlabID, $this->app->user->account); + if(!$openID) return print(js::alert($this->lang->gitlab->mustBindUser) . js::locate($this->createLink('gitlab', 'browse'))); + + $project = $this->gitlab->apiGetSingleProject($gitlabID, $projectID); + if(!$this->gitlab->checkUserAccess($gitlabID, $projectID, $project)) return print(js::alert($this->lang->gitlab->noAccess) . js::locate($this->createLink('gitlab', 'browse'))); + } + + $hasAccessBranches = $this->gitlab->apiGetBranchPrivs($gitlabID, $projectID, '', 'name_asc'); + foreach($hasAccessBranches as $branch) + { + $branch->pushAccess = $this->gitlab->checkAccessLevel($branch->push_access_levels); + $branch->mergeAccess = $this->gitlab->checkAccessLevel($branch->merge_access_levels); + } + + if(!empty($_POST)) + { + $result = $this->gitlab->manageBranchPrivs($gitlabID, $projectID, $hasAccessBranches); + if(!empty($result)) return $this->send(array('result' => 'fail', 'message' => sprintf($this->lang->gitlab->svaeFailed, implode(', ', $result)))); + + return $this->send(array('message' => $this->lang->saveSuccess, 'result' => 'success', 'locate' => inlink('browseProject', "gitlabID=$gitlabID"))); + } + $allBranches = $this->gitlab->apiGetBranches($gitlabID, $projectID); + $noAccessBranches = array(); + foreach($allBranches as $branch) + { + if(!isset($hasAccessBranches[$branch->name])) $noAccessBranches[$branch->name] = $branch->name; + } + + $this->view->title = $this->lang->gitlab->common . $this->lang->colon . $this->lang->gitlab->browseBranchPriv; + $this->view->gitlabID = $gitlabID; + $this->view->projectID = $projectID; + $this->view->hasAccessBranches = $hasAccessBranches; + $this->view->noAccessBranches = $noAccessBranches; + $this->display(); + } + + /** + * Manage a gitlab tag protected. + * + * @param int $repoID + * @param int $projectID + * @access public + * @return void + */ + public function manageTagPriv($gitlabID, $projectID) + { + if(!$this->app->user->admin) + { + $openID = $this->gitlab->getUserIDByZentaoAccount($gitlabID, $this->app->user->account); + if(!$openID) return print(js::alert($this->lang->gitlab->mustBindUser) . js::locate($this->createLink('gitlab', 'browse'))); + + $project = $this->gitlab->apiGetSingleProject($gitlabID, $projectID); + if(!$this->gitlab->checkUserAccess($gitlabID, $projectID, $project)) return print(js::alert($this->lang->gitlab->noAccess) . js::locate($this->createLink('gitlab', 'browse'))); + } + + $hasAccessTags = $this->gitlab->apiGetTagPrivs($gitlabID, $projectID, '', 'name_asc'); + foreach($hasAccessTags as $tag) + { + $tag->createAccess = $this->gitlab->checkAccessLevel($tag->create_access_levels); + } + + if(!empty($_POST)) + { + $result = $this->gitlab->manageTagPrivs($gitlabID, $projectID, $hasAccessTags); + if(!empty($result)) return $this->send(array('result' => 'fail', 'message' => sprintf($this->lang->gitlab->svaeFailed, implode(', ', $result)))); + + return $this->send(array('message' => $this->lang->saveSuccess, 'result' => 'success', 'locate' => inlink('browseProject', "gitlabID=$gitlabID"))); + } + $allTags = $this->gitlab->apiGetTags($gitlabID, $projectID); + $noAccessTags = array(); + foreach($allTags as $tag) + { + if(!isset($hasAccessTags[$tag->name])) $noAccessTags[$tag->name] = $tag->name; + } + + $this->view->title = $this->lang->gitlab->common . $this->lang->colon . $this->lang->gitlab->browseTagPriv; + $this->view->gitlabID = $gitlabID; + $this->view->projectID = $projectID; + $this->view->hasAccessTags = $hasAccessTags; + $this->view->noAccessTags = $noAccessTags; + $this->display(); + } } diff --git a/module/gitlab/js/managebranchpriv.js b/module/gitlab/js/managebranchpriv.js new file mode 100644 index 0000000000..5a7931c5e8 --- /dev/null +++ b/module/gitlab/js/managebranchpriv.js @@ -0,0 +1,74 @@ +/* Update other picker on change */ +$.zui.Picker.DEFAULTS.onChange = function(event) +{ + var picker = event.picker; + if(!picker.$formItem.is('[name^=branches]')) return; + + var select = picker.$formItem[0]; + var newItem = event.value.length ? $.extend({}, picker.getListItem(event.value), {disabled: true}) : $.extend({}, picker.getListItem(event.oldValue), {disabled: false}); + + $('.user-picker[name^=branches]').each(function() + { + if(this === select) return; + + var $select = $(this); + var selectPicker = $select.data('zui.picker'); + + if(selectPicker) selectPicker.updateOptionList([$.extend({}, newItem)]); + }); +} + +/** + * Save branch priv. + * + * @access public + * @return void + */ +function savePriv() +{ + $('#saveBtn').addClass('hidden'); + $('#submit').removeClass('hidden'); + $('#submit').click(); +} + +/** + * Add item. + * + * @param object $obj + * @access public + * @return void + */ +function addItem(obj) +{ + var item = $('#addItem').html().replace(/%i%/g, itemIndex); + var $tr = $('' + item + '').insertAfter($(obj).closest('tr')); + var $branches = $tr.find('select').addClass('user-picker').trigger('list:updated').picker({type: 'user'}); + itemIndex++; + + var disabledItems = []; + $('.user-picker[name^=branches]').each(function() + { + if(this === $branches[0]) return; + var $select = $(this); + var picker = $select.data('zui.picker'); + if(!picker) return; + var selectItem = picker.getListItem(picker.getValue()); + if(selectItem) disabledItems.push($.extend({}, selectItem, {disabled: true})); + }); + if(disabledItems.length) $branches.data('zui.picker').updateOptionList(disabledItems); +} + +/** + * Delete item. + * + * @param object $obj + * @access public + * @return void + */ +function deleteItem(obj) +{ + if($('#privForm .table tbody').children().length < 2) return false; + + $(obj).closest('tr').find('.picker .picker-selection-remove').click(); + $(obj).closest('tr').remove(); +} diff --git a/module/gitlab/js/managetagpriv.js b/module/gitlab/js/managetagpriv.js new file mode 100644 index 0000000000..c431f79906 --- /dev/null +++ b/module/gitlab/js/managetagpriv.js @@ -0,0 +1,74 @@ +/* Update other picker on change */ +$.zui.Picker.DEFAULTS.onChange = function(event) +{ + var picker = event.picker; + if(!picker.$formItem.is('[name^=tags]')) return; + + var select = picker.$formItem[0]; + var newItem = event.value.length ? $.extend({}, picker.getListItem(event.value), {disabled: true}) : $.extend({}, picker.getListItem(event.oldValue), {disabled: false}); + + $('.user-picker[name^=tags]').each(function() + { + if(this === select) return; + + var $select = $(this); + var selectPicker = $select.data('zui.picker'); + + if(selectPicker) selectPicker.updateOptionList([$.extend({}, newItem)]); + }); +} + +/** + * Save tag priv. + * + * @access public + * @return void + */ +function savePriv() +{ + $('#saveBtn').addClass('hidden'); + $('#submit').removeClass('hidden'); + $('#submit').click(); +} + +/** + * Add item. + * + * @param object $obj + * @access public + * @return void + */ +function addItem(obj) +{ + var item = $('#addItem').html().replace(/%i%/g, itemIndex); + var $tr = $('' + item + '').insertAfter($(obj).closest('tr')); + var $tags = $tr.find('select').addClass('user-picker').trigger('list:updated').picker({type: 'user'}); + itemIndex++; + + var disabledItems = []; + $('.user-picker[name^=tags]').each(function() + { + if(this === $tags[0]) return; + var $select = $(this); + var picker = $select.data('zui.picker'); + if(!picker) return; + var selectItem = picker.getListItem(picker.getValue()); + if(selectItem) disabledItems.push($.extend({}, selectItem, {disabled: true})); + }); + if(disabledItems.length) $tags.data('zui.picker').updateOptionList(disabledItems); +} + +/** + * Delete item. + * + * @param object $obj + * @access public + * @return void + */ +function deleteItem(obj) +{ + if($('#privForm .table tbody').children().length < 2) return false; + + $(obj).closest('tr').find('.picker .picker-selection-remove').click(); + $(obj).closest('tr').remove(); +} diff --git a/module/gitlab/lang/de.php b/module/gitlab/lang/de.php index 169875c665..41d82d8582 100644 --- a/module/gitlab/lang/de.php +++ b/module/gitlab/lang/de.php @@ -34,7 +34,7 @@ $lang->gitlab->browseUser = "User"; $lang->gitlab->browseGroup = "Group"; $lang->gitlab->browseBranch = "GitLab Branch List"; $lang->gitlab->browseTag = "GitLab Tag List"; -$lang->gitlab->browseTagPriv = "GitLab Tag protected List"; +$lang->gitlab->browseTagPriv = "Protected tag"; $lang->gitlab->gitlabIssue = "GitLab Issue"; $lang->gitlab->zentaoProduct = 'Zentao Product'; $lang->gitlab->objectType = 'Type'; // task, bug, story @@ -52,14 +52,9 @@ $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->createTag = 'Create Tag'; $lang->gitlab->deleteTag = 'Delete tag'; -$lang->gitlab->createTagPriv = 'Create tag protected'; -$lang->gitlab->editTagPriv = 'Edit tag protected'; -$lang->gitlab->deleteTagPriv = 'Delete tag protected'; +$lang->gitlab->svaeFailed = '『%s』save failed'; $lang->gitlab->id = 'ID'; $lang->gitlab->name = "Server Name"; diff --git a/module/gitlab/lang/en.php b/module/gitlab/lang/en.php index 169875c665..41d82d8582 100644 --- a/module/gitlab/lang/en.php +++ b/module/gitlab/lang/en.php @@ -34,7 +34,7 @@ $lang->gitlab->browseUser = "User"; $lang->gitlab->browseGroup = "Group"; $lang->gitlab->browseBranch = "GitLab Branch List"; $lang->gitlab->browseTag = "GitLab Tag List"; -$lang->gitlab->browseTagPriv = "GitLab Tag protected List"; +$lang->gitlab->browseTagPriv = "Protected tag"; $lang->gitlab->gitlabIssue = "GitLab Issue"; $lang->gitlab->zentaoProduct = 'Zentao Product'; $lang->gitlab->objectType = 'Type'; // task, bug, story @@ -52,14 +52,9 @@ $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->createTag = 'Create Tag'; $lang->gitlab->deleteTag = 'Delete tag'; -$lang->gitlab->createTagPriv = 'Create tag protected'; -$lang->gitlab->editTagPriv = 'Edit tag protected'; -$lang->gitlab->deleteTagPriv = 'Delete tag protected'; +$lang->gitlab->svaeFailed = '『%s』save failed'; $lang->gitlab->id = 'ID'; $lang->gitlab->name = "Server Name"; diff --git a/module/gitlab/lang/fr.php b/module/gitlab/lang/fr.php index 169875c665..41d82d8582 100644 --- a/module/gitlab/lang/fr.php +++ b/module/gitlab/lang/fr.php @@ -34,7 +34,7 @@ $lang->gitlab->browseUser = "User"; $lang->gitlab->browseGroup = "Group"; $lang->gitlab->browseBranch = "GitLab Branch List"; $lang->gitlab->browseTag = "GitLab Tag List"; -$lang->gitlab->browseTagPriv = "GitLab Tag protected List"; +$lang->gitlab->browseTagPriv = "Protected tag"; $lang->gitlab->gitlabIssue = "GitLab Issue"; $lang->gitlab->zentaoProduct = 'Zentao Product'; $lang->gitlab->objectType = 'Type'; // task, bug, story @@ -52,14 +52,9 @@ $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->createTag = 'Create Tag'; $lang->gitlab->deleteTag = 'Delete tag'; -$lang->gitlab->createTagPriv = 'Create tag protected'; -$lang->gitlab->editTagPriv = 'Edit tag protected'; -$lang->gitlab->deleteTagPriv = 'Delete tag protected'; +$lang->gitlab->svaeFailed = '『%s』save failed'; $lang->gitlab->id = 'ID'; $lang->gitlab->name = "Server Name"; diff --git a/module/gitlab/lang/vi.php b/module/gitlab/lang/vi.php index 169875c665..41d82d8582 100644 --- a/module/gitlab/lang/vi.php +++ b/module/gitlab/lang/vi.php @@ -34,7 +34,7 @@ $lang->gitlab->browseUser = "User"; $lang->gitlab->browseGroup = "Group"; $lang->gitlab->browseBranch = "GitLab Branch List"; $lang->gitlab->browseTag = "GitLab Tag List"; -$lang->gitlab->browseTagPriv = "GitLab Tag protected List"; +$lang->gitlab->browseTagPriv = "Protected tag"; $lang->gitlab->gitlabIssue = "GitLab Issue"; $lang->gitlab->zentaoProduct = 'Zentao Product'; $lang->gitlab->objectType = 'Type'; // task, bug, story @@ -52,14 +52,9 @@ $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->createTag = 'Create Tag'; $lang->gitlab->deleteTag = 'Delete tag'; -$lang->gitlab->createTagPriv = 'Create tag protected'; -$lang->gitlab->editTagPriv = 'Edit tag protected'; -$lang->gitlab->deleteTagPriv = 'Delete tag protected'; +$lang->gitlab->svaeFailed = '『%s』save failed'; $lang->gitlab->id = 'ID'; $lang->gitlab->name = "Server Name"; diff --git a/module/gitlab/lang/zh-cn.php b/module/gitlab/lang/zh-cn.php index d9ac66d15f..7273c0c8ef 100644 --- a/module/gitlab/lang/zh-cn.php +++ b/module/gitlab/lang/zh-cn.php @@ -34,7 +34,7 @@ $lang->gitlab->browseUser = "用户"; $lang->gitlab->browseGroup = "群组"; $lang->gitlab->browseBranch = "GitLab分支列表"; $lang->gitlab->browseTag = "GitLab标签列表"; -$lang->gitlab->browseTagPriv = "GitLab标签保护列表"; +$lang->gitlab->browseTagPriv = "标签保护管理"; $lang->gitlab->gitlabIssue = "{$lang->gitlab->common} issue"; $lang->gitlab->zentaoProduct = '禅道产品'; $lang->gitlab->objectType = '类型'; // task, bug, story @@ -52,14 +52,9 @@ $lang->gitlab->createBranch = '添加分支'; $lang->gitlab->manageGroupMembers = '群组成员管理'; $lang->gitlab->createWebhook = '创建Webhook'; $lang->gitlab->browseBranchPriv = '分支保护管理'; -$lang->gitlab->createBranchPriv = '创建分支保护'; -$lang->gitlab->editBranchPriv = '编辑分支保护'; -$lang->gitlab->deleteBranchPriv = '删除分支保护'; $lang->gitlab->createTag = '创建标签'; $lang->gitlab->deleteTag = '删除标签'; -$lang->gitlab->createTagPriv = '创建标签保护'; -$lang->gitlab->editTagPriv = '编辑标签保护'; -$lang->gitlab->deleteTagPriv = '删除标签保护'; +$lang->gitlab->svaeFailed = '『%s』保存失败'; $lang->gitlab->id = 'ID'; $lang->gitlab->name = "服务器名称"; diff --git a/module/gitlab/model.php b/module/gitlab/model.php index aa7d73dca6..561a2f4878 100644 --- a/module/gitlab/model.php +++ b/module/gitlab/model.php @@ -1203,7 +1203,7 @@ class gitlabModel extends model /* Return an empty array if where is one existing webhook. */ if($this->isWebhookExists($repo, $hook->url)) return array(); - $result = $this->apiCreateHook($repo->gitlab, $repo->project, $hook); + $result = $this->apiCreateHook($repo->gitService, $repo->project, $hook); if(!empty($result->id)) return true; return false; @@ -1218,7 +1218,7 @@ class gitlabModel extends model */ public function isWebhookExists($repo, $url = '') { - $hookList = $this->apiGetHooks($repo->gitlab, $repo->project); + $hookList = $this->apiGetHooks($repo->gitService, $repo->project); foreach($hookList as $hook) { if($hook->url == $url) return true; @@ -2549,59 +2549,49 @@ class gitlabModel extends model } /** - * Get single protct branch by API. + * Manage branch privs. * * @param int $gitlabID * @param int $projectID - * @param string $branch + * @param array $protected * @access public - * @return object + * @return array */ - public function apiGetSingleBranchPriv($gitlabID, $projectID, $branch) + public function manageBranchPrivs($gitlabID, $projectID, $protected = array()) { - if(empty($gitlabID)) return false; - $branch = urlencode($branch); - $url = sprintf($this->getApiRoot($gitlabID), "/projects/$projectID/protected_branches/$branch"); - return json_decode(commonModel::http($url)); - } + $data = (array)fixer::input('post')->get(); + extract($data); + $failure = array(); - /** - * 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)) + /* Remove privs. */ + foreach($protected as $name => $branch) { - dao::$errors['name'][] = $this->lang->gitlab->branch->emptyPrivNameError; - return false; + if(!in_array($name, $branches)) + { + $result = $this->apiDeleteBranchPriv($gitlabID, $projectID, $name); + if($result and substr($result->message, 0, 2) != '20') $failure[] = $name; + } } - $priv->name = urldecode(helper::safe64Decode($priv->name)); - $singleBranch = $this->apiGetSingleBranchPriv($gitlabID, $projectID, $priv->name); - if(empty($branch) && !empty($singleBranch->id)) + $priv = new stdClass(); + foreach($branches as $key => $name) { - dao::$errors['name'][] = $this->lang->gitlab->branch->issetPrivNameError; - return false; + /* Process exists data. */ + if(isset($protected[$name])) + { + if($protected[$name]->pushAccess == $pushLevels[$key] and $protected[$name]->mergeAccess == $mergeLevels[$key]) continue; + + $result = $this->apiDeleteBranchPriv($gitlabID, $projectID, $name); + if(isset($result->message) and substr($result->message, 0, 2) != '20') $failure[] = $name; + } + + $priv->name = $name; + $priv->push_access_level = $pushLevels[$key]; + $priv->merge_access_level = $mergeLevels[$key]; + $response = $this->apiCreateBranchPriv($gitlabID, $projectID, $priv); + if(isset($response->message) and substr($response->message, 0, 2) != '20') $failure[] = $name; } - - 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); + return array_unique($failure); } /** @@ -2630,7 +2620,7 @@ class gitlabModel extends model * @param int $projectID * @param string $branch * @access public - * @return object + * @return array */ public function apiDeleteBranchPriv($gitlabID, $projectID, $branch) { @@ -2642,58 +2632,48 @@ class gitlabModel extends model } /** - * Create gitlab protect tag. + * Manage tag privs. * * @param int $gitlabID * @param int $projectID - * @param string $tag + * @param array $protected * @access public - * @return bool + * @return array */ - public function createTagPriv($gitlabID, $projectID, $tag = '') + public function manageTagPrivs($gitlabID, $projectID, $protected = array()) { - $priv = fixer::input('post')->get(); - if(empty($priv->name)) + $data = (array)fixer::input('post')->get(); + extract($data); + $failure = array(); + + /* Remove privs. */ + foreach($protected as $name => $tag) { - dao::$errors['name'][] = $this->lang->gitlab->tag->emptyPrivNameError; - return false; + if(!in_array($name, $tags)) + { + $result = $this->apiDeleteTagPriv($gitlabID, $projectID, $name); + if($result and substr($result->message, 0, 2) != '20') $failure[] = $name; + } } - $singleTag = $this->apiGetSingleTagPriv($gitlabID, $projectID, $priv->name); - if(empty($tag) && !empty($singleTag->id)) + $priv = new stdClass(); + foreach($tags as $key => $name) { - dao::$errors['name'][] = $this->lang->gitlab->tag->issetPrivNameError; - return false; + /* Process exists data. */ + if(isset($protected[$name])) + { + if($protected[$name]->createAccess == $createLevels[$key]) continue; + + $result = $this->apiDeleteTagPriv($gitlabID, $projectID, $name); + if(isset($result->message) and substr($result->message, 0, 2) != '20') $failure[] = $name; + } + + $priv->name = $name; + $priv->create_access_level = $createLevels[$key]; + $response = $this->apiCreateTagPriv($gitlabID, $projectID, $priv); + if(isset($response->message) and substr($response->message, 0, 2) != '20') $failure[] = $name; } - - if(!empty($tag) && !empty($singleTag->name)) $this->apiDeleteTagPriv($gitlabID, $projectID, $tag); - $response = $this->apiCreateTagPriv($gitlabID, $projectID, $priv); - - if(!empty($response->id)) - { - $action = empty($tag) ? 'created' : 'edited'; - $this->loadModel('action')->create('gitlabtagpriv', $response->id, $action, '', $response->name); - return true; - } - - return $this->apiErrorHandling($response); - } - - /** - * Get single protct tag by API. - * - * @param int $gitlabID - * @param int $projectID - * @param string $tag - * @access public - * @return object - */ - public function apiGetSingleTagPriv($gitlabID, $projectID, $tag) - { - if(empty($gitlabID)) return false; - $tag = urlencode($tag); - $url = sprintf($this->getApiRoot($gitlabID), "/projects/$projectID/protected_tags/$tag"); - return json_decode(commonModel::http($url)); + return array_unique($failure); } /** @@ -2896,23 +2876,4 @@ class gitlabModel extends model $html .= ''; return $html; } - - /** - * Download zip code. - * - * @param int $gitlabID - * @param int $projectID - * @param string $branch - * @param string $ext tar.gz|tar.bz2|tbz|tbz2|tb2|bz2|tar|zip - * @access public - * @return string - */ - public function downloadCode($gitlabID = 0, $projectID = 0, $branch = '', $ext = 'zip') - { - if(empty($gitlabID) or empty($projectID)) return false; - - $url = sprintf($this->getApiRoot($gitlabID), "/projects/$projectID/repository/archive." . $ext); - if($branch) $url .= '&sha=' . $branch; - return $url; - } } diff --git a/module/gitlab/view/browse.html.php b/module/gitlab/view/browse.html.php index af931fd6d9..a83c6de4bf 100644 --- a/module/gitlab/view/browse.html.php +++ b/module/gitlab/view/browse.html.php @@ -43,7 +43,7 @@ $gitlab): ?> - + @@ -100,7 +100,7 @@ diff --git a/module/kanban/view/createspace.html.php b/module/kanban/view/createspace.html.php index 3f83d4260f..94ab7f9769 100644 --- a/module/kanban/view/createspace.html.php +++ b/module/kanban/view/createspace.html.php @@ -36,7 +36,7 @@ diff --git a/module/kanban/view/edit.html.php b/module/kanban/view/edit.html.php index 28823888a4..2eb21ae1ca 100644 --- a/module/kanban/view/edit.html.php +++ b/module/kanban/view/edit.html.php @@ -22,7 +22,7 @@
    doc->libType;?>
    doc->lib;?>
    doc->type;?>doc->types, 'text');?>
    confirm);?>
    execution->projectName;?> execution->$name;?>execution->$code;?> '>execution->$PM;?> '>execution->PO;?> '>execution->QD;?>project, "class='form-control picker-select' data-lastselected='{$executions[$executionID]->project}' onchange='changeProject(this, $executionID, {$executions[$executionID]->project})'");?> name, "id='names{$executionID}' class='form-control'");?>code, "class='form-control'");?>code, "class='form-control'");?> ' style='overflow:visible'>PM, "class='form-control picker-select'");?> ' style='overflow:visible'>PO, "class='form-control picker-select'");?> ' style='overflow:visible'>QD, "class='form-control picker-select'");?>
    execution->execCode : $lang->execution->code;?>
    execution->dateRange;?> diff --git a/module/execution/view/dynamic.html.php b/module/execution/view/dynamic.html.php index bb597e2819..ed80260a74 100755 --- a/module/execution/view/dynamic.html.php +++ b/module/execution/view/dynamic.html.php @@ -88,7 +88,7 @@ actionLabel;?> objectLabel;?> objectID;?> - objectName) echo html::a($action->objectLink, $action->objectName);?> + objectName) echo !empty($action->objectLink) ? html::a($action->objectLink, $action->objectName) : $action->objectName;?> diff --git a/module/execution/view/edit.html.php b/module/execution/view/edit.html.php index d1c59a4cf3..e8043c98f2 100644 --- a/module/execution/view/edit.html.php +++ b/module/execution/view/edit.html.php @@ -39,10 +39,12 @@ execution->name;?> name, "class='form-control' required");?>
    execution->code;?> code, "class='form-control' required");?>
    execution->dateRange;?> diff --git a/module/execution/view/view.html.php b/module/execution/view/view.html.php index 719f49369c..1307ded6a8 100644 --- a/module/execution/view/view.html.php +++ b/module/execution/view/view.html.php @@ -158,7 +158,8 @@
    -

    id;?> code;?> name;?>

    + setCode) and $config->setCode == 0) ? 'hidden' : '';?> +

    id;?> code;?> name;?>

    diff --git a/module/git/model.php b/module/git/model.php index 1632d45f6a..602afcea43 100644 --- a/module/git/model.php +++ b/module/git/model.php @@ -131,8 +131,14 @@ class gitModel extends model $gitlabAccountPairs = array(); if($repo->SCM == 'Gitlab') { - $gitlabUserList = $this->loadModel('gitlab')->apiGetUsers($repo->gitlab); - $acountIDPairs = $this->gitlab->getUserIdAccountPairs($repo->gitlab); + $gitlabUserList = $this->loadModel('gitlab')->apiGetUsers($repo->gitService); + $acountIDPairs = $this->gitlab->getUserIdAccountPairs($repo->gitService); + foreach($gitlabUserList as $gitlabUser) $gitlabAccountPairs[$gitlabUser->realname] = zget($acountIDPairs, $gitlabUser->id, ''); + } + elseif($repo->SCM == 'Gitea') + { + $gitlabUserList = $this->loadModel('gitea')->apiGetUsers($repo->gitService); + $acountIDPairs = $this->gitea->getUserAccountIdPairs($repo->gitService, 'openID,account'); foreach($gitlabUserList as $gitlabUser) $gitlabAccountPairs[$gitlabUser->realname] = zget($acountIDPairs, $gitlabUser->id, ''); } diff --git a/module/gitea/control.php b/module/gitea/control.php index 413f2c2e52..cd18b89de5 100644 --- a/module/gitea/control.php +++ b/module/gitea/control.php @@ -43,6 +43,12 @@ class gitea extends control /* Admin user don't need bind. */ $giteaList = $this->gitea->getList($orderBy, $pager); + $myGiteas = $this->gitea->getGiteaListByAccount(); + foreach($giteaList as $gitea) + { + $gitea->isBindUser = true; + if(!$this->app->user->admin and !isset($myGiteas[$gitea->id])) $gitea->isBindUser = false; + } $this->view->title = $this->lang->gitea->common . $this->lang->colon . $this->lang->gitea->browse; $this->view->giteaList = $giteaList; @@ -164,4 +170,53 @@ class gitea extends control return true; } + + /** + * Bind gitea user to zentao users. + * + * @param int $giteaID + * @access public + * @return void + */ + public function bindUser($giteaID) + { + $zentaoUsers = $this->dao->select('account,email,realname')->from(TABLE_USER)->fetchAll('account'); + $userPairs = $this->loadModel('user')->getPairs('noclosed|noletter'); + + if($_POST) + { + $this->gitea->bindUser($giteaID); + if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError())); + return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => $this->server->http_referer)); + } + + $this->view->title = $this->lang->gitea->bindUser; + $this->view->userPairs = $userPairs; + $this->view->giteaUsers = $this->gitea->apiGetUsers($giteaID); + $this->view->bindedUsers = $this->gitea->getUserAccountIdPairs($giteaID); + $this->view->matchedResult = $this->gitea->getMatchedUsers($giteaID, $this->view->giteaUsers, $zentaoUsers); + $this->display(); + } + + /** + * Ajax getProjectBranches + * + * @param int $giteaID + * @param string $project + * @access public + * @return void + */ + public function ajaxGetProjectBranches($giteaID, $project) + { + if(!$giteaID or !$project) return $this->send(array('message' => array())); + + $project = urldecode(base64_decode($project)); + $branches = $this->gitea->apiGetBranches($giteaID, $project); + $options = ""; + foreach($branches as $branch) + { + $options .= ""; + } + $this->send($options); + } } diff --git a/module/gitea/lang/de.php b/module/gitea/lang/de.php index 5d0779ba55..064ceb7d3e 100644 --- a/module/gitea/lang/de.php +++ b/module/gitea/lang/de.php @@ -8,6 +8,13 @@ $lang->gitea->edit = 'Edit Gitea'; $lang->gitea->view = 'View Gitea'; $lang->gitea->delete = 'Delete Gitea'; $lang->gitea->confirmDelete = 'Do you want to delete this Gitea server?'; +$lang->gitea->bindUser = 'Bind User'; +$lang->gitea->giteaAccount = 'Gitea Account'; +$lang->gitea->zentaoAccount = 'Zentao Account'; +$lang->gitea->bindingStatus = 'Binding Status'; +$lang->gitea->notBind = 'Not bind'; +$lang->gitea->binded = 'Binded'; +$lang->gitea->bindDynamic = '%s and Zentao user %s'; $lang->gitea->browseAction = 'Gitea List'; $lang->gitea->deleteAction = 'Delete Gitea'; @@ -17,8 +24,9 @@ $lang->gitea->name = "Server Name"; $lang->gitea->url = 'Server URL'; $lang->gitea->token = 'Token'; -$lang->gitea->tokenLimit = "The current token has no admin privilege. Please regenerate one with root user in Gitea."; -$lang->gitea->hostError = "So the current Gitea server address is invalid, please confirm that the current server can be accessed and try again."; +$lang->gitea->tokenLimit = "The current token has no admin privilege. Please regenerate one with root user in Gitea."; +$lang->gitea->hostError = "So the current Gitea server address is invalid, please confirm that the current server can be accessed and try again."; +$lang->gitea->bindUserError = "Can not bind users repeatedly %s"; $lang->gitea->server = "Server List"; $lang->gitea->lblCreate = 'Create Gitea Server'; diff --git a/module/gitea/lang/en.php b/module/gitea/lang/en.php index 5d0779ba55..064ceb7d3e 100644 --- a/module/gitea/lang/en.php +++ b/module/gitea/lang/en.php @@ -8,6 +8,13 @@ $lang->gitea->edit = 'Edit Gitea'; $lang->gitea->view = 'View Gitea'; $lang->gitea->delete = 'Delete Gitea'; $lang->gitea->confirmDelete = 'Do you want to delete this Gitea server?'; +$lang->gitea->bindUser = 'Bind User'; +$lang->gitea->giteaAccount = 'Gitea Account'; +$lang->gitea->zentaoAccount = 'Zentao Account'; +$lang->gitea->bindingStatus = 'Binding Status'; +$lang->gitea->notBind = 'Not bind'; +$lang->gitea->binded = 'Binded'; +$lang->gitea->bindDynamic = '%s and Zentao user %s'; $lang->gitea->browseAction = 'Gitea List'; $lang->gitea->deleteAction = 'Delete Gitea'; @@ -17,8 +24,9 @@ $lang->gitea->name = "Server Name"; $lang->gitea->url = 'Server URL'; $lang->gitea->token = 'Token'; -$lang->gitea->tokenLimit = "The current token has no admin privilege. Please regenerate one with root user in Gitea."; -$lang->gitea->hostError = "So the current Gitea server address is invalid, please confirm that the current server can be accessed and try again."; +$lang->gitea->tokenLimit = "The current token has no admin privilege. Please regenerate one with root user in Gitea."; +$lang->gitea->hostError = "So the current Gitea server address is invalid, please confirm that the current server can be accessed and try again."; +$lang->gitea->bindUserError = "Can not bind users repeatedly %s"; $lang->gitea->server = "Server List"; $lang->gitea->lblCreate = 'Create Gitea Server'; diff --git a/module/gitea/lang/fr.php b/module/gitea/lang/fr.php index 5d0779ba55..064ceb7d3e 100644 --- a/module/gitea/lang/fr.php +++ b/module/gitea/lang/fr.php @@ -8,6 +8,13 @@ $lang->gitea->edit = 'Edit Gitea'; $lang->gitea->view = 'View Gitea'; $lang->gitea->delete = 'Delete Gitea'; $lang->gitea->confirmDelete = 'Do you want to delete this Gitea server?'; +$lang->gitea->bindUser = 'Bind User'; +$lang->gitea->giteaAccount = 'Gitea Account'; +$lang->gitea->zentaoAccount = 'Zentao Account'; +$lang->gitea->bindingStatus = 'Binding Status'; +$lang->gitea->notBind = 'Not bind'; +$lang->gitea->binded = 'Binded'; +$lang->gitea->bindDynamic = '%s and Zentao user %s'; $lang->gitea->browseAction = 'Gitea List'; $lang->gitea->deleteAction = 'Delete Gitea'; @@ -17,8 +24,9 @@ $lang->gitea->name = "Server Name"; $lang->gitea->url = 'Server URL'; $lang->gitea->token = 'Token'; -$lang->gitea->tokenLimit = "The current token has no admin privilege. Please regenerate one with root user in Gitea."; -$lang->gitea->hostError = "So the current Gitea server address is invalid, please confirm that the current server can be accessed and try again."; +$lang->gitea->tokenLimit = "The current token has no admin privilege. Please regenerate one with root user in Gitea."; +$lang->gitea->hostError = "So the current Gitea server address is invalid, please confirm that the current server can be accessed and try again."; +$lang->gitea->bindUserError = "Can not bind users repeatedly %s"; $lang->gitea->server = "Server List"; $lang->gitea->lblCreate = 'Create Gitea Server'; diff --git a/module/gitea/lang/vi.php b/module/gitea/lang/vi.php index 5d0779ba55..064ceb7d3e 100644 --- a/module/gitea/lang/vi.php +++ b/module/gitea/lang/vi.php @@ -8,6 +8,13 @@ $lang->gitea->edit = 'Edit Gitea'; $lang->gitea->view = 'View Gitea'; $lang->gitea->delete = 'Delete Gitea'; $lang->gitea->confirmDelete = 'Do you want to delete this Gitea server?'; +$lang->gitea->bindUser = 'Bind User'; +$lang->gitea->giteaAccount = 'Gitea Account'; +$lang->gitea->zentaoAccount = 'Zentao Account'; +$lang->gitea->bindingStatus = 'Binding Status'; +$lang->gitea->notBind = 'Not bind'; +$lang->gitea->binded = 'Binded'; +$lang->gitea->bindDynamic = '%s and Zentao user %s'; $lang->gitea->browseAction = 'Gitea List'; $lang->gitea->deleteAction = 'Delete Gitea'; @@ -17,8 +24,9 @@ $lang->gitea->name = "Server Name"; $lang->gitea->url = 'Server URL'; $lang->gitea->token = 'Token'; -$lang->gitea->tokenLimit = "The current token has no admin privilege. Please regenerate one with root user in Gitea."; -$lang->gitea->hostError = "So the current Gitea server address is invalid, please confirm that the current server can be accessed and try again."; +$lang->gitea->tokenLimit = "The current token has no admin privilege. Please regenerate one with root user in Gitea."; +$lang->gitea->hostError = "So the current Gitea server address is invalid, please confirm that the current server can be accessed and try again."; +$lang->gitea->bindUserError = "Can not bind users repeatedly %s"; $lang->gitea->server = "Server List"; $lang->gitea->lblCreate = 'Create Gitea Server'; diff --git a/module/gitea/lang/zh-cn.php b/module/gitea/lang/zh-cn.php index dd8da67d29..35d94b0dd5 100644 --- a/module/gitea/lang/zh-cn.php +++ b/module/gitea/lang/zh-cn.php @@ -8,6 +8,13 @@ $lang->gitea->edit = '编辑Gitea'; $lang->gitea->view = '查看Gitea'; $lang->gitea->delete = '删除Gitea'; $lang->gitea->confirmDelete = '确认删除该Gitea吗?'; +$lang->gitea->bindUser = '绑定用户'; +$lang->gitea->giteaAccount = 'Gitea用户'; +$lang->gitea->zentaoAccount = '禅道用户'; +$lang->gitea->bindingStatus = '绑定状态'; +$lang->gitea->notBind = '未绑定'; +$lang->gitea->binded = '已绑定'; +$lang->gitea->bindDynamic = '%s与禅道用户%s'; $lang->gitea->browseAction = 'Gitea列表'; $lang->gitea->deleteAction = '删除Gitea'; @@ -17,8 +24,9 @@ $lang->gitea->name = "服务器名称"; $lang->gitea->url = '服务器地址'; $lang->gitea->token = 'Token'; -$lang->gitea->tokenLimit = "Gitea Token权限不足。"; -$lang->gitea->hostError = "当前Gitea服务器地址无效,请确认当前服务器可被访问"; +$lang->gitea->tokenLimit = "Gitea Token权限不足。"; +$lang->gitea->hostError = "当前Gitea服务器地址无效,请确认当前服务器可被访问"; +$lang->gitea->bindUserError = "不能重复绑定用户 %s"; $lang->gitea->server = "服务器列表"; $lang->gitea->lblCreate = '添加Gitea服务器'; diff --git a/module/gitea/lang/zh-tw.php b/module/gitea/lang/zh-tw.php index dd8da67d29..7e273df350 100644 --- a/module/gitea/lang/zh-tw.php +++ b/module/gitea/lang/zh-tw.php @@ -8,6 +8,13 @@ $lang->gitea->edit = '编辑Gitea'; $lang->gitea->view = '查看Gitea'; $lang->gitea->delete = '删除Gitea'; $lang->gitea->confirmDelete = '确认删除该Gitea吗?'; +$lang->gitea->bindUser = '绑定用户'; +$lang->gitea->giteaAccount = 'Gitea用户'; +$lang->gitea->zentaoAccount = '禅道用户'; +$lang->gitea->bindingStatus = '绑定状态'; +$lang->gitea->notBind = '未绑定'; +$lang->gitea->binded = '已绑定'; +$lang->gitea->bindDynamic = '%s与禅道用户%s'; $lang->gitea->browseAction = 'Gitea列表'; $lang->gitea->deleteAction = '删除Gitea'; diff --git a/module/gitea/model.php b/module/gitea/model.php index 2f72de8403..0930573c47 100644 --- a/module/gitea/model.php +++ b/module/gitea/model.php @@ -104,6 +104,63 @@ class giteaModel extends model return $this->loadModel('pipeline')->update($id); } + /** + * Bind users. + * + * @param int $giteaID + * @access public + * @return array + */ + public function bindUser($giteaID) + { + $userPairs = $this->loadModel('user')->getPairs('noclosed|noletter'); + $users = $this->post->zentaoUsers; + $giteaNames = $this->post->giteaUserNames; + $accountList = array(); + $repeatUsers = array(); + foreach($users as $openID => $user) + { + if(empty($user)) continue; + if(isset($accountList[$user])) $repeatUsers[] = zget($userPairs, $user); + $accountList[$user] = $openID; + } + + if(count($repeatUsers)) + { + dao::$errors[] = sprintf($this->lang->gitea->bindUserError, join(',', $repeatUsers)); + return false; + } + + $user = new stdclass; + $user->providerID = $giteaID; + $user->providerType = 'gitea'; + + $oldUsers = $this->dao->select('*')->from(TABLE_OAUTH)->where('providerType')->eq($user->providerType)->andWhere('providerID')->eq($user->providerID)->fetchAll('openID'); + foreach($users as $openID => $account) + { + $existAccount = isset($oldUsers[$openID]) ? $oldUsers[$openID] : ''; + + if($existAccount and $existAccount->account != $account) + { + $this->dao->delete() + ->from(TABLE_OAUTH) + ->where('openID')->eq($openID) + ->andWhere('providerType')->eq($user->providerType) + ->andWhere('providerID')->eq($user->providerID) + ->exec(); + $this->loadModel('action')->create('giteauser', $giteaID, 'unbind', '', sprintf($this->lang->gitea->bindDynamic, $giteaNames[$openID], $zentaoUsers[$existAccount->account]->realname)); + } + if(!$existAccount or $existAccount->account != $account) + { + if(!$account) continue; + $user->account = $account; + $user->openID = $openID; + $this->dao->insert(TABLE_OAUTH)->data($user)->exec(); + $this->loadModel('action')->create('giteauser', $giteaID, 'bind', '', sprintf($this->lang->gitea->bindDynamic, $giteaNames[$openID], $zentaoUsers[$account]->realname)); + } + } + } + /** * Api error handling. * @@ -224,4 +281,316 @@ class giteaModel extends model ->andWhere('account')->eq($account) ->fetchPairs('providerID'); } + + /** + * Get zentao account gitea user id pairs of one gitea. + * + * @param int $giteaID + * @access public + * @return array + */ + public function getUserAccountIdPairs($giteaID, $fields = 'account,openID') + { + return $this->dao->select($fields)->from(TABLE_OAUTH) + ->where('providerType')->eq('gitea') + ->andWhere('providerID')->eq($giteaID) + ->fetchPairs(); + } + + /** + * Get gitea user id by zentao account. + * + * @param int $giteaID + * @param string $zentaoAccount + * @access public + * @return array + */ + public function getUserIDByZentaoAccount($giteaID, $zentaoAccount) + { + return $this->dao->select('openID')->from(TABLE_OAUTH) + ->where('providerType')->eq('gitea') + ->andWhere('providerID')->eq($giteaID) + ->andWhere('account')->eq($zentaoAccount) + ->fetch('openID'); + } + + /** + * Get matched gitea users. + * + * @param int $giteaID + * @param array $giteaUsers + * @param array $zentaoUsers + * @access public + * @return array + */ + public function getMatchedUsers($giteaID, $giteaUsers, $zentaoUsers) + { + $matches = new stdclass; + foreach($giteaUsers as $giteaUser) + { + foreach($zentaoUsers as $zentaoUser) + { + if($giteaUser->account == $zentaoUser->account) $matches->accounts[$giteaUser->account][] = $zentaoUser->account; + if($giteaUser->realname == $zentaoUser->realname) $matches->names[$giteaUser->realname][] = $zentaoUser->account; + if($giteaUser->email == $zentaoUser->email) $matches->emails[$giteaUser->email][] = $zentaoUser->account; + } + } + + $bindedUsers = $this->getUserAccountIdPairs($giteaID, 'openID,account'); + $matchedUsers = array(); + foreach($giteaUsers as $giteaUser) + { + if(isset($bindedUsers[$giteaUser->account])) + { + $giteaUser->zentaoAccount = $bindedUsers[$giteaUser->account]; + $matchedUsers[] = $giteaUser; + continue; + } + + $matchedZentaoUsers = array(); + if(isset($matches->accounts[$giteaUser->account])) $matchedZentaoUsers = array_merge($matchedZentaoUsers, $matches->accounts[$giteaUser->account]); + if(isset($matches->emails[$giteaUser->email])) $matchedZentaoUsers = array_merge($matchedZentaoUsers, $matches->emails[$giteaUser->email]); + if(isset($matches->names[$giteaUser->realname])) $matchedZentaoUsers = array_merge($matchedZentaoUsers, $matches->names[$giteaUser->realname]); + + $matchedZentaoUsers = array_unique($matchedZentaoUsers); + if(count($matchedZentaoUsers) == 1) + { + $giteaUser->zentaoAccount = current($matchedZentaoUsers); + $matchedUsers[] = $giteaUser; + } + } + + return $matchedUsers; + } + + /** + * Get project by api. + * + * @param int $giteaID + * @param int $projectID + * @access public + * @return void + */ + public function apiGetSingleProject($giteaID, $projectID) + { + $apiRoot = $this->getApiRoot($giteaID); + if(!$apiRoot) return array(); + + $url = sprintf($apiRoot, "/repos/$projectID"); + $project = json_decode(commonModel::http($url)); + if(isset($project->name)) + { + $project->name_with_namespace = $project->full_name; + $project->path_with_namespace = $project->full_name; + $project->http_url_to_repo = $project->html_url; + $project->name_with_namespace = $project->full_name; + } + + return $project; + } + + /** + * Get projects by api. + * + * @param int $giteaID + * @param bool $sudo + * @access public + * @return array + */ + public function apiGetProjects($giteaID, $sudo = true) + { + $apiRoot = $this->getApiRoot($giteaID, $sudo); + if(!$apiRoot) return array(); + + $url = sprintf($apiRoot, "/repos/search"); + $allResults = array(); + for($page = 1; true; $page++) + { + $results = json_decode(commonModel::http($url . "&page={$page}&limit=50")); + if(!is_array($results->data)) break; + if(!empty($results->data)) $allResults = array_merge($allResults, $results->data); + if(count($results->data) < 50) break; + } + + return $allResults; + } + + /** + * Get gitea user list. + * + * @param int $giteaID + * @param bool $onlyLinked + * @access public + * @return array + */ + public function apiGetUsers($giteaID, $onlyLinked = false) + { + $response = array(); + $apiRoot = $this->getApiRoot($giteaID); + + for($page = 1; true; $page++) + { + $url = sprintf($apiRoot, "/users/search") . "&page={$page}&limit=50"; + $result = json_decode(commonModel::http($url)); + if(empty($result->data)) break; + + $response = array_merge($response, $result->data); + $page += 1; + } + + if(empty($response)) return array(); + + /* Get linked users. */ + $linkedUsers = array(); + if($onlyLinked) $linkedUsers = $this->getUserAccountIdPairs($giteaID, 'openID,account'); + + $users = array(); + foreach($response as $giteaUser) + { + if($onlyLinked and !isset($linkedUsers[$giteaUser->id])) continue; + + $user = new stdclass; + $user->id = $giteaUser->id; + $user->realname = $giteaUser->full_name ? $giteaUser->full_name : $giteaUser->username; + $user->account = $giteaUser->username; + $user->email = zget($giteaUser, 'email', ''); + $user->avatar = $giteaUser->avatar_url; + $user->createdAt = zget($giteaUser, 'created', ''); + $user->lastActivityOn = zget($giteaUser, 'last_login', ''); + + $users[] = $user; + } + + return $users; + } + + /** + * Get project repository branches by api. + * + * @param int $giteaID + * @param string $project + * @access public + * @return object + */ + public function apiGetBranches($giteaID, $project, $pager = null) + { + $url = sprintf($this->getApiRoot($giteaID), "/repos/{$project}/branches"); + $allResults = array(); + for($page = 1; true; $page++) + { + $results = json_decode(commonModel::http($url . "&page={$page}&limit=50")); + if(!is_array($results)) break; + if(!empty($results)) $allResults = array_merge($allResults, $results); + if(count($results) < 100) break; + } + + return $allResults; + } + + /** + * Get Forks of a project by API. + * + * @param int $giteaID + * @param string $projectID + * @access public + * @return object + */ + public function apiGetForks($giteaID, $projectID) + { + $url = sprintf($this->getApiRoot($giteaID), "/repos/$projectID/forks"); + return json_decode(commonModel::http($url)); + } + + /** + * Get upstream project by API. + * + * @param int $giteaID + * @param string $projectID + * @access public + * @return void + */ + public function apiGetUpstream($giteaID, $projectID) + { + $currentProject = $this->apiGetSingleProject($giteaID, $projectID); + if(isset($currentProject->parent->full_name)) return $currentProject->parent->full_name; + return array(); + } + + /** + * Get branches. + * + * @param int $giteaID + * @param string $project + * @access public + * @return array + */ + public function getBranches($giteaID, $project) + { + $rawBranches = $this->apiGetBranches($giteaID, $project); + + $branches = array(); + foreach($rawBranches as $branch) $branches[] = $branch->name; + + return $branches; + } + + /** + * Get gitea user id and realname pairs of one gitea. + * + * @param int $giteaID + * @access public + * @return array + */ + public function getUserIdRealnamePairs($giteaID) + { + return $this->dao->select('oauth.openID as openID,user.realname as realname') + ->from(TABLE_OAUTH)->alias('oauth') + ->leftJoin(TABLE_USER)->alias('user') + ->on("oauth.account = user.account") + ->where('providerType')->eq('gitea') + ->andWhere('providerID')->eq($giteaID) + ->fetchPairs(); + } + + /** + * Get single branch by API. + * + * @param int $giteaID + * @param int $projectID + * @param string $branch + * @access public + * @return object + */ + public function apiGetSingleBranch($giteaID, $projectID, $branch) + { + $url = sprintf($this->getApiRoot($giteaID), "/repos/$projectID/branches/$branch"); + return json_decode(commonModel::http($url)); + } + + /** + * Get protect branches of one project. + * + * @param int $giteaID + * @param string $project + * @param string $keyword + * @access public + * @return array + */ + public function apiGetBranchPrivs($giteaID, $project, $keyword = '') + { + $keyword = urlencode($keyword); + $url = sprintf($this->getApiRoot($giteaID), "/repos/$project/branch_protections"); + $branches = json_decode(commonModel::http($url)); + + if(!is_array($branches)) return $branches; + + $newBranches = array(); + foreach($branches as $branch) + { + $branch->name = $branch->branch_name; + if(empty($keyword) || stristr($branch->name, $keyword)) $newBranches[] = $branch; + } + + return $newBranches; + } } diff --git a/module/gitea/view/binduser.html.php b/module/gitea/view/binduser.html.php new file mode 100644 index 0000000000..83c2982d7c --- /dev/null +++ b/module/gitea/view/binduser.html.php @@ -0,0 +1,83 @@ + + * @package gitea + * @version $Id$ + * @link http://www.zentao.net + */ +?> + +

    +
    +

    gitea->bindUser;?>

    +
    + +
    + + + + + + + + + + + zentaoAccount)) continue;?> + account]", $giteaUser->realname);?> + + + + + + + + + zentaoAccount)) continue;?> + account]", $giteaUser->realname);?> + + + + + + + + + + + + + +
    gitea->giteaAccount;?>gitea->zentaoAccount;?>gitea->bindingStatus;?>
    avatar, "height=40");?> + realname;?> +
    + account;?> + email) echo " <" . $giteaUser->email . ">";?> +
    account]", $userPairs, '', "class='form-control select chosen'" );?>gitea->notBind;?>
    avatar, "height=40");?> + realname;?> +
    + account;?> + email) echo " <" . $giteaUser->email . ">";?> +
    account]", $userPairs, $giteaUser->zentaoAccount, "class='form-control select chosen'" );?> + zentaoAccount])):?> + zentaoAccount, '');?> + + gitea->binded;?> + + ' . $lang->gitea->bindedError . '';?> + + + gitea->notBind;?> + +
    + + goback, '', 'class="btn btn-wide"');?> +
    +
    + +
    + diff --git a/module/gitea/view/browse.html.php b/module/gitea/view/browse.html.php index d8a23425ac..fb02e955fc 100644 --- a/module/gitea/view/browse.html.php +++ b/module/gitea/view/browse.html.php @@ -56,6 +56,7 @@
    isBindUser); common::printIcon('gitea', 'delete', "giteaID=$id", '', 'list', 'trash', 'hiddenwin'); ?>
    @@ -55,7 +55,7 @@ url, $gitlab->url, '_target');?> isAdminToken) or !$gitlab->isBindUser) ? false : true; + $disabled = $gitlab->isBindUser ? true : false; common::printIcon('gitlab', 'edit', "gitlabID=$id", '', 'list', 'edit'); echo common::buildIconButton('gitlab', 'bindUser', "gitlabID=$id", '', 'list', 'link', '', '', false, '', '', 0, $disabled); common::printIcon('gitlab', 'delete', "gitlabID=$id", '', 'list', 'trash', 'hiddenwin'); diff --git a/module/gitlab/view/browsebranchpriv.html.php b/module/gitlab/view/browsebranchpriv.html.php deleted file mode 100644 index 181c913742..0000000000 --- a/module/gitlab/view/browsebranchpriv.html.php +++ /dev/null @@ -1,81 +0,0 @@ - - * @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)); - if(common::hasPriv('gitlab', 'editBranchPriv')) common::printLink('gitlab', 'editBranchPriv', "gitlabID=$gitlabID&projectID=$projectID&branch=$branchName", " ", '', "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=$branchName"), '', 'hiddenwin', "title='{$lang->gitlab->deleteBranchPriv}' class='btn'"); - ?> -
    - - - -
    -
    - - diff --git a/module/gitlab/view/browseproject.html.php b/module/gitlab/view/browseproject.html.php index 93fddbd2f7..486412f9d7 100644 --- a/module/gitlab/view/browseproject.html.php +++ b/module/gitlab/view/browseproject.html.php @@ -60,8 +60,8 @@
    last_activity_at, 0, 10);?> id", '', 'list', 'branch-lock', '', '', false, '', '', 0, ($gitlabProject->isMaintainer and $gitlabProject->default_branch)); - echo common::buildIconButton('gitlab', 'browseTagPriv', "gitlabID=$gitlabID&projectID=$gitlabProject->id", '', 'list', 'tag-lock', '', '', false, '', '', 0, ($gitlabProject->isMaintainer and $gitlabProject->default_branch)); + echo common::buildIconButton('gitlab', 'manageBranchPriv', "gitlabID=$gitlabID&projectID=$gitlabProject->id", '', 'list', 'branch-lock', '', '', false, '', $this->lang->gitlab->browseBranchPriv, 0, ($gitlabProject->isMaintainer and $gitlabProject->default_branch)); + echo common::buildIconButton('gitlab', 'manageTagPriv', "gitlabID=$gitlabID&projectID=$gitlabProject->id", '', 'list', 'tag-lock', '', '', false, '', $this->lang->gitlab->browseTagPriv, 0, ($gitlabProject->isMaintainer and $gitlabProject->default_branch)); echo common::buildIconButton('gitlab', 'manageProjectMembers', 'repoID=' . zget($repoPairs, $gitlabProject->id), '', 'list', 'team', '', '', false, '', '', 0, isset($repoPairs[$gitlabProject->id])); echo common::buildIconButton('gitlab', 'createWebhook', 'repoID=' . zget($repoPairs, $gitlabProject->id), '', 'list', 'change', 'hiddenwin', '', false, '', '', 0, isset($repoPairs[$gitlabProject->id])); echo common::buildIconButton('gitlab', 'importIssue', 'repoID=' . zget($repoPairs, $gitlabProject->id), '', 'list', 'link', '', '', false, '', '', 0, isset($repoPairs[$gitlabProject->id])); diff --git a/module/gitlab/view/browsetagpriv.html.php b/module/gitlab/view/browsetagpriv.html.php deleted file mode 100644 index 792e05531e..0000000000 --- a/module/gitlab/view/browsetagpriv.html.php +++ /dev/null @@ -1,82 +0,0 @@ - - * @package gitlab - * @version $Id$ - * @link http://www.zentao.net - */ -?> - -recTotal}&recPerPage={$pager->recPerPage}&pageID=1")?> - - - -
    -

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

    -
    - -
    -
    - - recTotal}&recPerPage={$pager->recPerPage}&pageID={$pager->pageID}";?> - - - - - - - - - - $gitlabTag): ?> - accessLevel = $this->gitlab->checkAccessLevel($gitlabTag->accessLevels); ?> - - - - - - - - -
    gitlab->tag->name);?>gitlab->tag->lastCommitter;?>gitlab->tag->accessLevel);?>actions;?>
    name;?>lastCommitter;?>gitlab->branch->branchCreationLevelList, $gitlabTag->accessLevel);?> - name)); - common::printLink('gitlab', 'editTagPriv', "gitlabID=$gitlabID&projectID=$projectID&tag_name=$tagName", " ", '', "title={$lang->gitlab->editTagPriv} class='btn btn-primary'"); - common::printLink('gitlab', 'deleteTagPriv', "gitlabID=$gitlabID&projectID={$projectID}&tag_name=$tagName", " ", '', "title='{$lang->gitlab->deleteTagPriv}' class='btn btn-primary' target='hiddenwin' onclick='if(confirm(\"{$lang->gitlab->tag->protectConfirmDel}\")==false) return false;'"); - ?> -
    - - - -
    -
    - - diff --git a/module/gitlab/view/createbranchpriv.html.php b/module/gitlab/view/createbranchpriv.html.php deleted file mode 100644 index 52c3e691f2..0000000000 --- a/module/gitlab/view/createbranchpriv.html.php +++ /dev/null @@ -1,47 +0,0 @@ - - * @package gitlab - * @version $Id$ - * @link http://www.zentao.net - */ -?> - -
    -
    -
    -
    -

    -
    -
    - name) echo html::hidden('name', $branchPriv->name);?> - - - - - - - - - - - - - - - - - -
    gitlab->branch->name;?>name, "class='form-control chosen' " . ($branch ? 'disabled' : ''));?>
    gitlab->branch->mergeAllowed;?>gitlab->branch->branchCreationLevelList, $branchPriv->mergeAccessLevel, "class='form-control'");?>
    gitlab->branch->pushAllowed;?>gitlab->branch->branchCreationLevelList, $branchPriv->pushAccessLevel, "class='form-control'");?>
    - - goback, '', 'class="btn btn-wide"');?> -
    -
    -
    -
    -
    - diff --git a/module/gitlab/view/createtagpriv.html.php b/module/gitlab/view/createtagpriv.html.php deleted file mode 100644 index cf45b66372..0000000000 --- a/module/gitlab/view/createtagpriv.html.php +++ /dev/null @@ -1,43 +0,0 @@ - - * @package gitlab - * @version $Id$ - * @link https://www.zentao.net - */ -?> - -
    -
    -
    -
    -

    gitlab->createTagPriv;?>

    -
    -
    - - - - - - - - - - - - - - -
    gitlab->tag->name;?>
    gitlab->tag->accessLevel;?>gitlab->branch->branchCreationLevelList, '40', "class='form-control chosen'");?>
    - - goback, '', 'class="btn btn-wide"');?> -
    -
    -
    -
    -
    - diff --git a/module/gitlab/view/edittagpriv.html.php b/module/gitlab/view/edittagpriv.html.php deleted file mode 100644 index aec4bbcbf2..0000000000 --- a/module/gitlab/view/edittagpriv.html.php +++ /dev/null @@ -1,44 +0,0 @@ - - * @package gitlab - * @version $Id$ - * @link https://www.zentao.net - */ -?> - -
    -
    -
    -
    -

    gitlab->editTagPriv;?>

    -
    -
    - - - - - - - - - - - - - - - -
    gitlab->tag->name;?>
    gitlab->tag->accessLevel;?>gitlab->branch->branchCreationLevelList, $tagPriv->createAccessLevel, "class='form-control chosen'");?>
    - - goback, '', 'class="btn btn-wide"');?> -
    -
    -
    -
    -
    - diff --git a/module/gitlab/view/managebranchpriv.html.php b/module/gitlab/view/managebranchpriv.html.php new file mode 100644 index 0000000000..52ea2da2e4 --- /dev/null +++ b/module/gitlab/view/managebranchpriv.html.php @@ -0,0 +1,82 @@ + + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    gitlab->branch->name;?>gitlab->branch->mergeAllowed;?>gitlab->branch->pushAllowed;?>actions;?>
    name, "class='form-control' readonly");?>gitlab->branch->branchCreationLevelList, $branch->mergeAccess, "class='form-control user-picker'");?> + gitlab->branch->branchCreationLevelList, $branch->pushAccess, "class='form-control user-picker'");?> + name);?> + + ", '', "onclick='addItem(this)' class='btn btn-link'");?> + ", '', "onclick='deleteItem(this)' class='btn btn-link'");?> +
    '') + $noAccessBranches, '', "class='form-control user-picker'");?>gitlab->branch->branchCreationLevelList, 40, "class='form-control user-picker'");?>gitlab->branch->branchCreationLevelList, 40, "class='form-control user-picker'");?> + ", '', "onclick='addItem(this)' class='btn btn-link'");?> + ", '', "onclick='deleteItem(this)' class='btn btn-link'");?> +
    + save, 'onclick="savePriv()" id="saveBtn"', 'btn btn-wide btn-primary'); + echo html::backButton(); + ?> +
    + +
    +
    +
    + + + + + + + + + +
    + diff --git a/module/gitlab/view/managetagpriv.html.php b/module/gitlab/view/managetagpriv.html.php new file mode 100644 index 0000000000..bca3de59b6 --- /dev/null +++ b/module/gitlab/view/managetagpriv.html.php @@ -0,0 +1,76 @@ + + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    gitlab->tag->name;?>gitlab->tag->accessLevel;?>actions;?>
    name, "class='form-control' readonly");?>gitlab->branch->branchCreationLevelList, $tag->createAccess, "class='form-control user-picker'");?> + name);?> + ", '', "onclick='addItem(this)' class='btn btn-link'");?> + ", '', "onclick='deleteItem(this)' class='btn btn-link'");?> +
    '') + $noAccessTags, '', "class='form-control user-picker'");?>gitlab->branch->branchCreationLevelList, 40, "class='form-control user-picker'");?> + ", '', "onclick='addItem(this)' class='btn btn-link'");?> + ", '', "onclick='deleteItem(this)' class='btn btn-link'");?> +
    + save, 'onclick="savePriv()" id="saveBtn"', 'btn btn-wide btn-primary'); + echo html::backButton(); + ?> +
    + +
    +
    +
    + + + + + + + + +
    + diff --git a/module/group/lang/resource.php b/module/group/lang/resource.php index 9893779893..30e63d973e 100644 --- a/module/group/lang/resource.php +++ b/module/group/lang/resource.php @@ -1284,6 +1284,7 @@ $lang->resource->custom->browseStoryConcept = 'browseStoryConcept'; $lang->resource->custom->setDefaultConcept = 'setDefaultConcept'; $lang->resource->custom->deleteStoryConcept = 'deleteStoryConcept'; $lang->resource->custom->kanban = 'kanban'; +$lang->resource->custom->code = 'code'; $lang->custom->methodOrder[5] = 'index'; $lang->custom->methodOrder[10] = 'set'; @@ -1300,6 +1301,8 @@ $lang->custom->methodOrder[60] = 'editStoryConcept'; $lang->custom->methodOrder[65] = 'browseStoryConcept'; $lang->custom->methodOrder[70] = 'setDefaultConcept'; $lang->custom->methodOrder[75] = 'deleteStoryConcept'; +$lang->custom->methodOrder[80] = 'kanban'; +$lang->custom->methodOrder[85] = 'code'; $lang->resource->datatable = new stdclass(); $lang->resource->datatable->setGlobal = 'setGlobal'; @@ -1344,17 +1347,11 @@ $lang->resource->gitlab->browseBranch = 'browseBranch'; $lang->resource->gitlab->webhook = 'webhook'; $lang->resource->gitlab->createWebhook = 'createWebhook'; $lang->resource->gitlab->manageProjectMembers = 'manageProjectMembers'; -$lang->resource->gitlab->browseBranchPriv = 'browseBranchPriv'; -$lang->resource->gitlab->createBranchPriv = 'createBranchPriv'; -$lang->resource->gitlab->editBranchPriv = 'editBranchPriv'; -$lang->resource->gitlab->deleteBranchPriv = 'deleteBranchPriv'; +$lang->resource->gitlab->manageBranchPriv = 'browseBranchPriv'; +$lang->resource->gitlab->manageTagPriv = 'browseTagPriv'; $lang->resource->gitlab->browseTag = 'browseTag'; $lang->resource->gitlab->createTag = 'createTag'; $lang->resource->gitlab->deleteTag = 'deleteTag'; -$lang->resource->gitlab->browseTagPriv = 'browseTagPriv'; -$lang->resource->gitlab->createTagPriv = 'createTagPriv'; -$lang->resource->gitlab->editTagPriv = 'editTagPriv'; -$lang->resource->gitlab->deleteTagPriv = 'deleteTagPriv'; $lang->gitlab->methodOrder[5] = 'browse'; $lang->gitlab->methodOrder[10] = 'create'; @@ -1381,23 +1378,27 @@ $lang->gitlab->methodOrder[115] = 'browseBranch'; $lang->gitlab->methodOrder[120] = 'webhook'; $lang->gitlab->methodOrder[125] = 'createWebhook'; $lang->gitlab->methodOrder[130] = 'manageProjectMembers'; -$lang->gitlab->methodOrder[135] = 'browseTag'; -$lang->gitlab->methodOrder[140] = 'browseTagPriv'; -$lang->gitlab->methodOrder[145] = 'deleteTagPriv'; +$lang->gitlab->methodOrder[135] = 'manageBranchPriv'; +$lang->gitlab->methodOrder[140] = 'manageTagPriv'; +$lang->gitlab->methodOrder[145] = 'browseTag'; +$lang->gitlab->methodOrder[150] = 'createTag'; +$lang->gitlab->methodOrder[155] = 'deleteTag'; /* Gitea. */ $lang->resource->gitea = new stdclass(); -$lang->resource->gitea->browse = 'browse'; -$lang->resource->gitea->create = 'create'; -$lang->resource->gitea->edit = 'edit'; -$lang->resource->gitea->view = 'view'; -$lang->resource->gitea->delete = 'delete'; +$lang->resource->gitea->browse = 'browse'; +$lang->resource->gitea->create = 'create'; +$lang->resource->gitea->edit = 'edit'; +$lang->resource->gitea->view = 'view'; +$lang->resource->gitea->delete = 'delete'; +$lang->resource->gitea->bindUser = 'bindUser'; $lang->gitea->methodOrder[5] = 'browse'; $lang->gitea->methodOrder[10] = 'create'; $lang->gitea->methodOrder[15] = 'edit'; $lang->gitea->methodOrder[20] = 'view'; $lang->gitea->methodOrder[25] = 'delete'; +$lang->gitea->methodOrder[30] = 'bindUser'; /* SonarQube. */ $lang->resource->sonarqube = new stdclass(); diff --git a/module/holiday/css/browse.css b/module/holiday/css/browse.css index 50d38310c3..9fb6ee448c 100644 --- a/module/holiday/css/browse.css +++ b/module/holiday/css/browse.css @@ -1,3 +1,5 @@ .tree .active{font-weight: bold;} .with-side .side {position: absolute; width: 130px;} .with-side .main {padding-left: 145px; float: left;} +.side-col {width: 160px;} +.panel-sm .panel-body {padding: 10px;} diff --git a/module/job/control.php b/module/job/control.php index d25c6a0fe9..87e7fabaa5 100644 --- a/module/job/control.php +++ b/module/job/control.php @@ -114,7 +114,7 @@ class job extends control $repoTypes[$repo->id] = $repo->SCM; if(strtolower($repo->SCM) == 'gitlab') { - if(isset($repo->gitlab)) $gitlab = $this->loadModel('gitlab')->getByID($repo->gitlab); + if(isset($repo->gitService)) $gitlab = $this->loadModel('gitlab')->getByID($repo->gitService); if(!empty($gitlab)) $tokenUser = $this->gitlab->apiGetCurrentUser($gitlab->url, $gitlab->token); if(!isset($tokenUser->is_admin) or !$tokenUser->is_admin) continue; $gitlabRepos[$repo->id] = $repo->name; @@ -180,7 +180,7 @@ class job extends control $repo = $this->loadModel('repo')->getRepoByID($job->repo); $this->view->repo = $this->loadModel('repo')->getRepoByID($job->repo); - if($repo->SCM == 'Gitlab') $this->view->refList = $this->loadModel('gitlab')->getReferenceOptions($repo->gitlab, $repo->project); + if($repo->SCM == 'Gitlab') $this->view->refList = $this->loadModel('gitlab')->getReferenceOptions($repo->gitService, $repo->project); $repoList = $this->repo->getList($this->projectID); $repoPairs = array(0 => '', $repo->id => $repo->name); @@ -383,7 +383,7 @@ class job extends control public function ajaxGetRefList($repoID) { $repo = $this->loadModel('repo')->getRepoByID($repoID); - if($repo->SCM == 'Gitlab') $refList = $this->loadModel('gitlab')->getReferenceOptions($repo->gitlab, $repo->project); + if($repo->SCM == 'Gitlab') $refList = $this->loadModel('gitlab')->getReferenceOptions($repo->gitService, $repo->project); if($repo->SCM != 'Gitlab') $refList = $this->repo->getBranches($repo, true); $this->send(array('result' => 'success', 'refList' => $refList)); } diff --git a/module/kanban/control.php b/module/kanban/control.php index d18576d95d..f05f52ccfc 100644 --- a/module/kanban/control.php +++ b/module/kanban/control.php @@ -1852,11 +1852,10 @@ class kanban extends control public function ajaxGetContactUsers($field, $contactListID) { $this->loadModel('user'); - $list = $contactListID ? $this->user->getContactListByID($contactListID) : ''; + $list = $contactListID ? $this->user->getContactListByID($contactListID) : ''; + $users = $this->user->getPairs('nodeleted|noclosed', '', $this->config->maxCount); - $users = $this->user->getPairs('devfirst|nodeleted|noclosed', $list ? $list->userList : '', $this->config->maxCount); - - if(!$contactListID) return print(html::select($field . '[]', $users, '', "class='form-control picker-select' multiple")); + if(!$contactListID or !isset($list->userList)) return print(html::select($field . '[]', $users, '', "class='form-control picker-select' multiple")); return print(html::select($field . '[]', $users, $list->userList, "class='form-control picker-select' multiple")); } diff --git a/module/kanban/css/create.css b/module/kanban/css/create.css index 3c757a4e05..8e64db6be5 100644 --- a/module/kanban/css/create.css +++ b/module/kanban/css/create.css @@ -23,5 +23,7 @@ #copyKanbanModal .copyContentBox > .checkbox-primary {display: inline-block; margin-left: 10px; margin-top: -1px;} #copyKanbanModal .copyContentBox > .checkbox-primary:first-child {margin-left: 20px;} #copyContentbasicInfo {cursor: not-allowed;} -#team ~ #contactListMenu_chosen, #whitelist ~ #contactListMenu_chosen {vertical-align: top;} -#team ~ #contactListMenu_chosen > .chosen-drop, #whitelist ~ #contactListMenu_chosen > .chosen-drop {top: 32px;} +#team ~ #contactListMenu_chosen {vertical-align: top;} +#whitelist ~ #contactListMenu_chosen {vertical-align: bottom;} +#team ~ #contactListMenu_chosen > .chosen-drop {top: 32px;} +#whitelist ~ #contactListMenu_chosen > .chosen-drop {bottom: 32px;} diff --git a/module/kanban/css/edit.css b/module/kanban/css/edit.css index fafbb33db0..0c6f74a6be 100644 --- a/module/kanban/css/edit.css +++ b/module/kanban/css/edit.css @@ -10,5 +10,7 @@ #mainContent .objectBox .checkbox-primary>label:after {width: 14px; height: 14px;} [lang^='en'] .columnWidth {width: 120px;} [lang^='zh-cn'] .columnWidth {width: 80px;} -#team ~ #contactListMenu_chosen, #whitelist ~ #contactListMenu_chosen {vertical-align: top;} -#team ~ #contactListMenu_chosen > .chosen-drop, #whitelist ~ #contactListMenu_chosen > .chosen-drop {top: 32px;} +#team ~ #contactListMenu_chosen {vertical-align: top;} +#whitelist ~ #contactListMenu_chosen {vertical-align: bottom;} +#team ~ #contactListMenu_chosen > .chosen-drop {top: 32px;} +#whitelist ~ #contactListMenu_chosen > .chosen-drop {bottom: 32px;} diff --git a/module/kanban/js/common.js b/module/kanban/js/common.js index 69b6bbdac5..3c124d5671 100644 --- a/module/kanban/js/common.js +++ b/module/kanban/js/common.js @@ -128,3 +128,23 @@ function loadAllUsers() $('#owner').chosen(); }); } + +/** + * The owners that loads kanban. + * + * @oaram int spaceID + * @access public + * @return void + */ +function loadOwners(spaceID) +{ + var link = createLink('kanban', 'ajaxLoadUsers', 'spaceID='+ spaceID + '&field=owner&selectedUser=' + $('#owner').val()); + + $.get(link, function(data) + { + $('#owner').replaceWith(data); + $('#owner' + "_chosen").remove(); + $('#owner').next('.picker').remove(); + $('#owner').chosen(); + }); +} diff --git a/module/kanban/js/create.js b/module/kanban/js/create.js index 6597751944..8101e62b2a 100644 --- a/module/kanban/js/create.js +++ b/module/kanban/js/create.js @@ -92,23 +92,3 @@ function loadUsers(spaceID) if(spaceType != 'private') loadOwners(spaceID); } - -/** - * The owners that loads kanban. - * - * @oaram int spaceID - * @access public - * @return void - */ -function loadOwners(spaceID) -{ - var link = createLink('kanban', 'ajaxLoadUsers', 'spaceID='+ spaceID + '&field=owner&selectedUser=' + $('#owner').val()); - - $.get(link, function(data) - { - $('#owner').replaceWith(data); - $('#owner' + "_chosen").remove(); - $('#owner').next('.picker').remove(); - $('#owner').chosen(); - }); -} diff --git a/module/kanban/view/create.html.php b/module/kanban/view/create.html.php index a9f0d1579d..e6f7c996b3 100644 --- a/module/kanban/view/create.html.php +++ b/module/kanban/view/create.html.php @@ -59,7 +59,7 @@
    team) ? $copyKanban->team : '', "class='form-control picker-select' multiple data-dropDirection='bottom'");?> - fetch('my', 'buildContactLists', 'dropdownName=team');?> + fetch('my', 'buildContactLists', "dropdownName=team");?>
    whitelist) ? $copyKanban->whitelist : '', 'class="form-control picker-select" multiple');?> - fetch('my', 'buildContactLists', 'dropdownName=whitelist');?> + fetch('my', 'buildContactLists', "dropdownName=whitelist&attr=data-drop_direction='up'");?>
    - fetch('my', 'buildContactLists');?> + fetch('my', 'buildContactLists', "dropdownName=team");?>
    - + @@ -99,7 +99,7 @@ diff --git a/module/kanban/view/editspace.html.php b/module/kanban/view/editspace.html.php index 292e7f060c..f58d01e18e 100644 --- a/module/kanban/view/editspace.html.php +++ b/module/kanban/view/editspace.html.php @@ -37,7 +37,7 @@ diff --git a/module/mr/config.php b/module/mr/config.php index 181b92d1f7..3ffe3fd9bd 100644 --- a/module/mr/config.php +++ b/module/mr/config.php @@ -32,3 +32,5 @@ $config->mrapproval = new stdclass(); $config->mrapproval->create = new stdclass(); $config->mrapproval->create->skippedFields = ''; $config->mrapproval->create->requiredFields = 'mrID,account,date,action'; + +$config->mr->gitServiceList = array('gitlab', 'gitea'); diff --git a/module/mr/control.php b/module/mr/control.php index 83fa102c98..6e7f73ff5d 100644 --- a/module/mr/control.php +++ b/module/mr/control.php @@ -34,25 +34,24 @@ class mr extends control $this->app->loadClass('pager', $static = true); $pager = new pager($recTotal, $recPerPage, $pageID); - $repos = $this->loadModel('repo')->getListBySCM('Gitlab'); + $repos = $this->loadModel('repo')->getListBySCM(array('Gitlab', 'Gitea')); if(empty($repos)) $this->locate($this->repo->createLink('create')); $repoID = $this->repo->saveState($repoID, $objectID); $repo = $this->repo->getRepoByID($repoID); - if($repo->SCM != 'Gitlab') $repo = $repos[0]; + if(!in_array(strtolower($repo->SCM), $this->config->mr->gitServiceList)) $repo = $repos[0]; $this->loadModel('ci')->setMenu($repo->id); - $projects = $this->mr->getAllGitlabProjects($repoID); + $projects = $this->mr->getAllProjects($repoID, $repo->SCM); $MRList = $this->mr->getList($mode, $param, $orderBy, $pager, empty($projects) ? false : $projects, $repoID); /* Save current URI to session. */ $this->session->set('mrList', $this->app->getURI(true), 'repo'); /* Sync GitLab MR to ZenTao Database. */ - $MRList = $this->mr->batchSyncMR($MRList); + $MRList = $this->mr->batchSyncMR($MRList, $repo->SCM); /* Check whether Mr is linked with the product. */ - $this->loadModel('gitlab'); foreach($MRList as $MR) { $product = $this->mr->getMRProduct($MR); @@ -63,7 +62,17 @@ class mr extends control $this->app->loadLang('compile'); $openIDList = array(); - if(!$this->app->user->admin) $openIDList = $this->loadModel('gitlab')->getGitLabListByAccount($this->app->user->account); + if(!$this->app->user->admin) + { + if($repo->SCM == 'Gitlab') + { + $openIDList = $this->loadModel('gitlab')->getGitLabListByAccount($this->app->user->account); + } + else + { + $openIDList = $this->loadModel('gitea')->getGiteaListByAccount($this->app->user->account); + } + } $this->view->title = $this->lang->mr->common . $this->lang->colon . $this->lang->mr->browse; $this->view->MRList = $MRList; @@ -95,19 +104,30 @@ class mr extends control return $this->send($result); } - $gitlabHosts = $this->loadModel('gitlab')->getPairs(); - $gitlabUsers = $this->gitlab->getGitLabListByAccount(); - foreach($gitlabHosts as $gitlabID=> $gitlabHost) + $hosts = $this->loadModel('pipeline')->getList(array('gitea', 'gitlab')); + if(!$this->app->user->admin) { - if(!$this->app->user->admin and !isset($gitlabUsers[$gitlabID])) unset($gitlabHosts[$gitlabID]); + $gitlabUsers = $this->loadModel('gitlab')->getGitLabListByAccount(); + $giteaUsers = $this->loadModel('gitea')->getGiteaListByAccount(); + foreach($hosts as $hostID => $host) + { + if($host->type == 'gitLab' and isset($gitlabUsers[$hostID])) continue; + if($host->type == 'gitea' and isset($giteaUsers[$hostID])) continue; + + unset($hosts[$hostID]); + } } + $hostPairs = array(); + foreach($hosts as $host) $hostPairs[$host->id] = '[' . ucfirst($host->type) . "] {$host->name}"; + $this->app->loadLang('repo'); /* Import lang in repo module. */ $this->app->loadLang('compile'); - $this->view->title = $this->lang->mr->create; - $this->view->users = $this->loadModel('user')->getPairs('noletter|noclosed'); - $this->view->jobList = $this->loadModel('job')->getList(); - $this->view->gitlabHosts = $gitlabHosts; + $this->view->title = $this->lang->mr->create; + $this->view->users = $this->loadModel('user')->getPairs('noletter|noclosed'); + $this->view->jobList = $this->loadModel('job')->getList(); + $this->view->hostPairs = $hostPairs; + $this->view->hosts = $hosts; $this->display(); } @@ -126,38 +146,40 @@ class mr extends control } $MR = $this->mr->getByID($MRID); - if(isset($MR->gitlabID)) $rawMR = $this->mr->apiGetSingleMR($MR->gitlabID, $MR->targetProject, $MR->mriid); + if(isset($MR->hostID)) $rawMR = $this->mr->apiGetSingleMR($MR->hostID, $MR->targetProject, $MR->mriid); $this->view->title = $this->lang->mr->edit; $this->view->MR = $MR; $this->view->rawMR = isset($rawMR) ? $rawMR : false; if(!isset($rawMR->id) or (isset($rawMR->message) and $rawMR->message == '404 Not found') or empty($rawMR)) return $this->display(); - $branchList = $this->loadModel('gitlab')->getBranches($MR->gitlabID, $MR->targetProject); + $host = $this->loadModel('pipeline')->getByID($MR->hostID); + $scm = $host->type; + $branchList = $this->loadModel($scm)->getBranches($MR->hostID, $MR->targetProject); + + $MR->canDeleteBranch = true; + $branchPrivs = $this->loadModel($scm)->apiGetBranchPrivs($MR->hostID, $MR->sourceProject); + foreach($branchPrivs as $priv) + { + if($MR->canDeleteBranch and $priv->name == $MR->sourceBranch) $MR->canDeleteBranch = false; + } + $targetBranchList = array(); foreach($branchList as $branch) $targetBranchList[$branch] = $branch; /* Fetch user list both in Zentao and current GitLab project. */ - $bindedUsers = $this->gitlab->getUserIdRealnamePairs($MR->gitlabID); - $rawProjectUsers = $this->gitlab->apiGetProjectUsers($MR->gitlabID, $MR->targetProject); - - $users = array(); - foreach($rawProjectUsers as $rawProjectUser) - { - if(!empty($bindedUsers[$rawProjectUser->id])) $users[$rawProjectUser->id] = $bindedUsers[$rawProjectUser->id]; - } - - $gitlabUsers = $this->gitlab->getUserAccountIdPairs($MR->gitlabID); + $bindedUsers = $this->$scm->getUserIdRealnamePairs($MR->hostID); + $gitUsers = $this->$scm->getUserAccountIdPairs($MR->hostID); /* Check permissions. */ - if(!$this->app->user->admin) + if(!$this->app->user->admin and $scm == 'gitlab') { $groupIDList = array(0 => 0); - $groups = $this->gitlab->apiGetGroups($MR->gitlabID, 'name_asc', 'developer'); + $groups = $this->scm->apiGetGroups($MR->hostID, 'name_asc', 'developer'); foreach($groups as $group) $groupIDList[] = $group->id; - $sourceProject = $this->gitlab->apiGetSingleProject($MR->gitlabID, $MR->sourceProject); - $isDeveloper = $this->gitlab->checkUserAccess($MR->gitlabID, 0, $sourceProject, $groupIDList, 'developer'); + $sourceProject = $this->scm->apiGetSingleProject($MR->hostID, $MR->sourceProject); + $isDeveloper = $this->scm->checkUserAccess($MR->hostID, 0, $sourceProject, $groupIDList, 'developer'); - if(!isset($gitlabUsers[$this->app->user->account]) or !$isDeveloper) return print(js::alert($this->lang->mr->errorLang[3]) . js::locate($this->createLink('mr', 'browse'))); + if(!isset($gitUsers[$this->app->user->account]) or !$isDeveloper) return print(js::alert($this->lang->mr->errorLang[3]) . js::locate($this->createLink('mr', 'browse'))); } /* Import lang for required modules. */ @@ -166,7 +188,7 @@ class mr extends control $this->loadModel('compile'); $repoList = array(); - $rawRepoList = $this->repo->getGitLabRepoList($MR->gitlabID, $MR->sourceProject); + $rawRepoList = $this->repo->getRepoListByClient($MR->hostID, $MR->sourceProject); foreach($rawRepoList as $rawRepo) $repoList[$rawRepo->id] = "[$rawRepo->id] $rawRepo->name"; $jobList = array(); @@ -181,10 +203,11 @@ class mr extends control $this->view->title = $this->lang->mr->edit; $this->view->MR = $MR; + $this->view->host = $host; $this->view->targetBranchList = $targetBranchList; $this->view->users = $this->loadModel('user')->getPairs('noletter|noclosed'); $this->view->assignee = $MR->assignee; - $this->view->reviewer = zget($gitlabUsers, $MR->reviewer, ''); + $this->view->reviewer = zget($gitUsers, $MR->reviewer, ''); $this->display(); } @@ -204,12 +227,12 @@ class mr extends control if($MR->synced) { - $res = $this->mr->apiDeleteMR($MR->gitlabID, $MR->targetProject, $MR->mriid); + $res = $this->mr->apiDeleteMR($MR->hostID, $MR->targetProject, $MR->mriid); if(isset($res->message)) return print(js::alert($this->mr->convertApiError($res->message))); } $this->dao->delete()->from(TABLE_MR)->where('id')->eq($id)->exec(); - echo js::locate(inlink('browse'), 'parent'); + echo js::reload('parent'); } /** @@ -223,23 +246,25 @@ class mr extends control { $MR = $this->mr->getByID($id); if(!$MR) return print(js::error($this->lang->notFound) . js::locate($this->createLink('mr', 'browse'))); - if(isset($MR->gitlabID)) $rawMR = $this->mr->apiGetSingleMR($MR->gitlabID, $MR->targetProject, $MR->mriid); + if(isset($MR->hostID)) $rawMR = $this->mr->apiGetSingleMR($MR->hostID, $MR->targetProject, $MR->mriid); if($MR->synced and (!isset($rawMR->id) or (isset($rawMR->message) and $rawMR->message == '404 Not found') or empty($rawMR))) return $this->display(); - $this->loadModel('gitlab'); + $host = $this->loadModel('pipeline')->getByID($MR->hostID); + $scm = $host->type; + $this->loadModel($scm); $this->loadModel('job'); /* Sync MR from GitLab to ZentaoPMS. */ $MR = $this->mr->apiSyncMR($MR); - $sourceProject = $this->gitlab->apiGetSingleProject($MR->gitlabID, $MR->sourceProject); - $targetProject = $this->gitlab->apiGetSingleProject($MR->gitlabID, $MR->targetProject); - $sourceBranch = $this->gitlab->apiGetSingleBranch($MR->gitlabID, $MR->sourceProject, $MR->sourceBranch); - $targetBranch = $this->gitlab->apiGetSingleBranch($MR->gitlabID, $MR->targetProject, $MR->targetBranch); + $sourceProject = $this->$scm->apiGetSingleProject($MR->hostID, $MR->sourceProject); + $targetProject = $this->$scm->apiGetSingleProject($MR->hostID, $MR->targetProject); + $sourceBranch = $this->$scm->apiGetSingleBranch($MR->hostID, $MR->sourceProject, $MR->sourceBranch); + $targetBranch = $this->$scm->apiGetSingleBranch($MR->hostID, $MR->targetProject, $MR->targetBranch); $projectOwner = true; - if(isset($MR->gitlabID) and !$this->app->user->admin) + if(isset($MR->hostID) and !$this->app->user->admin) { - $openID = $this->gitlab->getUserIDByZentaoAccount($MR->gitlabID, $this->app->user->account); + $openID = $this->$scm->getUserIDByZentaoAccount($MR->hostID, $this->app->user->account); if(!$projectOwner and isset($sourceProject->owner->id) and $sourceProject->owner->id == $openID) $projectOwner = true; } @@ -320,22 +345,10 @@ class mr extends control } } - /* Accept MR by using the mapped user in GitLab. */ - $sudoUser = $this->mr->getSudoUsername($MR->gitlabID, $MR->targetProject); - - if(isset($MR->gitlabID)) - { - if(!empty($sudoUser)) $rawMR = $this->mr->apiAcceptMR($MR->gitlabID, $MR->targetProject, $MR->mriid, $sudoUser); - if(empty($sudoUser)) $rawMR = $this->mr->apiAcceptMR($MR->gitlabID, $MR->targetProject, $MR->mriid); - } + if(isset($MR->hostID)) $rawMR = $this->mr->apiAcceptMR($MR->hostID, $MR->targetProject, $MR->mriid, $MR); if(isset($rawMR->state) and $rawMR->state == 'merged') { - ///* Force reload when locate to the url. */ - //$random = uniqid(); - //return $this->send(array('result' => 'success', 'message' => $this->lang->mr->mergeSuccess, 'locate' => helper::createLink('mr', 'browse', "random={$random}"))); - $this->mr->logMergedAction($MR); - return $this->send(array('result' => 'success', 'message' => $this->lang->mr->mergeSuccess, 'locate' => helper::createLink('mr', 'browse'))); } @@ -372,7 +385,7 @@ class mr extends control $rawMR = null; if($MR->synced) { - $rawMR = $this->mr->apiGetSingleMR($MR->gitlabID, $MR->targetProject, $MR->mriid); + $rawMR = $this->mr->apiGetSingleMR($MR->hostID, $MR->targetProject, $MR->mriid); if(!isset($rawMR->id) or (isset($rawMR->message) and $rawMR->message == '404 Not found') or empty($rawMR)) return $this->display(); } $this->view->rawMR = $rawMR; @@ -594,7 +607,7 @@ class mr extends control $this->loadModel('search')->setSearchParams($this->config->product->search); $MR = $this->mr->getByID($MRID); - $relatedStories = $this->mr->getCommitedLink($MR->gitlabID, $MR->targetProject, $MR->mriid, 'story'); + $relatedStories = $this->mr->getCommitedLink($MR->hostID, $MR->targetProject, $MR->mriid, 'story'); $linkedStories = $this->mr->getLinkList($MRID, $product->id, 'story'); if($browseType == 'bySearch') @@ -679,7 +692,7 @@ class mr extends control $this->loadModel('search')->setSearchParams($this->config->bug->search); $MR = $this->mr->getByID($MRID); - $relatedBugs = $this->mr->getCommitedLink($MR->gitlabID, $MR->targetProject, $MR->mriid, 'bug'); + $relatedBugs = $this->mr->getCommitedLink($MR->hostID, $MR->targetProject, $MR->mriid, 'bug'); $linkedBugs = $this->mr->getLinkList($MRID, $product->id, 'bug'); if($browseType == 'bySearch') @@ -751,7 +764,7 @@ class mr extends control $this->loadModel('search')->setSearchParams($this->config->execution->search); $MR = $this->mr->getByID($MRID); - $relatedTasks = $this->mr->getCommitedLink($MR->gitlabID, $MR->targetProject, $MR->mriid, 'task'); + $relatedTasks = $this->mr->getCommitedLink($MR->hostID, $MR->targetProject, $MR->mriid, 'task'); $linkedTasks = $this->mr->getLinkList($MRID, $product->id, 'task'); /* Get executions by product. */ @@ -884,46 +897,57 @@ class mr extends control /** * AJAX: Get MR target projects. * - * @param int $gitlabID + * @param int $hostID * @param int $projectID + * @param string $scm * @access public * @return void */ - public function ajaxGetMRTargetProjects($gitlabID, $projectID) + public function ajaxGetMRTargetProjects($hostID, $projectID, $scm = 'gitlab') { - $this->loadModel('gitlab'); + $this->loadModel($scm); + if($scm != 'gitlab') $projectID = urldecode(base64_decode($projectID)); /* First step: get forks. Only get first level forks(not recursively). */ - $projects = $this->gitlab->apiGetForks($gitlabID, $projectID); + $projects = $scm == 'gitlab' ? $this->$scm->apiGetForks($hostID, $projectID) : array(); /* Second step: get project itself. */ - $projects[] = $this->gitlab->apiGetSingleProject($gitlabID, $projectID); + $projects[] = $this->$scm->apiGetSingleProject($hostID, $projectID); /* Last step: find its upstream recursively. */ - $project = $this->gitlab->apiGetUpstream($gitlabID, $projectID); + $project = $this->$scm->apiGetUpstream($hostID, $projectID); if(!empty($project)) $projects[] = $project; - while(!empty($project) and isset($project->id)) + if(!empty($project) and isset($project->id)) { - $project = $this->gitlab->apiGetUpstream($gitlabID, $project->id); - if(empty($project)) break; - $projects[] = $project; + $project = $this->$scm->apiGetUpstream($hostID, $project->id); + if(!empty($project)) $projects[] = $project; } - $groupIDList = array(0 => 0); - $groups = $this->gitlab->apiGetGroups($gitlabID, 'name_asc', 'developer'); - foreach($groups as $group) $groupIDList[] = $group->id; - foreach($projects as $key => $project) + if($scm == 'gitlab') { - if($this->gitlab->checkUserAccess($gitlabID, 0, $project, $groupIDList, 'developer') == false) unset($projects[$key]); - } + $groupIDList = array(0 => 0); + $groups = $this->$scm->apiGetGroups($hostID, 'name_asc', 'developer'); + foreach($groups as $group) $groupIDList[] = $group->id; + foreach($projects as $key => $project) + { + if($this->$scm->checkUserAccess($hostID, 0, $project, $groupIDList, 'developer') == false) unset($projects[$key]); + } - if(!$projects) return $this->send(array('message' => array())); + if(!$projects) return $this->send(array('message' => array())); + } $options = ""; foreach($projects as $project) { - $options .= ""; + if($scm == 'gitlab') + { + $options .= ""; + } + else + { + $options .= ""; + } } $this->send($options); @@ -932,14 +956,16 @@ class mr extends control /** * AJAX: Get repo list. * - * @param int $gitlabID + * @param int $hostID * @param int $projectID * @return void */ - public function ajaxGetRepoList($gitlabID, $projectID) + public function ajaxGetRepoList($hostID, $projectID) { - $this->loadModel('repo'); - $repoList = $this->repo->getGitLabRepoList($gitlabID, $projectID); + $host = $this->loadModel('pipeline')->getByID($hostID); + if($host->type != 'gitlab') $projectID =urldecode(base64_decode($projectID)); + + $repoList = $this->loadModel('repo')->getRepoListByClient($hostID, $projectID); if(!$repoList) return $this->send(array('message' => array())); $options = ""; @@ -984,18 +1010,38 @@ class mr extends control /** * Ajax check same opened mr for source branch. * - * @param int $gitlabID + * @param int $hostID * @access public * @return void */ - public function ajaxCheckSameOpened($gitlabID) + public function ajaxCheckSameOpened($hostID) { $sourceProject = $this->post->sourceProject; $sourceBranch = $this->post->sourceBranch; $targetProject = $this->post->targetProject; $targetBranch = $this->post->targetBranch; - $result = $this->mr->checkSameOpened($gitlabID, $sourceProject, $sourceBranch, $targetProject, $targetBranch); + $result = $this->mr->checkSameOpened($hostID, $sourceProject, $sourceBranch, $targetProject, $targetBranch); echo json_encode($result); } + + /** + * Ajax get branch pivs. + * + * @param int $hostID + * @param int|string $project + * @access public + * @return void + */ + public function ajaxGetBranchPivs($hostID, $project) + { + $host = $this->loadModel('pipeline')->getByID($hostID); + $scm = $host->type; + if($scm == 'gitea') $project = urldecode(base64_decode($project)); + + $branches = $this->loadModel($scm)->apiGetBranchPrivs($hostID, $project); + $branchPrivs = array(); + foreach($branches as $branch) $branchPrivs[$branch->name] = $branch->name; + echo json_encode($branchPrivs); + } } diff --git a/module/mr/js/create.js b/module/mr/js/create.js index 00a0d02d22..9fe52f0126 100644 --- a/module/mr/js/create.js +++ b/module/mr/js/create.js @@ -1,11 +1,50 @@ +/** + * Urlencode param. + * + * @param param $param + * @access public + * @return string + */ +function urlencode(param) +{ + var hostID = $('#hostID').val(); + if(hosts[hostID].type != 'gitlab') return Base64.encode(encodeURIComponent(param)); + + return param; +} + +/** + * Get branch priv. + * + * @param int|string $project + * @access public + * @return void + */ +function getBranchPriv(project) +{ + var hostID = $('#hostID').val(); + var branchUrl = createLink('mr', 'ajaxGetBranchPivs', "hostID=" + hostID + "&project=" + project); + $.get(branchUrl, function(response) + { + branchPrivs = eval('(' + response + ')'); + }); +} + $(function() { - $('#gitlabID').change(function() + $('#hostID').change(function() { - var gitlabID = $('#gitlabID').val(); - if(gitlabID == '') return false; + var hostID = $('#hostID').val(); + if(hostID == '') return false; - var url = createLink('repo', 'ajaxgetgitlabprojects', "gitlabID=" + gitlabID + "&projectIdList=&filter=IS_DEVELOPER"); + if(hosts[hostID].type == 'gitlab') + { + var url = createLink('repo', 'ajaxGetGitlabProjects', "gitlabID=" + hostID + "&projectIdList=&filter=IS_DEVELOPER"); + } + else + { + var url = createLink('repo', 'ajaxGetGiteaProjects', "giteaID=" + hostID); + } $.get(url, function(response) { $('#sourceProject').html('').append(response); @@ -15,10 +54,10 @@ $(function() $('#sourceProject,#targetProject').change(function() { - var gitlabID = $('#gitlabID').val(); - var sourceProject = $(this).val(); + var hostID = $('#hostID').val(); + var sourceProject = urlencode($(this).val()); var branchSelect = $(this).parents('td').find('select[name*=Branch]'); - var branchUrl = createLink('gitlab', 'ajaxgetprojectbranches', "gitlabID=" + gitlabID + "&projectID=" + sourceProject); + var branchUrl = createLink(hosts[hostID].type, 'ajaxGetProjectBranches', hosts[hostID].type + "ID=" + hostID + "&projectID=" + sourceProject); $.get(branchUrl, function(response) { branchSelect.html('').append(response); @@ -29,34 +68,39 @@ $(function() $('#sourceProject').change(function() { - var gitlabID = $('#gitlabID').val(); - var sourceProject = $(this).val(); - var projectUrl = createLink('mr', 'ajaxGetMRTargetProjects', "gitlabID=" + gitlabID + "&projectID=" + sourceProject); + var hostID = $('#hostID').val(); + var sourceProject = urlencode($(this).val()); + var projectUrl = createLink('mr', 'ajaxGetMRTargetProjects', "hostID=" + hostID + "&projectID=" + sourceProject + "&scm=" + hosts[hostID].type); $.get(projectUrl, function(response) { $('#targetProject').html('').append(response); $('#targetProject').chosen().trigger("chosen:updated");; }); - var repoUrl = createLink('mr', 'ajaxGetRepoList', "gitlabID=" + gitlabID + "&projectID=" + sourceProject); + var repoUrl = createLink('mr', 'ajaxGetRepoList', "hostID=" + hostID + "&projectID=" + sourceProject); $.get(repoUrl, function(response) { $('#repoID').html('').append(response); $('#repoID').chosen().trigger("chosen:updated");; }); + + if(sourceProject) getBranchPriv(sourceProject); }); $('#sourceBranch,#targetBranch').change(function() { + $('#removeSourceBranch').removeAttr('disabled'); + var sourceProject = $('#sourceProject').val(); var sourceBranch = $('#sourceBranch').val(); var targetProject = $('#targetProject').val(); var targetBranch = $('#targetBranch').val(); + if(branchPrivs[sourceBranch]) $('#removeSourceBranch').attr('disabled', 'true'); if(!sourceProject || !sourceBranch || !targetProject || !targetBranch) return false; var $this = $(this); - var gitlabID = $('#gitlabID').val(); - var repoUrl = createLink('mr', 'ajaxCheckSameOpened', "gitlabID=" + gitlabID); + var hostID = $('#hostID').val(); + var repoUrl = createLink('mr', 'ajaxCheckSameOpened', "hostID=" + hostID); $.post(repoUrl, {"sourceProject": sourceProject, "sourceBranch": sourceBranch, "targetProject": targetProject, "targetBranch": targetBranch}, function(response) { response = $.parseJSON(response); @@ -64,29 +108,12 @@ $(function() { alert(response.message); $this.val('').trigger('chosen:updated'); + if($this.attr('id') == 'sourceBranch') $('#removeSourceBranch').removeAttr('disabled'); return false; } }); }); - /* - $('#targetProject').change(function() - { - targetProject = $(this).val(); - var gitlabID = $('#gitlabID').val(); - var assignee = $("#assignee").parents('td').find('select[name*=assignee]'); - var reviewer = $("#reviewer").parents('td').find('select[name*=reviewer]'); - usersUrl = createLink('gitlab', 'ajaxgetmruserpairs', "gitlabID=" + gitlabID + "&projectID=" + targetProject); - $.get(usersUrl, function(response) - { - assignee.html('').append(response); - assignee.chosen().trigger("chosen:updated");; - reviewer.html('').append(response); - reviewer.chosen().trigger("chosen:updated");; - }); - }); - */ - $('#repoID').change(function() { var repoID = $(this).val(); diff --git a/module/mr/lang/de.php b/module/mr/lang/de.php index 46ed175893..f0046ebdd7 100644 --- a/module/mr/lang/de.php +++ b/module/mr/lang/de.php @@ -1,6 +1,7 @@ mr = new stdclass; $lang->mr->common = "Merge Request"; +$lang->mr->server = "Server"; $lang->mr->view = "Survey"; $lang->mr->create = "Create"; $lang->mr->apiCreate = "Interface: Create"; @@ -13,7 +14,7 @@ $lang->mr->source = 'source'; $lang->mr->target = 'target'; $lang->mr->viewDiff = 'View diff'; $lang->mr->diff = 'View diff'; -$lang->mr->viewInGitlab = 'View in GitLab'; +$lang->mr->viewInGit = 'View in APP'; $lang->mr->link = 'Link of stories,Bugs,tasks'; $lang->mr->createAction = '%s, %s submitted a Merge Request.'; @@ -38,8 +39,8 @@ $lang->mr->gitlabID = 'GitLab'; $lang->mr->repoID = 'Repo'; $lang->mr->jobID = 'Compile job'; -$lang->mr->canMerge = "Can merge"; -$lang->mr->cantMerge = "不可合并"; +$lang->mr->canMerge = "Can be merged"; +$lang->mr->cantMerge = "Can not be merged"; $lang->mr->approval = 'Approval'; $lang->mr->approve = 'Approve'; @@ -116,11 +117,15 @@ $lang->mr->apiErrorMap[1] = "You can't use same project/branch for source and ta $lang->mr->apiErrorMap[2] = "/Another open merge request already exists for this source branch: !([0-9]+)/"; $lang->mr->apiErrorMap[3] = "401 Unauthorized"; $lang->mr->apiErrorMap[4] = "403 Forbidden"; +$lang->mr->apiErrorMap[5] = "/(pull request already exists for these targets).*/"; +$lang->mr->apiErrorMap[6] = "Invalid PullRequest: There are no changes between the head and the base"; $lang->mr->errorLang[1] = 'The source project branch cannot be the same as the target project branch'; $lang->mr->errorLang[2] = 'Another open merge request already exists for this source branch: ID%u'; $lang->mr->errorLang[3] = "Unauthorized"; $lang->mr->errorLang[4] = 'Permission denied'; +$lang->mr->errorLang[5] = 'Another open merge request already exists for this source branch'; +$lang->mr->errorLang[6] = 'The source project branch cannot be the same as the target project branch'; $lang->mr->from = "from"; $lang->mr->to = "to"; @@ -177,7 +182,7 @@ $lang->mr->commandDocument = <<< EOD git merge --no-ff "%s"

    - step 4. Push the result of the merge to GitLab + step 4. Push the result of the merge to Git

     git push origin "%s" 

    @@ -185,9 +190,10 @@ EOD; $lang->mr->noChanges = "Currently there are no changes in this merge request's source branch. Please push new commits or use a different branch."; -$lang->mr->linkTask = 'Link Tasks'; +$lang->mr->linkTask = "Link task"; $lang->mr->unlinkTask = "Remove task"; $lang->mr->linkedTasks = 'Task'; $lang->mr->unlinkedTasks = 'Task not linked'; $lang->mr->confirmUnlinkTask = "Are you sure to remove this task?"; $lang->mr->taskSummary = "There are %s tasks on this page"; +$lang->mr->notDelbranch = "The source branch cannot be deleted when it is a protected branch"; diff --git a/module/mr/lang/en.php b/module/mr/lang/en.php index 2b9f8e9ebc..f0046ebdd7 100644 --- a/module/mr/lang/en.php +++ b/module/mr/lang/en.php @@ -1,6 +1,7 @@ mr = new stdclass; $lang->mr->common = "Merge Request"; +$lang->mr->server = "Server"; $lang->mr->view = "Survey"; $lang->mr->create = "Create"; $lang->mr->apiCreate = "Interface: Create"; @@ -13,7 +14,7 @@ $lang->mr->source = 'source'; $lang->mr->target = 'target'; $lang->mr->viewDiff = 'View diff'; $lang->mr->diff = 'View diff'; -$lang->mr->viewInGitlab = 'View in GitLab'; +$lang->mr->viewInGit = 'View in APP'; $lang->mr->link = 'Link of stories,Bugs,tasks'; $lang->mr->createAction = '%s, %s submitted a Merge Request.'; @@ -38,8 +39,8 @@ $lang->mr->gitlabID = 'GitLab'; $lang->mr->repoID = 'Repo'; $lang->mr->jobID = 'Compile job'; -$lang->mr->canMerge = "Can merge"; -$lang->mr->cantMerge = "不可合并"; +$lang->mr->canMerge = "Can be merged"; +$lang->mr->cantMerge = "Can not be merged"; $lang->mr->approval = 'Approval'; $lang->mr->approve = 'Approve'; @@ -116,11 +117,15 @@ $lang->mr->apiErrorMap[1] = "You can't use same project/branch for source and ta $lang->mr->apiErrorMap[2] = "/Another open merge request already exists for this source branch: !([0-9]+)/"; $lang->mr->apiErrorMap[3] = "401 Unauthorized"; $lang->mr->apiErrorMap[4] = "403 Forbidden"; +$lang->mr->apiErrorMap[5] = "/(pull request already exists for these targets).*/"; +$lang->mr->apiErrorMap[6] = "Invalid PullRequest: There are no changes between the head and the base"; $lang->mr->errorLang[1] = 'The source project branch cannot be the same as the target project branch'; $lang->mr->errorLang[2] = 'Another open merge request already exists for this source branch: ID%u'; $lang->mr->errorLang[3] = "Unauthorized"; $lang->mr->errorLang[4] = 'Permission denied'; +$lang->mr->errorLang[5] = 'Another open merge request already exists for this source branch'; +$lang->mr->errorLang[6] = 'The source project branch cannot be the same as the target project branch'; $lang->mr->from = "from"; $lang->mr->to = "to"; @@ -177,7 +182,7 @@ $lang->mr->commandDocument = <<< EOD git merge --no-ff "%s"

    - step 4. Push the result of the merge to GitLab + step 4. Push the result of the merge to Git

     git push origin "%s" 

    @@ -191,3 +196,4 @@ $lang->mr->linkedTasks = 'Task'; $lang->mr->unlinkedTasks = 'Task not linked'; $lang->mr->confirmUnlinkTask = "Are you sure to remove this task?"; $lang->mr->taskSummary = "There are %s tasks on this page"; +$lang->mr->notDelbranch = "The source branch cannot be deleted when it is a protected branch"; diff --git a/module/mr/lang/fr.php b/module/mr/lang/fr.php index 46ed175893..f0046ebdd7 100644 --- a/module/mr/lang/fr.php +++ b/module/mr/lang/fr.php @@ -1,6 +1,7 @@ mr = new stdclass; $lang->mr->common = "Merge Request"; +$lang->mr->server = "Server"; $lang->mr->view = "Survey"; $lang->mr->create = "Create"; $lang->mr->apiCreate = "Interface: Create"; @@ -13,7 +14,7 @@ $lang->mr->source = 'source'; $lang->mr->target = 'target'; $lang->mr->viewDiff = 'View diff'; $lang->mr->diff = 'View diff'; -$lang->mr->viewInGitlab = 'View in GitLab'; +$lang->mr->viewInGit = 'View in APP'; $lang->mr->link = 'Link of stories,Bugs,tasks'; $lang->mr->createAction = '%s, %s submitted a Merge Request.'; @@ -38,8 +39,8 @@ $lang->mr->gitlabID = 'GitLab'; $lang->mr->repoID = 'Repo'; $lang->mr->jobID = 'Compile job'; -$lang->mr->canMerge = "Can merge"; -$lang->mr->cantMerge = "不可合并"; +$lang->mr->canMerge = "Can be merged"; +$lang->mr->cantMerge = "Can not be merged"; $lang->mr->approval = 'Approval'; $lang->mr->approve = 'Approve'; @@ -116,11 +117,15 @@ $lang->mr->apiErrorMap[1] = "You can't use same project/branch for source and ta $lang->mr->apiErrorMap[2] = "/Another open merge request already exists for this source branch: !([0-9]+)/"; $lang->mr->apiErrorMap[3] = "401 Unauthorized"; $lang->mr->apiErrorMap[4] = "403 Forbidden"; +$lang->mr->apiErrorMap[5] = "/(pull request already exists for these targets).*/"; +$lang->mr->apiErrorMap[6] = "Invalid PullRequest: There are no changes between the head and the base"; $lang->mr->errorLang[1] = 'The source project branch cannot be the same as the target project branch'; $lang->mr->errorLang[2] = 'Another open merge request already exists for this source branch: ID%u'; $lang->mr->errorLang[3] = "Unauthorized"; $lang->mr->errorLang[4] = 'Permission denied'; +$lang->mr->errorLang[5] = 'Another open merge request already exists for this source branch'; +$lang->mr->errorLang[6] = 'The source project branch cannot be the same as the target project branch'; $lang->mr->from = "from"; $lang->mr->to = "to"; @@ -177,7 +182,7 @@ $lang->mr->commandDocument = <<< EOD git merge --no-ff "%s"

    - step 4. Push the result of the merge to GitLab + step 4. Push the result of the merge to Git

     git push origin "%s" 

    @@ -185,9 +190,10 @@ EOD; $lang->mr->noChanges = "Currently there are no changes in this merge request's source branch. Please push new commits or use a different branch."; -$lang->mr->linkTask = 'Link Tasks'; +$lang->mr->linkTask = "Link task"; $lang->mr->unlinkTask = "Remove task"; $lang->mr->linkedTasks = 'Task'; $lang->mr->unlinkedTasks = 'Task not linked'; $lang->mr->confirmUnlinkTask = "Are you sure to remove this task?"; $lang->mr->taskSummary = "There are %s tasks on this page"; +$lang->mr->notDelbranch = "The source branch cannot be deleted when it is a protected branch"; diff --git a/module/mr/lang/vi.php b/module/mr/lang/vi.php new file mode 100644 index 0000000000..f0046ebdd7 --- /dev/null +++ b/module/mr/lang/vi.php @@ -0,0 +1,199 @@ +mr = new stdclass; +$lang->mr->common = "Merge Request"; +$lang->mr->server = "Server"; +$lang->mr->view = "Survey"; +$lang->mr->create = "Create"; +$lang->mr->apiCreate = "Interface: Create"; +$lang->mr->browse = "Browse"; +$lang->mr->list = "List"; +$lang->mr->edit = "Edit"; +$lang->mr->delete = "Delete"; +$lang->mr->accept = "Accept"; +$lang->mr->source = 'source'; +$lang->mr->target = 'target'; +$lang->mr->viewDiff = 'View diff'; +$lang->mr->diff = 'View diff'; +$lang->mr->viewInGit = 'View in APP'; +$lang->mr->link = 'Link of stories,Bugs,tasks'; +$lang->mr->createAction = '%s, %s submitted a Merge Request.'; + +$lang->mr->linkList = 'Link List of stories,Bugs,tasks'; +$lang->mr->linkStory = 'Link Stories'; +$lang->mr->linkBug = 'Link Bugs'; +$lang->mr->linkTask = 'Link Tasks'; +$lang->mr->unlink = 'UnLink of stories,Bugs,tasks'; +$lang->mr->addReview = 'Add Review'; + +$lang->mr->id = 'ID'; +$lang->mr->mriid = "raw MR ID"; +$lang->mr->title = 'Name'; +$lang->mr->status = 'Status'; +$lang->mr->author = 'Author'; +$lang->mr->assignee = 'Assignee'; +$lang->mr->reviewer = 'Reviewer'; +$lang->mr->mergeStatus = 'Merge status'; +$lang->mr->commits = 'commits'; +$lang->mr->changes = 'changes'; +$lang->mr->gitlabID = 'GitLab'; +$lang->mr->repoID = 'Repo'; +$lang->mr->jobID = 'Compile job'; + +$lang->mr->canMerge = "Can be merged"; +$lang->mr->cantMerge = "Can not be merged"; + +$lang->mr->approval = 'Approval'; +$lang->mr->approve = 'Approve'; +$lang->mr->reject = 'Reject'; +$lang->mr->close = 'Close'; +$lang->mr->reopen = 'Reopen'; + +$lang->mr->reviewType = 'Review Type'; +$lang->mr->reviewTypeList = array(); +$lang->mr->reviewTypeList['bug'] = 'Bug'; +$lang->mr->reviewTypeList['task'] = 'Task'; + +$lang->mr->approvalResult = 'Approval result'; +$lang->mr->approvalResultList = array(); +$lang->mr->approvalResultList['approve'] = 'Approve'; +$lang->mr->approvalResultList['reject'] = 'Reject'; + +$lang->mr->needApproved = 'This MR should be approved before merge'; +$lang->mr->needCI = 'Merge only after passing CI'; +$lang->mr->removeSourceBranch = 'Delete source branch after merge'; +$lang->mr->squash = 'Squash commits'; + +$lang->mr->repeatedOperation = 'Do not repeat operations'; + +$lang->mr->approvalStatus = 'Approve status'; +$lang->mr->approvalStatusList = array(); +$lang->mr->approvalStatusList['notReviewed'] = 'notReviewed'; +$lang->mr->approvalStatusList['approved'] = 'Approved'; +$lang->mr->approvalStatusList['rejected'] = 'Rejected'; + +$lang->mr->notApproved = 'Rejected'; +$lang->mr->assignedToMe = 'AssignedToMe'; +$lang->mr->createdByMe = 'CreatedByMe'; + +$lang->mr->statusList = array(); +$lang->mr->statusList['all'] = 'all'; +$lang->mr->statusList['opened'] = 'opened'; +$lang->mr->statusList['merged'] = 'merged'; +$lang->mr->statusList['closed'] = 'closed'; + +$lang->mr->mergeStatusList = array(); +$lang->mr->mergeStatusList['unchecked'] = 'unchecked'; +$lang->mr->mergeStatusList['checking'] = 'checking'; +$lang->mr->mergeStatusList['can_be_merged'] = 'can be merged'; +$lang->mr->mergeStatusList['cannot_be_merged'] = 'cannot be merged'; +$lang->mr->mergeStatusList['cannot_merge_by_fail'] = 'Cannot be merged, check failed'; + +$lang->mr->description = 'Description'; +$lang->mr->confirmDelete = 'Are you sure to delete this merge request?'; +$lang->mr->sourceProject = 'Source project'; +$lang->mr->sourceBranch = 'Source branch'; +$lang->mr->targetProject = 'Target project'; +$lang->mr->targetBranch = 'Target branch'; +$lang->mr->noCompileJob = 'No Compile Job'; +$lang->mr->compileUnexecuted = 'Compile Unexecuted'; + +$lang->mr->notFound = "Merge Request does not exist!"; +$lang->mr->toCreatedMessage = "The merge request you submitted:%s, the build task succeeded."; +$lang->mr->toReviewerMessage = "You have one merge request %s waiting."; +$lang->mr->failMessage = "Your merge request %s failed. Please check its execution result. "; +$lang->mr->storySummary = "Total %s {$lang->SRCommon} on this page."; + +$lang->mr->apiError = new stdclass; +$lang->mr->apiError->createMR = "Failed to create a merge request through API. Reason: %s"; +$lang->mr->apiError->sudo = "Unable to operate with the GitLab account bound to the current user. Reason: %s"; + +$lang->mr->createFailedFromAPI = "Failed to create Merge Request."; +$lang->mr->hasSameOpenedMR = "There are duplicate and unclosed merge requests: ID%u"; +$lang->mr->accessGitlabFailed = "Unable to connect to the GitLab server."; +$lang->mr->reopenSuccess = "The merge request was reopened."; +$lang->mr->closeSuccess = "Merge request closed."; + +$lang->mr->apiErrorMap[1] = "You can't use same project/branch for source and target"; +$lang->mr->apiErrorMap[2] = "/Another open merge request already exists for this source branch: !([0-9]+)/"; +$lang->mr->apiErrorMap[3] = "401 Unauthorized"; +$lang->mr->apiErrorMap[4] = "403 Forbidden"; +$lang->mr->apiErrorMap[5] = "/(pull request already exists for these targets).*/"; +$lang->mr->apiErrorMap[6] = "Invalid PullRequest: There are no changes between the head and the base"; + +$lang->mr->errorLang[1] = 'The source project branch cannot be the same as the target project branch'; +$lang->mr->errorLang[2] = 'Another open merge request already exists for this source branch: ID%u'; +$lang->mr->errorLang[3] = "Unauthorized"; +$lang->mr->errorLang[4] = 'Permission denied'; +$lang->mr->errorLang[5] = 'Another open merge request already exists for this source branch'; +$lang->mr->errorLang[6] = 'The source project branch cannot be the same as the target project branch'; + +$lang->mr->from = "from"; +$lang->mr->to = "to"; +$lang->mr->at = "at"; + +$lang->mr->pipeline = "Pipeline"; +$lang->mr->pipelineSuccess = "Success"; +$lang->mr->pipelineFailed = "Failed"; +$lang->mr->pipelineCanceled = "Canceled"; +$lang->mr->pipelineUnknown = "Unknown"; + +$lang->mr->pipelineStatus = array(); +$lang->mr->pipelineStatus['success'] = "success"; +$lang->mr->pipelineStatus['failed'] = "failed"; +$lang->mr->pipelineStatus['canceled'] = "canceled"; + +$lang->mr->MRHasConflicts = "Merge Request has a conflict"; +$lang->mr->hasConflicts = "There are merge conflicts or wait for push"; +$lang->mr->hasNoConflict = "Can merge"; +$lang->mr->acceptMR = "Accept Merge request "; +$lang->mr->mergeFailed = "Unable to merge request, please check the merge request status"; +$lang->mr->mergeSuccess = "Merge Request Successfully"; + +$lang->mr->todomessage = "project was assigned to you"; + +/** + * Merge Command Document. + * + * %s source_project::http_url_to_repo + * %s mr::source_branch + * %s source_project::path_with_namespace . '-' . mr::source_branch + * %s mr::target_branch + * %s source_project::path_with_namespace . '-' . mr::source_branch + * %s mr::target_branch + */ +$lang->mr->commandDocument = <<< EOD +
    Check out, review and merge locally
    +
    +

    Note: This merge request status will be changed automatically after you merged locally.

    +

    + step 1. Change directory to target project. Fetch and check out the branch for this merge request +

    +    git fetch "%s" %s
    +    git checkout -b "%s" FETCH_HEAD
    +

    +

    + step 2. Review the changes locally. You can use git log to view the changes +

    +

    + step 3. Merge the branch and fix any conflicts that come up +

    +    git fetch origin
    +    git checkout "%s"
    +    git merge --no-ff "%s"
    +

    +

    + step 4. Push the result of the merge to Git +

     git push origin "%s" 
    +

    +
    +EOD; + +$lang->mr->noChanges = "Currently there are no changes in this merge request's source branch. Please push new commits or use a different branch."; + +$lang->mr->linkTask = "Link task"; +$lang->mr->unlinkTask = "Remove task"; +$lang->mr->linkedTasks = 'Task'; +$lang->mr->unlinkedTasks = 'Task not linked'; +$lang->mr->confirmUnlinkTask = "Are you sure to remove this task?"; +$lang->mr->taskSummary = "There are %s tasks on this page"; +$lang->mr->notDelbranch = "The source branch cannot be deleted when it is a protected branch"; diff --git a/module/mr/lang/zh-cn.php b/module/mr/lang/zh-cn.php index 4f9558935b..cb129a2da4 100644 --- a/module/mr/lang/zh-cn.php +++ b/module/mr/lang/zh-cn.php @@ -1,6 +1,7 @@ mr = new stdclass; $lang->mr->common = "合并请求"; +$lang->mr->server = "服务器"; $lang->mr->view = "概况"; $lang->mr->create = "创建{$lang->mr->common}"; $lang->mr->apiCreate = "接口:创建{$lang->mr->common}"; @@ -13,7 +14,7 @@ $lang->mr->source = '源项目分支'; $lang->mr->target = '目标项目分支'; $lang->mr->viewDiff = '比对代码'; $lang->mr->diff = '比对代码'; -$lang->mr->viewInGitlab = '在GitLab查看'; +$lang->mr->viewInGit = '在应用中查看'; $lang->mr->link = '关联需求、Bug、任务'; $lang->mr->createAction = '%s, 由 %s 提交了 合并请求。'; @@ -116,11 +117,15 @@ $lang->mr->apiErrorMap[1] = "You can't use same project/branch for source and ta $lang->mr->apiErrorMap[2] = "/Another open merge request already exists for this source branch: !([0-9]+)/"; $lang->mr->apiErrorMap[3] = "401 Unauthorized"; $lang->mr->apiErrorMap[4] = "403 Forbidden"; +$lang->mr->apiErrorMap[5] = "/(pull request already exists for these targets).*/"; +$lang->mr->apiErrorMap[6] = "Invalid PullRequest: There are no changes between the head and the base"; $lang->mr->errorLang[1] = '源项目分支与目标项目分支不能相同'; $lang->mr->errorLang[2] = '存在另外一个同样的合并请求在源项目分支中: ID%u'; $lang->mr->errorLang[3] = '权限不足'; $lang->mr->errorLang[4] = '权限不足'; +$lang->mr->errorLang[5] = '存在另外一个同样的合并请求在源项目分支中'; +$lang->mr->errorLang[6] = '源项目分支与目标项目分支不能相同'; $lang->mr->from = "从"; $lang->mr->to = "合并到"; @@ -177,7 +182,7 @@ $lang->mr->commandDocument = <<< EOD git merge --no-ff "%s"

    - 第 4 步. 将合并结果推送到GitLab + 第 4 步. 将合并结果推送到Git

     git push origin "%s" 

    @@ -191,3 +196,4 @@ $lang->mr->linkedTasks = '任务'; $lang->mr->unlinkedTasks = '未关联任务'; $lang->mr->confirmUnlinkTask = "您确认移除该任务吗?"; $lang->mr->taskSummary = "本页共 %s 个任务"; +$lang->mr->notDelbranch = "源分支为受保护分支时不可删除"; diff --git a/module/mr/model.php b/module/mr/model.php index 6cd9154a69..fc75d69952 100644 --- a/module/mr/model.php +++ b/module/mr/model.php @@ -55,10 +55,10 @@ class mrModel extends model $filterProjectSql = ''; if(!$this->app->user->admin and !empty($filterProjects)) { - foreach($filterProjects as $gitlabID => $projects) + foreach($filterProjects as $hostID => $projects) { $projectIDList = array_keys($projects); - if(!empty($projectIDList)) $filterProjectSql .= "(gitlabID = {$gitlabID} and sourceProject " . helper::dbIN($projectIDList) . ") or "; + if(!empty($projectIDList)) $filterProjectSql .= "(hostID = {$hostID} and sourceProject " . helper::dbIN($projectIDList) . ") or "; } if($filterProjectSql) $filterProjectSql = '(' . substr($filterProjectSql, 0, -3) . ')'; // Remove last or. @@ -99,54 +99,78 @@ class mrModel extends model * Get all gitlab server projects. If not an administrator, the role of project member should be higher than guest. * * @param int $repoID + * @param string $scm * @access public * @return array */ - public function getAllGitlabProjects($repoID = 0) + public function getAllProjects($repoID = 0, $scm = 'Gitlab') { - $gitlabIDList = $this->dao->select('distinct gitlabID')->from(TABLE_MR) + $hostID = $this->dao->select('hostID')->from(TABLE_MR) ->where('deleted')->eq('0') - ->beginIF($repoID)->andWhere('repoID')->eq($repoID)->fi() - ->fetchPairs('gitlabID'); + ->andWhere('repoID')->eq($repoID) + ->fetch('hostID'); + return $this->{'get' . $scm . 'Projects'}($hostID); + } + + /** + * Get gitea projects. + * + * @param int $hostID + * @access public + * @return array + */ + public function getGiteaProjects($hostID = 0) + { + $projects = $this->loadModel('gitea')->apiGetProjects($hostID); + return array($hostID => array_column($projects, null, 'full_name')); + } + + /** + * Get gitlab projects. + * + * @param int $hostID + * @access public + * @return array + */ + public function getGitlabProjects($hostID = 0) + { $allProjects = array(); $allGroups = array(); - $gitlabUsers = $this->gitlab->getGitLabListByAccount(); - foreach($gitlabIDList as $gitlabID) + $gitlabUsers = $this->loadModel('gitlab')->getGitLabListByAccount(); + if(!$this->app->user->admin and !isset($gitlabUsers[$hostID])) return array(); + + $minProject = $maxProject = 0; + /* Mysql string to int. */ + $projectCount = $this->dao->select('min(sourceProject + 0) as minSource, MAX(sourceProject + 0) as maxSource,MIN(targetProject) as minTarget,MAX(targetProject) as maxTarget')->from(TABLE_MR) + ->where('deleted')->eq('0') + ->andWhere('hostID')->eq($hostID) + ->fetch(); + if($projectCount) { - if(!$this->app->user->admin and !isset($gitlabUsers[$gitlabID])) continue; - - $minProject = $maxProject = 0; - $projectCount = $this->dao->select('min(sourceProject) as minSource,MAX(sourceProject) as maxSource,MIN(targetProject) as minTarget,MAX(targetProject) as maxTarget')->from(TABLE_MR) - ->where('deleted')->eq('0') - ->andWhere('gitlabID')->eq($gitlabID) - ->fetch(); - if($projectCount) - { - $minProject = min($projectCount->minSource, $projectCount->minTarget); - $maxProject = max($projectCount->maxSource, $projectCount->maxTarget); - } - $allProjects[$gitlabID] = $this->gitlab->apiGetProjects($gitlabID, 'false', $minProject, $maxProject); - - /* If not an administrator, need to obtain group member information. */ - $groupIDList = array(0 => 0); - if(!$this->app->user->admin) - { - $groups = $this->gitlab->apiGetGroups($gitlabID, 'name_asc', 'reporter'); - foreach($groups as $group) $groupIDList[] = $group->id; - } - $allGroups[$gitlabID] = $groupIDList; + $minProject = min($projectCount->minSource, $projectCount->minTarget); + $maxProject = max($projectCount->maxSource, $projectCount->maxTarget); } + $allProjects[$hostID] = $this->gitlab->apiGetProjects($hostID, 'false', $minProject, $maxProject); + + /* If not an administrator, need to obtain group member information. */ + $groupIDList = array(0 => 0); + if(!$this->app->user->admin) + { + $groups = $this->gitlab->apiGetGroups($hostID, 'name_asc', 'reporter'); + foreach($groups as $group) $groupIDList[] = $group->id; + } + $allGroups[$hostID] = $groupIDList; $allProjectPairs = array(); - foreach($allProjects as $gitlabID => $projects) + foreach($allProjects as $hostID => $projects) { foreach($projects as $key => $project) { - if($this->gitlab->checkUserAccess($gitlabID, 0, $project, $allGroups[$gitlabID], 'reporter') == false) continue; - $project->isDeveloper = $this->gitlab->checkUserAccess($gitlabID, 0, $project, $allGroups[$gitlabID], 'developer'); + if($this->gitlab->checkUserAccess($hostID, 0, $project, $allGroups[$hostID], 'reporter') == false) continue; + $project->isDeveloper = $this->gitlab->checkUserAccess($hostID, 0, $project, $allGroups[$hostID], 'developer'); - $allProjectPairs[$gitlabID][$project->id] = $project; + $allProjectPairs[$hostID][$project->id] = $project; } } @@ -171,7 +195,7 @@ class mrModel extends model ->add('createdDate', helper::now()) ->get(); - $result = $this->checkSameOpened($MR->gitlabID, $MR->sourceProject, $MR->sourceBranch, $MR->targetProject, $MR->targetBranch); + $result = $this->checkSameOpened($MR->hostID, $MR->sourceProject, $MR->sourceBranch, $MR->targetProject, $MR->targetBranch); if($result['result'] == 'fail') return $result; /* Exec Job */ @@ -195,21 +219,7 @@ class mrModel extends model $MRID = $this->dao->lastInsertId(); $this->loadModel('action')->create('mr', $MRID, 'opened'); - $MRObject = new stdclass; - $MRObject->target_project_id = $MR->targetProject; - $MRObject->source_branch = $MR->sourceBranch; - $MRObject->target_branch = $MR->targetBranch; - $MRObject->title = $MR->title; - $MRObject->description = $MR->description; - $MRObject->remove_source_branch = $MR->removeSourceBranch == '1' ? true : false; - $MRObject->squash = $MR->squash == '1' ? 1 : 0; - if($MR->assignee) - { - $gitlabAssignee = $this->gitlab->getUserIDByZentaoAccount($this->post->gitlabID, $MR->assignee); - if($gitlabAssignee) $MRObject->assignee_ids = $gitlabAssignee; - } - - $rawMR = $this->apiCreateMR($this->post->gitlabID, $this->post->sourceProject, $MRObject); + $rawMR = $this->apiCreateMR($this->post->hostID, $this->post->sourceProject, $MR); /** * Another open merge request already exists for this source branch. @@ -231,7 +241,7 @@ class mrModel extends model } /* Create a todo item for this MR. */ - if(empty($MR->jobID)) $this->apiCreateMRTodo($this->post->gitlabID, $this->post->targetProject, $rawMR->iid); + if(empty($MR->jobID)) $this->apiCreateMRTodo($this->post->hostID, $this->post->targetProject, $rawMR->iid); $newMR = new stdclass; $newMR->mriid = $rawMR->iid; @@ -269,7 +279,7 @@ class mrModel extends model /* Process and insert mr data. */ $MR = new stdClass(); - $MR->gitlabID = $repo->client; + $MR->hostID = $repo->client; $MR->sourceProject = $repo->path; $MR->sourceBranch = $postData->sourceBranch; $MR->targetProject = $repo->path; @@ -292,7 +302,7 @@ class mrModel extends model return false; } - $result = $this->checkSameOpened($MR->gitlabID, $MR->sourceProject, $MR->sourceBranch, $MR->targetProject, $MR->targetBranch); + $result = $this->checkSameOpened($MR->hostID, $MR->sourceProject, $MR->sourceBranch, $MR->targetProject, $MR->targetBranch); if($result['result'] == 'fail') { dao::$errors[] = $result['message']; @@ -355,6 +365,7 @@ class mrModel extends model ->get(); $oldMR = $this->getByID($MRID); + if($oldMR->sourceProject == $oldMR->targetProject and $oldMR->sourceBranch == $MR->targetBranch) dao::$errors['targetBranch'] = $this->lang->mr->errorLang[1]; $this->dao->update(TABLE_MR)->data($MR)->checkIF($MR->needCI, 'jobID', 'notempty'); if(dao::isError()) return array('result' => 'fail', 'message' => dao::getError()); @@ -371,21 +382,8 @@ class mrModel extends model } } - /* Update MR in GitLab. */ - $newMR = new stdclass; - $newMR->title = $MR->title; - $newMR->description = $MR->description; - $newMR->target_branch = $MR->targetBranch; - $newMR->remove_source_branch = $MR->removeSourceBranch == '1' ? true : false; - $newMR->squash = $MR->squash == '1' ? 1 : 0; - if($MR->assignee) - { - $gitlabAssignee = $this->gitlab->getUserIDByZentaoAccount($oldMR->gitlabID, $MR->assignee); - if($gitlabAssignee) $newMR->assignee_ids = $gitlabAssignee; - } - /* Known issue: `reviewer_ids` takes no effect. */ - $rawMR = $this->apiUpdateMR($oldMR->gitlabID, $oldMR->targetProject, $oldMR->mriid, $newMR); + $rawMR = $this->apiUpdateMR($oldMR->hostID, $oldMR->targetProject, $oldMR->mriid, $MR); if(!isset($rawMR->id) and isset($rawMR->message)) { $errorMessage = $this->convertApiError($rawMR->message); @@ -415,12 +413,12 @@ class mrModel extends model */ public function apiSyncMR($MR) { - $rawMR = $this->apiGetSingleMR($MR->gitlabID, $MR->targetProject, $MR->mriid); + $rawMR = $this->apiGetSingleMR($MR->hostID, $MR->targetProject, $MR->mriid); /* Sync MR in ZenTao database whatever status of MR in GitLab. */ if(isset($rawMR->iid)) { $map = $this->config->mr->maps->sync; - $gitlabUsers = $this->gitlab->getUserIdAccountPairs($MR->gitlabID); + $gitlabUsers = $this->gitlab->getUserIdAccountPairs($MR->hostID); $newMR = new stdclass; foreach($map as $syncField => $config) @@ -455,20 +453,23 @@ class mrModel extends model * Batch Sync GitLab MR Database. * * @param object $MRList + * @param string $scm * @access public * @return array */ - public function batchSyncMR($MRList) + public function batchSyncMR($MRList, $scm = 'Gitlab') { if(empty($MRList)) return array(); + $this->loadModel('gitlab'); + $this->loadModel('gitea'); foreach($MRList as $key => $MR) { if($MR->status != 'opened') continue; - if(!isset($rawMRList[$MR->gitlabID][$MR->targetProject])) $rawMRList[$MR->gitlabID][$MR->targetProject] = $this->apiGetMRList($MR->gitlabID, $MR->targetProject); + if(!isset($rawMRList[$MR->hostID][$MR->targetProject])) $rawMRList[$MR->hostID][$MR->targetProject] = $this->apiGetMRList($MR->hostID, $MR->targetProject, $scm); $rawMR = new stdClass(); - foreach($rawMRList[$MR->gitlabID][$MR->targetProject] as $projcetRawMR) + foreach($rawMRList[$MR->hostID][$MR->targetProject] as $projcetRawMR) { if(isset($projcetRawMR->iid) and $projcetRawMR->iid == $MR->mriid) { @@ -480,10 +481,17 @@ class mrModel extends model if(isset($rawMR->iid)) { /* create gitlab mr todo to zentao todo */ - $this->batchSyncTodo($MR->gitlabID, $MR->targetProject); + if($scm == 'Gitlab') $this->batchSyncTodo($MR->hostID, $MR->targetProject); - $map = $this->config->mr->maps->sync; - $gitlabUsers = $this->gitlab->getUserIdAccountPairs($MR->gitlabID); + $map = $this->config->mr->maps->sync; + if($scm == 'Gitlab') + { + $users = $this->gitlab->getUserIdAccountPairs($MR->hostID); + } + else + { + $users = $this->gitea->getUserAccountIdPairs($MR->hostID, 'openID,account'); + } $newMR = new stdclass; @@ -501,7 +509,7 @@ class mrModel extends model $values = $rawMR->$field; if(isset($values[0])) $gitlabUserID = $values[0]->$options; } - $value = zget($gitlabUsers, $gitlabUserID, ''); + $value = zget($users, $gitlabUserID, ''); } if($value) $newMR->$syncField = $value; @@ -534,29 +542,29 @@ class mrModel extends model /** * Sync GitLab Todo to ZenTao Todo. * - * @param int $gitlabID + * @param int $hostID * @param int $projectID * @access public * @return void */ - public function batchSyncTodo($gitlabID, $projectID) + public function batchSyncTodo($hostID, $projectID) { /* It can only get todo from GitLab API by its assignee. So here should use sudo as the assignee to get the todo list. */ /* In this case, ignore sync todo for reviewer due to an issue in GitLab API. */ $accountList = $this->dao->select('assignee')->from(TABLE_MR) ->where('deleted')->eq('0') ->andWhere('status')->eq('opened') - ->andWhere('gitlabID')->eq($gitlabID) + ->andWhere('hostID')->eq($hostID) ->andWhere('targetProject')->eq($projectID) ->fetchPairs(); foreach($accountList as $account) { - $accountPair = $this->getSudoAccountPair($gitlabID, $projectID, $account); + $accountPair = $this->getSudoAccountPair($hostID, $projectID, $account); if(!empty($accountPair) and isset($accountPair[$account])) { $sudo = $accountPair[$account]; - $todoList = $this->gitlab->apiGetTodoList($gitlabID, $projectID, $sudo); + $todoList = $this->gitlab->apiGetTodoList($hostID, $projectID, $sudo); foreach($todoList as $rawTodo) { @@ -566,7 +574,7 @@ class mrModel extends model ->fetch(); if(empty($todoDesc)) { - $acountPairs = $this->gitlab->getUserIdRealnamePairs($gitlabID); + $acountPairs = $this->gitlab->getUserIdRealnamePairs($hostID); $author = isset($acountPairs[$rawTodo->author->id]) ? $acountPairs[$rawTodo->author->id] : $rawTodo->author->name; $todo = new stdClass; @@ -581,7 +589,7 @@ class mrModel extends model $todo->idvalue = $rawTodo->id; $todo->pri = 3; $todo->name = $this->lang->mr->common . ": " . $rawTodo->target->title; - $todo->desc = $author . ' ' . $this->lang->mr->at . ' ' . '' . $rawTodo->project->path .'' . ' ' . $this->lang->mr->todomessage . '' . ' ' . $this->lang->mr->common .'' . '。'; + $todo->desc = $author . ' ' . $this->lang->mr->at . ' ' . '' . $rawTodo->project->path .'' . ' ' . $this->lang->mr->todomessage . '' . ' ' . $this->lang->mr->common .'' . '。'; $todo->status = 'wait'; $todo->finishedBy = ''; @@ -595,14 +603,14 @@ class mrModel extends model /** * Get a list of todo items. * - * @param int $gitlabID + * @param int $hostID * @param int $projectID * @access public * @return object */ - public function todoDescriptionLink($gitlabID, $projectID) + public function todoDescriptionLink($hostID, $projectID) { - $gitlab = $this->gitlab->getByID($gitlabID); + $gitlab = $this->gitlab->getByID($hostID); if(!$gitlab) return ''; return rtrim($gitlab->url, '/')."/dashboard/todos?project_id=$projectID&type=MergeRequest"; } @@ -611,33 +619,100 @@ class mrModel extends model * Create MR by API. * * @link https://docs.gitlab.com/ee/api/merge_requests.html#create-mr - * @param int $gitlabID + * @param int $hostID * @param int $projectID * @param object $MR * @access public * @return object */ - public function apiCreateMR($gitlabID, $projectID, $MR) + public function apiCreateMR($hostID, $projectID, $MR) { - $url = sprintf($this->gitlab->getApiRoot($gitlabID), "/projects/$projectID/merge_requests"); - return json_decode(commonModel::http($url, $MR)); + $host = $this->loadModel('pipeline')->getByID($hostID); + + $MRObject = new stdclass; + $MRObject->title = $MR->title; + if($host->type == 'gitlab') + { + $url = sprintf($this->loadModel('gitlab')->getApiRoot($hostID), "/projects/$projectID/merge_requests"); + + $MRObject->target_project_id = $MR->targetProject; + $MRObject->source_branch = $MR->sourceBranch; + $MRObject->target_branch = $MR->targetBranch; + $MRObject->description = $MR->description; + $MRObject->remove_source_branch = $MR->removeSourceBranch == '1' ? true : false; + $MRObject->squash = $MR->squash == '1' ? 1 : 0; + if($MR->assignee) + { + $gitlabAssignee = $this->gitlab->getUserIDByZentaoAccount($this->post->hostID, $MR->assignee); + if($gitlabAssignee) $MRObject->assignee_ids = $gitlabAssignee; + } + return json_decode(commonModel::http($url, $MRObject)); + } + else + { + $url = sprintf($this->loadModel('gitea')->getApiRoot($hostID), "/repos/$projectID/pulls"); + + $MRObject->head = $MR->sourceBranch; + $MRObject->base = $MR->targetBranch; + $MRObject->body = $MR->description; + if($MR->assignee) + { + $assignee = $this->gitea->getUserIDByZentaoAccount($this->post->hostID, $MR->assignee); + if($assignee) $MRObject->assignee = $assignee; + } + + $mergeResult = json_decode(commonModel::http($url, $MRObject)); + if(isset($mergeResult->number)) $mergeResult->iid = $mergeResult->number; + if(isset($mergeResult->mergeable)) + { + if($mergeResult->mergeable) $mergeResult->merge_status = 'can_be_merged'; + if(!$mergeResult->mergeable) $mergeResult->merge_status = 'cannot_be_merged'; + } + if(isset($mergeResult->state) and $mergeResult->state == 'open') $mergeResult->state = 'opened'; + if(isset($mergeResult->merged) and $mergeResult->merged) $mergeResult->state = 'merged'; + return $mergeResult; + } } /** * Get MR list by API. * * @link https://docs.gitlab.com/ee/api/merge_requests.html#list-project-merge-requests - * @param int $gitlabID + * @param int $hostID * @param int $projectID + * @param string $scm * @access public * @return object */ - public function apiGetMRList($gitlabID, $projectID) + public function apiGetMRList($hostID, $projectID, $scm = 'Gitlab') { - $url = sprintf($this->gitlab->getApiRoot($gitlabID), "/projects/$projectID/merge_requests"); + if($scm == 'Gitlab') + { + $url = sprintf($this->loadModel('gitlab')->getApiRoot($hostID), "/projects/$projectID/merge_requests"); + } + else + { + $url = sprintf($this->loadModel('gitea')->getApiRoot($hostID), "/repos/$projectID/pulls"); + } $response = json_decode(commonModel::http($url)); if(empty($response)) $response = array(); + if($scm == 'Gitea') + { + foreach($response as $MR) + { + $MR->iid = $MR->number; + $MR->state = $MR->state == 'open' ? 'opened' : $MR->state; + if($MR->merged) $MR->state = 'merged'; + + $MR->merge_status = $MR->mergeable ? 'can_be_merged' : 'cannot_be_merged'; + $MR->description = $MR->body; + $MR->target_branch = $MR->base->ref; + $MR->source_branch = $MR->head->ref; + $MR->source_project_id = $projectID; + $MR->target_project_id = $projectID; + } + } return $response; } @@ -645,7 +720,7 @@ class mrModel extends model /** * Get same opened mr by api. * - * @param int $gitlabID + * @param int $hostID * @param int $sourceProject * @param string $sourceBranch * @param int $targetProject @@ -653,19 +728,19 @@ class mrModel extends model * @access public * @return object */ - public function apiGetSameOpened($gitlabID, $sourceProject, $sourceBranch, $targetProject, $targetBranch) + public function apiGetSameOpened($hostID, $sourceProject, $sourceBranch, $targetProject, $targetBranch) { - if(empty($gitlabID) or empty($sourceProject) or empty($sourceBranch) or empty($targetProject) or empty($targetBranch)) return null; + if(empty($hostID) or empty($sourceProject) or empty($sourceBranch) or empty($targetProject) or empty($targetBranch)) return null; - $url = sprintf($this->loadModel('gitlab')->getApiRoot((int)$gitlabID), "/projects/{$sourceProject}/merge_requests") . "&state=opened&source_branch={$sourceBranch}&target_branch={$targetBranch}"; + $url = sprintf($this->loadModel('gitlab')->getApiRoot((int)$hostID), "/projects/{$sourceProject}/merge_requests") . "&state=opened&source_branch={$sourceBranch}&target_branch={$targetBranch}"; $response = json_decode(commonModel::http($url)); if($response) { - foreach($response as $mr) + foreach($response as $MR) { - if(empty($mr->source_project_id) or empty($mr->target_project_id)) return null; - if($mr->source_project_id == $sourceProject and $mr->target_project_id == $targetProject) return $mr; + if(empty($MR->source_project_id) or empty($MR->target_project_id)) return null; + if($MR->source_project_id == $sourceProject and $MR->target_project_id == $targetProject) return $MMRR; } } return null; @@ -675,31 +750,60 @@ class mrModel extends model * Get single MR by API. * * @link https://docs.gitlab.com/ee/api/merge_requests.html#get-single-mr - * @param int $gitlabID + * @param int $hostID * @param int $projectID targetProject * @param int $MRID * @access public * @return object */ - public function apiGetSingleMR($gitlabID, $projectID, $MRID) + public function apiGetSingleMR($hostID, $projectID, $MRID) { - $url = sprintf($this->gitlab->getApiRoot($gitlabID), "/projects/$projectID/merge_requests/$MRID"); - return json_decode(commonModel::http($url)); + $host = $this->loadModel('pipeline')->getByID($hostID); + if($host->type == 'gitlab') + { + $url = sprintf($this->gitlab->getApiRoot($hostID), "/projects/$projectID/merge_requests/$MRID"); + return json_decode(commonModel::http($url)); + } + else + { + $url = sprintf($this->loadModel('gitea')->getApiRoot($hostID), "/repos/$projectID/pulls/$MRID"); + $MR = json_decode(commonModel::http($url)); + if(isset($MR->url)) + { + $diff = $this->apiGetDiffs($hostID, $projectID, $MRID); + + $MR->web_url = $MR->url; + $MR->iid = $MR->number; + $MR->state = $MR->state == 'open' ? 'opened' : $MR->state; + if($MR->merged) $MR->state = 'merged'; + + $MR->merge_status = $MR->mergeable ? 'can_be_merged' : 'cannot_be_merged'; + $MR->changes_count = (int)$diff; + $MR->description = $MR->body; + $MR->target_branch = $MR->base->ref; + $MR->source_branch = $MR->head->ref; + $MR->source_project_id = $projectID; + $MR->target_project_id = $projectID; + $MR->has_conflicts = !(bool)$diff; + } + + return $MR; + } } /** * Get MR commits by API. * * @link https://docs.gitlab.com/ee/api/merge_requests.html#get-commits - * @param int $gitlabID + * @param int $hostID * @param int $projectID targetProject * @param int $MRID * @access public * @return object */ - public function apiGetMRCommits($gitlabID, $projectID, $MRID) + public function apiGetMRCommits($hostID, $projectID, $MRID) { - $url = sprintf($this->gitlab->getApiRoot($gitlabID), "/projects/$projectID/merge_requests/$MRID/commits"); + $url = sprintf($this->gitlab->getApiRoot($hostID), "/projects/$projectID/merge_requests/$MRID/commits"); return json_decode(commonModel::http($url)); } @@ -707,87 +811,188 @@ class mrModel extends model * Update MR by API. * * @link https://docs.gitlab.com/ee/api/merge_requests.html#update-mr - * @param int $gitlabID + * @param int $hostID * @param int $projectID * @param int $MRID * @param object $MR * @access public * @return object */ - public function apiUpdateMR($gitlabID, $projectID, $MRID, $MR) + public function apiUpdateMR($hostID, $projectID, $MRID, $MR) { - $url = sprintf($this->gitlab->getApiRoot($gitlabID), "/projects/$projectID/merge_requests/$MRID"); - return json_decode(commonModel::http($url, $MR, $options = array(CURLOPT_CUSTOMREQUEST => 'PUT'))); + $host = $this->loadModel('pipeline')->getByID($hostID); + $newMR = new stdclass; + $newMR->title = $MR->title; + if($host->type == 'gitlab') + { + $newMR->description = $MR->description; + $newMR->target_branch = $MR->targetBranch; + $newMR->remove_source_branch = $MR->removeSourceBranch == '1' ? true : false; + $newMR->squash = $MR->squash == '1' ? 1 : 0; + if($MR->assignee) + { + $gitlabAssignee = $this->gitlab->getUserIDByZentaoAccount($oldMR->hostID, $MR->assignee); + if($gitlabAssignee) $newMR->assignee_ids = $gitlabAssignee; + } + $url = sprintf($this->gitlab->getApiRoot($hostID), "/projects/$projectID/merge_requests/$MRID"); + return json_decode(commonModel::http($url, $MR, $options = array(CURLOPT_CUSTOMREQUEST => 'PUT'))); + } + else + { + $url = sprintf($this->loadModel('gitea')->getApiRoot($hostID), "/repos/$projectID/pulls/$MRID"); + + $newMR->base = $MR->targetBranch; + $newMR->body = $MR->description; + if($MR->assignee) + { + $assignee = $this->gitea->getUserIDByZentaoAccount($this->post->hostID, $MR->assignee); + if($assignee) $newMR->assignee = $assignee; + } + + $mergeResult = json_decode(commonModel::http($url, $newMR, array(), array(), 'json', 'PATCH')); + if(isset($mergeResult->number)) $mergeResult->iid = $mergeResult->number; + if(isset($mergeResult->mergeable)) + { + if($mergeResult->mergeable) $mergeResult->merge_status = 'can_be_merged'; + if(!$mergeResult->mergeable) $mergeResult->merge_status = 'cannot_be_merged'; + } + if(isset($mergeResult->state) and $mergeResult->state == 'open') $mergeResult->state = 'opened'; + if(isset($mergeResult->merged) and $mergeResult->merged) $mergeResult->state = 'merged'; + return $mergeResult; + } } /** * Delete MR by API. * * @link https://docs.gitlab.com/ee/api/merge_requests.html#delete-a-merge-request - * @param int $gitlabID + * @param int $hostID * @param int $projectID * @param int $MRID * @access public * @return object */ - public function apiDeleteMR($gitlabID, $projectID, $MRID) + public function apiDeleteMR($hostID, $projectID, $MRID) { - $url = sprintf($this->gitlab->getApiRoot($gitlabID), "/projects/$projectID/merge_requests/$MRID"); - return json_decode(commonModel::http($url, null, array(CURLOPT_CUSTOMREQUEST => 'DELETE'))); + $host = $this->loadModel('pipeline')->getByID($hostID); + if($host->type == 'gitlab') + { + $url = sprintf($this->loadModel('gitlab')->getApiRoot($hostID), "/projects/$projectID/merge_requests/$MRID"); + return json_decode(commonModel::http($url, null, array(CURLOPT_CUSTOMREQUEST => 'DELETE'))); + } + else + { + $url = sprintf($this->loadModel('gitea')->getApiRoot($hostID), "/repos/$projectID/pulls/$MRID"); + return json_decode(commonModel::http($url, array('state' => 'closed'), array(), array(), 'json', 'PATCH')); + } } /** * Close MR by API. * * @link https://docs.gitlab.com/ee/api/merge_requests.html#update-mr - * @param int $gitlabID + * @param int $hostID * @param int $projectID * @param int $MRID * @access public * @return object */ - public function apiCloseMR($gitlabID, $projectID, $MRID) + public function apiCloseMR($hostID, $projectID, $MRID) { - $url = sprintf($this->gitlab->getApiRoot($gitlabID), "/projects/$projectID/merge_requests/$MRID") . '&state_event=close'; - return json_decode(commonModel::http($url, null, array(CURLOPT_CUSTOMREQUEST => 'PUT'))); + $host = $this->loadModel('pipeline')->getByID($hostID); + if($host->type == 'gitlab') + { + $url = sprintf($this->gitlab->getApiRoot($hostID), "/projects/$projectID/merge_requests/$MRID") . '&state_event=close'; + return json_decode(commonModel::http($url, null, array(CURLOPT_CUSTOMREQUEST => 'PUT'))); + } + else + { + $url = sprintf($this->loadModel('gitea')->getApiRoot($hostID), "/repos/$projectID/pulls/$MRID"); + return json_decode(commonModel::http($url, array('state' => 'closed'), array(), array(), 'json', 'PATCH')); + } } /** * Reopen MR by API. * * @link https://docs.gitlab.com/ee/api/merge_requests.html#update-mr - * @param int $gitlabID + * @param int $hostID * @param int $projectID * @param int $MRID * @access public * @return object */ - public function apiReopenMR($gitlabID, $projectID, $MRID) + public function apiReopenMR($hostID, $projectID, $MRID) { - $url = sprintf($this->gitlab->getApiRoot($gitlabID), "/projects/$projectID/merge_requests/$MRID") . '&state_event=reopen'; - return json_decode(commonModel::http($url, null, array(CURLOPT_CUSTOMREQUEST => 'PUT'))); + $host = $this->loadModel('pipeline')->getByID($hostID); + if($host->type == 'gitlab') + { + $url = sprintf($this->gitlab->getApiRoot($hostID), "/projects/$projectID/merge_requests/$MRID") . '&state_event=reopen'; + return json_decode(commonModel::http($url, null, array(CURLOPT_CUSTOMREQUEST => 'PUT'))); + } + else + { + $url = sprintf($this->loadModel('gitea')->getApiRoot($hostID), "/repos/$projectID/pulls/$MRID"); + $MR = json_decode(commonModel::http($url, array('state' => 'open'), array(), array(), 'json', 'PATCH')); + $MR->iid = $MR->number; + $MR->state = $MR->state == 'open' ? 'opened' : $MR->state; + if($MR->merged) $MR->state = 'merged'; + + $MR->merge_status = $MR->mergeable ? 'can_be_merged' : 'cannot_be_merged'; + $MR->description = $MR->body; + $MR->target_branch = $MR->base->ref; + $MR->source_branch = $MR->head->ref; + $MR->source_project_id = $projectID; + $MR->target_project_id = $projectID; + + return $MR; + } } /** * Accept MR by API. * * @link https://docs.gitlab.com/ee/api/merge_requests.html#accept-mr - * @param int $gitlabID + * @param int $hostID * @param int $projectID * @param int $MRID - * @param string $sudo + * @param object $MR * @access public * @return object */ - public function apiAcceptMR($gitlabID, $projectID, $MRID, $sudo = "") + public function apiAcceptMR($hostID, $projectID, $MRID, $MR = null) { - $apiRoot = $this->gitlab->getApiRoot($gitlabID); - $approveUrl = sprintf($apiRoot, "/projects/$projectID/merge_requests/$MRID/approved"); - commonModel::http($approveUrl, null, array(CURLOPT_CUSTOMREQUEST => 'POST')); + $host = $this->loadModel('pipeline')->getByID($hostID); + if($host->type == 'gitlab') + { + $apiRoot = $this->gitlab->getApiRoot($hostID); + $approveUrl = sprintf($apiRoot, "/projects/$projectID/merge_requests/$MRID/approved"); + commonModel::http($approveUrl, null, array(CURLOPT_CUSTOMREQUEST => 'POST')); - $url = sprintf($apiRoot, "/projects/$projectID/merge_requests/$MRID/merge"); - if($sudo != "") return json_decode(commonModel::http($url, null, array(CURLOPT_CUSTOMREQUEST => 'PUT'), $headers = array("sudo: {$sudo}"))); - return json_decode(commonModel::http($url, null, array(CURLOPT_CUSTOMREQUEST => 'PUT'))); + $url = sprintf($apiRoot, "/projects/$projectID/merge_requests/$MRID/merge"); + return json_decode(commonModel::http($url, null, array(CURLOPT_CUSTOMREQUEST => 'PUT'))); + } + elseif($host->type == 'gitea') + { + $apiRoot = $this->loadModel('gitea')->getApiRoot($hostID); + $url = sprintf($apiRoot, "/repos/$projectID/pulls/$MRID/merge"); + + $merege = ($MR and $MR->squash == '1') ? 'squash' : 'merge'; + $data = array('Do' => $merge); + if($MR and $MR->removeSourceBranch == '1') $data['delete_branch_after_merge'] = true; + + $rowMR = json_decode(commonModel::http($url, $data, array(), array(), 'json', 'POST')); + if(!isset($rowMR->massage)) + { + $rowMR = $this->apiGetSingleMR($hostID, $projectID, $MRID); + + $this->dao->update(TABLE_MR)->data(array('status' => 'merged')) + ->where('id')->eq($MRID) + ->autoCheck() + ->exec(); + } + return $rowMR; + } } /** @@ -802,40 +1007,49 @@ class mrModel extends model public function getDiffs($MR, $encoding = '') { $diffVersions = array(); - if($MR->synced) $diffVersions = $this->apiGetDiffVersions($MR->gitlabID, $MR->targetProject, $MR->mriid); - $gitlab = $this->gitlab->getByID($MR->gitlabID); + $host = $this->loadModel('pipeline')->getByID($MR->hostID); + $scm = $host->type; $this->loadModel('repo'); $repo = new stdclass; - $repo->SCM = 'GitLab'; - $repo->gitlab = $gitlab->id; - $repo->project = $MR->targetProject; - $repo->path = sprintf($this->config->repo->gitlab->apiPath, $gitlab->url, $MR->targetProject); - $repo->client = $gitlab->url; - $repo->password = $gitlab->token; - $repo->account = ''; - $repo->encoding = $encoding; + $repo->SCM = $this->lang->repo->scmList[ucfirst($scm)]; + $repo->gitService = $host->id; + $repo->project = $MR->targetProject; + $repo->path = sprintf($this->config->repo->$scm->apiPath, $host->url, $MR->targetProject); + $repo->client = $host->url; + $repo->password = $host->token; + $repo->account = ''; + $repo->encoding = $encoding; $lines = array(); $commitList = array(); - foreach($diffVersions as $diffVersion) + if($scm == 'gitlab') { - $singleDiff = $this->apiGetSingleDiffVersion($MR->gitlabID, $MR->targetProject, $MR->mriid, $diffVersion->id); - if($singleDiff->state == 'empty') continue; - - $commits = $singleDiff->commits; - $diffs = $singleDiff->diffs; - foreach($diffs as $index => $diff) + if($MR->synced) $diffVersions = $this->apiGetDiffVersions($MR->hostID, $MR->targetProject, $MR->mriid); + foreach($diffVersions as $diffVersion) { - $lines[] = sprintf("diff --git a/%s b/%s", $diff->old_path, $diff->new_path); - $lines[] = sprintf("index %s ... %s %s ", $singleDiff->head_commit_sha, $singleDiff->base_commit_sha, $diff->b_mode); - $lines[] = sprintf("--a/%s", $diff->old_path); - $lines[] = sprintf("--b/%s", $diff->new_path); - $diffLines = explode("\n", $diff->diff); - foreach($diffLines as $diffLine) $lines[] = $diffLine; + $singleDiff = $this->apiGetSingleDiffVersion($MR->hostID, $MR->targetProject, $MR->mriid, $diffVersion->id); + if($singleDiff->state == 'empty') continue; + + $commits = $singleDiff->commits; + $diffs = $singleDiff->diffs; + foreach($diffs as $index => $diff) + { + $lines[] = sprintf("diff --git a/%s b/%s", $diff->old_path, $diff->new_path); + $lines[] = sprintf("index %s ... %s %s ", $singleDiff->head_commit_sha, $singleDiff->base_commit_sha, $diff->b_mode); + $lines[] = sprintf("--a/%s", $diff->old_path); + $lines[] = sprintf("--b/%s", $diff->new_path); + $diffLines = explode("\n", $diff->diff); + foreach($diffLines as $diffLine) $lines[] = $diffLine; + } } } + else + { + $diffs = $this->apiGetDiffs($MR->hostID, $MR->targetProject, $MR->mriid); + $lines = explode("\n", $diffs); + } if(empty($MR->synced)) { @@ -852,15 +1066,15 @@ class mrModel extends model /** * Get sudo account pair, such as "zentao account" => "gitlab account|id". * - * @param int $gitlabID + * @param int $hostID * @param int $projectID * @param int $account * @access public * @return array */ - public function getSudoAccountPair($gitlabID, $projectID, $account) + public function getSudoAccountPair($hostID, $projectID, $account) { - $bindedUsers = $this->gitlab->getUserAccountIdPairs($gitlabID); + $bindedUsers = $this->gitlab->getUserAccountIdPairs($hostID); $accountPair = array(); if(isset($bindedUsers[$account])) $accountPair[$account] = $bindedUsers[$account]; return $accountPair; @@ -869,18 +1083,18 @@ class mrModel extends model /** * Get sudo user ID in both GitLab and Project. * Note: sudo parameter in GitLab API can be user ID or username. - * @param int $gitlabID + * @param int $hostID * @param int $projectID * @access public * @return int|string */ - public function getSudoUsername($gitlabID, $projectID) + public function getSudoUsername($hostID, $projectID) { $zentaoUser = $this->app->user->account; /* Fetch user list both in Zentao and current GitLab project. */ - $bindedUsers = $this->gitlab->getUserAccountIdPairs($gitlabID); - $rawProjectUsers = $this->gitlab->apiGetProjectUsers($gitlabID, $projectID); + $bindedUsers = $this->gitlab->getUserAccountIdPairs($hostID); + $rawProjectUsers = $this->gitlab->apiGetProjectUsers($hostID, $projectID); $users = array(); foreach($rawProjectUsers as $rawProjectUser) { @@ -893,64 +1107,87 @@ class mrModel extends model /** * Create a todo item for merge request. * - * @param int $gitlabID + * @param int $hostID * @param int $projectID * @param int $MRID * @access public * @return object */ - public function apiCreateMRTodo($gitlabID, $projectID, $MRID) + public function apiCreateMRTodo($hostID, $projectID, $MRID) { - $url = sprintf($this->gitlab->getApiRoot($gitlabID), "/projects/$projectID/merge_requests/$MRID/todo"); + $url = sprintf($this->gitlab->getApiRoot($hostID), "/projects/$projectID/merge_requests/$MRID/todo"); return json_decode(commonModel::http($url, $data = null, $options = array(CURLOPT_CUSTOMREQUEST => 'POST'))); } /** * Get diff versions of MR from GitLab API. * - * @param int $gitlabID + * @param int $hostID * @param int $projectID * @param int $MRID * @access public * @return object */ - public function apiGetDiffVersions($gitlabID, $projectID, $MRID) + public function apiGetDiffVersions($hostID, $projectID, $MRID) { - $url = sprintf($this->gitlab->getApiRoot($gitlabID), "/projects/$projectID/merge_requests/$MRID/versions"); + $url = sprintf($this->gitlab->getApiRoot($hostID), "/projects/$projectID/merge_requests/$MRID/versions"); return json_decode(commonModel::http($url)); } /** * Get a single diff version of MR from GitLab API. * - * @param int $gitlabID + * @param int $hostID * @param int $projectID * @param int $MRID * @param int $versionID * @access public * @return object */ - public function apiGetSingleDiffVersion($gitlabID, $projectID, $MRID, $versionID) + public function apiGetSingleDiffVersion($hostID, $projectID, $MRID, $versionID) { - $url = sprintf($this->gitlab->getApiRoot($gitlabID), "/projects/$projectID/merge_requests/$MRID/versions/$versionID"); + $url = sprintf($this->gitlab->getApiRoot($hostID), "/projects/$projectID/merge_requests/$MRID/versions/$versionID"); return json_decode(commonModel::http($url)); } /** * Get diff commits of MR from GitLab API. * - * @param int $gitlabID + * @param int $hostID * @param int $projectID * @param int $MRID * @access public * @return object */ - public function apiGetDiffCommits($gitlabID, $projectID, $MRID) + public function apiGetDiffCommits($hostID, $projectID, $MRID) { - $url = sprintf($this->gitlab->getApiRoot($gitlabID), "/projects/$projectID/merge_requests/$MRID/commits"); + $host = $this->loadModel('pipeline')->getByID($hostID); + if($host->type == 'gitlab') + { + $url = sprintf($this->gitlab->getApiRoot($hostID), "/projects/$projectID/merge_requests/$MRID/commits"); + } + else + { + $url = sprintf($this->loadModel('gitea')->getApiRoot($hostID), "/repos/$projectID/pulls/$MRID/commits"); + } return json_decode(commonModel::http($url)); } + /** + * Get diff of MR from Gitea API. + * + * @param int $hostID + * @param int $projectID + * @param int $MRID + * @access public + * @return object + */ + public function apiGetDiffs($hostID, $projectID, $MRID) + { + $url = sprintf($this->loadModel('gitea')->getApiRoot($hostID), "/repos/$projectID/pulls/$MRID.diff"); + return commonModel::http($url); + } + /** * Reject or Approve this MR. * @@ -962,7 +1199,7 @@ class mrModel extends model public function approve($MR, $action = 'approve', $comment = '') { $this->loadModel('action'); - $actionID = $this->action->create('mr', $MR->id, $action); + $actionID = $this->action->create('mrapproval', $MR->id, $action); $oldMR = $MR; if(isset($MR->status) and $MR->status == 'opened') @@ -970,9 +1207,9 @@ class mrModel extends model $rawApprovalStatus = ''; if(isset($MR->approvalStatus)) $rawApprovalStatus = $MR->approvalStatus; $MR->approver = $this->app->user->account; - if ($action == 'reject' and $rawApprovalStatus != 'rejected') $MR->approvalStatus = 'rejected'; - if ($action == 'approve' and $rawApprovalStatus != 'approved') $MR->approvalStatus = 'approved'; - if (isset($MR->approvalStatus) and $rawApprovalStatus != $MR->approvalStatus) + if($action == 'reject' and $rawApprovalStatus != 'rejected') $MR->approvalStatus = 'rejected'; + if($action == 'approve' and $rawApprovalStatus != 'approved') $MR->approvalStatus = 'approved'; + if(isset($MR->approvalStatus) and $rawApprovalStatus != $MR->approvalStatus) { $changes = common::createChanges($oldMR, $MR); $this->action->logHistory($actionID, $changes); @@ -1010,7 +1247,7 @@ class mrModel extends model { $this->loadModel('action'); $actionID = $this->action->create('mr', $MR->id, 'closed'); - $rawMR = $this->apiCloseMR($MR->gitlabID, $MR->targetProject, $MR->mriid); + $rawMR = $this->apiCloseMR($MR->hostID, $MR->targetProject, $MR->mriid); $changes = common::createChanges($MR, $rawMR); $this->action->logHistory($actionID, $changes); if(isset($rawMR->state) and $rawMR->state == 'closed') return array('result' => 'success', 'message' => $this->lang->mr->closeSuccess, 'locate' => helper::createLink('mr', 'view', "mr={$MR->id}")); @@ -1027,7 +1264,7 @@ class mrModel extends model { $this->loadModel('action'); $actionID = $this->action->create('mr', $MR->id, 'reopen'); - $rawMR = $this->apiReopenMR($MR->gitlabID, $MR->targetProject, $MR->mriid); + $rawMR = $this->apiReopenMR($MR->hostID, $MR->targetProject, $MR->mriid); $changes = common::createChanges($MR, $rawMR); $this->action->logHistory($actionID, $changes); if(isset($rawMR->state) and $rawMR->state == 'opened') return array('result' => 'success', 'message' => $this->lang->mr->reopenSuccess, 'locate' => helper::createLink('mr', 'view', "mr={$MR->id}")); @@ -1479,7 +1716,7 @@ class mrModel extends model $stories = $bugs = $tasks = array(); /* Get commits by MR. */ - $commits = $this->apiGetMRCommits($MR->gitlabID, $MR->targetProject, $MR->mriid); + $commits = $this->apiGetMRCommits($MR->hostID, $MR->targetProject, $MR->mriid); foreach($commits as $commit) { $objects = $this->repo->parseComment($commit->message); @@ -1555,16 +1792,16 @@ class mrModel extends model /** * Get links by mr commites. * - * @param int $gitlabID + * @param int $hostID * @param int $projectID * @param int $MRID * @param string $type * @access public * @return array */ - public function getCommitedLink($gitlabID, $projectID, $MRID, $type) + public function getCommitedLink($hostID, $projectID, $MRID, $type) { - $DiffCommits = $this->apiGetDiffCommits($gitlabID, $projectID, $MRID); + $DiffCommits = $this->apiGetDiffCommits($hostID, $projectID, $MRID); $commits = array(); foreach($DiffCommits as $DiffCommit) @@ -1603,13 +1840,13 @@ class mrModel extends model /** * Get toList and ccList. * - * @param object $mr + * @param object $MR * @access public * @return bool|array */ - public function getToAndCcList($mr) + public function getToAndCcList($MR) { - return array($mr->createdBy, $mr->assignee); + return array($MR->createdBy, $MR->assignee); } /** @@ -1646,7 +1883,7 @@ class mrModel extends model /** * Check same opened mr for source branch. * - * @param int $gitlabID + * @param int $hostID * @param int $sourceProject * @param string $sourceBranch * @param int $targetProject @@ -1654,12 +1891,13 @@ class mrModel extends model * @access public * @return array */ - public function checkSameOpened($gitlabID, $sourceProject, $sourceBranch, $targetProject, $targetBranch) + public function checkSameOpened($hostID, $sourceProject, $sourceBranch, $targetProject, $targetBranch) { if(empty($sourceProject) or empty($sourceBranch) or empty($targetProject) or empty($targetBranch)) return array('result' => 'success'); + if($sourceProject == $targetProject and $sourceBranch == $targetBranch) return array('result' => 'fail', 'message' => $this->lang->mr->errorLang[1]); $dbOpenedID = $this->dao->select('id')->from(TABLE_MR) - ->where('gitlabID')->eq($gitlabID) + ->where('hostID')->eq($hostID) ->andWhere('sourceProject')->eq($sourceProject) ->andWhere('sourceBranch')->eq($sourceBranch) ->andWhere('targetProject')->eq($targetProject) @@ -1669,8 +1907,8 @@ class mrModel extends model ->fetch('id'); if(!empty($dbOpenedID)) return array('result' => 'fail', 'message' => sprintf($this->lang->mr->hasSameOpenedMR, $dbOpenedID)); - $mr = $this->apiGetSameOpened($gitlabID, $sourceProject, $sourceBranch, $targetProject, $targetBranch); - if($mr) return array('result' => 'fail', 'message' => sprintf($this->lang->mr->errorLang[2], $mr->iid)); + $MR = $this->apiGetSameOpened($hostID, $sourceProject, $sourceBranch, $targetProject, $targetBranch); + if($MR) return array('result' => 'fail', 'message' => sprintf($this->lang->mr->errorLang[2], $MR->iid)); return array('result' => 'success'); } diff --git a/module/mr/view/browse.html.php b/module/mr/view/browse.html.php index 86ede0244f..b029f82314 100644 --- a/module/mr/view/browse.html.php +++ b/module/mr/view/browse.html.php @@ -58,8 +58,18 @@ - gitlabID][$MR->sourceProject]) ? $projects[$MR->gitlabID][$MR->sourceProject]->name_with_namespace . ':' . $MR->sourceBranch : $MR->sourceProject . ':' . $MR->sourceBranch; ?> - gitlabID][$MR->targetProject]) ? $projects[$MR->gitlabID][$MR->targetProject]->name_with_namespace . ':' . $MR->targetBranch : $MR->targetProject . ':' . $MR->targetBranch; ?> + SCM == 'Gitlab') + { + $sourceProject = isset($projects[$MR->hostID][$MR->sourceProject]) ? $projects[$MR->hostID][$MR->sourceProject]->name_with_namespace . ':' . $MR->sourceBranch : $MR->sourceProject . ':' . $MR->sourceBranch; + $targetProject = isset($projects[$MR->hostID][$MR->targetProject]) ? $projects[$MR->hostID][$MR->targetProject]->name_with_namespace . ':' . $MR->targetBranch : $MR->targetProject . ':' . $MR->targetBranch; + } + else + { + $sourceProject = isset($projects[$MR->hostID][$MR->sourceProject]) ? $projects[$MR->hostID][$MR->sourceProject]->full_name . ':' . $MR->sourceBranch : $MR->sourceProject . ':' . $MR->sourceBranch; + $targetProject = isset($projects[$MR->hostID][$MR->targetProject]) ? $projects[$MR->hostID][$MR->targetProject]->full_name . ':' . $MR->targetBranch : $MR->targetProject . ':' . $MR->targetBranch; + } + ?> @@ -79,8 +89,15 @@
    kanban->space;?>space, "class='form-control chosen'");?>space, "class='form-control chosen' onchange='loadOwners(this.value)'");?>
    kanban->WIPCount;?>
    whitelist, 'class="form-control picker-select" multiple');?> - fetch('my', 'buildContactLists', 'dropdownName=whitelist');?> + fetch('my', 'buildContactLists', "dropdownName=whitelist&attr=data-drop_direction='up'");?>
    - fetch('my', 'buildContactLists');?> + fetch('my', 'buildContactLists', "dropdownName=team");?>
    id;?> id}"), $MR->title);?>createdBy);?> user->admin or (isset($projects[$MR->gitlabID][$MR->sourceProject]->owner->id) and $projects[$MR->gitlabID][$MR->sourceProject]->owner->id == $openIDList[$MR->gitlabID])) ? '' : 'disabled'; - $canEdit = (isset($projects[$MR->gitlabID][$MR->sourceProject]->isDeveloper) and $projects[$MR->gitlabID][$MR->sourceProject]->isDeveloper == true) ? '' : 'disabled'; + $canDelete = ($app->user->admin or (isset($projects[$MR->hostID][$MR->sourceProject]->owner->id) and $projects[$MR->hostID][$MR->sourceProject]->owner->id == $openIDList[$MR->hostID])) ? '' : 'disabled'; + if($repo->SCM == 'Gitlab') + { + $canEdit = (isset($projects[$MR->hostID][$MR->sourceProject]->isDeveloper) and $projects[$MR->hostID][$MR->sourceProject]->isDeveloper == true) ? '' : 'disabled'; + } + else + { + $canEdit = (isset($projects[$MR->hostID][$MR->sourceProject]->allow_merge_commits) and $projects[$MR->hostID][$MR->sourceProject]->allow_merge_commits == true) ? '' : 'disabled'; + } common::printLink('mr', 'view', "mr={$MR->id}", '', '', "title='{$lang->mr->view}' class='btn btn-info'"); common::printIcon('mr', 'edit', "mr={$MR->id}", $MR, 'list', '', '', '', false, "{$canEdit}"); common::printLink('mr', 'diff', "mr={$MR->id}", '', '', "title='{$lang->mr->viewDiff}' class='btn btn-info'"); diff --git a/module/mr/view/create.html.php b/module/mr/view/create.html.php index 91b26e8ef4..7e7aca7bf9 100644 --- a/module/mr/view/create.html.php +++ b/module/mr/view/create.html.php @@ -10,6 +10,9 @@ */ ?> + + +
    @@ -19,8 +22,8 @@
    - - + + @@ -57,7 +60,7 @@ - - - + + + - - - + + + - + - + - + - + - - - + + + - - - + + + - + - + - + - +
    gitlab->common;?>mr->server;?>
    mr->sourceProject;?>
    mr->removeSourceBranch;?> -
    +
    diff --git a/module/mr/view/edit.html.php b/module/mr/view/edit.html.php index 94ed0d2620..f25de0ee27 100644 --- a/module/mr/view/edit.html.php +++ b/module/mr/view/edit.html.php @@ -9,7 +9,7 @@ */ ?> -gitlabID);?> +hostID);?> sourceProject);?> id)): ?> @@ -32,15 +32,15 @@ - - + + diff --git a/module/mr/view/view.html.php b/module/mr/view/view.html.php index 83cb52472c..e386b8f05f 100644 --- a/module/mr/view/view.html.php +++ b/module/mr/view/view.html.php @@ -31,7 +31,7 @@ id ?>title; ?>synced):?> - web_url, $lang->mr->viewInGitlab, "_blank", "class='btn btn-link btn-active-text' style='color: blue'"); ?> + web_url, $lang->mr->viewInGit, "_blank", "class='btn btn-link btn-active-text' style='color: blue'"); ?> @@ -85,7 +85,7 @@ - synced === '1' ? $rawMR->has_conflicts : (bool)$MR->hasNoConflict; ?> + synced === '1' ? $rawMR->has_conflicts : (bool)$MR->hasNoConflict;?> diff --git a/module/my/control.php b/module/my/control.php index 16dd05beba..0ca06bfc6c 100755 --- a/module/my/control.php +++ b/module/my/control.php @@ -1373,13 +1373,15 @@ EOF; * Build contact lists. * * @param string $dropdownName + * @param string $attr * @access public * @return void */ - public function buildContactLists($dropdownName = 'mailto') + public function buildContactLists($dropdownName = 'mailto', $attr = '') { $this->view->contactLists = $this->user->getContactLists($this->app->user->account, 'withnote'); $this->view->dropdownName = $dropdownName; + $this->view->attr = $attr; $this->display(); } diff --git a/module/my/view/buildcontactlists.html.php b/module/my/view/buildcontactlists.html.php index 428a417131..a8a1216780 100644 --- a/module/my/view/buildcontactlists.html.php +++ b/module/my/view/buildcontactlists.html.php @@ -13,7 +13,7 @@ dao->select('*')->from(TABLE_PIPELINE) ->where('deleted')->eq('0') - ->AndWhere('type')->eq($type) + ->AndWhere('type')->in($type) ->orderBy($orderBy) ->page($pager) ->fetchAll('id'); diff --git a/module/product/config.php b/module/product/config.php index 789f16d593..967c5f8df0 100644 --- a/module/product/config.php +++ b/module/product/config.php @@ -93,7 +93,7 @@ $app->loadLang('product'); $config->product->all = new stdclass(); $config->product->all->search['module'] = 'product'; $config->product->all->search['fields']['name'] = $lang->product->name; -$config->product->all->search['fields']['code'] = $lang->product->code; +if(!isset($config->setCode) or $config->setCode == 1) $config->product->all->search['fields']['code'] = $lang->product->code; $config->product->all->search['fields']['id'] = $lang->product->id; if($config->systemMode == 'new') $config->product->all->search['fields']['program'] = $lang->product->program; $config->product->all->search['fields']['line'] = $lang->product->line; diff --git a/module/product/view/create.html.php b/module/product/view/create.html.php index b1b22554a0..e02e822238 100644 --- a/module/product/view/create.html.php +++ b/module/product/view/create.html.php @@ -56,10 +56,12 @@ + setCode) or $config->setCode == 1):?> + diff --git a/module/product/view/dynamic.html.php b/module/product/view/dynamic.html.php index c1737d9ea1..0e1c9f3341 100755 --- a/module/product/view/dynamic.html.php +++ b/module/product/view/dynamic.html.php @@ -86,7 +86,7 @@ actionLabel;?>objectLabel;?>objectType == 'module' and strpos(',created,edited,moved,', "$action->action") !== false) ? trim($action->extra, ',') : $action->objectID;?> - objectName) echo html::a($action->objectLink, $action->objectName);?> + objectName) echo !empty($action->objectLink) ? html::a($action->objectLink, $action->objectName) : $action->objectName;?> diff --git a/module/product/view/edit.html.php b/module/product/view/edit.html.php index c577fa0f96..1e7d95c235 100644 --- a/module/product/view/edit.html.php +++ b/module/product/view/edit.html.php @@ -51,10 +51,12 @@ + setCode) or $config->setCode == 1):?> + diff --git a/module/product/view/view.html.php b/module/product/view/view.html.php index 2263f04f35..5e666130d8 100644 --- a/module/product/view/view.html.php +++ b/module/product/view/view.html.php @@ -19,7 +19,8 @@
    -

    id;?> code;?> name;?>

    + setCode) and $config->setCode == 0) ? 'hidden' : '';?> +

    id;?> code;?> name;?>

    desc;?>

    @@ -72,6 +73,7 @@
    gitlab->common;?>loadModel('gitlab')->getByID($MR->gitlabID)->name;?>mr->server;?>loadModel('pipeline')->getByID($MR->hostID)->name;?>
    mr->sourceProject;?>
    - loadModel('gitlab')->apiGetSingleProject($MR->gitlabID, $MR->sourceProject)->name_with_namespace;?>: + type == 'gitlab' ? $this->loadModel('gitlab')->apiGetSingleProject($MR->hostID, $MR->sourceProject)->name_with_namespace : $MR->sourceProject;?>: sourceBranch;?>
    @@ -52,12 +52,12 @@
    status == 'merged' or $MR->status == 'closed'):?> - loadModel('gitlab')->apiGetSingleProject($MR->gitlabID, $MR->targetProject)->name_with_namespace;?>: + type == 'gitlab' ? $this->loadModel('gitlab')->apiGetSingleProject($MR->hostID, $MR->targetProject)->name_with_namespace : $MR->targetProject;?>: targetBranch;?> - loadModel('gitlab')->apiGetSingleProject($MR->gitlabID, $MR->targetProject)->name_with_namespace;?> + type == 'gitlab' ? $this->loadModel('gitlab')->apiGetSingleProject($MR->hostID, $MR->targetProject)->name_with_namespace : $MR->targetProject;?>: targetBranch, "class='form-control chosen'");?> @@ -79,9 +79,9 @@
    mr->removeSourceBranch;?> -
    - removeSourceBranch== '1' ? 'checked' : '' ?> - name="removeSourceBranch" value="1" id="removeSourceBranch"> +
    + canDeleteBranch and $MR->removeSourceBranch== '1' ? 'checked' : '' ?> + canDeleteBranch) echo 'disabled';?> name="removeSourceBranch" value="1" id="removeSourceBranch">
    mr->MRHasConflicts; ?>mr->hasConflicts : $lang->mr->hasNoConflict);?>
    product->name;?>
    product->code;?>
    product->PO;?> app->user->account, "class='form-control chosen'");?> product->name;?> name, "class='form-control' required");?>
    product->code;?> code, "class='form-control' required");?>
    product->PO;?> PO, "class='form-control chosen'");?>
    + @@ -90,6 +92,24 @@ + + + + + + + + + + + + + + + + + + acl == 'custom'):?> diff --git a/module/project/config.php b/module/project/config.php index e86ae4721a..c75ee66c9e 100644 --- a/module/project/config.php +++ b/module/project/config.php @@ -49,13 +49,16 @@ $config->project->datatable->fieldList['name']['required'] = 'yes'; $config->project->datatable->fieldList['name']['sort'] = 'no'; $config->project->datatable->fieldList['name']['pri'] = '1'; -$config->project->datatable->fieldList['code']['title'] = 'code'; -$config->project->datatable->fieldList['code']['fixed'] = 'left'; -$config->project->datatable->fieldList['code']['width'] = '100'; -$config->project->datatable->fieldList['code']['minWidth'] = '180'; -$config->project->datatable->fieldList['code']['required'] = 'no'; -$config->project->datatable->fieldList['code']['sort'] = 'no'; -$config->project->datatable->fieldList['code']['pri'] = '1'; +if(!isset($config->setCode) or $config->setCode == 1) +{ + $config->project->datatable->fieldList['code']['title'] = 'code'; + $config->project->datatable->fieldList['code']['fixed'] = 'left'; + $config->project->datatable->fieldList['code']['width'] = '100'; + $config->project->datatable->fieldList['code']['minWidth'] = '180'; + $config->project->datatable->fieldList['code']['required'] = 'no'; + $config->project->datatable->fieldList['code']['sort'] = 'no'; + $config->project->datatable->fieldList['code']['pri'] = '1'; +} $config->project->datatable->fieldList['PM']['title'] = 'PM'; $config->project->datatable->fieldList['PM']['fixed'] = 'no'; @@ -134,7 +137,7 @@ $config->project->maxCheckList->waterfall = array('execution', 'design', 'doc', $config->project->search['module'] = 'project'; $config->project->search['fields']['name'] = $lang->project->name; -$config->project->search['fields']['code'] = $lang->project->code; +if(!isset($config->setCode) or $config->setCode == 1) $config->project->search['fields']['code'] = $lang->project->code; $config->project->search['fields']['id'] = $lang->project->id; $config->project->search['fields']['model'] = $lang->project->model; $config->project->search['fields']['parent'] = $lang->project->parent; diff --git a/module/project/model.php b/module/project/model.php index d3c887f5c6..5cc3740b7f 100644 --- a/module/project/model.php +++ b/module/project/model.php @@ -1524,13 +1524,12 @@ class projectModel extends model { $projectID = (int)$projectID; $projectName = $data->names[$projectID]; - $projectCode = $data->codes[$projectID]; + if(isset($data->codes)) $projectCode = $data->codes[$projectID]; $projects[$projectID] = new stdClass(); if(isset($data->parents[$projectID])) $projects[$projectID]->parent = $data->parents[$projectID]; $projects[$projectID]->id = $projectID; $projects[$projectID]->name = $projectName; - $projects[$projectID]->code = $projectCode; $projects[$projectID]->model = $oldProjects[$projectID]->model; $projects[$projectID]->PM = $data->PMs[$projectID]; $projects[$projectID]->begin = $data->begins[$projectID]; @@ -1540,6 +1539,7 @@ class projectModel extends model $projects[$projectID]->lastEditedBy = $this->app->user->account; $projects[$projectID]->lastEditedDate = helper::now(); + if(isset($data->codes)) $projects[$projectID]->code = $projectCode; if($projects[$projectID]->parent) { $parentProject = $this->dao->select('*')->from(TABLE_PROGRAM)->where('id')->eq($projects[$projectID]->parent)->fetch(); @@ -1577,7 +1577,7 @@ class projectModel extends model $this->dao->update(TABLE_PROJECT)->data($project) ->autoCheck($skipFields = 'begin,end') - ->batchCheck($this->config->project->edit->requiredFields , 'notempty') + ->batchCheck($this->config->project->edit->requiredFields, 'notempty') ->checkIF($project->begin != '', 'begin', 'date') ->checkIF($project->end != '', 'end', 'date') ->checkIF($project->end != '', 'end', 'gt', $project->begin) diff --git a/module/project/view/batchedit.html.php b/module/project/view/batchedit.html.php index 2ce4a609f4..2a3674c3d3 100644 --- a/module/project/view/batchedit.html.php +++ b/module/project/view/batchedit.html.php @@ -26,7 +26,9 @@ + setCode) and $config->setCode == 1):?> + @@ -51,7 +53,9 @@ + setCode) and $config->setCode == 1):?> + + setCode) or $config->setCode == 1):?> + diff --git a/module/project/view/dynamic.html.php b/module/project/view/dynamic.html.php index 69531bc782..c93898fb56 100755 --- a/module/project/view/dynamic.html.php +++ b/module/project/view/dynamic.html.php @@ -87,7 +87,7 @@ actionLabel;?>objectLabel;?>objectID;?> - objectName) echo html::a($action->objectLink, $action->objectName);?> + objectName) echo !empty($action->objectLink) ? html::a($action->objectLink, $action->objectName) : $action->objectName;?> diff --git a/module/project/view/edit.html.php b/module/project/view/edit.html.php index f58d75b508..eb68ff2970 100755 --- a/module/project/view/edit.html.php +++ b/module/project/view/edit.html.php @@ -61,10 +61,12 @@ + setCode) or $config->setCode == 1):?> + diff --git a/module/project/view/view.html.php b/module/project/view/view.html.php index 48457ad88d..95ebb4e235 100644 --- a/module/project/view/view.html.php +++ b/module/project/view/view.html.php @@ -107,7 +107,8 @@
    -

    id;?> code;?> name;?>

    + setCode) and $config->setCode == 0) ? 'hidden' : '';?> +

    id;?> code;?> name;?>

    diff --git a/module/repo/config.php b/module/repo/config.php index 3c258706c1..4bd26c4601 100644 --- a/module/repo/config.php +++ b/module/repo/config.php @@ -49,6 +49,11 @@ $config->repo->gitlab = new stdclass; $config->repo->gitlab->perPage = 300; $config->repo->gitlab->apiPath = "%s/api/v4/projects/%s/repository/"; +$config->repo->gitea = new stdclass; +$config->repo->gitea->apiPath = "%s/api/v1/repos/%s/"; + +$config->repo->gitServiceList = array('gitlab', 'gitea'); + $config->repo->rules['module']['task'] = 'Task'; $config->repo->rules['module']['bug'] = 'Bug'; $config->repo->rules['module']['story'] = 'Story'; diff --git a/module/repo/control.php b/module/repo/control.php index 3d40711f1d..84bd9ba78a 100644 --- a/module/repo/control.php +++ b/module/repo/control.php @@ -142,14 +142,14 @@ class repo extends control $products = $this->loadModel('product')->getProductPairsByProject($objectID); $productID = count($products) > 0 ? key($products) : ''; - $this->view->title = $this->lang->repo->common . $this->lang->colon . $this->lang->repo->create; - $this->view->position[] = $this->lang->repo->create; - $this->view->groups = $this->loadModel('group')->getPairs(); - $this->view->users = $this->loadModel('user')->getPairs('noletter|noempty|nodeleted'); - $this->view->products = $products; - $this->view->productID = $productID; - $this->view->gitlabHosts = $this->loadModel('gitlab')->getPairs(); - $this->view->objectID = $objectID; + $this->view->title = $this->lang->repo->common . $this->lang->colon . $this->lang->repo->create; + $this->view->position[] = $this->lang->repo->create; + $this->view->groups = $this->loadModel('group')->getPairs(); + $this->view->users = $this->loadModel('user')->getPairs('noletter|noempty|nodeleted|noclosed'); + $this->view->products = $products; + $this->view->productID = $productID; + $this->view->serviceHosts = $this->loadModel('gitlab')->getPairs(); + $this->view->objectID = $objectID; $this->display(); } @@ -182,25 +182,29 @@ class repo extends control $this->app->loadLang('action'); - if(strtolower($repo->SCM) == 'gitlab') + $scm = strtolower($repo->SCM); + if(in_array($scm, $this->config->repo->gitServiceList)) { - $gitlabID = isset($repo->gitlab) ? $repo->gitlab : 0; - $projects = $this->loadModel('gitlab')->apiGetProjects($gitlabID); - $options = array(); - foreach($projects as $project) $options[$project->id] = $project->name_with_namespace; + $serviceID = isset($repo->gitService) ? $repo->gitService : 0; + $projects = $this->loadModel($scm)->apiGetProjects($serviceID); + $options = array(); + foreach($projects as $project) + { + if($scm == 'gitlab') $options[$project->id] = $project->name_with_namespace; + if($scm == 'gitea') $options[$project->full_name] = $project->full_name; + } $this->view->projects = $options; } - $this->view->title = $this->lang->repo->common . $this->lang->colon . $this->lang->repo->edit; - $repo->repoType = $repo->id . '-' . $repo->SCM; - $this->view->repo = $repo; - $this->view->repoID = $repoID; - $this->view->objectID = $objectID; - $this->view->groups = $this->loadModel('group')->getPairs(); - $this->view->users = $this->loadModel('user')->getPairs('noletter|noempty|nodeleted'); - $this->view->products = $objectID ? $this->loadModel('product')->getProductPairsByProject($objectID) : $this->loadModel('product')->getPairs(); - $this->view->gitlabHosts = array('' => '') + $this->loadModel('gitlab')->getPairs(); + $this->view->title = $this->lang->repo->common . $this->lang->colon . $this->lang->repo->edit; + $this->view->repo = $repo; + $this->view->repoID = $repoID; + $this->view->objectID = $objectID; + $this->view->groups = $this->loadModel('group')->getPairs(); + $this->view->users = $this->loadModel('user')->getPairs('noletter|noempty|nodeleted|noclosed'); + $this->view->products = $objectID ? $this->loadModel('product')->getProductPairsByProject($objectID) : $this->loadModel('product')->getPairs(); + $this->view->serviceHosts = array('' => '') + $this->loadModel('pipeline')->getPairs($repo->SCM); $this->view->position[] = html::a(inlink('maintain'), $this->lang->repo->common); $this->view->position[] = $this->lang->repo->edit; @@ -233,11 +237,7 @@ class repo extends control if($error) return print(js::alert($error)); - $this->dao->delete()->from(TABLE_REPO)->where('id')->eq($repoID)->exec(); - $this->dao->delete()->from(TABLE_REPOHISTORY)->where('repo')->eq($repoID)->exec(); - $this->dao->delete()->from(TABLE_REPOFILES)->where('repo')->eq($repoID)->exec(); - $this->dao->delete()->from(TABLE_REPOBRANCH)->where('repo')->eq($repoID)->exec(); - + $this->repo->delete(TABLE_REPO, $repoID); if(dao::isError()) return print(js::error(dao::getError())); echo js::reload('parent'); } @@ -1155,7 +1155,7 @@ class repo extends control { foreach($repoGroup as $type => $group) { - if(strtolower($type) != 'gitlab') unset($repoGroup[$type]); + if(!in_array(strtolower($type), $this->config->repo->gitServiceList)) unset($repoGroup[$type]); } } @@ -1166,6 +1166,54 @@ class repo extends control $this->display(); } + /** + * Ajax get hosts. + * + * @param int $scm + * @access public + * @return void + */ + public function ajaxGetHosts($scm) + { + $scm = strtolower($scm); + $hosts = $this->loadModel($scm)->getPairs(); + return print(html::select('pipelineHost', $hosts, '', "class='form-control chosen'")); + } + + /** + * Ajax get projects by server. + * + * @param int $serverID + * @access public + * @return void + */ + public function ajaxGetProjects($serverID) + { + $server = $this->loadModel('pipeline')->getByID($serverID); + $getProjectFunc = 'ajaxGet' . $server->type . 'Projects'; + + $this->$getProjectFunc($serverID); + } + + /** + * Ajax get gitea projects. + * + * @param string $gitlabID + * @param string $projectIdList + * @access public + * @return void + */ + public function ajaxGetGiteaProjects($giteaID) + { + $projects = $this->loadModel('gitea')->apiGetProjects($giteaID); + if(!$projects) $this->send(array('message' => array())); + + $options = ""; + foreach($projects as $project) $options .= ""; + + return print($options); + } + /** * Ajax get gitlab projects. * @@ -1316,9 +1364,11 @@ class repo extends control } $repo = $this->repo->getRepoByID($repoID); - if($repo->SCM == 'Gitlab') + if(in_array(strtolower($repo->SCM), $this->config->repo->gitServiceList)) { - $url = $this->loadModel('gitlab')->downloadCode($repo->gitlab, $repo->project, $branch); + $this->scm = $this->app->loadClass('scm'); + $this->scm->setEngine($repo); + $url = $this->scm->getDownloadUrl($branch); } elseif($repo->SCM == 'Git') { diff --git a/module/repo/css/common.css b/module/repo/css/common.css index 7d19921566..141b05002f 100644 --- a/module/repo/css/common.css +++ b/module/repo/css/common.css @@ -85,7 +85,6 @@ h3 {font-size: 16px;} .repoCode tr.over.commented .comment-btn {margin-left: -20px; width: 25px; height:18px;} .repoCode tr.over.commented .comment-btn .icon-wrapper, .repoCode tr.selected.commented .comment-btn .icon-wrapper {line-height: 20px; height: 20px; background: #4183C4; color: #fff; left: -6px;} -.repoCode tr.over.commented .comment-btn .icon-wrapper {left: 13px;} .repoCode tr.over.commented .comment-btn .icon-wrapper > i:before {font-size: 14px;} .repoCode tr.selected.commented .comment-btn .icon-wrapper > i:before {font-size: 14px;} .repoCode tr.over.commented .comment-btn .icon-wrapper:before, .repoCode tr.selected.commented .comment-btn .icon-wrapper:before {display: block;} diff --git a/module/repo/js/create.js b/module/repo/js/create.js index a5ad8b9a92..d6db74f6e3 100644 --- a/module/repo/js/create.js +++ b/module/repo/js/create.js @@ -23,28 +23,35 @@ $(function() } }); - $('#gitlabHost').change(function() + $('#serviceHost').change(function() { - host = $('#gitlabHost').val(); - url = createLink('repo', 'ajaxGetGitlabProjects', "host=" + host); + var host = $('#serviceHost').val(); + var url = createLink('repo', 'ajaxGetProjects', "host=" + host); if(host == '') return false; $.get(url, function(response) { - $('#gitlabProject').html('').append(response); - $('#gitlabProject').chosen().trigger("chosen:updated");; + $('#serviceProject').html('').append(response); + $('#serviceProject').chosen().trigger("chosen:updated");; }); }); - $('#gitlabProject').change(function() + $('#serviceProject').change(function() { $option = $(this).find('option:selected'); $('#name').val($option.data('name')); }); - $('#gitlabHost').change(); + $('#serviceHost').change(); }); +/** + * Changed SCM. + * + * @param string $scm + * @access public + * @return void + */ function scmChanged(scm) { if(scm == 'Git') @@ -62,6 +69,22 @@ function scmChanged(scm) $('.tips-svn').removeClass('hidden'); } - $('tr.gitlab').toggle(scm == 'Gitlab'); - $('tr.hide-gitlab').toggle(scm != 'Gitlab'); + if(scm == 'Git' || scm == 'Subversion') + { + $('tr.service').toggle(false); + $('tr.hide-service').toggle(true); + } + else + { + $('tr.service').toggle(true); + $('tr.hide-service').toggle(false); + + var url = createLink('repo', 'ajaxGetHosts', "scm=" + scm); + $.get(url, function(response) + { + $('#serviceHost').html(response); + $('#serviceHost').chosen().trigger("chosen:updated");; + $('#serviceHost').change(); + }); + } } diff --git a/module/repo/js/edit.js b/module/repo/js/edit.js index 60505a9229..229f4907ab 100644 --- a/module/repo/js/edit.js +++ b/module/repo/js/edit.js @@ -1,26 +1,26 @@ $(function() { - scmChanged(scm); + scmChanged(scm, true); $('#submit').mousedown(function() { $form = $(this).closest('form'); $form.css('min-height', $form.height()); }) - $('#gitlabHost').change(function() + $('#serviceHost').change(function() { - host = $('#gitlabHost').val(); + host = $('#serviceHost').val(); if(host == '') return false; - url = createLink('repo', 'ajaxGetGitlabProjects', "host=" + host); + url = createLink('repo', 'ajaxGetProjects', "host=" + host); $.get(url, function(response) { - $('#gitlabProject').html('').append(response); - $('#gitlabProject').chosen().trigger("chosen:updated");; + $('#serviceProject').html('').append(response); + $('#serviceProject').chosen().trigger("chosen:updated");; }); }); - $('#gitlabProject').change(function() + $('#serviceProject').change(function() { $option = $(this).find('option:selected'); if(!$option.data('name')) return false; @@ -29,7 +29,14 @@ $(function() }); }); -function scmChanged(scm) +/** + * Changed SCM. + * + * @param string $scm + * @access public + * @return void + */ +function scmChanged(scm, isFirstRequest = false) { if(scm == 'Git') { @@ -46,6 +53,25 @@ function scmChanged(scm) $('.tips-svn').removeClass('hidden'); } - $('tr.gitlab').toggle(scm == 'Gitlab'); - $('tr.hide-gitlab').toggle(scm != 'Gitlab'); + if(scm == 'Git' || scm == 'Subversion') + { + $('tr.service').toggle(false); + $('tr.hide-service').toggle(true); + } + else + { + $('tr.service').toggle(true); + $('tr.hide-service').toggle(false); + + if(!isFirstRequest) + { + var url = createLink('repo', 'ajaxGetHosts', "scm=" + scm); + $.get(url, function(response) + { + $('#serviceHost').html(response); + $('#serviceHost').chosen().trigger("chosen:updated");; + $('#serviceHost').change(); + }); + } + } } diff --git a/module/repo/lang/de.php b/module/repo/lang/de.php index e17e9084cc..cffe5ebcfd 100644 --- a/module/repo/lang/de.php +++ b/module/repo/lang/de.php @@ -142,6 +142,7 @@ $lang->repo->encodingList['utf_8'] = 'UTF-8'; $lang->repo->encodingList['gbk'] = 'GBK'; $lang->repo->scmList['Gitlab'] = 'GitLab'; +$lang->repo->scmList['Gitea'] = 'Gitea'; $lang->repo->scmList['Git'] = 'Git'; $lang->repo->scmList['Subversion'] = 'SVN'; @@ -149,6 +150,9 @@ $lang->repo->gitlabHost = 'GitLab Host'; $lang->repo->gitlabToken = 'GitLab Token'; $lang->repo->gitlabProject = 'Project'; +$lang->repo->serviceHost = 'Host'; +$lang->repo->serviceProject = 'Project'; + $lang->repo->placeholder = new stdclass; $lang->repo->placeholder->gitlabHost = 'Input url of gitlab'; diff --git a/module/repo/lang/en.php b/module/repo/lang/en.php index 62ab96d159..725f3d2263 100644 --- a/module/repo/lang/en.php +++ b/module/repo/lang/en.php @@ -142,6 +142,7 @@ $lang->repo->encodingList['utf_8'] = 'UTF-8'; $lang->repo->encodingList['gbk'] = 'GBK'; $lang->repo->scmList['Gitlab'] = 'GitLab'; +$lang->repo->scmList['Gitea'] = 'Gitea'; $lang->repo->scmList['Git'] = 'Git'; $lang->repo->scmList['Subversion'] = 'SVN'; @@ -149,6 +150,9 @@ $lang->repo->gitlabHost = 'GitLab Host'; $lang->repo->gitlabToken = 'GitLab Token'; $lang->repo->gitlabProject = 'Project'; +$lang->repo->serviceHost = 'Host'; +$lang->repo->serviceProject = 'Project'; + $lang->repo->placeholder = new stdclass; $lang->repo->placeholder->gitlabHost = 'Input url of gitlab'; diff --git a/module/repo/lang/fr.php b/module/repo/lang/fr.php index 160d388e3f..22661b03db 100644 --- a/module/repo/lang/fr.php +++ b/module/repo/lang/fr.php @@ -142,6 +142,7 @@ $lang->repo->encodingList['utf_8'] = 'UTF-8'; $lang->repo->encodingList['gbk'] = 'GBK'; $lang->repo->scmList['Gitlab'] = 'GitLab'; +$lang->repo->scmList['Gitea'] = 'Gitea'; $lang->repo->scmList['Git'] = 'Git'; $lang->repo->scmList['Subversion'] = 'Subversion'; @@ -149,6 +150,9 @@ $lang->repo->gitlabHost = 'GitLab Host'; $lang->repo->gitlabToken = 'GitLab Token'; $lang->repo->gitlabProject = 'Project'; +$lang->repo->serviceHost = 'Host'; +$lang->repo->serviceProject = 'Project'; + $lang->repo->placeholder = new stdclass; $lang->repo->placeholder->gitlabHost = 'Input url of gitlab'; diff --git a/module/repo/lang/vi.php b/module/repo/lang/vi.php index 01a694336e..e84f6866e6 100644 --- a/module/repo/lang/vi.php +++ b/module/repo/lang/vi.php @@ -137,9 +137,18 @@ $lang->repo->logStyles['D'] = 'Xóa'; $lang->repo->encodingList['utf_8'] = 'UTF-8'; $lang->repo->encodingList['gbk'] = 'GBK'; +$lang->repo->scmList['Gitlab'] = 'GitLab'; +$lang->repo->scmList['Gitea'] = 'Gitea'; $lang->repo->scmList['Git'] = 'Git'; $lang->repo->scmList['Subversion'] = 'SVN'; +$lang->repo->gitlabHost = 'GitLab Host'; +$lang->repo->gitlabToken = 'GitLab Token'; +$lang->repo->gitlabProject = 'Project'; + +$lang->repo->serviceHost = 'Host'; +$lang->repo->serviceProject = 'Project'; + $lang->repo->notice = new stdclass(); $lang->repo->notice->syncing = 'Đang đồng bộ. Vui lòng đợi ...'; $lang->repo->notice->syncComplete = 'Synchronized. Now redirecting ...'; diff --git a/module/repo/lang/zh-cn.php b/module/repo/lang/zh-cn.php index 964d445042..d9c12cd196 100644 --- a/module/repo/lang/zh-cn.php +++ b/module/repo/lang/zh-cn.php @@ -142,6 +142,7 @@ $lang->repo->encodingList['utf_8'] = 'UTF-8'; $lang->repo->encodingList['gbk'] = 'GBK'; $lang->repo->scmList['Gitlab'] = 'GitLab'; +$lang->repo->scmList['Gitea'] = 'Gitea'; $lang->repo->scmList['Git'] = '本地 Git'; $lang->repo->scmList['Subversion'] = 'Subversion'; @@ -149,6 +150,9 @@ $lang->repo->gitlabHost = 'GitLab Server'; $lang->repo->gitlabToken = 'GitLab Token'; $lang->repo->gitlabProject = 'GitLab 项目'; +$lang->repo->serviceHost = '服务器'; +$lang->repo->serviceProject = '仓库'; + $lang->repo->placeholder = new stdclass; $lang->repo->placeholder->gitlabHost = '请填写GitLab访问地址'; diff --git a/module/repo/lang/zh-tw.php b/module/repo/lang/zh-tw.php index 839ae5e4b0..9811b114f1 100644 --- a/module/repo/lang/zh-tw.php +++ b/module/repo/lang/zh-tw.php @@ -135,6 +135,7 @@ $lang->repo->encodingList['utf_8'] = 'UTF-8'; $lang->repo->encodingList['gbk'] = 'GBK'; $lang->repo->scmList['Gitlab'] = 'GitLab'; +$lang->repo->scmList['Gitea'] = 'Gitea'; $lang->repo->scmList['Git'] = '本地 Git'; $lang->repo->scmList['Subversion'] = 'Subversion'; @@ -142,6 +143,9 @@ $lang->repo->gitlabHost = 'GitLab Server'; $lang->repo->gitlabToken = 'GitLab Token'; $lang->repo->gitlabProject = 'GitLab 項目'; +$lang->repo->serviceHost = '服务器'; +$lang->repo->serviceProject = '仓库'; + $lang->repo->placeholder = new stdclass; $lang->repo->placeholder->gitlabHost = '請填寫GitLab訪問地址'; diff --git a/module/repo/model.php b/module/repo/model.php index fc8e128802..3ccca373f5 100644 --- a/module/repo/model.php +++ b/module/repo/model.php @@ -38,6 +38,9 @@ class repoModel extends model if(empty($repoID)) $repoID = $this->session->repoID ? $this->session->repoID : key($repos); if(!isset($repos[$repoID])) $repoID = key($repos); + /* Init switcher menu. */ + $this->lang->switcherMenu = ''; + /* Check the privilege. */ if($repoID) { @@ -54,7 +57,7 @@ class repoModel extends model return print(js::locate('back')); } - if($repo->SCM != 'Gitlab') unset($this->lang->devops->menu->mr); + if(!in_array(strtolower($repo->SCM), $this->config->repo->gitServiceList)) unset($this->lang->devops->menu->mr); $this->lang->switcherMenu = $this->getSwitcher($repoID); } @@ -138,7 +141,7 @@ class repoModel extends model } } - if($repo->SCM == 'Gitlab') $repo = $this->processGitlab($repo); + if(in_array(strtolower($repo->SCM), $this->config->repo->gitServiceList)) $repo = $this->processGitService($repo); } return $repos; @@ -165,7 +168,7 @@ class repoModel extends model if($repo->encrypt == 'base64') $repo->password = base64_decode($repo->password); $repo->acl = json_decode($repo->acl); if($type == 'haspriv' and !$this->checkPriv($repo)) unset($repos[$i]); - if(strtolower($repo->SCM) == 'gitlab') $repo = $this->processGitlab($repo); + if(in_array(strtolower($repo->SCM), $this->config->repo->gitServiceList)) $repo = $this->processGitService($repo); } return $repos; @@ -182,19 +185,20 @@ class repoModel extends model if(!$this->checkClient()) return false; if(!$this->checkConnection()) return false; - if($this->post->SCM == 'Gitlab') + $isPipelineServer = in_array(strtolower($this->post->SCM), $this->config->repo->gitServiceList) ? true : false; + if($isPipelineServer) { - if($this->post->gitlabHost == '') dao::$errors['gitlabHost'] = sprintf($this->lang->error->notempty, $this->lang->repo->gitlabHost); - if($this->post->gitlabProject == '') dao::$errors['gitlabProject'] = sprintf($this->lang->error->notempty, $this->lang->repo->gitlabProject); + if($this->post->serviceHost == '') dao::$errors['serviceHost'] = sprintf($this->lang->error->notempty, $this->lang->repo->serviceHost); + if($this->post->serviceProject == '') dao::$errors['serviceProject'] = sprintf($this->lang->error->notempty, $this->lang->repo->serviceProject); if(dao::isError()) return false; } $data = fixer::input('post') - ->setIf($this->post->SCM == 'Gitlab', 'password', $this->post->gitlabToken) - ->setIf($this->post->SCM == 'Gitlab', 'path', $this->post->gitlabProject) - ->setIf($this->post->SCM == 'Gitlab', 'client', $this->post->gitlabHost) - ->setIf($this->post->SCM == 'Gitlab', 'extra', $this->post->gitlabProject) - ->setIf($this->post->SCM == 'Gitlab', 'prefix', '') + ->setIf($isPipelineServer, 'password', $this->post->serviceToken) + ->setIf($isPipelineServer, 'path', $this->post->serviceProject) + ->setIf($isPipelineServer, 'client', $this->post->serviceHost) + ->setIf($isPipelineServer, 'extra', $this->post->serviceProject) + ->setIf($isPipelineServer, 'prefix', '') ->setIf($this->post->SCM == 'Git', 'account', '') ->setIf($this->post->SCM == 'Git', 'password', '') ->skipSpecial('path,client,account,password') @@ -209,7 +213,7 @@ class repoModel extends model ->andWhere('client')->eq($data->client) ->andWhere('path')->eq($data->path) ->fetch(); - if(!empty($repo)) dao::$errors['gitlabProject'] = sprintf($this->lang->error->unique, $this->lang->repo->gitlabProject, $repo->id); + if(!empty($repo)) dao::$errors['serviceProject'] = sprintf($this->lang->error->unique, $this->lang->repo->serviceProject, $repo->id); if(dao::isError()) return false; } @@ -226,9 +230,9 @@ class repoModel extends model } if($data->encrypt == 'base64') $data->password = base64_encode($data->password); - $this->dao->insert(TABLE_REPO)->data($data, $skip = 'gitlabHost,gitlabToken,gitlabProject') + $this->dao->insert(TABLE_REPO)->data($data, $skip = 'serviceHost,serviceToken,serviceProject') ->batchCheck($this->config->repo->create->requiredFields, 'notempty') - ->checkIF($data->SCM == 'Gitlab', 'gitlabProject', 'notempty') + ->checkIF($isPipelineServer, 'serviceProject', 'notempty') ->checkIF($data->SCM == 'Subversion', $this->config->repo->svn->requiredFields, 'notempty') ->checkIF($data->SCM == 'Git', 'path', 'unique', "`SCM` = 'Git'") ->checkIF($data->SCM == 'Subversion', 'path', 'unique', "`SCM` = 'Subversion'") @@ -262,17 +266,18 @@ class repoModel extends model { $repo = $this->getRepoByID($id); - if($this->post->SCM == 'Gitlab') + $isPipelineServer = in_array(strtolower($this->post->SCM), $this->config->repo->gitServiceList) ? true : false; + if($isPipelineServer) { - if($this->post->gitlabHost == '') dao::$errors['gitlabHost'] = sprintf($this->lang->error->notempty, $this->lang->repo->gitlabHost); - if($this->post->gitlabProject == '') dao::$errors['gitlabProject'] = sprintf($this->lang->error->notempty, $this->lang->repo->gitlabProject); + if($this->post->serviceHost == '') dao::$errors['serviceHost'] = sprintf($this->lang->error->notempty, $this->lang->repo->serviceHost); + if($this->post->serviceProject == '') dao::$errors['serviceProject'] = sprintf($this->lang->error->notempty, $this->lang->repo->serviceProject); } $data = fixer::input('post') - ->setIf($this->post->SCM == 'Gitlab', 'password', $this->post->gitlabToken) - ->setIf($this->post->SCM == 'Gitlab', 'path', $this->post->gitlabProject) - ->setIf($this->post->SCM == 'Gitlab', 'client', $this->post->gitlabHost) - ->setIf($this->post->SCM == 'Gitlab', 'extra', $this->post->gitlabProject) + ->setIf($isPipelineServer, 'password', $this->post->serviceToken) + ->setIf($isPipelineServer, 'path', $this->post->serviceProject) + ->setIf($isPipelineServer, 'client', $this->post->serviceHost) + ->setIf($isPipelineServer, 'extra', $this->post->serviceProject) ->setDefault('prefix', $repo->prefix) ->setIf($this->post->SCM == 'Gitlab', 'prefix', '') ->setDefault('client', 'svn') @@ -307,7 +312,7 @@ class repoModel extends model ->andWhere('path')->eq($data->path) ->andWhere('id')->ne($id) ->fetch(); - if(!empty($repo)) dao::$errors['gitlabProject'] = sprintf($this->lang->error->unique, $this->lang->repo->gitlabProject, $repo->id); + if(!empty($repo)) dao::$errors['serviceProject'] = sprintf($this->lang->error->unique, $this->lang->repo->serviceProject, $repo->id); if(dao::isError()) return false; } @@ -315,7 +320,7 @@ class repoModel extends model if(!$this->checkConnection()) return false; if($data->encrypt == 'base64') $data->password = base64_encode($data->password); - $this->dao->update(TABLE_REPO)->data($data, $skip = 'gitlabHost,gitlabToken,gitlabProject') + $this->dao->update(TABLE_REPO)->data($data, $skip = 'serviceHost,serviceToken,serviceProject') ->batchCheck($this->config->repo->edit->requiredFields, 'notempty') ->checkIF($data->SCM == 'Subversion', $this->config->repo->svn->requiredFields, 'notempty') ->checkIF($data->SCM == 'Gitlab', 'extra', 'notempty') @@ -416,10 +421,8 @@ class repoModel extends model { $repoPairs = $this->getRepoPairs($type, $projectID); - $repos = array(); - $repos['Gitlab'] = array(); - $repos['SVN'] = array(); - $repos['Git'] = array(); + $repos = array(); + foreach($this->lang->repo->scmList as $scmType => $scm) $repos[$scmType] = array(); foreach($repoPairs as $id => $repo) { @@ -428,6 +431,11 @@ class repoModel extends model $repo = str_replace('[gitlab]', '', $repo); $repos['Gitlab'][$id] = $repo; } + if(strpos($repo, '[gitea]') !== false) + { + $repo = str_replace('[gitea]', '', $repo); + $repos['Gitea'][$id] = $repo; + } if(strpos($repo, '[svn]') !== false) { $repo = str_replace('[svn]', '', $repo); @@ -455,7 +463,7 @@ class repoModel extends model if(!$repo) return false; if($repo->encrypt == 'base64') $repo->password = base64_decode($repo->password); - if(strtolower($repo->SCM) == 'gitlab') $repo = $this->processGitlab($repo); + if(in_array(strtolower($repo->SCM), $this->config->repo->gitServiceList)) $repo = $this->processGitService($repo); $repo->acl = json_decode($repo->acl); return $repo; } @@ -882,14 +890,17 @@ class repoModel extends model { $commitID = $this->dao->lastInsertID(); if($branch) $this->dao->replace(TABLE_REPOBRANCH)->set('repo')->eq($repoID)->set('revision')->eq($commitID)->set('branch')->eq($branch)->exec(); - foreach($logs['files'][$i] as $file) + if(!empty($logs['files'])) { - $parentPath = dirname($file->path); + foreach($logs['files'][$i] as $file) + { + $parentPath = dirname($file->path); - $file->parent = $parentPath == '\\' ? '/' : $parentPath; - $file->revision = $commitID; - $file->repo = $repoID; - $this->dao->insert(TABLE_REPOFILES)->data($file)->exec(); + $file->parent = $parentPath == '\\' ? '/' : $parentPath; + $file->revision = $commitID; + $file->repo = $repoID; + $this->dao->insert(TABLE_REPOFILES)->data($file)->exec(); + } } $revisionPairs[$commit->revision] = $commit->revision; $version++; @@ -1274,7 +1285,7 @@ class repoModel extends model */ public function checkClient() { - if($this->post->SCM == 'Gitlab') return true; + if(in_array(strtolower($this->post->SCM), $this->config->repo->gitServiceList)) return true; if(!$this->config->features->checkClient) return true; if(!$this->post->client) @@ -2016,21 +2027,21 @@ class repoModel extends model } /** - * Process gitlab repo. + * Process git service repo. * * @param object $repo * @access public * @return object */ - public function processGitlab($repo) + public function processGitService($repo) { - $gitlab = $this->loadModel('gitlab')->getByID($repo->client); // The $repo->client is gitlabID. + $service = $this->loadModel('pipeline')->getByID($repo->client); - $repo->gitlab = $gitlab ? $gitlab->id : 0; - $repo->project = $gitlab ? $repo->path : ''; // The projectID in gitlab. - $repo->path = $gitlab ? sprintf($this->config->repo->gitlab->apiPath, $gitlab->url, $repo->path) : ''; - $repo->client = $gitlab ? $gitlab->url : ''; - $repo->password = $gitlab ? $gitlab->token : ''; + $repo->gitService = $service ? $service->id : 0; + $repo->project = $service ? $repo->path : ''; // The projectID in gitlab. + $repo->path = $service ? sprintf($this->config->repo->{$service->type}->apiPath, $service->url, $repo->path) : ''; + $repo->client = $service ? $service->url : ''; + $repo->password = $service ? $service->token : ''; return $repo; } @@ -2041,10 +2052,9 @@ class repoModel extends model * @param int $projectID * @return array */ - public function getGitLabRepoList($gitlabID, $projectID = 0) + public function getRepoListByClient($gitlabID, $projectID = 0) { return $this->dao->select('*')->from(TABLE_REPO)->where('deleted')->eq('0') - ->andWhere('SCM')->eq('Gitlab') ->andWhere('synced')->eq(1) ->andWhere('client')->eq($gitlabID) ->beginIF($projectID)->andWhere('path')->eq($projectID)->fi() @@ -2151,13 +2161,22 @@ class repoModel extends model } elseif($repo->SCM == 'Gitlab') { - $project = $this->loadModel('gitlab')->apiGetSingleProject($repo->gitlab, $repo->project); + $project = $this->loadModel('gitlab')->apiGetSingleProject($repo->gitService, $repo->project); if(isset($project->id)) { $url->http = $project->http_url_to_repo; $url->ssh = $project->ssh_url_to_repo; } } + elseif($repo->SCM == 'Gitea') + { + $project = $this->loadModel('gitea')->apiGetSingleProject($repo->gitService, $repo->project); + if(isset($project->id)) + { + $url->http = $project->clone_url; + $url->ssh = $project->ssh_url; + } + } else { $this->scm = $this->app->loadClass('scm'); diff --git a/module/repo/view/ajaxsidecommits.html.php b/module/repo/view/ajaxsidecommits.html.php index 43e29ac258..74a1480b15 100644 --- a/module/repo/view/ajaxsidecommits.html.php +++ b/module/repo/view/ajaxsidecommits.html.php @@ -19,7 +19,9 @@ if(isset($entry)) $pathInfo .= '&type=file';

    product->code;?> code;?>product->acl;?> code) ? "colspan='4'" : "colspan='2'";?>>product->aclList[$product->acl];?>
    product->type;?>product->typeList, $product->type);?>story->openedBy?>createdBy);?>
    productCommon . $lang->product->status;?>product->statusList, $product->status);?>story->openedDate?>createdDate, DT_DATE1);?>
    product->acl;?>product->aclList[$product->acl];?>
    product->whitelist;?>idAB;?> project->parent;?> project->name;?>project->code;?> project->PM;?> project->begin;?> project->end;?>parent, "class='form-control chosen' data-id='$projectID' data-name='{$project->name}' data-parent='{$project->parent}'");?> name, "class='form-control'");?>code, "class='form-control'");?> PM, "class='form-control chosen'");?> begin, "class='form-control form-date' onchange='computeWorkDays(this.id);' placeholder='" . $lang->project->begin . "'");?> diff --git a/module/project/view/create.html.php b/module/project/view/create.html.php index 4c1e257bba..4866641897 100755 --- a/module/project/view/create.html.php +++ b/module/project/view/create.html.php @@ -55,10 +55,12 @@ project->name;?>
    project->code;?>
    project->PM;?> project->name;?> name, "class='form-control' required");?>
    project->code;?> code, "class='form-control' required");?>
    project->PM;?> PM, "class='form-control chosen'" . (strpos($requiredFields, 'PM') !== false ? ' required' : ''));?>
    + SCM != 'Gitea'):?> + SCM != 'Subversion'):?> @@ -32,12 +34,14 @@ if(isset($entry)) $pathInfo .= '&type=file'; + SCM != 'Gitea'):?> + SCM != 'Subversion'):?> @@ -50,7 +54,7 @@ if(isset($entry)) $pathInfo .= '&type=file';
    repo->revisionA?> repo->commit?>
    repo->createLink('revision', "repoID=$repoID&objectID=$objectID&revision={$log->revision}" . $pathInfo), $repo->SCM != 'Subversion' ? substr($log->revision, 0, 10) : $log->revision, '', "data-app='{$this->app->tab}'");?> commit?>
    repo->scmList, 'Gitlab', "onchange='scmChanged(this.value)' class='form-control chosen'"); ?> repo->syncTips; ?>
    repo->gitlabHost;?>repo->placeholder->gitlabHost}'");?>
    repo->serviceHost;?>
    repo->gitlabProject;?>
    repo->serviceProject;?>
    repo->name; ?>
    repo->path; ?> @@ -58,7 +58,7 @@ repo->encodingsTips; ?>
    repo->client;?> @@ -66,11 +66,11 @@ repo->example->client->svn;?>
    repo->gitlabHost;?>gitlab) ? $repo->gitlab : '', "class='form-control chosen' placeholder='{$lang->repo->placeholder->gitlabHost}'");?>
    repo->serviceHost;?>gitService) ? $repo->gitService : '', "class='form-control chosen'");?>
    repo->gitlabProject;?>project) ? $repo->project : '', "class='form-control chosen'");?>
    repo->serviceProject;?>project) ? $repo->project : '', "class='form-control chosen'");?>
    repo->name; ?> name, "class='form-control'"); ?>
    repo->path; ?> path, "class='form-control'"); ?> @@ -62,7 +62,7 @@ encoding, "class='form-control'"); ?> repo->encodingsTips; ?>
    repo->client;?> client, "class='form-control'")?> @@ -70,11 +70,11 @@ repo->example->client->svn;?>