306 lines
9.7 KiB
PHP
306 lines
9.7 KiB
PHP
<?php
|
|
/**
|
|
* The model file of sonarqube module of ZenTaoPMS.
|
|
*
|
|
* @copyright Copyright 2009-2022 禅道软件(青岛)有限公司(ZenTao Software (Qingdao) Co., Ltd. www.cnezsoft.com)
|
|
* @license ZPL(http://zpl.pub/page/zplv12.html) or AGPL(https://www.gnu.org/licenses/agpl-3.0.en.html)
|
|
* @author Yanyi Cao <caoyanyi@easycorp.ltd>
|
|
* @package sonarqube
|
|
* @version $Id: $
|
|
* @link http://www.zentao.net
|
|
*/
|
|
|
|
class sonarqubeModel extends model
|
|
{
|
|
/**
|
|
* Get sonarqube api base url and header by id.
|
|
*
|
|
* @param int $sonarqubeID
|
|
* @access public
|
|
* @return array
|
|
*/
|
|
public function getApiBase($sonarqubeID)
|
|
{
|
|
$sonarqube = $this->loadModel('pipeline')->getByID($sonarqubeID);
|
|
if(!$sonarqube) return array('', array());
|
|
|
|
$url = rtrim($sonarqube->url, '/') . '/api/%s';
|
|
$header[] = 'Authorization: Basic ' . $sonarqube->token;
|
|
|
|
return array($url, $header);
|
|
}
|
|
|
|
/**
|
|
* check sonarqube valid
|
|
*
|
|
* @param string $host
|
|
* @param string $token
|
|
* @access public
|
|
* @return array
|
|
*/
|
|
public function apiValidate($host, $token)
|
|
{
|
|
$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));
|
|
|
|
$url = rtrim($host, '/') . "/api/user_groups/search";
|
|
$header = 'Authorization: Basic ' . $token;
|
|
$adminer = json_decode(commonModel::http($url, null, array(), $header));
|
|
if(empty($adminer) or isset($adminer->errors)) return array('account' => array($this->lang->sonarqube->notAdminer));
|
|
|
|
return array();
|
|
}
|
|
|
|
/**
|
|
* Get sonarqube report.
|
|
*
|
|
* @param int $sonarqubeID
|
|
* @param stirng $projectKey
|
|
* @param string $metricKeys
|
|
* @access public
|
|
* @return object
|
|
*/
|
|
public function apiGetReport($sonarqubeID, $projectKey, $metricKeys = '')
|
|
{
|
|
list($apiRoot, $header) = $this->getApiBase($sonarqubeID);
|
|
if(!$apiRoot) return array();
|
|
|
|
if(!$metricKeys) $metricKeys = 'bugs,coverage,vulnerabilities,duplicated_lines_density,code_smells,ncloc,security_hotspots_reviewed';
|
|
$url = sprintf($apiRoot, "measures/component?component={$projectKey}&metricKeys={$metricKeys}");
|
|
return json_decode(commonModel::http($url, null, array(), $header));
|
|
}
|
|
|
|
/**
|
|
* Get sonarqube qualitygate by project.
|
|
*
|
|
* @param int $sonarqubeID
|
|
* @param string $projectKey
|
|
* @access public
|
|
* @return object
|
|
*/
|
|
public function apiGetQualitygate($sonarqubeID, $projectKey)
|
|
{
|
|
list($apiRoot, $header) = $this->getApiBase($sonarqubeID);
|
|
if(!$apiRoot) return array();
|
|
|
|
$url = sprintf($apiRoot, "qualitygates/project_status?projectKey={$projectKey}");
|
|
return json_decode(commonModel::http($url, null, array(), $header));
|
|
}
|
|
|
|
/**
|
|
* Get issues of one sonarqube.
|
|
*
|
|
* @param int $sonarqubeID
|
|
* @param string $projectKey
|
|
* @access public
|
|
* @return array
|
|
*/
|
|
public function apiGetIssues($sonarqubeID, $projectKey = '')
|
|
{
|
|
list($apiRoot, $header) = $this->getApiBase($sonarqubeID);
|
|
if(!$apiRoot) return array();
|
|
|
|
$url = sprintf($apiRoot, "issues/search");
|
|
$url .= "?ps=500";
|
|
if($projectKey) $url .= "&componentKeys={$projectKey}";
|
|
|
|
$allResults = array();
|
|
for($page = 1; true; $page++)
|
|
{
|
|
$result = json_decode(commonModel::http($url . "&p={$page}", null, array(), $header));
|
|
if(!isset($result->issues)) break;
|
|
if(!empty($result->issues)) $allResults = array_merge($allResults, $result->issues);
|
|
if(count($result->issues) < 500) break;
|
|
}
|
|
|
|
return $allResults;
|
|
}
|
|
|
|
/**
|
|
* Get projects of one sonarqube.
|
|
*
|
|
* @param int $sonarqubeID
|
|
* @param string $keyword
|
|
* @access public
|
|
* @return array
|
|
*/
|
|
public function apiGetProjects($sonarqubeID, $keyword = '', $projectKey = '')
|
|
{
|
|
list($apiRoot, $header) = $this->getApiBase($sonarqubeID);
|
|
if(!$apiRoot) return array();
|
|
|
|
$url = sprintf($apiRoot, "projects/search");
|
|
$url .= "?ps=500";
|
|
if($keyword) $url .= "&q={$keyword}";
|
|
if($projectKey) $url .= "&projects={$projectKey}";
|
|
|
|
$allResults = array();
|
|
for($page = 1; true; $page++)
|
|
{
|
|
$result = json_decode(commonModel::http($url . "&p={$page}", null, array(), $header));
|
|
if(!isset($result->components)) break;
|
|
if(!empty($result->components)) $allResults = array_merge($allResults, $result->components);
|
|
if(count($result->components) < 500) break;
|
|
}
|
|
|
|
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.
|
|
*
|
|
* @param int $sonarqubeID
|
|
* @param int $projectKey
|
|
* @access public
|
|
* @return bool|object
|
|
*/
|
|
public function apiDeleteProject($sonarqubeID, $projectKey)
|
|
{
|
|
list($apiRoot, $header) = $this->getApiBase($sonarqubeID);
|
|
if(!$apiRoot) return false;
|
|
|
|
$url = sprintf($apiRoot, "projects/delete?project=$projectKey");
|
|
$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;
|
|
|
|
if(mb_strlen($project->projectName) > 255) dao::$errors['projectName'][] = sprintf($this->lang->sonarqube->lengthError, $this->lang->sonarqube->projectName, 255);
|
|
if(mb_strlen($project->projectKey) > 400) dao::$errors['projectKey'][] = sprintf($this->lang->sonarqube->lengthError, $this->lang->sonarqube->projectKey, 400);
|
|
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;
|
|
}
|
|
|
|
/**
|
|
* Get cache file.
|
|
*
|
|
* @param int $sonarqubeID
|
|
* @param string $projectKey
|
|
* @access public
|
|
* @return string
|
|
*/
|
|
public function getCacheFile($sonarqubeID, $projectKey)
|
|
{
|
|
$cachePath = $this->app->getCacheRoot() . '/' . 'sonarqube';
|
|
if(!is_dir($cachePath)) mkdir($cachePath, 0777, true);
|
|
if(!is_writable($cachePath)) return false;
|
|
return $cachePath . '/' . $sonarqubeID . '-' . md5($projectKey);
|
|
}
|
|
|
|
/**
|
|
* Get linked products.
|
|
*
|
|
* @param int $sonarqubeID
|
|
* @param string $projectKey
|
|
* @access public
|
|
* @return string
|
|
*/
|
|
public function getLinkedProducts($sonarqubeID, $projectKey)
|
|
{
|
|
return $this->dao->select('t2.product')->from(TABLE_JOB)->alias('t1')
|
|
->leftJoin(TABLE_REPO)->alias('t2')->on('t1.repo=t2.id')
|
|
->where('t1.frame')->eq('sonarqube')
|
|
->andWhere('sonarqubeServer')->eq($sonarqubeID)
|
|
->andWhere('projectKey')->eq($projectKey)
|
|
->fetch('product');
|
|
}
|
|
}
|