PageRenderTime 27ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/features/jira/lib.php

https://gitlab.com/MotoSport/morgue
PHP | 307 lines | 204 code | 36 blank | 67 comment | 17 complexity | ec92b32012a0ccffdc56b87eeef9db1c MD5 | raw file
  1. <?php
  2. class Jira {
  3. /** constants mapped from Persistence class */
  4. const OK = Persistence::OK;
  5. const ERROR = Persistence::ERROR;
  6. /**
  7. * get all jira tickets associated with an event. The ticket maps have the
  8. * keys "id" and "ticket"
  9. *
  10. * @param $event_id - the numeric event id
  11. * @param $conn - a PDO connection object
  12. *
  13. * @returns ( "status" => self::OK, "error" => "", "values" => array(tickets) ) on success
  14. * and ( "status" => self::ERROR, "error" => "message", "values" => array() ) on failure
  15. */
  16. static function get_jira_tickets_for_event($event_id, $conn = null) {
  17. $conn = $conn ?: Persistence::get_database_object();
  18. $columns = array('id', 'ticket');
  19. $table = 'jira';
  20. $where = array(
  21. 'postmortem_id' => $event_id,
  22. 'deleted' => 0,
  23. );
  24. if (is_null($conn)) {
  25. return array("status" => self::ERROR,
  26. "error" => "Couldn't get connection object.",
  27. "values" => array());
  28. }
  29. return Persistence::get_array($columns, $where, $table, $conn);
  30. }
  31. /**
  32. * save tickets belonging to a certain event to the database
  33. *
  34. * @param $event_id - numeric ID of the event to store for
  35. * @param $tickets - array of ticket URLs to store
  36. * @param $conn - a PDO connection object
  37. *
  38. * @returns ( "status" => self::OK ) on success
  39. * or ( "status" => self::ERROR, "error" => "an error message" ) on failure
  40. */
  41. static function save_jira_tickets_for_event($event_id, $tickets, $conn = null) {
  42. $conn = $conn ?: Persistence::get_database_object();
  43. $table_name = 'jira';
  44. $assoc_column = 'ticket';
  45. if (is_null($conn)) {
  46. return array("status" => self::ERROR,
  47. "error" => "Couldn't get connection object.");
  48. }
  49. return Persistence::store_array($table_name, $assoc_column, $tickets,
  50. $event_id, $conn);
  51. }
  52. /**
  53. * delete jira tickets belonging to a certain event from the database
  54. *
  55. * @param $event_id - numeric ID of the event to delete for
  56. * @param $conn - a PDO connection object
  57. *
  58. * @returns ( "status" => self::OK ) on success
  59. * or ( "status" => self::ERROR, "error" => "an error message" ) on failure
  60. */
  61. static function delete_jira_tickets_for_event($event_id, $conn = null) {
  62. $conn = $conn ?: Persistence::get_database_object();
  63. if (is_null($conn)) {
  64. return array("status" => self::ERROR,
  65. "error" => "Couldn't get connection object.");
  66. }
  67. return Persistence::flag_as_deleted('jira', 'postmortem_id', $event_id, $conn);
  68. }
  69. /**
  70. * function to get a ticket from the association table
  71. *
  72. * @param $id - ID to get
  73. * @param $conn - PDO connection object (default: null)
  74. *
  75. * @returns ( "status" => self::OK, "value" => $row ) on success
  76. * or ( "status" => self::ERROR, "error" => "an error message" ) on failure
  77. */
  78. static function get_ticket($theid, $conn = null) {
  79. $conn = $conn ?: Persistence::get_database_object();
  80. $columns = array('id', 'ticket');
  81. $table_name = 'jira';
  82. if (is_null($conn)) {
  83. return array("status" => self::ERROR,
  84. "error" => "Couldn't get connection object.");
  85. }
  86. return Persistence::get_association_by_id($columns, $table_name, $theid, $conn);
  87. }
  88. /**
  89. * function to delete a ticket from the association table
  90. *
  91. * @param $id - ID to delete
  92. * @param $conn - PDO connection object (default: null)
  93. *
  94. * @returns ( "status" => self::OK ) on success
  95. * or ( "status" => self::ERROR, "error" => "an error message" ) on failure
  96. */
  97. static function delete_ticket($theid, $conn = null) {
  98. $conn = $conn ?: Persistence::get_database_object();
  99. if (is_null($conn)) {
  100. return array("status" => self::ERROR,
  101. "error" => "Couldn't get connection object.");
  102. }
  103. return Persistence::flag_as_deleted('jira', 'id', $theid, $conn);
  104. }
  105. /**
  106. * function to UNdelete a ticket from the association table
  107. *
  108. * @param $id - ID to undelete
  109. * @param $conn - PDO connection object (default: null)
  110. *
  111. * @returns ( "status" => self::OK ) on success
  112. * or ( "status" => self::ERROR, "error" => "an error message" ) on failure
  113. */
  114. static function undelete_ticket($theid, $conn = null) {
  115. $conn = $conn ?: Persistence::get_database_object();
  116. $table_name = 'tickets';
  117. if (is_null($conn)) {
  118. return array("status" => self::ERROR,
  119. "error" => "Couldn't get connection object.");
  120. }
  121. return Persistence::flag_as_undeleted($table_name, 'postmortem_id', $theid, $conn);
  122. }
  123. /**
  124. * function to merge JIRA ticket info from the database with info from the
  125. * JIRA API
  126. *
  127. * @param $tickets - array of JIRA ticket objects from the DB
  128. * @param $curl - curl client to use (default: null)
  129. *
  130. * @returns array of merged JIRA tickets
  131. */
  132. static function merge_jira_tickets($tickets, $curl = null) {
  133. if (empty($tickets)) {
  134. return array();
  135. }
  136. $jira_tickets = array();
  137. if (is_null($curl)) {
  138. $curl = new CurlClient();
  139. }
  140. $tickets_ids = array();
  141. foreach($tickets as $k => $v) {
  142. array_push($tickets_ids, $v['ticket']);
  143. }
  144. $jira_client = new JiraClient($curl);
  145. $jira_info = $jira_client->getJiraTickets(array_values($tickets_ids));
  146. foreach ($tickets as $ticket) {
  147. $key = $ticket['ticket'];
  148. $id = $ticket['id'];
  149. if (isset($jira_info[$key])) {
  150. $ticket_info = $jira_info[$key];
  151. $ticket_info['id'] = $id;
  152. $jira_tickets[$key] = $ticket_info;
  153. }
  154. }
  155. return $jira_tickets;
  156. }
  157. }
  158. class JiraClient {
  159. function __construct($curl_client, $config = null) {
  160. $this->curl_client = $curl_client;
  161. $config = is_null($config) ? Configuration::get_configuration("jira") : $config;
  162. $this->jira_base_url = $config['baseurl'];
  163. $this->username = $config['username'];
  164. $this->password = $config['password'];
  165. if (isset($config['proxy'])) {
  166. $this->proxy = $config['proxy'];
  167. } else {
  168. $this->proxy = null;
  169. }
  170. $this->additional_fields = array();
  171. if (isset($config['additional_fields'])) {
  172. $this->additional_fields = $config['additional_fields'];
  173. }
  174. }
  175. public function getJiraBaseUrl() {
  176. return $this->jira_base_url;
  177. }
  178. public function getAdditionalIssueFields() {
  179. return $this->additional_fields;
  180. }
  181. /**
  182. * Make a JQL query for all the issue keys passed as input and return the
  183. * JSON representation sent by the JIRA server
  184. *
  185. * @param $jira_key_input -> an array of trimmed JIRA ticket keys (i.e. 'CORE-1204')
  186. * @param $field -> an array of fields to retrieve for each issue
  187. *
  188. * @return $jira_api_response, an array of json-decoded issues as returned by JIRA
  189. */
  190. function getJiraApiResponse($jira_key_input, $fields) {
  191. $jira_api_responses = array();
  192. $tickets_count = count($jira_key_input);
  193. if ($tickets_count === 0) {
  194. return $jira_api_responses;
  195. }
  196. $params = array(
  197. 'jql' => 'issuekey in ("' . implode($jira_key_input, '","') . '")',
  198. 'maxResults' => $tickets_count,
  199. 'fields' => implode($fields, ',')
  200. );
  201. $response = $this->curl_client->get($this->getJiraBaseUrl() . '/rest/api/2/search' , $params, $this->username . ':' . $this->password, $this->proxy);
  202. $jira_api_response = json_decode($response, true);
  203. return $jira_api_response;
  204. }
  205. /**
  206. * given an array of JIRA issues keys, query JIRA for a set of
  207. * base field + addtional field, flatten each issue field and index
  208. * the return array by issue key
  209. *
  210. * @param $jira_key_input -> same parameter given for getJiraApiResponse, $api_response -> defaults to null
  211. *
  212. * @return $jira_tickets an array where key is an jira ticket key (i.e. 'CORE-1204') and val is an array of jira ticket attributes, such as 'ticket_url' => 'https://jira.foo.com/CORE-1204'
  213. */
  214. function getJiraTickets($jira_key_input, $api_response = null) {
  215. $raw_issues = array();
  216. $jira_tickets = array();
  217. $fields = array(
  218. 'key' => 'key',
  219. 'summary' => 'summary',
  220. 'assignee' => 'assignee',
  221. 'status' => 'status'
  222. );
  223. $fields = $fields + $this->getAdditionalIssueFields();
  224. if (is_null($api_response)) {
  225. $api_response = $this->getJiraApiResponse($jira_key_input, $fields);
  226. }
  227. if (isset($api_response['issues'])) {
  228. $raw_issues = $api_response['issues'];
  229. }
  230. foreach ($raw_issues as $issue) {
  231. if (isset($issue['key'])) {
  232. $key = $issue['key'];
  233. $jira_tickets[$key] = $this->unpackTicketInfo($issue, $fields);
  234. }
  235. }
  236. return $jira_tickets;
  237. }
  238. /**
  239. * Givent a json JIRA representation of an issue and a set of fields,
  240. * extract each field from the issue object and return the extracted
  241. * value as an associative array, along with the ticket_url
  242. *
  243. * @param $ticket_info -> json JIRA representation of an issue
  244. * @param $field -> an array of fields to retrieve for each issue
  245. *
  246. * @returns array of field->value for the issue
  247. */
  248. public function unpackTicketInfo($ticket_info, $fields) {
  249. $ticket = array();
  250. foreach($fields as $k => $v) {
  251. # set a default value
  252. $ticket[$k] = "";
  253. if (isset($ticket_info['fields'][$v])) {
  254. $val = $ticket_info['fields'][$v];
  255. if (is_string($val)) {
  256. $ticket[$k] = $val;
  257. } elseif (is_array($val) && isset($val['name'])) {
  258. $ticket[$k] = $val['name'];
  259. }
  260. }
  261. }
  262. if (isset($ticket_info['key'])) {
  263. $ticket['ticket_url'] = $this->getJiraBaseUrl() . '/browse/' . $ticket_info['key'];
  264. }
  265. return $ticket;
  266. }
  267. }
  268. ?>