diff --git a/module/group/lang/resource.php b/module/group/lang/resource.php index e5046d4280..e34fe1783b 100644 --- a/module/group/lang/resource.php +++ b/module/group/lang/resource.php @@ -1401,6 +1401,7 @@ $lang->resource->sonarqube->create = 'create'; $lang->resource->sonarqube->edit = 'edit'; $lang->resource->sonarqube->delete = 'delete'; $lang->resource->sonarqube->browseProject = 'browseProject'; +$lang->resource->sonarqube->createProject = 'createProject'; $lang->resource->sonarqube->deleteProject = 'deleteProject'; $lang->resource->sonarqube->execJob = 'execJob'; $lang->resource->sonarqube->reportView = 'reportView'; @@ -1411,6 +1412,7 @@ $lang->sonarqube->methodOrder[10] = 'create'; $lang->sonarqube->methodOrder[15] = 'edit'; $lang->sonarqube->methodOrder[20] = 'delete'; $lang->sonarqube->methodOrder[25] = 'browseProject'; +$lang->sonarqube->methodOrder[30] = 'createProject'; $lang->sonarqube->methodOrder[35] = 'deleteProject'; $lang->sonarqube->methodOrder[40] = 'execJob'; $lang->sonarqube->methodOrder[45] = 'reportView'; diff --git a/module/sonarqube/config.php b/module/sonarqube/config.php index c19e3cfd41..a601183ac7 100644 --- a/module/sonarqube/config.php +++ b/module/sonarqube/config.php @@ -11,3 +11,6 @@ $config->sonarqube->projectStatusClass = array(); $config->sonarqube->projectStatusClass['OK'] = 'success'; $config->sonarqube->projectStatusClass['WARN'] = 'warning'; $config->sonarqube->projectStatusClass['ERROR'] = 'danger'; + +$config->sonarqube->createproject = new stdclass(); +$config->sonarqube->createproject->requiredFields = 'projectName,projectKey'; diff --git a/module/sonarqube/control.php b/module/sonarqube/control.php index b024f27a2e..43561dc0a7 100644 --- a/module/sonarqube/control.php +++ b/module/sonarqube/control.php @@ -286,6 +286,28 @@ class sonarqube extends control $this->display(); } + /** + * Creat a sonarqube project. + * + * @param int $sonarqubeID + * @access public + * @return void + */ + public function createProject($sonarqubeID) + { + if($_POST) + { + $this->sonarqube->createProject($sonarqubeID); + + if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError())); + return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => inlink('browseProject', "sonarqubeID=$sonarqubeID"))); + } + + $this->view->title = $this->lang->sonarqube->common . $this->lang->colon . $this->lang->sonarqube->createProject; + $this->view->sonarqubeID = $sonarqubeID; + $this->display(); + } + /** * Delete project. * diff --git a/module/sonarqube/lang/en.php b/module/sonarqube/lang/en.php index a7d3a58573..d6cf51680a 100644 --- a/module/sonarqube/lang/en.php +++ b/module/sonarqube/lang/en.php @@ -30,9 +30,11 @@ $lang->sonarqube->editServer = 'Edit SonarQube Server'; $lang->sonarqube->createSuccess = 'Create success'; $lang->sonarqube->placeholder = new stdclass; -$lang->sonarqube->placeholder->name = ''; -$lang->sonarqube->placeholder->url = "Please fill in the access address of the SonarQube Server homepage, as: https://sonarqube.zentao.net."; -$lang->sonarqube->placeholder->account = "Please fill in the SonarQube user information with Administrator privileges"; +$lang->sonarqube->placeholder->name = ''; +$lang->sonarqube->placeholder->url = "Please fill in the access address of the SonarQube Server homepage, as: https://sonarqube.zentao.net."; +$lang->sonarqube->placeholder->account = "Please fill in the SonarQube user information with Administrator privileges"; +$lang->sonarqube->placeholder->projectName = 'Up to 255 characters.'; +$lang->sonarqube->placeholder->projectKey = "It may contain up to 400 characters. Allowed characters are alphanumeric, '-' (dash), '_' (underscore), '.' (period) and ':' (colon), with at least one non-digit."; $lang->sonarqube->nameRepeatError = "Server name already exists!"; $lang->sonarqube->urlRepeatError = 'Server address already exists!'; diff --git a/module/sonarqube/lang/zh-cn.php b/module/sonarqube/lang/zh-cn.php index e75af4d1d7..ece4a058e4 100644 --- a/module/sonarqube/lang/zh-cn.php +++ b/module/sonarqube/lang/zh-cn.php @@ -30,9 +30,11 @@ $lang->sonarqube->editServer = '修改SonarQube服务器'; $lang->sonarqube->createSuccess = "创建成功"; $lang->sonarqube->placeholder = new stdclass; -$lang->sonarqube->placeholder->name = ''; -$lang->sonarqube->placeholder->url = "请填写SonarQube Server首页的访问地址,如:https://sonarqube.zentao.net。"; -$lang->sonarqube->placeholder->account = "请填写具有Administrator权限的SonarQube用户信息"; +$lang->sonarqube->placeholder->name = ''; +$lang->sonarqube->placeholder->url = "请填写SonarQube Server首页的访问地址,如:https://sonarqube.zentao.net。"; +$lang->sonarqube->placeholder->account = "请填写具有Administrator权限的SonarQube用户信息"; +$lang->sonarqube->placeholder->projectName = '最多255个字符'; +$lang->sonarqube->placeholder->projectKey = "最多400个字符。 允许的字符为字母数字,'-','_','. '和':',至少有一个非数字"; $lang->sonarqube->nameRepeatError = "服务器名称已存在!"; $lang->sonarqube->urlRepeatError = "服务器地址已存在!"; @@ -60,3 +62,7 @@ $lang->sonarqube->qualitygateList = array(); $lang->sonarqube->qualitygateList['OK'] = 'Passed'; $lang->sonarqube->qualitygateList['WARN'] = 'Warning'; $lang->sonarqube->qualitygateList['ERROR'] = 'Failed'; + +$lang->sonarqube->apiErrorMap[1] = "/Malformed key for Project: '([\s\S]+)'. Allowed characters are alphanumeric, '-', '_', '\.' and ':', with at least one non-digit\./"; + +$lang->sonarqube->errorLang[1] = "项目'%s'的格式不正确。允许的字符为字母数字、'-'、''、'.'和“:”,至少有一个非数字。"; diff --git a/module/sonarqube/model.php b/module/sonarqube/model.php index 58a5e804eb..5ed62474a2 100644 --- a/module/sonarqube/model.php +++ b/module/sonarqube/model.php @@ -43,7 +43,7 @@ class sonarqubeModel extends model $url = rtrim($host, '/') . "/api/authentication/validate"; $header = 'Authorization: Basic ' . $token; $result = json_decode(commonModel::http($url, null, array(), $header)); - if(!isset($result->valid) or !$result->valid) return array('password' => array($this->lang->sonarqube->validError)); + if(!isset($result->valid) or !$result->valid) return array('password' => array($this->lang->sonarqube->validError)); $url = rtrim($host, '/') . "/api/user_groups/search"; $header = 'Authorization: Basic ' . $token; @@ -120,6 +120,25 @@ class sonarqubeModel extends model return $allResults; } + /** + * Create a sonarqube project by api. + * + * @param int $sonarqubeID + * @param object $project + * @access public + * @return object + */ + public function apiCreateProject($sonarqubeID, $project) + { + list($apiRoot, $header) = $this->getApiBase($sonarqubeID); + if(!$apiRoot) return false; + + $url = sprintf($apiRoot, "projects/create?name=" . urlencode($project->projectName) . "&project=" . urlencode($project->projectKey)); + $result = json_decode(commonModel::http($url, null, array(CURLOPT_CUSTOMREQUEST => 'POST'), $header)); + return $result; + } + + /** * Delete sonarqube project by api. * @@ -137,4 +156,83 @@ class sonarqubeModel extends model $result = json_decode(commonModel::http($url, null, array(CURLOPT_CUSTOMREQUEST => 'POST'), $header)); return $result; } + + /** + * Create a sonarqube project. + * + * @param int $sonarqubeID + * @access public + * @return bool + */ + public function createProject($sonarqubeID) + { + $project = fixer::input('post')->get(); + + $this->dao->insert('sonarqube')->data($project)->batchCheck($this->config->sonarqube->createproject->requiredFields, 'notempty'); + if(dao::isError()) return false; + + $response = $this->apiCreateProject($sonarqubeID, $project); + + if(!empty($response->project->key)) + { + $this->loadModel('action')->create('sonarqubeproject', 0, 'created', '', $response->project->name); + return true; + } + + return $this->apiErrorHandling($response); + } + + /** + * Api error handling. + * + * @param object $response + * @access public + * @return bool + */ + public function apiErrorHandling($response) + { + if(!empty($response->errors)) + { + foreach($response->errors as $error) + { + if(isset($error->msg)) + { + dao::$errors[] = $this->convertApiError($error->msg); + } + } + return false; + } + + if(!$response) dao::$errors[] = false; + return false; + } + + /** + * Convert API error. + * + * @param array $message + * @access public + * @return string + */ + public function convertApiError($message) + { + if(is_array($message)) $message = $message[0]; + if(!is_string($message)) return $message; + + if(!isset($this->lang->sonarqube->apiErrorMap)) return $message; + foreach($this->lang->sonarqube->apiErrorMap as $key => $errorMsg) + { + if(strpos($errorMsg, '/') === 0) + { + $result = preg_match($errorMsg, $message, $matches); + if($result) $errorMessage = sprintf(zget($this->lang->sonarqube->errorLang, $key), $matches[1]); + } + elseif($message == $errorMsg) + { + $errorMessage = zget($this->lang->mr->errorLang, $key, $message); + } + if(isset($errorMessage)) break; + } + return isset($errorMessage) ? $errorMessage : $message; + } } diff --git a/module/sonarqube/view/browseproject.html.php b/module/sonarqube/view/browseproject.html.php index 9e769f166d..7dd3cbedad 100644 --- a/module/sonarqube/view/browseproject.html.php +++ b/module/sonarqube/view/browseproject.html.php @@ -26,7 +26,7 @@ -
@@ -35,7 +35,7 @@noData;?> - createLink('sonarqube', 'createProject', "sonarqubeID=$sonarqubeID"), " " . $lang->sonarqube->createProject, '', "class='btn btn-info'");?> + createLink('sonarqube', 'createProject', "sonarqubeID=$sonarqubeID"), " " . $lang->sonarqube->createProject, '', "class='btn btn-info'");?>
diff --git a/module/sonarqube/view/createproject.html.php b/module/sonarqube/view/createproject.html.php new file mode 100644 index 0000000000..b418e2aaa9 --- /dev/null +++ b/module/sonarqube/view/createproject.html.php @@ -0,0 +1,42 @@ + + * @package sonarqube + * @version $Id$ + * @link https://www.zentao.net + */ +?> + +