From 396822686ced619df40771cd21d53d99da13c537 Mon Sep 17 00:00:00 2001 From: Francisco Mancardi Date: Sat, 30 Nov 2013 10:04:39 +0100 Subject: [PATCH 1/6] host config option changed, used has to provide full url to API Examples: http://testlink.atlassian.net/rest/api/latest/ https://testlink.atlassian.net/rest/api/latest/ --- src/JiraApi/Jira.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/JiraApi/Jira.php b/src/JiraApi/Jira.php index 7a7b240..b3c9d34 100644 --- a/src/JiraApi/Jira.php +++ b/src/JiraApi/Jira.php @@ -12,8 +12,7 @@ public function __construct(array $config = array()) $this->request = new RestRequest(); $this->request->username = (isset($config['username'])) ? $config['username'] : null; $this->request->password = (isset($config['password'])) ? $config['password'] : null; - $host = (isset($config['host'])) ? $config['host'] : null; - $this->host = 'https://' . $host . '/rest/api/2/'; + $this->host = (isset($config['host'])) ? $config['host'] : null; } public function testLogin() From dd75201f12332cf3c617b9bd9950cc355318ae3e Mon Sep 17 00:00:00 2001 From: Francisco Mancardi Date: Sat, 30 Nov 2013 16:02:36 +0100 Subject: [PATCH 2/6] configCheck() method getIssue() method --- src/JiraApi/Jira.php | 42 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 38 insertions(+), 4 deletions(-) diff --git a/src/JiraApi/Jira.php b/src/JiraApi/Jira.php index b3c9d34..bf7c50d 100644 --- a/src/JiraApi/Jira.php +++ b/src/JiraApi/Jira.php @@ -9,10 +9,36 @@ class Jira public function __construct(array $config = array()) { + // Check config before do nothing $this->request = new RestRequest(); - $this->request->username = (isset($config['username'])) ? $config['username'] : null; - $this->request->password = (isset($config['password'])) ? $config['password'] : null; - $this->host = (isset($config['host'])) ? $config['host'] : null; + $this->request->username = (isset($config['username'])) ? trim($config['username']) : null; + $this->request->password = (isset($config['password'])) ? trim($config['password']) : null; + $this->host = (isset($config['host'])) ? trim($config['host']) : null; + + $this->configCheck(); + $this->host = trim($this->host,"/") . '/'; + + if( ($last = $this->host[strlen($this->host)-1]) != '/' ) + { + $this->host .= '/'; + } + + } + + private function configCheck() + { + if(is_null($this->host) || $this->host == '') + { + throw new \Exception('Missing or Empty host (url to API) - unable to continue'); + } + if(is_null($this->request->username) || $this->request->username == '' ) + { + throw new \Exception('Missing or Empty username - unable to continue'); + } + if(is_null($this->request->password) || $this->request->password == '') + { + throw new \Exception('Missing or Empty password - unable to continue'); + } } public function testLogin() @@ -175,5 +201,13 @@ public function addComment($comment, $issueKey) return $this->request->lastRequestStatus(); } + + public function getIssue($issueKey) + { + $this->request->openConnect($this->host . 'issue/' . $issueKey, 'GET'); + $this->request->execute(); + $item = json_decode($this->request->getResponseBody()); + + return $item; + } } -?> From 2d5f0811ad8b7735847c157eebffec0498f1d580 Mon Sep 17 00:00:00 2001 From: Francisco Mancardi Date: Sat, 30 Nov 2013 16:02:59 +0100 Subject: [PATCH 3/6] simple examples --- examples/getIssue.test.class.php | 23 +++++++++++++++++++++++ examples/getUser.test.class.php | 23 +++++++++++++++++++++++ 2 files changed, 46 insertions(+) create mode 100644 examples/getIssue.test.class.php create mode 100644 examples/getUser.test.class.php diff --git a/examples/getIssue.test.class.php b/examples/getIssue.test.class.php new file mode 100644 index 0000000..68b16f8 --- /dev/null +++ b/examples/getIssue.test.class.php @@ -0,0 +1,23 @@ + 'https://testlink.atlassian.net/rest/api/latest/', + 'username' => 'testlink.forum', 'password' => 'forum'); + +$api = new JiraApi\Jira($settings); +$issueKey = 'ZOFF-2'; +$out = $api->getIssue($issueKey); +echo 'Test - Get Issue ' . $issueKey . '
'; +echo '
';
+var_dump($out);
+echo '
'; \ No newline at end of file diff --git a/examples/getUser.test.class.php b/examples/getUser.test.class.php new file mode 100644 index 0000000..fb01c90 --- /dev/null +++ b/examples/getUser.test.class.php @@ -0,0 +1,23 @@ + 'https://testlink.atlassian.net/rest/api/latest/', + 'username' => 'testlink.forum', 'password' => 'forum'); + +$api = new JiraApi\Jira($settings); + +$out = $api->getUser($settings['username']); +echo 'Test - Get Data about connected user' . $settings['username'] . '
'; +echo '
';
+var_dump($out);
+echo '
'; \ No newline at end of file From f70678b4322a3ee4d2696809dd58be23449a4d98 Mon Sep 17 00:00:00 2001 From: Francisco Mancardi Date: Sun, 1 Dec 2013 12:20:58 +0100 Subject: [PATCH 4/6] code layout --- src/JiraApi/RestRequest.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/JiraApi/RestRequest.php b/src/JiraApi/RestRequest.php index cc287a1..e11eaad 100644 --- a/src/JiraApi/RestRequest.php +++ b/src/JiraApi/RestRequest.php @@ -29,7 +29,9 @@ public function openConnect($url = null, $verb = 'GET', $requestBody = null, $fi $this->contentType = 'Content-Type: application/json'; if ($this->requestBody !== null || $this->filename !== null) + { $this->buildPostBody(); + } } public function flush() @@ -90,10 +92,14 @@ public function buildPostBody($data = null) $this->contentType = 'Content-Type: multipart/form-data; boundary='.$boundary; } else + { $this->requestBody = json_encode($this->requestBody); + } } else + { $this->requestBody = json_encode($data); + } } public function getResponseBody() @@ -179,4 +185,3 @@ protected function setAuth(&$ch) } } } -?> From c94ec8e47f31f9c2b89e7d5be8506b50e8a6fa8d Mon Sep 17 00:00:00 2001 From: Francisco Mancardi Date: Sun, 1 Dec 2013 12:22:08 +0100 Subject: [PATCH 5/6] some documentation, return type for createIssue() changed --- src/JiraApi/Jira.php | 67 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 61 insertions(+), 6 deletions(-) diff --git a/src/JiraApi/Jira.php b/src/JiraApi/Jira.php index bf7c50d..fc4574b 100644 --- a/src/JiraApi/Jira.php +++ b/src/JiraApi/Jira.php @@ -1,4 +1,10 @@ + */ namespace JiraApi; @@ -25,6 +31,9 @@ public function __construct(array $config = array()) } + /** + * + */ private function configCheck() { if(is_null($this->host) || $this->host == '') @@ -41,6 +50,9 @@ private function configCheck() } } + /** + * + */ public function testLogin() { $user = $this->getUser($this->request->username); @@ -51,6 +63,9 @@ public function testLogin() return false; } + /** + * + */ public function getUser($username) { $this->request->openConnect($this->host . 'user/search/?username=' . $username, 'GET'); @@ -60,6 +75,9 @@ public function getUser($username) return $user; } + /** + * + */ public function getStatuses() { $this->request->openConnect($this->host . 'status', 'GET'); @@ -156,14 +174,46 @@ function createPairs($obj) { return false; } - public function createIssue($json) + /** + * + * @param array $issueFields using 'fields' member + * + * Here's an example: + * + * $issueFields = array('fields' => + * array('project' => array('key' => (string)'ZOFF'), + * 'summary' => 'My First JIRA Issue via REST', + * 'description' => '', + * 'issuetype' => array( 'id' => 1) + * ) + * ); + * + * For more details about fields: + * https://developer.atlassian.com/display/JIRADEV/ + * JIRA+REST+API+Example+-+Create+Issue#JIRARESTAPIExample-CreateIssue-Examplesofcreatinganissue + * + * https://developer.atlassian.com/display/JIRADEV/ + * JIRA+REST+API+Example+-+Discovering+meta-data+for+creating+issues + * + * + * @return object reponse body (ATTENTION: can be null if something wrong has happened) + * properties: id,key,self + * Example: + * {"id":"12505","key":"ZOFF-186","self":"https://testlink.atlassian.net/rest/api/latest/issue/12505"} + * + */ + public function createIssue($issueFields) { - $this->request->openConnect($this->host . 'issue/', 'POST', $json); + $this->request->openConnect($this->host . 'issue/', 'POST', $issueFields); $this->request->execute(); - return $this->request->lastRequestStatus(); + return json_decode($this->request->getResponseBody()); } + /** + * + * + */ public function addAttachment($filename, $issueKey) { $this->request->openConnect($this->host . 'issue/' . $issueKey . '/attachments', 'POST', null, $filename); @@ -172,9 +222,14 @@ public function addAttachment($filename, $issueKey) return $this->request->lastRequestStatus(); } - public function updateIssue($json, $issueKey) + /** + * + * @param array $issueFields using 'fields' member + * + */ + public function updateIssue($issueFields, $issueKey) { - $this->request->openConnect($this->host . 'issue/' . $issueKey, 'PUT', $json); + $this->request->openConnect($this->host . 'issue/' . $issueKey, 'PUT', $issueFields); $this->request->execute(); return $this->request->lastRequestStatus(); @@ -210,4 +265,4 @@ public function getIssue($issueKey) return $item; } -} +} \ No newline at end of file From 5c68f04869c2dc9ff0312f5655bd770504c51ade Mon Sep 17 00:00:00 2001 From: Francisco Mancardi Date: Sun, 25 Dec 2016 17:39:16 +0100 Subject: [PATCH 6/6] Merge branch 'getCreateIssueMetadata' --- .../getCreateIssueMetadata.test.class.php | 50 +++++++++ src/JiraApi/Jira.php | 102 +++++++++++++++++- 2 files changed, 150 insertions(+), 2 deletions(-) create mode 100644 examples/getCreateIssueMetadata.test.class.php diff --git a/examples/getCreateIssueMetadata.test.class.php b/examples/getCreateIssueMetadata.test.class.php new file mode 100644 index 0000000..8855b21 --- /dev/null +++ b/examples/getCreateIssueMetadata.test.class.php @@ -0,0 +1,50 @@ + 'https://testlink.atlassian.net/rest/api/latest/', + 'username' => 'testlink.forum', 'password' => 'forum'); + +$api = new JiraApi\Jira($settings); + +/* +$out = $api->getCreateIssueMetadata(); +echo 'Test - Get Create Issue Metadata for all projects' . '
'; +echo '
';
+var_dump($out);
+echo '
'; +*/ + +$tg = 'ZOFF'; +$out = $api->getCreateIssueMetadata($tg); +echo 'Test - Get Create Issue Metadata for project: ' . $tg . '
'; +echo '
';
+var_dump($out);
+echo '
'; + +/* +$tg = 'ZOFF,SCRUM20NOV'; +$out = $api->getCreateIssueMetadata($tg); +echo 'Test - Get Create Issue Metadata for projects: ' . $tg . '
'; +echo '
';
+var_dump($out);
+echo '
'; + + +$tg = 'ZOFF,SCRUM20NOV'; +$out = $api->getCreateIssueFields($tg); +echo 'Test - Get Create Issue Fields for project: ' . $tg . '
'; +echo '
';
+
+var_dump($out);
+echo '
'; +*/ diff --git a/src/JiraApi/Jira.php b/src/JiraApi/Jira.php index fc4574b..7795912 100644 --- a/src/JiraApi/Jira.php +++ b/src/JiraApi/Jira.php @@ -64,11 +64,11 @@ public function testLogin() } /** - * + * https://docs.atlassian.com/jira/REST/latest/#api/2/user-getUser */ public function getUser($username) { - $this->request->openConnect($this->host . 'user/search/?username=' . $username, 'GET'); + $this->request->openConnect($this->host . 'user/?username=' . $username, 'GET'); $this->request->execute(); $user = json_decode($this->request->getResponseBody()); @@ -265,4 +265,102 @@ public function getIssue($issueKey) return $item; } + + /** + * return a map where main key is projectkey (if call has returned infor + * for this key) + * Each element is an map with issueTypeID as key, and each element inside + * this map has to elements with two keys: + * - issueTypeName + * - fields => array with field names + * + * Here a partial example for project with key ZOFF + * array(1) { + * ["ZOFF"]=> + * array(7) { + * [1]=> + * array(2) { + * ["issueTypeName"]=> "Bug" + * ["fields"]=> array(21) { + * ["summary"] => "summary" + * ["reporter"] => "reporter" + */ + public function getCreateIssueFields($projectKeys=null) + { + $opt = 'expand=projects.issuetypes.fields'; + $items = $this->getCreateIssueMetadata($projectKeys,$opt); + $ret = null; + if(!is_null($items) && count($items->projects) > 0) + { + $ro = &$items->projects; + foreach($ro as $ele) + { + $ret[$ele->key] = array(); + $rx = &$ele->issuetypes; + foreach($rx as $it) + { + $ret[$ele->key][$it->id]['issueTypeName'] = $it->name; + foreach($it->fields as $field) + { + $ret[$ele->key][$it->id]['fields'][$field->key] = $field->key; + } + } + } + //return $items->projects; + } + return $ret; + } + + + + /** + * https://docs.atlassian.com/jira/REST/cloud/#api/2/issue-getCreateIssueMeta + * + * https://developer.atlassian.com/jiradev/jira-apis/jira-rest-apis/ + * jira-rest-api-tutorials/jira-rest-api-example-discovering-meta-data-for-creating-issues + * + * + * curl -D- -u fred:fred -X GET -H "Content-Type: application/json" \ + * http://kelpie9:8081/rest/api/2/issue/createmeta + * + * curl -D- -u fred:fred -X GET -H "Content-Type: application/json" \ + * http://kelpie9:8081/rest/api/2/issue/createmeta?projectKeys=QA + * + * curl -D- -u fred:fred -X GET -H "Content-Type: application/json" \ + * http://kelpie9:8081/rest/api/2/issue/createmeta?projectKeys=QA,XSS + * + * From Atlassian documentation + * projectKeys string + * lists the projects with which to filter the results. + * If absent, all projects are returned. + * This parameter can be comma-separated list. + * Specifiying a project that does not exist + * (or that you cannot create issues in) is not an error, + * but it will not be in the results. + * + * opt can contain issuetypeIds, issuetypeNames, expand=projects.issuetypes.fields. + * Fields will only be returned if expand=projects.issuetypes.fields. + */ + public function getCreateIssueMetadata($projectKeys=null,$opt=null) + { + $cmd = $this->host . 'issue/createmeta'; + $ope = '?'; + if( !is_null($projectKeys) ) + { + $cmd .= $ope . 'projectKeys=' . $projectKeys; + $ope = '&'; + } + + if( !is_null($opt) ) + { + $cmd .= $ope . $opt; + } + + $this->request->openConnect($cmd, 'GET'); + $this->request->execute(); + $items = json_decode($this->request->getResponseBody()); + + return $items; + } + } \ No newline at end of file