diff --git a/api/v1/entries/user.php b/api/v1/entries/user.php index b4d2dba06e..5be0be2c25 100644 --- a/api/v1/entries/user.php +++ b/api/v1/entries/user.php @@ -210,7 +210,7 @@ class userEntry extends Entry if(!common::hasPriv('my', 'work')) break; $control = $this->loadController('my', 'bug'); - $control->bug($this->param('type', 'assignedTo'), $this->param('order', 'id_desc'), $this->param('total', 0), $this->param('limit', 5), $this->param('page', 1)); + $control->bug($this->param('type', 'assignedTo'), 0, $this->param('order', 'id_desc'), $this->param('total', 0), $this->param('limit', 5), $this->param('page', 1)); $data = $this->getData(); if($data->status == 'success') @@ -266,7 +266,7 @@ class userEntry extends Entry if(!common::hasPriv('my', 'work')) break; $control = $this->loadController('my', 'story'); - $control->story($this->param('type', 'assignedTo'), $this->param('order', 'id_desc'), $this->param('total', 0), $this->param('limit', 5), $this->param('page', 1)); + $control->story($this->param('type', 'assignedTo'), 0, $this->param('order', 'id_desc'), $this->param('total', 0), $this->param('limit', 5), $this->param('page', 1)); $data = $this->getData(); if($data->status == 'success') @@ -290,7 +290,7 @@ class userEntry extends Entry if($this->config->edition == 'max') { $control = $this->loadController('my', 'issue'); - $control->issue('createdBy', 'id_desc', 0, $this->param('limit', 5), 1); + $control->issue('createdBy', 0, 'id_desc', 0, $this->param('limit', 5), 1); $data = $this->getData(); if($data->status == 'success') @@ -307,7 +307,7 @@ class userEntry extends Entry if($this->config->edition == 'max') { $control = $this->loadController('my', 'risk'); - $control->risk('createdBy', 'id_desc', 0, $this->param('limit', 5), 1); + $control->risk('createdBy', 0, 'id_desc', 0, $this->param('limit', 5), 1); $data = $this->getData(); if($data->status == 'success') @@ -324,7 +324,7 @@ class userEntry extends Entry if($this->config->edition == 'max') { $control = $this->loadController('my', 'myMeeting'); - $control->myMeeting('all', 'id_desc', 0, $this->param('limit', 5), 1); + $control->myMeeting('all', '', 'id_desc', 0, $this->param('limit', 5), 1); $data = $this->getData(); if($data->status == 'success') diff --git a/db/update17.3.sql b/db/update17.3.sql index 8a2671fe3c..e27fcd7259 100644 --- a/db/update17.3.sql +++ b/db/update17.3.sql @@ -2,6 +2,10 @@ ALTER TABLE `zt_mr` CHANGE COLUMN `gitlabID` `hostID` mediumint(8) UNSIGNED NOT 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`; UPDATE `zt_project` SET `status`='closed' WHERE `type` IN ('sprint', 'stage', 'kanban') AND `model`='' AND `status` = 'done'; +ALTER TABLE `zt_repo` ADD COLUMN `serviceHost` varchar(50) NOT NULL AFTER `client`; +ALTER TABLE `zt_repo` ADD COLUMN `serviceProject` varchar(100) NOT NULL AFTER `serviceHost`; +UPDATE `zt_repo` SET `serviceHost` = `client`, `serviceProject` = `path` WHERE `SCM` = 'Gitlab'; +UPDATE `zt_repo` SET `client` = '', `path` = '' WHERE `SCM` = 'Gitlab'; UPDATE `zt_workflowfield` SET `options`='user' WHERE `buildin`='1' AND `options`='8'; INSERT IGNORE INTO `zt_workflowfield` (`module`, `field`, `type`, `length`, `name`, `control`, `expression`, `options`, `default`, `rules`, `placeholder`, `order`, `searchOrder`, `exportOrder`, `canExport`, `canSearch`, `isValue`, `readonly`, `buildin`, `desc`, `createdBy`, `createdDate`, `editedBy`, `editedDate`) VALUES @@ -9,4 +13,4 @@ INSERT IGNORE INTO `zt_workflowfield` (`module`, `field`, `type`, `length`, `nam ('testcase', 'execution', 'mediumint', '8', '所属执行', 'select', '', '44', '0', '', '', 4, 0, 0, '0', '1', '0', '1', 1, '', '', '2022-03-18 09:16:38', '', '0000-00-00 00:00:00'), ('task', 'execution', 'mediumint', '8', '所属执行', 'select', '', '44', '0', '', '', 4, 0, 0, '0', '1', '0', '1', 1, '', '', '2022-03-18 09:16:38', '', '0000-00-00 00:00:00'), ('bug', 'execution', 'mediumint', '8', '所属执行', 'select', '', '44', '0', '', '', 6, 0, 0, '0', '1', '0', '1', 1, '', '', '2022-03-18 09:16:38', '', '0000-00-00 00:00:00'), -('build', 'execution', 'mediumint', '8', '所属执行', 'select', '', '44', '0', '', '', 5, 0, 0, '0', '1', '0', '1', 1, '', '', '2022-03-18 09:16:38', '', '0000-00-00 00:00:00'); +('build', 'execution', 'mediumint', '8', '所属执行', 'select', '', '44', '0', '', '', 5, 0, 0, '0', '1', '0', '1', 1, '', '', '2022-03-18 09:16:38', '', '0000-00-00 00:00:00'); \ No newline at end of file diff --git a/db/zentao.sql b/db/zentao.sql index ad5feb37ee..c0af747c5d 100755 --- a/db/zentao.sql +++ b/db/zentao.sql @@ -1257,6 +1257,8 @@ CREATE TABLE IF NOT EXISTS `zt_repo` ( `encoding` varchar(20) NOT NULL, `SCM` varchar(10) NOT NULL, `client` varchar(100) NOT NULL, + `serviceHost` varchar(50) NOT NULL, + `serviceProject` varchar(100) NOT NULL, `commits` mediumint(8) unsigned NOT NULL, `account` varchar(30) NOT NULL, `password` varchar(30) NOT NULL, diff --git a/framework/base/helper.class.php b/framework/base/helper.class.php index a9490316bf..c787cc08fe 100644 --- a/framework/base/helper.class.php +++ b/framework/base/helper.class.php @@ -164,7 +164,7 @@ class baseHelper $sign = strpos($link, '?') === false ? "?" : "&"; $appendString = ''; if($onlyBody or self::inOnlyBodyMode()) $appendString = $sign . "onlybody=yes"; - if(self::isWithTID()) $appendString .= empty($appendString) ? "{$sign}tid={$_GET['tid']}" : "&tid={$_GET['tid']}"; + if(self::isWithTID() and strpos($link, 'tid=') === false) $appendString .= empty($appendString) ? "{$sign}tid={$_GET['tid']}" : "&tid={$_GET['tid']}"; return $link . $appendString; } diff --git a/lib/scm/gitea.class.php b/lib/scm/gitea.class.php index 1585de2822..d64adf54d9 100644 --- a/lib/scm/gitea.class.php +++ b/lib/scm/gitea.class.php @@ -1,27 +1,37 @@ client = $client; - $this->root = rtrim($root, '/') . '/'; - $this->token = $password; - $this->branch = isset($_COOKIE['repoBranch']) ? $_COOKIE['repoBranch'] : 'HEAD'; + $this->root = rtrim($root, DIRECTORY_SEPARATOR); + + $branch = isset($_COOKIE['repoBranch']) ? $_COOKIE['repoBranch'] : ''; + if($branch) + { + $branches = $this->branch(); + if(isset($branches[$branch])) $branch = "origin/$branch"; + } + $this->branch = $branch; + + chdir($this->root); + exec("{$this->client} config core.quotepath false"); } /** @@ -35,50 +45,48 @@ class gitea 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; + $path = ltrim($path, DIRECTORY_SEPARATOR); + $sub = ''; + chdir($this->root); + if(!empty($path)) $sub = ":$path"; + if(!empty($this->branch))$revision = $this->branch; + $cmd = escapeCmd("$this->client ls-tree -l $revision$sub"); + $list = execCmd($cmd . ' 2>&1', 'array', $result); + if($result) return array(); - $list = $this->fetch($api, $param, true); - if(empty($list)) return array(); - - $infos = array(); - foreach($list as $file) + $infos = array(); + foreach($list as $entry) { - if(!isset($file->type)) continue; + list($mod, $kind, $revision, $size, $name) = preg_split('/[\t ]+/', $entry); - $info = new stdClass(); - $info->name = $file->name; - $info->kind = $file->type; + /* Get commit info. */ + $pathName = ltrim($path . DIRECTORY_SEPARATOR . $name, DIRECTORY_SEPARATOR); + $cmd = escapeCmd("$this->client log -1 $this->branch -- $pathName"); + $commit = execCmd($cmd, 'array'); + $logs = $this->parseLog($commit); - if($file->type == 'file') + if($size > 1024 * 1024) { - $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', ''); + $size = round($size / (1024 * 1024), 2) . 'MB'; + } + else if($size > 1024) + { + $size = round($size / 1024, 2) . 'KB'; } 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; + $size .= 'Bytes'; } + $info = new stdClass(); + $info->name = $name; + $info->kind = $kind == 'tree' ? 'dir' : 'file'; + $info->revision = $logs ? $logs[0]->revision : $revision; + $info->size = $size; + $info->account = $logs ? $logs[0]->committer : ''; + $info->date = $logs ? $logs[0]->time : ''; + $info->comment = $logs ? $logs[0]->comment : ''; $infos[] = $info; unset($info); } @@ -86,45 +94,10 @@ class gitea /* 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 * @@ -135,69 +108,56 @@ class gitea */ public function tags($path, $revision = 'HEAD') { - $api = "tags"; - $tags = array(); + if(!scm::checkRevision($revision)) return array(); - $params = array(); - $params['limit'] = $this->pageLimit; - for($page = 1; true; $page ++) + chdir($this->root); + $cmd = escapeCmd("$this->client tag --sort=taggerdate"); + $list = execCmd($cmd . ' 2>&1', 'array', $result); + if($result) return array(); + + foreach($list as $key => $tag) { - $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; + if(!$tag) unset($list[$key]); } - return $tags; + return $list; } /** - * Get branches. + * Get branch. * * @access public * @return array */ public function branch() { - /* Max size of limit in gitea API is 50. */ - $params = array(); - $params['limit'] = $this->pageLimit; + chdir($this->root); + + /* Get local branch. */ + $cmd = escapeCmd("$this->client branch -a"); + $list = execCmd($cmd . ' 2>&1', 'array', $result); + if($result) return array(); /* Get default branch. */ - $project = $this->fetch(''); - $defaultBranch = $project->default_branch; + $defaultBranch = execCmd("$this->client symbolic-ref refs/remotes/origin/HEAD | sed 's@^refs/remotes/origin/@@'"); + $defaultBranch = trim($defaultBranch); $branches = array(); - $default = array(); - for($page = 1; true; $page ++) + foreach($list as $localBranch) { - $params['page'] = $page; - $branchList = $this->fetch("branches", $params); - if(empty($branchList)) break; + $localBranch = trim($localBranch); + if(substr($localBranch, 0, 19) == 'remotes/origin/HEAD') continue; + if(substr($localBranch, 0, 1) == '*') $localBranch = substr($localBranch, 1); + if(substr($localBranch, 0, 15) == 'remotes/origin/') $localBranch = substr($localBranch, 15); - 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; + $localBranch = trim($localBranch); + if(empty($localBranch))continue; + if($localBranch != $defaultBranch) $branches[$localBranch] = $localBranch; } - if(empty($branches) and empty($default)) $branches['master'] = 'master'; asort($branches); + if($defaultBranch) $branches = array($defaultBranch => $defaultBranch) + $branches; - $branches = $default + $branches; return $branches; } @@ -211,11 +171,18 @@ class gitea */ public function getLastLog($path, $count = 10) { - return $this->log($path); + $path = ltrim($path, DIRECTORY_SEPARATOR); + $revision = $this->branch ? $this->branch : 'HEAD'; + + chdir($this->root); + $list = execCmd(escapeCmd("$this->client log -10 $revision -- $path"), 'array'); + $logs = $this->parseLog($list); + + return $logs; } /** - * Get logs. + * Get logs * * @param string $path * @param string $fromRevision @@ -231,13 +198,32 @@ class gitea $path = ltrim($path, DIRECTORY_SEPARATOR); $count = $count == 0 ? '' : "-n $count"; - $list = $this->getCommitsByPath($path, $fromRevision, $toRevision, 1, 1); - foreach($list as $commit) + /* compatible with svn. */ + if($fromRevision == 'HEAD' and $this->branch) $fromRevision = $this->branch; + if($toRevision == 'HEAD' and $this->branch) $toRevision = $this->branch; + if($fromRevision === $toRevision) { - if(isset($commit->sha)) $commit->diffs = $this->getFilesByCommit($commit->sha); + $logs = array(); + chdir($this->root); + + $list = execCmd(escapeCmd("$this->client log --stat=1024 --name-status --stat-name-width=1000 -1 $fromRevision -- $path"), 'array'); + $logs = $this->parseLog($list); + return $logs; } - return $this->parseLog($list); + if(!$fromRevision) + { + $revisions = " $toRevision"; + } + else + { + $revisions = "$fromRevision..$toRevision"; + } + chdir($this->root); + $list = execCmd(escapeCmd("$this->client log --stat=1024 --name-status --stat-name-width=1000 $count $revisions -- $path"), 'array'); + $logs = $this->parseLog($list); + + return $logs; } /** @@ -250,7 +236,46 @@ class gitea */ public function blame($path, $revision) { - return array(); + if(!scm::checkRevision($revision)) return array(); + + $path = ltrim($path, DIRECTORY_SEPARATOR); + chdir($this->root); + $list = execCmd(escapeCmd("$this->client blame -l $revision -- $path"), 'array'); + + $blames = array(); + $revLine = 0; + $revision = ''; + foreach($list as $line) + { + if(empty($line)) continue; + if($line[0] == '^') $line = substr($line, 1); + preg_match('/^([0-9a-f]{39,40})\s.*\((\S+)\s+([\d-]+)\s(.*)\s(\d+)\)(.*)$/U', $line, $matches); + + if(isset($matches[1]) and $matches[1] != $revision) + { + $blame = array(); + $blame['revision'] = $matches[1]; + $blame['committer'] = $matches[2]; + $blame['time'] = $matches[3]; + $blame['line'] = $matches[5]; + $blame['lines'] = 1; + $blame['content'] = strpos($matches[6], ' ') === false ? $matches[6] : substr($matches[6], 1); + + $revision = $matches[1]; + $revLine = $matches[5]; + $blames[$revLine] = $blame; + } + elseif(isset($matches[5])) + { + $blame = array(); + $blame['line'] = $matches[5]; + $blame['content'] = strpos($matches[6], ' ') === false ? $matches[6] : substr($matches[6], 1); + + $blames[$matches[5]] = $blame; + $blames[$revLine]['lines'] ++; + } + } + return $blames; } /** @@ -259,19 +284,25 @@ class gitea * @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 = '') + public function diff($path, $fromRevision, $toRevision, $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); + $path = ltrim($path, DIRECTORY_SEPARATOR); + chdir($this->root); + if($toRevision == 'HEAD' and $this->branch) $toRevision = $this->branch; + if($fromRevision == '^') $fromRevision = $toRevision . '^'; + if(strpos($fromRevision, '^') !== false) + { + $list = execCmd(escapeCmd("$this->client log -2 $toRevision --pretty=format:%H -- $path"), 'array'); + if(isset($list[1])) $fromRevision = $list[1]; + } + $lines = execCmd(escapeCmd("$this->client diff $fromRevision $toRevision -- $path"), 'array'); return $lines; } @@ -286,9 +317,13 @@ class gitea public function cat($entry, $revision = 'HEAD') { if(!scm::checkRevision($revision)) return false; + + chdir($this->root); if($revision == 'HEAD' and $this->branch) $revision = $this->branch; - $file = $this->files($entry, $revision); - return base64_decode($file->content); + $cmd = escapeCmd("$this->client show $revision:$entry"); + $content = execCmd($cmd); + if(is_array($content)) $content = implode("\n", $content); + return $content; } /** @@ -303,28 +338,33 @@ class gitea { 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) + chdir($this->root); + if($revision == 'HEAD' and $this->branch) $revision = $this->branch; + $path = ltrim($entry, DIRECTORY_SEPARATOR); + $cmd = escapeCmd("$this->client ls-tree $revision -- $path"); + $result = execCmd($cmd); + $kind = ''; + if($result) { - $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, $revision, $revision); - if(!empty($commits)) $file->revision = zget($commits[0], 'sha', ''); - $info->kind = (isset($file->type) and $file->type == 'tree') ? 'dir' : 'file'; + $results = explode("\n", trim($result)); + if(count($results) >= 2) + { + $kind = 'dir'; + } + else + { + list($mode, $type) = explode(' ', $results[0]); + $kind = $type == 'tree' ? 'dir' : 'file'; + } } + $list = execCmd(escapeCmd("$this->client log -1 $revision --pretty=format:%H -- $path"), 'array'); + $revision = $list[0]; + $info = new stdclass(); + $info->kind = $kind; + $info->path = $entry; + $info->revision = $revision; + $info->root = $this->root; return $info; } @@ -333,11 +373,11 @@ class gitea * * @param string $cmd * @access public - * @todo Exec commands by gitea api. * @return array */ public function exec($cmd) { + chdir($this->root); return execCmd(escapeCmd("$this->client $cmd"), 'array'); } @@ -489,280 +529,90 @@ class gitea /** * Get commits. * - * @param string $version + * @param string $rversion * @param int $count * @param string $branch * @access public * @return array */ - public function getCommits($version = '', $count = 0, $branch = '') + public function getCommits($revision = '', $count = 0, $branch = '') { - if(!scm::checkRevision($version)) return array(); - $api = "commits"; - $commits = array(); - $files = array(); + if(!scm::checkRevision($revision)) return array(); - if(empty($count)) $count = $this->pageLimit; + if($revision == 'HEAD' and $branch) $revision = $branch; + $revision = is_numeric($revision) ? "--skip=$revision $branch" : $revision; + $count = $count == 0 ? '' : "-n $count"; - if(!empty($version) and $count == 1) + chdir($this->root); + if($branch) { - $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); - } + execCmd(escapeCmd("$this->client checkout $branch")); + execCmd(escapeCmd("$this->client pull")); } - $params['sha'] = $branch; - if($version and $version != 'HEAD') + $list = execCmd(escapeCmd("$this->client log $count $revision -- ./"), 'array'); + $commits = $this->parseLog($list); + + $logs = array(); + foreach($commits as $commit) { - /* Get since param. */ - if(substr($version, 0, 5) == 'since') - { - $since = true; - $version = substr($version, 5); - } + $hash = $commit->revision; + $log = new stdClass(); + $log->committer = $commit->committer; + $log->revision = $commit->revision; + $log->comment = $commit->comment; + $log->time = $commit->time; + $logs['commits'][$hash] = $log; + $logs['files'][$hash] = array(); + } + if(empty($logs)) return $logs; - $committedDate = $this->getCommittedDate($version); - if(!$committedDate) return array('commits' => array(), 'files' => array()); - - if(!empty($since)) + $hash = ''; + $files = execCmd(escapeCmd("$this->client whatchanged $count $revision --pretty=format:%an@_@%cd@_@%H@_@%s -- ./"), 'array'); + foreach($files as $commit) + { + $commit = trim($commit); + if(empty($commit)) continue; + $parsedCommit = explode('@_@', $commit); + if(count($parsedCommit) == 4) { - $params['since'] = $committedDate; + list($account, $date, $hash, $comment) = $parsedCommit; } else { - $params['until'] = $committedDate; + $file = explode(' ', $commit); + $file = explode("\t", end($file)); + if(!isset($file[1])) $file[1] = ''; + list($action, $path) = $file; + + $parsedFile = new stdclass(); + $parsedFile->revision = $hash; + $parsedFile->path = '/' . trim($path); + $parsedFile->type = 'file'; + $parsedFile->action = $action; + $logs['files'][$hash][] = $parsedFile; } } - - $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); + return $logs; } /** - * getCommit + * Get clone url. * - * @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) + public function getCloneUrl() { - 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'; + $url = new stdclass(); + $remote = execCmd(escapeCmd("$this->client remote -v"), 'array'); + $pregHttp = '/http(s)?:\/\/(www\.)?[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+(:\d+)*(\/\w+)*\.git/'; + $pregSSH = '/ssh:\/\/git@[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+(:\d+)*(\/\w+)*\.git/'; + + if(preg_match($pregHttp, $remote[0], $matches)) $url->http = $matches[0]; + if(preg_match($pregSSH, $remote[0], $matches)) $url->ssh = $matches[0]; + + return $url; } /** @@ -776,39 +626,56 @@ class gitea { $parsedLogs = array(); $i = 0; - foreach($logs as $commit) + foreach($logs as $line) { - 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) + if(strpos($line, 'commit ') === 0) { - $parsedLog->change[$diff->path] = array(); - $parsedLog->change[$diff->path]['action'] = $diff->action; - $parsedLog->change[$diff->path]['kind'] = $diff->type; + if(isset($log)) + { + $log->comment = trim($comment); + $log->change = $changes; + $parsedLogs[$i] = $log; + $i++; + } + + $log = new stdclass(); + $comment = ''; + $changes = array(); + + $log->revision = trim(preg_replace('/^commit/', '', $line)); } - $parsedLogs[] = $parsedLog; + elseif(strpos($line, 'Author:') === 0) + { + $account = preg_replace('/^Author:/', '', $line); + $log->committer = trim(preg_replace('/<[a-zA-Z0-9_\-\.]+@[a-zA-Z0-9_\-\.]+>/', '', $account)); + } + elseif(strpos($line, 'Date:') === 0) + { + $date = trim(preg_replace('/^Date:/', '', $line)); + $log->time = date('Y-m-d H:i:s', strtotime($date)); + } + elseif(preg_match('/^\s{2,}/', $line)) + { + $comment .= $line; + } + elseif(strpos($line, "\t") !== false) + { + list($action, $entry) = explode("\t", $line); + $entry = '/' . trim($entry); + $pathInfo = array(); + $pathInfo['action'] = $action; + $pathInfo['kind'] = 'file'; + $changes[$entry] = $pathInfo; + } + } + + if(isset($log)) + { + $log->comment = trim($comment); + $log->change = $changes; + $parsedLogs[$i] = $log; } 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/gitrepo.class.php b/lib/scm/gitrepo.class.php index 92729062cb..bb39bcb417 100644 --- a/lib/scm/gitrepo.class.php +++ b/lib/scm/gitrepo.class.php @@ -21,7 +21,14 @@ class GitRepo $this->client = $client; $this->root = rtrim($root, DIRECTORY_SEPARATOR); - $this->branch = isset($_COOKIE['repoBranch']) ? $_COOKIE['repoBranch'] : ''; + + $branch = isset($_COOKIE['repoBranch']) ? $_COOKIE['repoBranch'] : ''; + if($branch) + { + $branches = $this->branch(); + if(isset($branches[$branch])) $branch = "origin/$branch"; + } + $this->branch = $branch; chdir($this->root); exec("{$this->client} config core.quotepath false"); @@ -117,7 +124,7 @@ class GitRepo } /** - * Get branch + * Get branch. * * @access public * @return array @@ -127,17 +134,21 @@ class GitRepo chdir($this->root); /* Get local branch. */ - $cmd = escapeCmd("$this->client branch"); + $cmd = escapeCmd("$this->client branch -a"); $list = execCmd($cmd . ' 2>&1', 'array', $result); if($result) return array(); /* Get default branch. */ $defaultBranch = execCmd("$this->client symbolic-ref refs/remotes/origin/HEAD | sed 's@^refs/remotes/origin/@@'"); + $defaultBranch = trim($defaultBranch); $branches = array(); foreach($list as $localBranch) { + $localBranch = trim($localBranch); + if(substr($localBranch, 0, 19) == 'remotes/origin/HEAD') continue; if(substr($localBranch, 0, 1) == '*') $localBranch = substr($localBranch, 1); + if(substr($localBranch, 0, 15) == 'remotes/origin/') $localBranch = substr($localBranch, 15); $localBranch = trim($localBranch); if(empty($localBranch))continue; @@ -533,6 +544,8 @@ class GitRepo $count = $count == 0 ? '' : "-n $count"; chdir($this->root); + if($branch) execCmd(escapeCmd("$this->client checkout $branch"), 'array'); + $list = execCmd(escapeCmd("$this->client log $count $revision -- ./"), 'array'); $commits = $this->parseLog($list); diff --git a/module/action/lang/de.php b/module/action/lang/de.php index 38218a2bd1..dd04ece590 100644 --- a/module/action/lang/de.php +++ b/module/action/lang/de.php @@ -216,6 +216,8 @@ $lang->action->desc->fromsonarqube = '$date, created by $actoraction->desc->tolib = '$date, imported by $actor .' . "\n"; $lang->action->desc->updatetolib = '$date, updated to ' . $lang->testcase->common . ' by $actor.' . "\n"; $lang->action->desc->adjusttasktowait = '$date, System Reminder: The task status will be set to Not Started as the consumed work hour is adjusted to 0. ' . "\n"; +$lang->action->desc->reopen = '$date, reopened by $actor .' . "\n"; +$lang->action->desc->merged = '$date, merged by $actor .' . "\n"; /* Used to describe the history of operations related to parent-child tasks. */ $lang->action->desc->createchildren = '$date, $actor created a child task $extra。' . "\n"; diff --git a/module/action/lang/en.php b/module/action/lang/en.php index 51cedddc58..1a927d1e7e 100755 --- a/module/action/lang/en.php +++ b/module/action/lang/en.php @@ -216,6 +216,8 @@ $lang->action->desc->fromsonarqube = '$date, created by $actoraction->desc->tolib = '$date, imported by $actor .' . "\n"; $lang->action->desc->updatetolib = '$date, updated to ' . $lang->testcase->common . ' by $actor.' . "\n"; $lang->action->desc->adjusttasktowait = '$date, System Reminder: The task status will be set to Not Started as the consumed work hour is adjusted to 0. ' . "\n"; +$lang->action->desc->reopen = '$date, reopened by $actor .' . "\n"; +$lang->action->desc->merged = '$date, merged by $actor .' . "\n"; /* Used to describe the history of operations related to parent-child tasks. */ $lang->action->desc->createchildren = '$date, $actor created a child task $extra。' . "\n"; diff --git a/module/action/lang/fr.php b/module/action/lang/fr.php index f50eae6e17..534a5cbe99 100644 --- a/module/action/lang/fr.php +++ b/module/action/lang/fr.php @@ -216,6 +216,8 @@ $lang->action->desc->fromsonarqube = '$date, created by $actoraction->desc->tolib = '$date, Importé par $actor .' . "\n"; $lang->action->desc->updatetolib = '$date, MàJ de ' . $lang->testcase->common . ' par $actor.' . "\n"; $lang->action->desc->adjusttasktowait = '$date, System Reminder: The task status will be set to Not Started as the consumed work hour is adjusted to 0. ' . "\n"; +$lang->action->desc->reopen = '$date, reopened by $actor .' . "\n"; +$lang->action->desc->merged = '$date, merged by $actor .' . "\n"; /* Used to describe the history of operations related to parent-child tasks. */ $lang->action->desc->createchildren = '$date, $actor a créé un sous-tâche $extra。' . "\n"; diff --git a/module/action/lang/vi.php b/module/action/lang/vi.php index 56a4ac1674..09f6928001 100644 --- a/module/action/lang/vi.php +++ b/module/action/lang/vi.php @@ -176,6 +176,8 @@ $lang->action->desc->run = '$date, by $actor execut $lang->action->desc->syncprogram = '$date, started by $actor(starting the project sets the program status as Ongoing).' . "\n"; $lang->action->desc->syncproject = '$date, starting the execution sets the project status as Ongoing.' . "\n"; $lang->action->desc->syncexecution = '$date, starting the task sets the execution status as Ongoing.' . "\n"; +$lang->action->desc->reopen = '$date, reopened by $actor .' . "\n"; +$lang->action->desc->merged = '$date, merged by $actor .' . "\n"; /* Used to describe the history of operations related to parent-child tasks. */ $lang->action->desc->createchildren = '$date, $actor created a child task $extra。' . "\n"; diff --git a/module/action/lang/zh-cn.php b/module/action/lang/zh-cn.php index eda00b9ed1..f3a4d1a7cc 100755 --- a/module/action/lang/zh-cn.php +++ b/module/action/lang/zh-cn.php @@ -216,6 +216,8 @@ $lang->action->desc->fromsonarqube = '$date, 由 $actor $lang->action->desc->tolib = '$date, 由 $actor 导入。' . "\n"; $lang->action->desc->updatetolib = '$date, 由 $actor 从' . $lang->testcase->common . '更新。' . "\n"; $lang->action->desc->adjusttasktowait = '$date, 系统判断由于消耗工时调整为0,将任务状态置为未开始。' . "\n"; +$lang->action->desc->reopen = '$date, 由 $actor 重新打开。' . "\n"; +$lang->action->desc->merged = '$date, 由 $actor 合并。' . "\n"; /* 用来描述和父子任务相关的操作历史记录。*/ $lang->action->desc->createchildren = '$date, 由 $actor 创建子任务 $extra。' . "\n"; diff --git a/module/action/model.php b/module/action/model.php index 30b1be5396..695c954c7d 100755 --- a/module/action/model.php +++ b/module/action/model.php @@ -1558,8 +1558,8 @@ class actionModel extends model } elseif($action->objectType == 'team') { - if($action->project) $action->objectLink = helper::createLink('project', 'team', 'projectID=' . $action->project); - if($action->execution) $action->objectLink = helper::createLink('execution', 'team', 'executionID=' . $action->execution); + if($action->project) $action->objectLink = common::hasPriv('project', 'team') ? helper::createLink('project', 'team', 'projectID=' . $action->project) : ''; + if($action->execution) $action->objectLink = common::hasPriv('execution', 'team') ? helper::createLink('execution', 'team', 'executionID=' . $action->execution) : ''; } if($action->objectType == 'stakeholder' and $action->project == 0) $action->objectLink = ''; diff --git a/module/block/control.php b/module/block/control.php index e7baea9b88..fecf665e14 100644 --- a/module/block/control.php +++ b/module/block/control.php @@ -1748,6 +1748,7 @@ class block extends control ->beginIF($objectType == 'story' or $objectType == 'requirement')->leftJoin(TABLE_PRODUCT)->alias('t2')->on('t1.product=t2.id')->fi() ->beginIF($objectType == 'bug')->leftJoin(TABLE_PRODUCT)->alias('t2')->on('t1.product=t2.id')->fi() ->beginIF($objectType == 'task')->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.execution=t2.id')->fi() + ->beginIF($objectType == 'issue' or $objectType == 'risk')->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.project=t2.id')->fi() ->where('t1.deleted')->eq(0) ->andWhere('t1.assignedTo')->eq($this->app->user->account)->fi() ->beginIF($objectType == 'story')->andWhere('t1.type')->eq('story')->andWhere('t2.deleted')->eq('0')->fi() @@ -1757,6 +1758,7 @@ class block extends control ->beginIF($objectType == 'todo')->andWhere('t1.cycle')->eq(0)->andWhere('t1.status')->eq('wait')->andWhere('t1.vision')->eq($this->config->vision)->fi() ->beginIF($objectType != 'todo')->andWhere('t1.status')->ne('closed')->fi() ->beginIF($objectType == 'feedback')->andWhere('t1.status')->in('wait, noreview')->fi() + ->beginIF($objectType == 'issue' or $objectType == 'risk')->andWhere('t2.deleted')->eq(0)->fi() ->orderBy($orderBy) ->beginIF($limitCount)->limit($limitCount)->fi() ->fetchAll(); @@ -1813,16 +1815,18 @@ class block extends control $now = date('H:i:s', strtotime(helper::now())); $meetingCount = isset($params->meetingCount) ? isset($params->meetingCount) : 0; - $meetings = $this->dao->select('*')->from(TABLE_MEETING) - ->where('deleted')->eq('0') - ->andWhere('(date')->gt($today) - ->orWhere('(begin')->gt($now) - ->andWhere('date')->eq($today) + $meetings = $this->dao->select('*')->from(TABLE_MEETING)->alias('t1') + ->leftjoin(TABLE_PROJECT)->alias('t2')->on('t1.project = t2.id') + ->where('t1.deleted')->eq('0') + ->andWhere('t2.deleted')->eq('0') + ->andWhere('(t1.date')->gt($today) + ->orWhere('(t1.begin')->gt($now) + ->andWhere('t1.date')->eq($today) ->markRight(2) - ->andwhere('(host')->eq($this->app->user->account) - ->orWhere('participant')->in($this->app->user->account) + ->andwhere('(t1.host')->eq($this->app->user->account) + ->orWhere('t1.participant')->in($this->app->user->account) ->markRight(1) - ->orderBy('id_desc') + ->orderBy('t1.id_desc') ->beginIF($meetingCount)->limit($meetingCount)->fi() ->fetchAll(); diff --git a/module/block/model.php b/module/block/model.php index 1c9b01f470..837f4435f7 100644 --- a/module/block/model.php +++ b/module/block/model.php @@ -185,9 +185,11 @@ class blockModel extends model $data['tasks'] = isset($tasks->tasks) ? $tasks->tasks : 0; $data['doneTasks'] = isset($tasks->doneTasks) ? $tasks->doneTasks : 0; - $data['bugs'] = (int)$this->dao->select('count(*) AS count')->from(TABLE_BUG) - ->where('assignedTo')->eq($this->app->user->account) - ->andWhere('deleted')->eq(0) + $data['bugs'] = (int)$this->dao->select('count(*) AS count')->from(TABLE_BUG)->alias('t1') + ->leftJoin(TABLE_PRODUCT)->alias('t2')->on("t1.product = t2.id") + ->where('t1.assignedTo')->eq($this->app->user->account) + ->andWhere('t1.deleted')->eq(0) + ->andWhere('t2.deleted')->eq(0) ->fetch('count'); $data['stories'] = (int)$this->dao->select('count(*) AS count')->from(TABLE_STORY)->alias('t1') ->leftJoin(TABLE_PRODUCT)->alias('t2')->on('t1.product=t2.id') diff --git a/module/block/view/executionblock.html.php b/module/block/view/executionblock.html.php index c85a231180..5f1e4e89d4 100644 --- a/module/block/view/executionblock.html.php +++ b/module/block/view/executionblock.html.php @@ -41,6 +41,8 @@ children)) continue; + $appid = isset($_GET['entry']) ? "class='app-btn text-center' data-id='{$this->get->entry}'" : "class='text-center'"; $viewLink = $this->createLink('execution', 'task', 'executionID=' . $execution->id); if($config->systemMode == 'new') $execution->name = zget($projectPairs, $execution->project, '') . ' / ' . $execution->name; diff --git a/module/bug/model.php b/module/bug/model.php index deedb60f28..c89de7171a 100644 --- a/module/bug/model.php +++ b/module/bug/model.php @@ -1691,6 +1691,7 @@ class bugModel extends model return $this->dao->select('t1.*,t2.name as productName')->from(TABLE_BUG)->alias('t1') ->leftJoin(TABLE_PRODUCT)->alias('t2')->on('t1.product = t2.id') ->where('t1.deleted')->eq(0) + ->andWhere('t2.deleted')->eq('0') ->beginIF($type == 'bySearch')->andWhere($query)->fi() ->beginIF($executionID)->andWhere('t1.execution')->eq($executionID)->fi() ->beginIF($type != 'closedBy' and $this->app->moduleName == 'block')->andWhere('t1.status')->ne('closed')->fi() diff --git a/module/bug/view/browse.html.php b/module/bug/view/browse.html.php index c809ced659..0f9fe04b39 100644 --- a/module/bug/view/browse.html.php +++ b/module/bug/view/browse.html.php @@ -377,7 +377,7 @@ $currentBrowseType = isset($lang->bug->mySelects[$browseType]) && in_array($brow - + type == 'normal' or $branch !== 'all')):?>
6;?> diff --git a/module/doc/config.php b/module/doc/config.php index 61c0bc9719..dd5ec6214c 100644 --- a/module/doc/config.php +++ b/module/doc/config.php @@ -15,6 +15,7 @@ $config->doc->edit->requiredFields = 'title'; $config->doc->customObjectLibs = 'files,customFiles'; $config->doc->notArticleType = ''; $config->doc->officeTypes = 'word,ppt,excel'; +$config->doc->textTypes = 'html,markdown,text'; $config->doc->custom = new stdclass(); $config->doc->custom->objectLibs = $config->doc->customObjectLibs; diff --git a/module/doc/control.php b/module/doc/control.php index 1f767ce221..2e328503c5 100755 --- a/module/doc/control.php +++ b/module/doc/control.php @@ -286,15 +286,16 @@ class doc extends control /** * Create a doc. * - * @param string $objectType - * @param int $objectID - * @param int|string $libID - * @param int $moduleID - * @param string $docType + * @param string $objectType + * @param int $objectID + * @param int|string $libID + * @param int $moduleID + * @param string $docType + * @param bool $fromGlobal * @access public * @return void */ - public function create($objectType, $objectID, $libID, $moduleID = 0, $docType = '') + public function create($objectType, $objectID, $libID, $moduleID = 0, $docType = '', $fromGlobal = false) { if(!empty($_POST)) { @@ -315,10 +316,23 @@ class doc extends control $this->action->create('doc', $docID, 'Created', $fileAction); if($this->viewType == 'json') return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'id' => $docID)); - $objectID = zget($lib, $lib->type, ''); + $objectID = zget($lib, $lib->type, 0); $params = "type={$lib->type}&objectID=$objectID&libID={$lib->id}&docID=" . $docResult['id']; $link = isonlybody() ? 'parent' : $this->createLink('doc', 'objectLibs', $params, 'html') . '#app=' . $this->app->tab; - return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => $link)); + $response = array('result' => 'success', 'message' => $this->lang->saveSuccess); + + if(isonlybody() and $docResult['docType'] == 'text') + { + $link = helper::createLink('doc', 'edit', "docID=$docID&comment=false&objectType=$objectType&objectID=$objectID&libID={$docResult['libID']}"); + + $response['callback'] = "redirect2Edit($docID, \"$objectType\", $objectID, {$docResult['libID']})"; + } + else + { + $response['locate'] = "$link"; + } + + return $this->send($response); } unset($_GET['onlybody']); @@ -347,7 +361,9 @@ class doc extends control if($this->config->systemMode == 'new') unset($this->lang->doc->menu->project['subMenu']); } - $this->config->showMainMenu = strpos(',html,markdown,text,', ",$docType,") === false; + /* {$this->view->from} is the zentaomax code, compatible with zentaomax. */ + $from = $this->view->from; + $this->config->showMainMenu = (strpos($this->config->doc->textTypes, $docType) === false or (!empty($from) and $from == 'template')); /* Get libs and the default lib id. */ $gobackLink = ($objectID == 0 and $libID == 0) ? $this->createLink('doc', 'tableContents', "type=$objectType") : ''; @@ -362,7 +378,7 @@ class doc extends control $this->view->title = $libName . $this->lang->doc->create; $this->view->objectType = $objectType; - $this->view->objectID = $objectID; + $this->view->objectID = zget($lib, $lib->type, 0); $this->view->libID = $libID; $this->view->lib = $lib; $this->view->libs = $libs; @@ -373,6 +389,7 @@ class doc extends control $this->view->docType = $docType; $this->view->groups = $this->loadModel('group')->getPairs(); $this->view->users = $this->user->getPairs('nocode|noclosed|nodeleted'); + $this->view->fromGlobal = $fromGlobal; $this->display(); } @@ -380,15 +397,16 @@ class doc extends control /** * Edit a doc. * - * @param int $docID - * @param bool $comment - * @param string $objectType - * @param int $objectID - * @param int $libID + * @param int $docID + * @param bool $comment + * @param string $objectType + * @param int $objectID + * @param int $libID + * @param string $from * @access public * @return void */ - public function edit($docID, $comment = false, $objectType = '', $objectID = 0, $libID = 0) + public function edit($docID, $comment = false, $objectType = '', $objectID = 0, $libID = 0, $from = 'edit') { if(!empty($_POST)) { @@ -490,6 +508,9 @@ class doc extends control $this->view->lib = $lib; $this->view->groups = $this->loadModel('group')->getPairs(); $this->view->users = $this->user->getPairs('noletter|noclosed|nodeleted', $doc->users); + $this->view->from = $from; + $this->view->files = $this->loadModel('file')->getByObject('doc', $docID); + $this->view->objectID = zget($lib, $type, 0); $this->display(); } diff --git a/module/doc/js/create.js b/module/doc/js/create.js index d3e25d9fd5..8547c1beeb 100644 --- a/module/doc/js/create.js +++ b/module/doc/js/create.js @@ -87,7 +87,7 @@ function initPage(type) { $('#contentBox .contentmarkdown').removeClass('hidden'); $('#contentBox .contenthtml').addClass('hidden'); - $('#contentBox #contentType').val(type); + $('#contentType').val(type); } } else if(type == 'url') @@ -150,3 +150,17 @@ function loadWhitelist(libID) } }); } + +/** + * Redirect to edit page when create the doc of text type. + * + * @param int docID + * @param string objectType + * @param int objectID + * @param int libID + * @return void + */ +function redirect2Edit(docID, objectType, objectID, libID) +{ + parent.location.href = createLink('doc', 'edit', 'docID=' + docID + '&comment=false&objectType=' + objectType + '&objectID=' + objectID + '&libID=' + libID + '&from=create'); +} diff --git a/module/doc/js/selectlibtype.js b/module/doc/js/selectlibtype.js index b3711fee8e..02393b4e56 100644 --- a/module/doc/js/selectlibtype.js +++ b/module/doc/js/selectlibtype.js @@ -16,7 +16,7 @@ function redirectParentWindow(objectType, libID, docType) } else { - var link = createLink('doc', 'create', 'objectType=' + objectType + '&objectID=0&libID=' + libID + '&moduleID=0&docType=' + docType) + '#app=doc'; + var link = createLink('doc', 'create', 'objectType=' + objectType + '&objectID=0&libID=' + libID + '&moduleID=0&docType=' + docType + '&fromGlobal=true') + '#app=doc'; } window.parent.$.apps.open(link); } diff --git a/module/doc/model.php b/module/doc/model.php index 142f262d78..07fed51fb8 100644 --- a/module/doc/model.php +++ b/module/doc/model.php @@ -782,7 +782,7 @@ class docModel extends model $docContent->files = join(',', array_keys($files)); $this->dao->insert(TABLE_DOCCONTENT)->data($docContent)->exec(); $this->loadModel('score')->create('doc', 'create', $docID); - return array('status' => 'new', 'id' => $docID, 'files' => $files); + return array('status' => 'new', 'id' => $docID, 'files' => $files, 'docType' => $doc->type, 'libID' => $doc->lib); } return false; } @@ -2126,11 +2126,11 @@ class docModel extends model { foreach($this->lang->doc->typeList as $typeKey => $typeName) { - $class = strpos($this->config->doc->officeTypes, $typeKey) !== false ? 'iframe' : ''; + $class = (strpos($this->config->doc->officeTypes, $typeKey) !== false or strpos($this->config->doc->textTypes, $typeKey) !== false) ? 'iframe' : ''; $icon = zget($this->config->doc->iconList, $typeKey); - $html .= "
  • "; - $html .= html::a(helper::createLink('doc', 'create', "objectType=$objectType&objectID=$objectID&libID=$libID&moduleID=0&type=$typeKey", '', $class ? true : false), " " . $typeName, '', "class='$class' data-app='{$this->app->tab}'"); - $html .= "
  • "; + $html .= "
  • "; + $html .= html::a(helper::createLink('doc', 'create', "objectType=$objectType&objectID=$objectID&libID=$libID&moduleID=0&type=$typeKey", '', $class ? true : false), " " . $typeName, '', "class='$class' data-app='{$this->app->tab}'"); + $html .= "
  • "; if($typeKey == 'url') $html .= '
  • '; } } diff --git a/module/doc/view/create.html.php b/module/doc/view/create.html.php index 76ebc29f2e..833b42349b 100644 --- a/module/doc/view/create.html.php +++ b/module/doc/view/create.html.php @@ -10,8 +10,142 @@ * @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"');?> + +
    + + + + + + + + + + + + + + + + + + + config->doc->textTypes, $docType) !== false ? 'hidden' : '';?> + + + + + + + doc->types as $typeKey => $typeName) $typeKeyList[$typeKey] = $typeKey; + ?> + + + + + + + + + + + + + + + + + + + + + + + + + + +
    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];?> +
    + + + showMainMenu):?> + 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 deleted file mode 100644 index 06cb9cc168..0000000000 --- a/module/doc/view/createothertype.html.php +++ /dev/null @@ -1,137 +0,0 @@ - - * @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 index 4192310850..0f0c667773 100644 --- a/module/doc/view/createtexttype.html.php +++ b/module/doc/view/createtexttype.html.php @@ -19,55 +19,64 @@ #main {padding: 0;} .container {padding: 0 !important;} #mainContent {padding: 0 !important;} -#dataform {overflow: hidden} .doc-title input {border: unset; font-size: 18px; font-weight: bold; color: #3c4353; padding-left: 16px;} .doc-title .form-control:focus {border: unset; box-shadow: unset;} .doc-title input::-webkit-input-placeholder {color: #D8DBDE;} .doc-title.required:after {top: 4px; right: 0; left: 12px; display: inline-table;} -#submit {margin-right: 12px;} +#submit {margin-right: 16px;} #headerBox {border-bottom: 1px solid #e3e3e3;} +#headerBox td:last-child {padding-right: 24px;} #editorContent {padding: 0;} #contentBox {padding: 0; width: 100%;} .ke-container {overflow: visible;} -.ke-container, .contentmarkdown {border: unset; background: #efefef;} +.ke-container, .contenthtml {border: unset; background: #efefef;} .ke-container.focus {box-shadow: unset; border-color: unset;} -.ke-toolbar {padding-left: 20px; width: 150%; height: 30px; border-bottom: unset;} +.ke-toolbar {padding-left: 20px; width: 100%; height: 30px;} .ke-edit {border-top: 1px solid rgb(220, 220, 220)} -.ke-edit, .CodeMirror {margin-left: 20px; background: #fff;} +.ke-edit, .CodeMirror {margin: 8px 200px 0 200px; background: #fff;} .kindeditor-ph {padding-left: 20px !important;} .editor-toolbar {background: #fff; padding-left: 20px; border-right: unset; border-top: unset; height: 30px;} .hide-sidebar .ke-edit {padding-right: 20px;} .hide-sidebar .CodeMirror {padding-right: 50px;} .CodeMirror.CodeMirror-wrap {border-left: 0; border-right: 0; border-bottom: 0;} .ke-statusbar {display: none;} +.contentmarkdown {background: #efefef;} -#sidebar {top: 30px;} -#sidebar .sidebar-toggle {right: 0; left: 0px; background: #efefef; border-radius: 0px; width: 20px; border-top: 1px solid rgb(220, 220, 220);} -#sidebar > .sidebar-toggle:hover {background: #efefef;} -#sidebar {width: 500px;} -#sidebar table {margin-top: 5px;} -#sidebar table th {font-weight: 400 !important;} -.hide-sidebar #sidebar > .sidebar-toggle > .icon:before {content: "\e314";} -.hide-sidebar #sidebar > .sidebar-toggle {left: -20px; z-index: 9;} -#sidebar .cell {border-top: 1px solid rgb(220, 220, 220); border-radius: 0px; height: 100%;} -#sidebar > .sidebar-toggle > .icon.icon-angle-right {left: 4px;} -.file-title {max-width: 130px !important;} +.article-content {padding: 8px 20px;} -.th-control {vertical-align: top !important;} +#noticeAcl {margin-left: 10px; vertical-align: middle;} -#noticeAcl {margin: 0;} +#moreList {display: inline-block; padding: 7px;} +#moreList .icon-more-circle {font-size: 20px;} +#moreList ul.dropdown-menu {left: -77px;} + +#backBtn {border: unset;} +#backBtn i {font-size: 20px;} + +.modal-title {font-size: 14px !important; font-weight: 700 !important;} +#modalBasicInfo .modal-dialog {width: 720px;} ' . $lang->doc->createLib, '', 'class="iframe hidden createCustomLib"');?> +createLink('doc', 'tableContents', "type=$objectType&objectID=$objectID&libID=$libID");?>
    - - + + +
    doc->titlePlaceholder}' class='form-control' required");?>", $backLink, 'self', "id='backBtn'");?>doc->titlePlaceholder}' class='form-control' required");?> + + +
    @@ -78,90 +87,107 @@ -
    + +
    diff --git a/module/doc/view/edittexttype.html.php b/module/doc/view/edittexttype.html.php index 1a9b167c60..ded396749b 100644 --- a/module/doc/view/edittexttype.html.php +++ b/module/doc/view/edittexttype.html.php @@ -23,22 +23,22 @@ #main {padding: 0;} .container {padding: 0 !important;} #mainContent {padding: 0 !important;} -#dataform {overflow: hidden} .doc-title input {border: unset; font-size: 18px; font-weight: bold; color: #3c4353; padding-left: 16px;} .doc-title .form-control:focus {border: unset; box-shadow: unset;} .doc-title input::-webkit-input-placeholder {color: #D8DBDE;} .doc-title.required:after {top: 4px; right: 0; left: 12px; display: inline-table;} -#submit {margin-right: 12px;} +#submit {margin-right: 16px;} #headerBox {border-bottom: 1px solid #e3e3e3;} +#headerBox td:last-child {padding-right: 24px;} #editorContent {padding: 0;} #contentBox {padding: 0; width: 100%;} .ke-container {overflow: visible;} .ke-container, .contenthtml {border: unset; background: #efefef;} .ke-container.focus {box-shadow: unset; border-color: unset;} -.ke-toolbar {padding-left: 20px; width: 150%; height: 30px; border-bottom: unset;} +.ke-toolbar {padding-left: 20px; width: 100%; height: 30px;} .ke-edit {border-top: 1px solid rgb(220, 220, 220)} -.ke-edit, .CodeMirror {margin-left: 20px; background: #fff;} +.ke-edit, .CodeMirror {margin: 8px 200px 0 200px; background: #fff;} .kindeditor-ph {padding-left: 20px !important;} .editor-toolbar {background: #fff; padding-left: 20px; border-right: unset; border-top: unset; height: 30px;} .hide-sidebar .ke-edit {padding-right: 20px;} @@ -46,29 +46,41 @@ .CodeMirror.CodeMirror-wrap {border-left: 0; border-right: 0; border-bottom: 0;} .ke-statusbar {display: none;} -#sidebar {top: 30px;} -#sidebar .sidebar-toggle {right: 0; left: 0px; background: #efefef; border-radius: 0px; width: 20px; border-top: 1px solid rgb(220, 220, 220);} -#sidebar > .sidebar-toggle:hover {background: #efefef;} -#sidebar {width: 500px;} -#sidebar table {margin-top: 5px;} -#sidebar table th {font-weight: 400 !important;} -.hide-sidebar #sidebar > .sidebar-toggle > .icon:before {content: "\e314";} -.hide-sidebar #sidebar > .sidebar-toggle {left: -20px; z-index: 9;} -#sidebar .cell {border-top: 1px solid rgb(220, 220, 220); border-radius: 0px; height: 100%;} -#sidebar > .sidebar-toggle > .icon.icon-angle-right {left: 4px;} -.file-title {max-width: 130px !important;} +.article-content {padding: 8px 20px;} -.th-control {vertical-align: top !important;} +#noticeAcl {margin-left: 10px; vertical-align: middle;} -#noticeAcl {margin: 0;} +#moreList {display: inline-block; padding: 7px;} +#moreList .icon-more-circle {font-size: 20px;} +#moreList ul.dropdown-menu {left: -77px;} + +#backBtn {border: unset;} +#backBtn i {font-size: 20px;} + +.modal-title {font-size: 14px !important; font-weight: 700 !important;} +#modalBasicInfo .modal-dialog {width: 720px;} +createLink('doc', 'objectlibs', "type=$type&objectID=$objectID&libID={$lib->id}&docID={$doc->id}");?>
    - - + + + + + + +
    title, "placeholder='{$lang->doc->titlePlaceholder}' class='form-control' required");?>", $backLink, 'self', "id='backBtn'");?>", "id='backBtn'", '');?>title, "placeholder='{$lang->doc->titlePlaceholder}' class='form-control' required");?> + + +
    @@ -79,89 +91,104 @@ editedDate);?> -
    + +
    doc->noticeAcl['doc']);?> diff --git a/module/doc/view/selectlibtype.html.php b/module/doc/view/selectlibtype.html.php index aa1057648c..4f831ee8af 100644 --- a/module/doc/view/selectlibtype.html.php +++ b/module/doc/view/selectlibtype.html.php @@ -14,7 +14,7 @@
    -

    ' . $lang->doc->selectLibType . '';?>

    +

    ' . $lang->doc->create . '';?>

    diff --git a/module/execution/control.php b/module/execution/control.php index 43c685c403..f25924ed41 100644 --- a/module/execution/control.php +++ b/module/execution/control.php @@ -2300,6 +2300,7 @@ class execution extends control $end = helper::today(); $dateList = date::getDateList($begin, $end, 'Y-m-d', 'noweekend'); $chartData = $this->execution->buildCFDData($executionID, $dateList, 'task'); + if(isset($chartData['line'])) $chartData['line'] = array_reverse($chartData['line']); $this->view->begin = helper::safe64Encode(urlencode($begin)); $this->view->end = helper::safe64Encode(urlencode($end)); diff --git a/module/execution/css/view.css b/module/execution/css/view.css index 71b4b621c2..50fb65983c 100644 --- a/module/execution/css/view.css +++ b/module/execution/css/view.css @@ -21,3 +21,6 @@ .timeline .timeline-text {display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;} #cfdChart {margin-top: -20px;} + +#triggerModal .modal-dialog {top: 15% !important; overflow-y: auto; max-height: 80%;} +#triggerModal .modal-dialog::-webkit-scrollbar-track {background-color: white;} diff --git a/module/execution/view/view.html.php b/module/execution/view/view.html.php index 0b799c90de..938dcafd6b 100644 --- a/module/execution/view/view.html.php +++ b/module/execution/view/view.html.php @@ -269,8 +269,10 @@

    deleted):?> execution->deleted;?> - + + lifetime)):?> execution->lifeTimeList, $execution->lifetime);?> + delay)):?> execution->delayed;?> diff --git a/module/gitea/model.php b/module/gitea/model.php index 1b52f42608..5ee5469e49 100644 --- a/module/gitea/model.php +++ b/module/gitea/model.php @@ -600,4 +600,36 @@ class giteaModel extends model return $newBranches; } + + /** + * Check remote url. + * + * @param int $giteaID + * @param string $project + * @param string $client + * @param string $path + * @access public + * @return bool + */ + public function checkRemoteUrl($giteaID, $project, $client, $path) + { + if(chdir($path)) + { + $url = new stdclass(); + $remote = execCmd(escapeCmd("$client remote -v"), 'array'); + $pregHttp = '/http(s)?:\/\/(www\.)?[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+(:\d+)*(\/\w+)*\.git/'; + $pregSSH = '/ssh:\/\/git@[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+(:\d+)*(\/\w+)*\.git/'; + + if(preg_match($pregHttp, $remote[0], $matches)) $url->http = $matches[0]; + if(preg_match($pregSSH, $remote[0], $matches)) $url->ssh = $matches[0]; + + $project = $this->apiGetSingleProject($giteaID, $project); + if(isset($project->clone_url)) + { + if($project->clone_url == $url->http or $project->ssh_url == $url->ssh) return true; + } + } + + return false; + } } diff --git a/module/mr/control.php b/module/mr/control.php index 7fe28b3372..85e6294589 100644 --- a/module/mr/control.php +++ b/module/mr/control.php @@ -976,7 +976,7 @@ class mr extends control public function ajaxGetRepoList($hostID, $projectID) { $host = $this->loadModel('pipeline')->getByID($hostID); - if($host->type != 'gitlab') $projectID =urldecode(base64_decode($projectID)); + if($host->type != 'gitlab') $projectID = urldecode(base64_decode($projectID)); $repoList = $this->loadModel('repo')->getRepoListByClient($hostID, $projectID); diff --git a/module/mr/css/browse.css b/module/mr/css/browse.css index 37c751af56..2178adff41 100644 --- a/module/mr/css/browse.css +++ b/module/mr/css/browse.css @@ -15,6 +15,6 @@ .c-id {width: 60px;} .c-title {min-width: 120px;} .c-branch {width: 240px;} -.c-status {width: 100px;} +.c-status {width: 120px;} .c-author {width: 100px;} .c-date {width: 140px;} diff --git a/module/mr/model.php b/module/mr/model.php index 66d7129e2c..e85a33f5a6 100644 --- a/module/mr/model.php +++ b/module/mr/model.php @@ -400,6 +400,8 @@ class mrModel extends model $MR = $this->getByID($MRID); $this->linkObjects($MR); + $this->loadModel('action')->create('mr', $MRID, 'edited'); + if(dao::isError()) return array('result' => 'fail', 'message' => dao::getError()); return array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => helper::createLink('mr', 'browse')); } @@ -1018,13 +1020,9 @@ class mrModel extends model $host = $this->loadModel('pipeline')->getByID($MR->hostID); $scm = $host->type; - $this->loadModel('repo'); - $repo = new stdclass; - $repo->SCM = $this->lang->repo->scmList[ucfirst($scm)]; + $repo = $this->loadModel('repo')->getRepoByID($MR->repoID); $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; @@ -1865,7 +1863,7 @@ class mrModel extends model */ public function logMergedAction($MR) { - $this->loadModel('action'); + $this->loadModel('action')->create('mr', $MR->id, 'merged'); $product = $this->getMRProduct($MR); $stories = $this->getLinkList($MR->id, $product->id, 'story'); diff --git a/module/my/control.php b/module/my/control.php index f9b16e7c7a..95a2e02f76 100755 --- a/module/my/control.php +++ b/module/my/control.php @@ -895,7 +895,7 @@ EOF; * @param int $pageID * @return void */ - public function risk($type = 'assignedTo', $param = 0,$orderBy = 'id_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1) + public function risk($type = 'assignedTo', $param = 0, $orderBy = 'id_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1) { /* Set the pager. */ $this->loadModel('risk'); @@ -993,7 +993,7 @@ EOF; * @access public * @return void */ - public function nc($browseType = 'assignedToMe', $orderBy = 'id_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1) + public function nc($browseType = 'assignedToMe', $param = 0, $orderBy = 'id_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1) { $this->loadModel('nc'); $this->session->set('ncList', $this->app->getURI(true)); @@ -1015,6 +1015,7 @@ EOF; $this->view->projects = $this->loadModel('project')->getPairsByProgram(); $this->view->pager = $pager; $this->view->orderBy = $orderBy; + $this->view->param = $param; $this->view->mode = 'nc'; $this->display(); } diff --git a/module/my/model.php b/module/my/model.php index efd54ce73d..5986ff02ec 100644 --- a/module/my/model.php +++ b/module/my/model.php @@ -334,21 +334,52 @@ class myModel extends model ->fetchAll('objectID'); if(empty($objectIDList)) return array(); - $objectList = $this->dao->select('*')->from($this->config->objectTables[$module]) - ->where('deleted')->eq(0) - ->andWhere('id')->in(array_keys($objectIDList)) - ->beginIF($objectType == 'requirement' or $objectType == 'story')->andWhere('type')->eq($objectType)->fi() - ->orderBy($orderBy) - ->page($pager) - ->fetchAll('id'); + if($objectType == 'task') + { + $objectList = $this->dao->select('t1.*, t2.name as executionName')->from($this->config->objectTables[$module])->alias('t1') + ->leftJoin(TABLE_EXECUTION)->alias('t2')->on("t1.execution = t2.id") + ->where('t1.deleted')->eq(0) + ->andWhere('t2.deleted')->eq(0) + ->andWhere('t1.id')->in(array_keys($objectIDList)) + ->orderBy('t1.' . $orderBy) + ->page($pager) + ->fetchAll('id'); + } + elseif($objectType == 'requirement' or $objectType == 'story' or $objectType == 'bug') + { + $objectList = $this->dao->select('t1.*')->from($this->config->objectTables[$module])->alias('t1') + ->leftJoin(TABLE_PRODUCT)->alias('t2')->on("t1.product = t2.id") + ->where('t1.deleted')->eq(0) + ->andWhere('t2.deleted')->eq(0) + ->andWhere('t1.id')->in(array_keys($objectIDList)) + ->beginIF($objectType == 'requirement' or $objectType == 'story')->andWhere('t1.type')->eq($objectType)->fi() + ->orderBy('t1.' . $orderBy) + ->page($pager) + ->fetchAll('id'); + } + elseif($objectType == 'risk' or $objectType == 'issue' or $objectType == 'nc') + { + $objectList = $this->dao->select('t1.*')->from($this->config->objectTables[$module])->alias('t1') + ->leftJoin(TABLE_PROJECT)->alias('t2')->on("t1.project = t2.id") + ->where('t1.deleted')->eq(0) + ->andWhere('t2.deleted')->eq(0) + ->andWhere('t1.id')->in(array_keys($objectIDList)) + ->orderBy('t1.' . $orderBy) + ->page($pager) + ->fetchAll('id'); + } + else + { + $objectList = $this->dao->select('*')->from($this->config->objectTables[$module]) + ->where('deleted')->eq(0) + ->andWhere('id')->in(array_keys($objectIDList)) + ->orderBy($orderBy) + ->page($pager) + ->fetchAll('id'); + } if($objectType == 'task') { - $executionList = array(); - foreach($objectList as $task) $executionList[$task->execution] = $task->execution; - $objectPairs = $this->dao->select('id,name')->from(TABLE_PROJECT)->where('id')->in($executionList)->fetchPairs('id'); - foreach($objectList as $task) $task->executionName = zget($objectPairs, $task->execution, ''); - if($objectList) return $this->loadModel('task')->processTasks($objectList); return $objectList; } diff --git a/module/program/model.php b/module/program/model.php index abc9048db0..47b702d040 100644 --- a/module/program/model.php +++ b/module/program/model.php @@ -562,7 +562,7 @@ class programModel extends model } else { - if($this->session->projectQuery == false) $this->session->set('projectQuery', ' 1 = 1'); + if($browseType == 'bySearch' and $this->session->projectQuery == false) $this->session->set('projectQuery', ' 1 = 1'); } $query = str_replace('`id`','t1.id', $this->session->projectQuery); diff --git a/module/project/config.php b/module/project/config.php index 32bf6a8d8f..c90e9b5f05 100644 --- a/module/project/config.php +++ b/module/project/config.php @@ -184,9 +184,3 @@ $config->project->includedPriv['repo'] = array('create', 'showSyncCommit', $config->project->includedPriv['testreport'] = array('create', 'view', 'delete', 'edit', 'export'); $config->project->includedPriv['auditplan'] = array('browse', 'create', 'edit', 'batchCreate', 'batchCheck', 'check', 'nc', 'result', 'assignTo'); if($config->edition != 'max') $config->project->includedPriv['stakeholder'] = array('browse', 'create', 'batchCreate', 'edit', 'delete', 'view', 'communicate', 'expect', 'expectation', 'deleteExpect', 'createExpect', 'editExpect', 'viewExpect'); -$config->project->unsetWhitelist['view'] = 'project'; -$config->project->unsetWhitelist['manageproducts'] = 'project'; -$config->project->unsetWhitelist['team'] = 'project'; -$config->project->unsetWhitelist['browse'] = 'stakeholder'; -$config->project->unsetWhitelist['group'] = 'project'; -$config->project->unsetWhitelist['approval'] = 'project'; diff --git a/module/project/control.php b/module/project/control.php index 2863a233cd..bbcfb82415 100644 --- a/module/project/control.php +++ b/module/project/control.php @@ -1856,7 +1856,7 @@ class project extends control $this->user->updateUserView($projectID, 'project'); /* Delete the execution under the project. */ - $executionIdList = $this->loadModel('execution')->getByProject($projectID); + $executionIdList = $this->loadModel('execution')->getPairs($projectID); $message = $this->executeHooks($projectID); if($message) $this->lang->saveSuccess = $message; diff --git a/module/project/model.php b/module/project/model.php index 3e815f6808..5985ba0aad 100644 --- a/module/project/model.php +++ b/module/project/model.php @@ -2631,10 +2631,8 @@ class projectModel extends model $this->saveState($objectID, $this->getPairsByProgram()); $project = $this->getById($objectID); - if(isset($project->acl) and $project->acl == 'open' and isset($this->config->project->unsetWhitelist[$methodName]) and $this->config->project->unsetWhitelist[$methodName] == $moduleName) - { - unset($this->lang->project->menu->settings['subMenu']->whitelist); - } + + if(isset($project->acl) and $project->acl == 'open') unset($this->lang->project->menu->settings['subMenu']->whitelist); common::setMenuVars('project', $objectID); return $objectID; diff --git a/module/project/view/browsebycard.html.php b/module/project/view/browsebycard.html.php index 71385af60b..0cd1d727d8 100644 --- a/module/project/view/browsebycard.html.php +++ b/module/project/view/browsebycard.html.php @@ -74,7 +74,7 @@

    " . $lang->export, '', "class='btn btn-link export'")?> - ' . $lang->project->create, '', 'class="btn btn-primary create-project-btn" data-toggle="modal" data-target="#guideDialog"');?> + ' . $lang->project->create, '', 'class="btn btn-primary create-project-btn" data-toggle="modal"');?> ' . $lang->project->create, '', 'class="btn btn-primary create-project-btn"');?> @@ -88,7 +88,7 @@

    project->empty;?> - ' . $lang->project->create, '', 'class="btn btn-info" data-toggle="modal" data-target="#guideDialog"');?> + ' . $lang->project->create, '', 'class="btn btn-info" data-toggle="modal"');?> ' . $lang->execution->create, '', 'class="btn btn-info"');?> diff --git a/module/repo/js/create.js b/module/repo/js/create.js index d6db74f6e3..1c2d0a00f2 100644 --- a/module/repo/js/create.js +++ b/module/repo/js/create.js @@ -54,7 +54,7 @@ $(function() */ function scmChanged(scm) { - if(scm == 'Git') + if(scm == 'Git' || scm == 'Gitea') { $('.account-fields').addClass('hidden'); @@ -77,7 +77,14 @@ function scmChanged(scm) else { $('tr.service').toggle(true); - $('tr.hide-service').toggle(false); + if(scm == 'Gitea') + { + $('tr.hide-service').toggle(true); + } + else + { + $('tr.hide-service').toggle(false); + } var url = createLink('repo', 'ajaxGetHosts', "scm=" + scm); $.get(url, function(response) diff --git a/module/repo/js/edit.js b/module/repo/js/edit.js index 229f4907ab..6f8167d17c 100644 --- a/module/repo/js/edit.js +++ b/module/repo/js/edit.js @@ -38,7 +38,7 @@ $(function() */ function scmChanged(scm, isFirstRequest = false) { - if(scm == 'Git') + if(scm == 'Git' || scm == 'Gitea') { $('.account-fields').addClass('hidden'); @@ -61,7 +61,14 @@ function scmChanged(scm, isFirstRequest = false) else { $('tr.service').toggle(true); - $('tr.hide-service').toggle(false); + if(scm == 'Gitea') + { + $('tr.hide-service').toggle(true); + } + else + { + $('tr.hide-service').toggle(false); + } if(!isFirstRequest) { diff --git a/module/repo/lang/de.php b/module/repo/lang/de.php index cffe5ebcfd..4f5484b589 100644 --- a/module/repo/lang/de.php +++ b/module/repo/lang/de.php @@ -199,6 +199,7 @@ $lang->repo->error->linkedJob = "Deletion of the repository failed. The curr $lang->repo->error->clientPath = "The client installation directory cannot have spaces!"; $lang->repo->error->notFound = "The repository %s’s URL %s does not exist. Please confirm if this repository has been deleted from the local server."; $lang->repo->error->noWritable = '%s is not writable! Please check the privilege, or download will not be done.'; +$lang->repo->error->unconnected = 'The directory does not match the repository'; $lang->repo->syncTips = 'You may find the reference about how to set Git sync from here.'; $lang->repo->encodingsTips = "The encodings of comments can be comma separated values, e.g. utf-8."; diff --git a/module/repo/lang/en.php b/module/repo/lang/en.php index 725f3d2263..a29be6e3c7 100644 --- a/module/repo/lang/en.php +++ b/module/repo/lang/en.php @@ -199,6 +199,7 @@ $lang->repo->error->linkedJob = "Deletion of the repository failed. The curr $lang->repo->error->clientPath = "The client installation directory cannot have spaces!"; $lang->repo->error->notFound = "The repository %s’s URL %s does not exist. Please confirm if this repository has been deleted from the local server."; $lang->repo->error->noWritable = '%s is not writable! Please check the privilege, or download will not be done.'; +$lang->repo->error->unconnected = 'The directory does not match the repository'; $lang->repo->syncTips = 'You may find the reference about how to set Git sync from here.'; $lang->repo->encodingsTips = "The encodings of comments can be comma separated values, e.g. utf-8."; diff --git a/module/repo/lang/fr.php b/module/repo/lang/fr.php index 22661b03db..5e77a34092 100644 --- a/module/repo/lang/fr.php +++ b/module/repo/lang/fr.php @@ -199,6 +199,7 @@ $lang->repo->error->linkedJob = "Deletion of the repository failed. The curr $lang->repo->error->clientPath = "The client installation directory cannot have spaces!"; $lang->repo->error->notFound = "The repository %s’s URL %s does not exist. Please confirm if this repository has been deleted from the local server."; $lang->repo->error->noWritable = '%s is not writable! Please check the privilege, or download will not be done.'; +$lang->repo->error->unconnected = 'The directory does not match the repository'; $lang->repo->syncTips = 'Vous pouvez trouver la référence sur la façon de définir la synchronisation Git à partir de la page se trouvant ici.'; $lang->repo->encodingsTips = "Les encodages des commentaires de validation peuvent être des valeurs séparées par des virgules,ex: utf-8"; diff --git a/module/repo/lang/vi.php b/module/repo/lang/vi.php index e84f6866e6..92d29cc587 100644 --- a/module/repo/lang/vi.php +++ b/module/repo/lang/vi.php @@ -57,48 +57,52 @@ $lang->repo->line = 'Dòng'; $lang->repo->expand = 'Mở ra'; $lang->repo->collapse = 'Gấp lại'; -$lang->repo->id = 'ID'; -$lang->repo->SCM = 'Loại'; -$lang->repo->name = 'Tên'; -$lang->repo->path = 'Đường dẫn'; -$lang->repo->prefix = 'Prefix'; -$lang->repo->config = 'Cấu hình'; -$lang->repo->desc = 'Mô tả'; -$lang->repo->account = 'Người dùng'; -$lang->repo->password = 'Mật khẩu'; -$lang->repo->encoding = 'Encoding'; -$lang->repo->client = 'Client Path'; -$lang->repo->size = 'Size'; -$lang->repo->revision = 'Revision'; -$lang->repo->revisionA = 'Revision'; -$lang->repo->revisions = 'Revision'; -$lang->repo->time = 'Ngày'; -$lang->repo->committer = 'Committer'; -$lang->repo->commits = 'Commits'; -$lang->repo->synced = 'Khởi tạo đồng bộ'; -$lang->repo->lastSync = 'Last Sync'; -$lang->repo->deleted = 'Đã xóa'; -$lang->repo->commit = 'Giao phó'; -$lang->repo->comment = 'Nhận xét'; -$lang->repo->view = 'Xem File'; -$lang->repo->viewA = 'Xem'; -$lang->repo->log = 'Revision nhật ký'; -$lang->repo->blame = 'Blame'; -$lang->repo->date = 'Ngày'; -$lang->repo->diff = 'Diff'; -$lang->repo->diffAB = 'Diff'; -$lang->repo->diffAll = 'Diff tất cả'; -$lang->repo->viewDiff = 'Xem diff'; -$lang->repo->allLog = 'Tất cả Revisions'; -$lang->repo->location = 'Vị trí'; -$lang->repo->file = 'File'; -$lang->repo->action = 'Hành động'; -$lang->repo->code = 'Mã'; -$lang->repo->review = 'Repo duyệt'; -$lang->repo->acl = 'Phân quyền'; -$lang->repo->group = 'Nhóm'; -$lang->repo->user = 'Người dùng'; -$lang->repo->info = 'Thông tin phiên bản'; +$lang->repo->id = 'ID'; +$lang->repo->SCM = 'Loại'; +$lang->repo->name = 'Tên'; +$lang->repo->path = 'Đường dẫn'; +$lang->repo->prefix = 'Prefix'; +$lang->repo->config = 'Cấu hình'; +$lang->repo->desc = 'Mô tả'; +$lang->repo->account = 'Người dùng'; +$lang->repo->password = 'Mật khẩu'; +$lang->repo->encoding = 'Encoding'; +$lang->repo->client = 'Client Path'; +$lang->repo->size = 'Size'; +$lang->repo->revision = 'Revision'; +$lang->repo->revisionA = 'Revision'; +$lang->repo->revisions = 'Revision'; +$lang->repo->time = 'Ngày'; +$lang->repo->committer = 'Committer'; +$lang->repo->commits = 'Commits'; +$lang->repo->synced = 'Khởi tạo đồng bộ'; +$lang->repo->lastSync = 'Last Sync'; +$lang->repo->deleted = 'Đã xóa'; +$lang->repo->commit = 'Giao phó'; +$lang->repo->comment = 'Nhận xét'; +$lang->repo->view = 'Xem File'; +$lang->repo->viewA = 'Xem'; +$lang->repo->log = 'Revision nhật ký'; +$lang->repo->blame = 'Blame'; +$lang->repo->date = 'Ngày'; +$lang->repo->diff = 'Diff'; +$lang->repo->diffAB = 'Diff'; +$lang->repo->diffAll = 'Diff tất cả'; +$lang->repo->viewDiff = 'Xem diff'; +$lang->repo->allLog = 'Tất cả Revisions'; +$lang->repo->location = 'Vị trí'; +$lang->repo->file = 'File'; +$lang->repo->action = 'Hành động'; +$lang->repo->code = 'Mã'; +$lang->repo->review = 'Repo duyệt'; +$lang->repo->acl = 'Phân quyền'; +$lang->repo->group = 'Nhóm'; +$lang->repo->user = 'Người dùng'; +$lang->repo->info = 'Thông tin phiên bản'; +$lang->repo->job = 'Job'; +$lang->repo->fileServerUrl = 'File Server Url'; +$lang->repo->fileServerAccount = 'File Server Account'; +$lang->repo->fileServerPassword = 'File Server Password'; $lang->repo->title = 'Tiêu đề'; $lang->repo->status = 'Tình trạng'; @@ -149,6 +153,9 @@ $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'; + $lang->repo->notice = new stdclass(); $lang->repo->notice->syncing = 'Đang đồng bộ. Vui lòng đợi ...'; $lang->repo->notice->syncComplete = 'Synchronized. Now redirecting ...'; @@ -156,6 +163,7 @@ $lang->repo->notice->syncedCount = 'The number of records synchronized is '; $lang->repo->notice->delete = 'Bạn có muốn xóa this repo?'; $lang->repo->notice->successDelete = 'Repository is removed.'; $lang->repo->notice->commentContent = 'Nhận xét'; +$lang->repo->notice->deleteReview = 'Do you want to delete this review?'; $lang->repo->notice->deleteBug = 'Bạn có muốn xóa bug này?'; $lang->repo->notice->deleteComment = 'Bạn có muốn xóa this comment?'; $lang->repo->notice->lastSyncTime = 'Last Sync:'; @@ -187,11 +195,15 @@ $lang->repo->error->output = "The command is: %s\nThe error is(%s): %s\n" $lang->repo->error->clientVersion = "Client version is too low, please upgrade or change SVN client"; $lang->repo->error->encoding = "The encoding maybe wrong. Vui lòng change the encoding and try again."; $lang->repo->error->deleted = "Deletion of the repository failed. The current repository has a commit record associated with the design."; +$lang->repo->error->linkedJob = "Deletion of the repository failed. The current repository has associated with the Compile."; $lang->repo->error->clientPath = "The client installation directory cannot have spaces!"; +$lang->repo->error->notFound = "The repository %s’s URL %s does not exist. Please confirm if this repository has been deleted from the local server."; $lang->repo->error->noWritable = '%s is not writable! Please check the privilege, or download will not be done.'; +$lang->repo->error->unconnected = 'The directory does not match the repository'; -$lang->repo->syncTips = 'Bạn có thể tìm tham khảo làm sao thiết lập đồng bộ Git từ here.'; -$lang->repo->encodingsTips = "The encodings of commit comments, can be comma separated values,ví dụ: utf-8"; +$lang->repo->syncTips = 'Bạn có thể tìm tham khảo làm sao thiết lập đồng bộ Git từ here.'; +$lang->repo->encodingsTips = "The encodings of commit comments, can be comma separated values,ví dụ: utf-8"; +$lang->repo->pathTipsForGitlab = "GitLab Project URL"; $lang->repo->example = new stdclass(); $lang->repo->example->client = new stdclass(); diff --git a/module/repo/lang/zh-cn.php b/module/repo/lang/zh-cn.php index d9c12cd196..d3fa3981e7 100644 --- a/module/repo/lang/zh-cn.php +++ b/module/repo/lang/zh-cn.php @@ -199,6 +199,7 @@ $lang->repo->error->linkedJob = "删除代码库失败,当前代码库与 $lang->repo->error->clientPath = "客户端安装目录不能有空格!"; $lang->repo->error->notFound = "代码库『%s』路径 %s 不存在,请确认此代码库是否已在本地服务器被删除"; $lang->repo->error->noWritable = '%s 不可写!请检查该目录权限,否则无法下载。'; +$lang->repo->error->unconnected = '目录地址与仓库不匹配'; $lang->repo->syncTips = '请参照这里,设置代码库定时同步。'; $lang->repo->encodingsTips = "提交日志的编码,可以用逗号连接起来的多个,比如utf-8。"; diff --git a/module/repo/model.php b/module/repo/model.php index c5ff290a53..c0266a4bb2 100644 --- a/module/repo/model.php +++ b/module/repo/model.php @@ -122,7 +122,8 @@ class repoModel extends model $productIdList = $this->loadModel('product')->getProductIDByProject($projectID, false); foreach($repos as $i => $repo) { - $repo->acl = json_decode($repo->acl); + $repo->acl = json_decode($repo->acl); + $repo->codePath = $repo->path; if(!$this->checkPriv($repo)) { unset($repos[$i]); @@ -166,7 +167,8 @@ class repoModel extends model foreach($repos as $i => $repo) { if($repo->encrypt == 'base64') $repo->password = base64_decode($repo->password); - $repo->acl = json_decode($repo->acl); + $repo->acl = json_decode($repo->acl); + $repo->codePath = $repo->path; if($type == 'haspriv' and !$this->checkPriv($repo)) unset($repos[$i]); if(in_array(strtolower($repo->SCM), $this->config->repo->gitServiceList)) $repo = $this->processGitService($repo); } @@ -195,8 +197,8 @@ class repoModel extends model $data = fixer::input('post') ->setIf($isPipelineServer, 'password', $this->post->serviceToken) - ->setIf($isPipelineServer, 'path', $this->post->serviceProject) - ->setIf($isPipelineServer, 'client', $this->post->serviceHost) + ->setIf($isPipelineServer and $this->post->SCM == 'Gitlab', 'path', '') + ->setIf($isPipelineServer and $this->post->SCM == 'Gitlab', 'client', '') ->setIf($isPipelineServer, 'extra', $this->post->serviceProject) ->setIf($isPipelineServer, 'prefix', '') ->setIf($this->post->SCM == 'Git', 'account', '') @@ -206,12 +208,12 @@ class repoModel extends model ->join('product', ',') ->get(); - if(in_array(strtolower($this->post->SCM), $this->config->repo->gitServiceList)) + if($isPipelineServer) { $repo = $this->dao->select('id')->from(TABLE_REPO) ->where('SCM')->eq($this->post->SCM) - ->andWhere('client')->eq($data->client) - ->andWhere('path')->eq($data->path) + ->andWhere('serviceHost')->eq($data->client) + ->andWhere('serviceProject')->eq($data->path) ->fetch(); if(!empty($repo)) dao::$errors['serviceProject'] = sprintf($this->lang->error->unique, $this->lang->repo->serviceProject, $repo->name); if(dao::isError()) return false; @@ -219,6 +221,15 @@ class repoModel extends model $data->acl = empty($data->acl) ? '' : json_encode($data->acl); + if($data->SCM == 'Gitea') + { + $relation = $this->loadModel('gitea')->checkRemoteUrl($data->serviceHost, $data->serviceProject, $data->client, $data->path); + if(!$relation) + { + dao::$errors['path'] = $this->lang->repo->error->unconnected; + return false; + } + } if($data->SCM == 'Subversion') { $scm = $this->app->loadClass('scm'); @@ -230,10 +241,11 @@ class repoModel extends model } if($data->encrypt == 'base64') $data->password = base64_encode($data->password); - $this->dao->insert(TABLE_REPO)->data($data, $skip = 'serviceHost,serviceToken,serviceProject') + $this->dao->insert(TABLE_REPO)->data($data, $skip = 'serviceToken') ->batchCheck($this->config->repo->create->requiredFields, 'notempty') - ->checkIF($isPipelineServer, 'serviceProject', 'notempty') + ->checkIF($isPipelineServer, 'serviceHost,serviceProject', 'notempty') ->checkIF($data->SCM == 'Subversion', $this->config->repo->svn->requiredFields, 'notempty') + ->checkIF($data->SCM == 'Gitea', $this->config->repo->gitea->requiredFields, 'notempty') ->checkIF($data->SCM == 'Git', 'path', 'unique', "`SCM` = 'Git'") ->checkIF($data->SCM == 'Subversion', 'path', 'unique', "`SCM` = 'Subversion'") ->autoCheck() @@ -275,8 +287,8 @@ class repoModel extends model $data = fixer::input('post') ->setIf($isPipelineServer, 'password', $this->post->serviceToken) - ->setIf($isPipelineServer, 'path', $this->post->serviceProject) - ->setIf($isPipelineServer, 'client', $this->post->serviceHost) + ->setIf($isPipelineServer and $this->post->SCM == 'Gitlab', 'path', '') + ->setIf($isPipelineServer and $this->post->SCM == 'Gitlab', 'client', '') ->setIf($isPipelineServer, 'extra', $this->post->serviceProject) ->setDefault('prefix', $repo->prefix) ->setIf($this->post->SCM == 'Gitlab', 'prefix', '') @@ -304,12 +316,12 @@ class repoModel extends model $data->prefix = ''; } - if(in_array(strtolower($this->post->SCM), $this->config->repo->gitServiceList)) + if($isPipelineServer) { $repo = $this->dao->select('id')->from(TABLE_REPO) ->where('SCM')->eq($this->post->SCM) - ->andWhere('client')->eq($data->client) - ->andWhere('path')->eq($data->path) + ->andWhere('serviceHost')->eq($data->client) + ->andWhere('serviceProject')->eq($data->path) ->andWhere('id')->ne($id) ->fetch(); if(!empty($repo)) dao::$errors['serviceProject'] = sprintf($this->lang->error->unique, $this->lang->repo->serviceProject, $repo->name); @@ -320,7 +332,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 = 'serviceHost,serviceToken,serviceProject') + $this->dao->update(TABLE_REPO)->data($data, $skip = 'serviceToken') ->batchCheck($this->config->repo->edit->requiredFields, 'notempty') ->checkIF($data->SCM == 'Subversion', $this->config->repo->svn->requiredFields, 'notempty') ->checkIF($data->SCM == 'Gitlab', 'extra', 'notempty') @@ -463,6 +475,7 @@ class repoModel extends model if(!$repo) return false; if($repo->encrypt == 'base64') $repo->password = base64_decode($repo->password); + $repo->codePath = $repo->path; if(in_array(strtolower($repo->SCM), $this->config->repo->gitServiceList)) $repo = $this->processGitService($repo); $repo->acl = json_decode($repo->acl); return $repo; @@ -1285,7 +1298,7 @@ class repoModel extends model */ public function checkClient() { - if(in_array(strtolower($this->post->SCM), $this->config->repo->gitServiceList)) return true; + if($this->post->SCM == 'Gitlab') return true; if(!$this->config->features->checkClient) return true; if(!$this->post->client) @@ -1409,7 +1422,7 @@ class repoModel extends model return false; } } - elseif($scm == 'Git') + elseif(in_array($scm, array('Git', 'Gitea'))) { if(!is_dir($path)) { @@ -2035,13 +2048,22 @@ class repoModel extends model */ public function processGitService($repo) { - $service = $this->loadModel('pipeline')->getByID($repo->client); + $service = $this->loadModel('pipeline')->getByID($repo->serviceHost); + if($repo->SCM == 'Gitlab') + { + $project = $this->loadModel('gitlab')->apiGetSingleProject($repo->serviceHost, $repo->serviceProject); - $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 : ''; + $repo->path = $service ? sprintf($this->config->repo->{$service->type}->apiPath, $service->url, $repo->serviceProject) : ''; + $repo->client = $service ? $service->url : ''; + $repo->password = $service ? $service->token : ''; + $repo->codePath = $project ? $project->web_url : $repo->path; + } + elseif($repo->SCM == 'Gitea') + { + $repo->codePath = $service ? "{$service->url}/{$repo->serviceProject}" : $repo->path; + } + $repo->gitService = $repo->serviceHost; + $repo->project = $repo->serviceProject; return $repo; } @@ -2056,8 +2078,8 @@ class repoModel extends model { return $this->dao->select('*')->from(TABLE_REPO)->where('deleted')->eq('0') ->andWhere('synced')->eq(1) - ->andWhere('client')->eq($gitlabID) - ->beginIF($projectID)->andWhere('path')->eq($projectID)->fi() + ->andWhere('serviceHost')->eq($gitlabID) + ->beginIF($projectID)->andWhere('serviceProject')->eq($projectID)->fi() ->fetchAll(); } diff --git a/module/repo/view/ajaxsidecommits.html.php b/module/repo/view/ajaxsidecommits.html.php index a78b02425a..27102e03ee 100644 --- a/module/repo/view/ajaxsidecommits.html.php +++ b/module/repo/view/ajaxsidecommits.html.php @@ -19,9 +19,7 @@ if(isset($entry)) $pathInfo .= '&type=file'; - SCM != 'Gitea'):?> - SCM != 'Subversion'):?> @@ -34,14 +32,12 @@ if(isset($entry)) $pathInfo .= '&type=file'; - SCM != 'Gitea'):?> - SCM != 'Subversion'):?> @@ -54,7 +50,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?>