znt/lib/jira/jira.class.php

574 lines
21 KiB
PHP

<?php
class jira
{
/**
* Jira接口的域名。
* Jira api domain.
*
* @var string
* @access public
*/
public $jiraDomain;
/**
* Jira接口的用户名。
* Jira api account.
*
* @var string
* @access public
*/
public $jiraAccount;
/**
* Jira接口的Token。
* Jira api token.
*
* @var string
* @access public
*/
public $jiraToken;
/**
* 构造方法。
* The construct function.
*
* @param string $jiraDomain
* @param string $jiraAccount
* @param string $jiraToken
* @access public
* @return void
*/
public function __construct(string $jiraDomain, string $jiraAccount, string $jiraToken)
{
$this->jiraDomain = $jiraDomain;
$this->jiraAccount = $jiraAccount;
$this->jiraToken = $jiraToken;
}
/**
* 获取Jira中所有项目。
*
* @param string $url Jira地址
* @param string $account Jira账号
* @param string $password Jira密码
* @return array
*/
public function getProjects($startAt = 0): array
{
if($startAt > 0) return array(); // 项目没有分页,第二次直接返回空数组
$url = $this->jiraDomain . '/rest/api/3/project?expand=lead,description';
$account = $this->jiraAccount;
$password = $this->jiraToken;
$authHeader = base64_encode($account . ':' . $password);
$header = array('Authorization: Basic ' . $authHeader);
$result = common::http($url, null, array(), $header, 'data', 'GET');
$result = json_decode($result, true);
if(!$result) return array();
$projects = array();
foreach($result as $project)
{
$project['versions'] = $this->getBuilds($project['id']);
$project['lead'] = !empty($project['lead']['accountId']) ? $project['lead']['accountId'] : '';
$projects[$project['id']] = $project;
}
return $projects;
}
/**
* 获取Jira中所有的版本。
*
* @param int $startAt 开始位置
* @param int $maxResults 最大返回数量
* @return array
*/
public function getBuilds($projectID = 0, $startAt = 0, $maxResults = 50): array
{
$url = $this->jiraDomain . '/rest/api/3/project/' . $projectID . '/versions?startAt=' . $startAt . '&maxResults=' . $maxResults;
$account = $this->jiraAccount;
$password = $this->jiraToken;
$authHeader = base64_encode($account . ':' . $password);
$header = array('Authorization: Basic ' . $authHeader);
$result = common::http($url, null, array(), $header, 'data', 'GET');
$versions = json_decode($result, true);
if(!$versions) return array();
if(count($versions) == $maxResults) $versions = arrayUnion($versions, $this->getBuilds($startAt + $maxResults, $maxResults));
return $versions;
}
/**
* 获取Jira中所有的Issue链接。
*
* @param int $startAt 开始位置
* @param int $maxResults 最大返回数量
* @return array
*/
public function getIssueLinks($startAt = 0, $maxResults = 50): array
{
$url = $this->jiraDomain . '/rest/api/2/issueLink?startAt=' . $startAt . '&maxResults=' . $maxResults;
$account = $this->jiraAccount;
$password = $this->jiraToken;
$authHeader = base64_encode($account . ':' . $password);
$header = array('Authorization: Basic ' . $authHeader);
$result = common::http($url, null, array(), $header, 'data', 'GET');
$issueLinks = json_decode($result, true);
if(!$issueLinks) return array();
if(count($issueLinks) == $maxResults) $issueLinks = arrayUnion($issueLinks, $this->getIssueLinks($startAt + $maxResults, $maxResults));
return $issueLinks;
}
/**
* 获取Jira中所有的Issue类型。
*
* @return array
*/
public function getIssueTypes(): array
{
$url = $this->jiraDomain . '/rest/api/2/issuetype/';
$account = $this->jiraAccount;
$password = $this->jiraToken;
$authHeader = base64_encode($account . ':' . $password);
$header = array('Authorization: Basic ' . $authHeader);
$result = common::http($url, null, array(), $header, 'data', 'GET');
$issueTypes = json_decode($result, true);
if(!$issueTypes) return array();
$typeList = array();
foreach($issueTypes as $issueType) $typeList[$issueType['id']] = $issueType;
return $typeList;
}
/**
* 获取Jira中所有的Issue链接类型。
*
* @return array
*/
public function getIssueLinkTypes()
{
$url = $this->jiraDomain . '/rest/api/2/issueLinkType';
$account = $this->jiraAccount;
$password = $this->jiraToken;
$authHeader = base64_encode($account . ':' . $password);
$header = array('Authorization: Basic ' . $authHeader);
$result = common::http($url, null, array(), $header, 'data', 'GET');
$linkTypes = json_decode($result, true);
if(!$linkTypes) return array();
$linkTypeList = array();
foreach($linkTypes['issueLinkTypes'] as $linkType) $linkTypeList[$linkType['id']] = $linkType;
return $linkTypeList;
}
/**
* 获取Jira中的所有issue。
*
* @param int $lastID
* @param int $maxResults
* @return string
*/
public function getIssues($lastID = 0, $maxResults = 5000)
{
if(!$lastID) unset($_SESSION['nextPageToken']);
if(!empty($_SESSION['nextPageToken']) && $_SESSION['nextPageToken'] == 'isLast')
{
unset($_SESSION['nextPageToken']);
return array();
}
$url = $this->jiraDomain . '/rest/api/3/search/jql';
$account = $this->jiraAccount;
$password = $this->jiraToken;
$maxResults = $maxResults ?: 5000;
$nextPageToken = !empty($_SESSION['nextPageToken']) ? $_SESSION['nextPageToken'] : '';
$authHeader = base64_encode($account . ':' . $password);
$header = array('Authorization: Basic ' . $authHeader);
$jql = 'created<=' . date('Y-m-d', strtotime('+1 day'));
$url .= '?jql=' . urlencode($jql) . "&fields=*all&maxResults=$maxResults&nextPageToken=$nextPageToken&expand=renderedFields,changelog";
$result = common::http($url, null, array(), $header, 'data', 'GET');
$result = json_decode($result, true);
if(!$result || empty($result['issues'])) return array();
$issueList = array();
foreach($result['issues'] as $issue)
{
if(!empty($issue['fields']))
{
foreach($issue['fields'] as $field => $value) $issue[$field] = $value;
}
if(!empty($issue['priority']['id'])) $issue['priority'] = $issue['priority']['id'];
if(!empty($issue['project']['id'])) $issue['project'] = $issue['project']['id'];
if(!empty($issue['status']['id'])) $issue['status'] = $issue['status']['id'];
if(!empty($issue['creator']['accountId'])) $issue['creator'] = $issue['creator']['accountId'];
if(!empty($issue['issuetype']['id'])) $issue['type'] = $issue['issuetype']['id'];
if(!empty($issue['assignee']['accountId'])) $issue['assignee'] = $issue['assignee']['accountId'];
if(!empty($issue['resolution']['id'])) $issue['resolution'] = $issue['resolution']['id'];
if(!empty($issue['renderedFields']['description'])) $issue['description'] = $issue['renderedFields']['description'];
if(!empty($issue['changelog']['histories']))
{
$changeGroups = array();
$changeItems = array();
foreach($issue['changelog']['histories'] as $history)
{
$changeGroup = array();
$changeGroup['id'] = $history['id'];
$changeGroup['issue'] = $issue['id'];
$changeGroup['author'] = $history['author']['accountId'];
$changeGroup['created'] = date('Y-m-d H:i:s', strtotime($history['created']));
$changeGroups[$changeGroup['id']] = $changeGroup;
foreach($history['items'] as $index => $item)
{
$changeItem = array();
$changeItem['id'] = $changeGroup['id'] . '_' . $index;
$changeItem['group'] = $changeGroup['id'];
$changeItem['fieldtype'] = $item['fieldtype'];
$changeItem['field'] = $item['field'];
$changeItem['oldvalue'] = $item['from'];
$changeItem['oldstring'] = $item['fromString'];
$changeItem['newvalue'] = $item['to'];
$changeItem['newstring'] = $item['toString'];
$changeItems[$changeItem['id']] = $changeItem;
}
}
$issue['changeGroups'] = $changeGroups;
$issue['changeItems'] = $changeItems;
}
if(!empty($issue['comment']['comments']))
{
$comments = array();
foreach($issue['comment']['comments'] as $index => $comment)
{
$commentItem = array();
$commentItem['id'] = $comment['id'];
$commentItem['issue'] = $issue['id'];
$commentItem['body'] = $issue['renderedFields']['comment']['comments'][$index]['body'];
$commentItem['author'] = $comment['author']['accountId'];
$commentItem['created'] = date('Y-m-d H:i:s', strtotime($comment['created']));
$comments[$commentItem['id']] = $commentItem;
}
$issue['comments'] = $comments;
}
if(!empty($issue['worklog']['worklogs']))
{
$worklogs = array();
foreach($issue['worklog']['worklogs'] as $index => $work)
{
$worklog = array();
$worklog['id'] = $work['id'];
$worklog['issue'] = $issue['id'];
$worklog['body'] = !empty($issue['renderedFields']['worklog']['worklogs'][$index]['comment']) ? $issue['renderedFields']['worklog']['worklogs'][$index]['comment'] : '';
$worklog['author'] = $work['author']['accountId'];
$worklog['timeworked'] = $work['timeSpentSeconds'];
$worklog['created'] = date('Y-m-d H:i:s', strtotime($work['created']));
$worklogs[$worklog['id']] = $worklog;
}
$issue['worklogs'] = $worklogs;
}
if(!empty($issue['attachment']))
{
$files = array();
foreach($issue['attachment'] as $attachment)
{
$file = array();
$file['issue'] = $issue['id'];
$file['id'] = $attachment['id'];
$file['filename'] = $attachment['filename'];
$file['mimetype'] = $attachment['mimeType'];
$file['filesize'] = $attachment['size'];
$file['author'] = $attachment['author']['accountId'];
$file['created'] = date('Y-m-d H:i:s', strtotime($attachment['created']));
$file['content'] = $attachment['content'];
$files[$file['id']] = $file;
}
$issue['files'] = $files;
}
if(!empty($issue['issuelinks']))
{
$links = array();
foreach($issue['issuelinks'] as $issueLink)
{
if(empty($issueLink['outwardIssue']['id'])) continue;
$link = array();
$link['id'] = $issueLink['id'];
$link['linktype'] = $issueLink['type']['id'];
$link['source'] = $issueLink['outwardIssue']['id'];
$link['destination'] = $issue['id'];
$links[$link['id']] = $link;
}
$issue['links'] = $links;
}
if(!empty($issue['subtasks']))
{
$links = !empty($issue['links']) ? $issue['links'] : array();
foreach($issue['subtasks'] as $subtask)
{
$link = array();
$link['id'] = 'subtask' . $subtask['id'];
$link['linktype'] = 'jiraSubTask';
$link['source'] = $issue['id'];
$link['destination'] = $subtask['id'];
$links[$link['id']] = $link;
}
$issue['links'] = $links;
}
$issue['created'] = date('Y-m-d H:i:s', strtotime($issue['created']));
$issueList[$issue['id']] = $issue;
}
if(empty($result['isLast']) && !empty($result['nextPageToken'])) $_SESSION['nextPageToken'] = $result['nextPageToken'];
if(!empty($result['isLast'])) $_SESSION['nextPageToken'] = 'isLast';
return $issueList;
}
/**
* 获取Jira中的用户。
*
* @param int $startAt 开始位置
* @param int $maxResults 最大返回数量
* @return string
*/
public function getUsers($startAt = 0, $maxResults = 50)
{
$url = $this->jiraDomain . '/rest/api/2/user/search?query=.&startAt=' . $startAt . '&maxResults=' . $maxResults;
$account = $this->jiraAccount;
$password = $this->jiraToken;
$authHeader = base64_encode($account . ':' . $password);
$header = array('Authorization: Basic ' . $authHeader);
$result = common::http($url, null, array(), $header, 'data', 'GET');
$result = json_decode($result, true);
$users = array();
foreach($result as $index => $user)
{
if($user['accountType'] != 'atlassian') continue;
$user['id'] = $index;
$user['lowerUserName'] = $user['accountId'];
$user['lowerDisplayName'] = $user['displayName'];
$user['createdDate'] = '';
$users[$index] = $user;
}
if(count($result) == $maxResults) $users = arrayUnion($users, $this->getUsers($startAt + $maxResults, $maxResults));
return $users;
}
/**
* 从jira接口下载文件内容。
* Download jira File.
*
* @param string $fileURL
* @access public
* @return void
*/
public function downloadFile(string $fileURL)
{
$account = $this->jiraAccount;
$password = $this->jiraToken;
$authHeader = base64_encode($account . ':' . $password);
$header = array('Authorization: Basic ' . $authHeader);
return common::http($fileURL, null, array(), $header, 'data', 'GET');
}
/**
* 获取Jira中指定项目的Board。
*
* @param int $projectID 项目ID
* @return string
*/
public function getBoardId($projectID)
{
$url = $this->jiraDomain . '/rest/agile/1.0/board?projectKeyOrId=' . $projectID;
$account = $this->jiraAccount;
$password = $this->jiraToken;
$authHeader = base64_encode($account . ':' . $password);
$header = array('Authorization: Basic ' . $authHeader);
$result = common::http($url, null, array(), $header, 'data', 'GET');
return json_decode($result, true);
}
/**
* 获取Jira中的解决方式。
*
* @return array
*/
public function getResolutions()
{
$url = $this->jiraDomain . '/rest/api/2/resolution';
$account = $this->jiraAccount;
$password = $this->jiraToken;
$authHeader = base64_encode($account . ':' . $password);
$header = array('Authorization: Basic ' . $authHeader);
$result = common::http($url, null, array(), $header, 'data', 'GET');
return json_decode($result, true);
}
/**
* 获取Jira中所有的优先级。
*
* @return array
*/
public function getPriority()
{
$url = $this->jiraDomain . '/rest/api/2/priority';
$account = $this->jiraAccount;
$password = $this->jiraToken;
$authHeader = base64_encode($account . ':' . $password);
$header = array('Authorization: Basic ' . $authHeader);
$result = common::http($url, null, array(), $header, 'data', 'GET');
return json_decode($result, true);
}
/**
* 获取Jira中所有的状态。
*
* @return array
*/
public function getStatus()
{
$url = $this->jiraDomain . '/rest/api/2/status';
$account = $this->jiraAccount;
$password = $this->jiraToken;
$authHeader = base64_encode($account . ':' . $password);
$header = array('Authorization: Basic ' . $authHeader);
$result = common::http($url, null, array(), $header, 'data', 'GET');
$result = json_decode($result, true);
if(!$result) return array();
$statusList = array();
foreach($result as $status)
{
$status['name'] = $status['untranslatedName'];
$statusList[$status['id']] = $status;
}
return $statusList;
}
/**
* 获取Jira中的自定义字段。
*
* @return array
*/
public function getCustomFields()
{
$url = $this->jiraDomain . '/rest/api/3/issue/createmeta?expand=projects.issuetypes.fields';
$account = $this->jiraAccount;
$password = $this->jiraToken;
$authHeader = base64_encode($account . ':' . $password);
$header = array('Authorization: Basic ' . $authHeader);
$result = common::http($url, null, array(), $header, 'data', 'GET');
$result = json_decode($result, true);
if(!$result['projects']) return array();
$customFields = array();
foreach($result['projects'] as $project)
{
if(empty($project['issuetypes'])) continue;
foreach($project['issuetypes'] as $issuetype)
{
foreach($issuetype['fields'] as $key => $field)
{
if(strpos($key, 'customfield_') === false) continue;
$customField = array();
$customField['id'] = str_replace('customfield_', '', $key);
$customField['name'] = $field['name'];
$customField['description'] = '';
$customField['customfieldtypekey'] = $field['schema']['custom'];
$customField['customfieldsearcherkey'] = '';
$customField['issueTypeIds'] = '';
$customFields[$issuetype['id']][$customField['id']] = $customField;
}
}
}
return $customFields;
}
/**
* 获取Jira中的自定义字段选项。
*
* @return array
*/
public function getCustomFieldOption()
{
$url = $this->jiraDomain . '/rest/api/3/issue/createmeta?expand=projects.issuetypes.fields';
$account = $this->jiraAccount;
$password = $this->jiraToken;
$authHeader = base64_encode($account . ':' . $password);
$header = array('Authorization: Basic ' . $authHeader);
$result = common::http($url, null, array(), $header, 'data', 'GET');
$result = json_decode($result, true);
if(!$result['projects']) return array();
$customFieldOptions = array();
foreach($result['projects'] as $project)
{
if(empty($project['issuetypes'])) continue;
foreach($project['issuetypes'] as $issuetype)
{
foreach($issuetype['fields'] as $key => $field)
{
if(strpos($key, 'customfield_') === false || empty($field['allowedValues'])) continue;
foreach($field['allowedValues'] as $allowedValue)
{
$customFieldOption = array();
$customFieldOption['id'] = str_replace('customfield_', '', $key);
$customFieldOption['customfield'] = str_replace('customfield_', '', $key);
$customFieldOption['customfieldconfig'] = $field['schema']['custom'];
$customFieldOption['value'] = $allowedValue['value'];
$customFieldOption['disabled'] = false;
$customFieldOptions[$allowedValue['id']] = $customFieldOption;
}
}
}
}
return $customFieldOptions;
}
}