diff --git a/README.md b/README.md index 862ad143..92969728 100644 --- a/README.md +++ b/README.md @@ -2470,6 +2470,43 @@ try { } ``` + +#### Get boards +[See Jira API reference](https://developer.atlassian.com/cloud/jira/software/rest/#api-rest-agile-1-0-board-get) + +```php +boardService->getBoards([ + 'startAt' => $startAt, + 'maxResults' => $maxResults + ]); + + $results = [...$results, ...$response->getBoards()]; + + $startAt += $maxResults; + + } while($startAt < $response->total); + + var_dump($results); + +} catch (JiraRestApi\JiraException $e) { + print('Error Occured! ' . $e->getMessage()); +} + +``` + + + #### Get board info [See Jira API reference](https://developer.atlassian.com/cloud/jira/software/rest/#api-rest-agile-1-0-board-boardId-get) diff --git a/composer.json b/composer.json index f3afe122..58cc2c0e 100644 --- a/composer.json +++ b/composer.json @@ -7,7 +7,7 @@ "php": "^8.0", "ext-curl": "*", "ext-json": "*", - "netresearch/jsonmapper": "^3.0|^4.0|^5.0", + "netresearch/jsonmapper": "^4.2", "monolog/monolog": "^2.0|^3.0" }, "suggest": { diff --git a/src/Auth/AuthService.php b/src/Auth/AuthService.php index d28391af..8ed530fa 100644 --- a/src/Auth/AuthService.php +++ b/src/Auth/AuthService.php @@ -80,7 +80,7 @@ public function getSessionCookieValue() * @throws \Exception * @throws \JiraRestApi\JiraException */ - public function __construct(ConfigurationInterface $configuration = null, LoggerInterface $logger = null, $path = './') + public function __construct(?ConfigurationInterface $configuration = null, ?LoggerInterface $logger = null, $path = './') { parent::__construct($configuration, $logger, $path); $this->setAPIUri($this->auth_api_uri); diff --git a/src/Board/BoardService.php b/src/Board/BoardService.php index 07a94179..fb2c5352 100644 --- a/src/Board/BoardService.php +++ b/src/Board/BoardService.php @@ -14,7 +14,7 @@ class BoardService extends \JiraRestApi\JiraClient private $agileVersion = '1.0'; - public function __construct(ConfigurationInterface $configuration = null, LoggerInterface $logger = null, $path = './') + public function __construct(?ConfigurationInterface $configuration = null, ?LoggerInterface $logger = null, $path = './') { parent::__construct($configuration, $logger, $path); $this->setAPIUri('/rest/agile/'.$this->agileVersion); @@ -46,6 +46,31 @@ public function getBoardList($paramArray = []): ?\ArrayObject } } + /** + * Get list of boards with paginated results. + * + * @param array $paramArray + * + * @throws \JiraRestApi\JiraException + * + * @return PaginatedResult|null array of Board class + */ + public function getBoards($paramArray = []): ?PaginatedResult + { + $json = $this->exec($this->uri.$this->toHttpQueryParameter($paramArray), null); + + try { + return $this->json_mapper->map( + json_decode($json, false, 512, $this->getJsonOptions()), + new PaginatedResult() + ); + } catch (\JsonException $exception) { + $this->log->error("Response cannot be decoded from json\nException: {$exception->getMessage()}"); + + return null; + } + } + public function getBoard($id, $paramArray = []): ?Board { $json = $this->exec($this->uri.'/'.$id.$this->toHttpQueryParameter($paramArray), null); @@ -122,6 +147,31 @@ public function getBoardSprints($boardId, $paramArray = []): ?\ArrayObject } } + /** + * Get list of boards with paginated results. + * + * @param array $paramArray + * + * @throws \JiraRestApi\JiraException + * + * @return PaginatedResult|null array of Board class + */ + public function getSprintsForBoard($boardId, $paramArray = []): ?PaginatedResult + { + $json = $this->exec($this->uri.'/'.$boardId.'/sprint'.$this->toHttpQueryParameter($paramArray), null); + + try { + return $this->json_mapper->map( + json_decode($json, false, 512, $this->getJsonOptions()), + new PaginatedResult() + ); + } catch (\JsonException $exception) { + $this->log->error("Response cannot be decoded from json\nException: {$exception->getMessage()}"); + + return null; + } + } + /** * @return \ArrayObject|Epic[]|null */ diff --git a/src/Board/PaginatedResult.php b/src/Board/PaginatedResult.php new file mode 100644 index 00000000..62f62f40 --- /dev/null +++ b/src/Board/PaginatedResult.php @@ -0,0 +1,129 @@ +startAt; + } + + /** + * @param int $startAt + */ + public function setStartAt($startAt) + { + $this->startAt = $startAt; + } + + /** + * @return int + */ + public function getMaxResults() + { + return $this->maxResults; + } + + /** + * @param int $maxResults + */ + public function setMaxResults($maxResults) + { + $this->maxResults = $maxResults; + } + + /** + * @return int + */ + public function getTotal() + { + return $this->total; + } + + /** + * @param int $total + */ + public function setTotal($total) + { + $this->total = $total; + } + + /** + * @return array + */ + public function getValues() + { + return $this->values; + } + + /** + * @param array $values + */ + public function setValues($values) + { + $this->values = $values; + } + + /** + * @param int $index + * + * @return mixed + */ + public function getValue($index) + { + return $this->values[$index]; + } + + /** + * @return string + */ + public function getExpand() + { + return $this->expand; + } + + /** + * @param string $expand + */ + public function setExpand($expand) + { + $this->expand = $expand; + } +} diff --git a/src/Component/Component.php b/src/Component/Component.php index 0efe298b..a5f42081 100644 --- a/src/Component/Component.php +++ b/src/Component/Component.php @@ -25,7 +25,7 @@ class Component implements \JsonSerializable public string $description; - public ?User $lead; + public ?User $lead = null; public string $leadUserName; diff --git a/src/Configuration/AbstractConfiguration.php b/src/Configuration/AbstractConfiguration.php index 993def43..603b28f9 100644 --- a/src/Configuration/AbstractConfiguration.php +++ b/src/Configuration/AbstractConfiguration.php @@ -64,6 +64,11 @@ abstract class AbstractConfiguration implements ConfigurationInterface */ protected ?string $proxyPort = null; + /** + * Proxy type. + */ + protected ?int $proxyType = null; + /** * Proxy user. */ @@ -198,6 +203,11 @@ public function getProxyPort(): ?string return $this->proxyPort; } + public function getProxyType(): ?int + { + return $this->proxyType; + } + public function getProxyUser(): ?string { return $this->proxyUser; diff --git a/src/Configuration/ArrayConfiguration.php b/src/Configuration/ArrayConfiguration.php index df0e6000..267568ba 100644 --- a/src/Configuration/ArrayConfiguration.php +++ b/src/Configuration/ArrayConfiguration.php @@ -1,4 +1,5 @@ curlOptVerbose = $this->env('CURLOPT_VERBOSE', false); $this->proxyServer = $this->env('PROXY_SERVER'); $this->proxyPort = $this->env('PROXY_PORT'); + $this->proxyType = $this->env('PROXY_TYPE'); $this->proxyUser = $this->env('PROXY_USER'); $this->proxyPassword = $this->env('PROXY_PASSWORD'); diff --git a/src/Epic/EpicService.php b/src/Epic/EpicService.php index 6213cca0..5b9df95e 100644 --- a/src/Epic/EpicService.php +++ b/src/Epic/EpicService.php @@ -11,7 +11,7 @@ class EpicService extends \JiraRestApi\JiraClient private $uri = '/epic'; private $version = '1.0'; - public function __construct(ConfigurationInterface $configuration = null, LoggerInterface $logger = null, $path = './') + public function __construct(?ConfigurationInterface $configuration = null, ?LoggerInterface $logger = null, $path = './') { parent::__construct($configuration, $logger, $path); $this->setAPIUri('/rest/agile/'.$this->version); diff --git a/src/Issue/AgileIssueService.php b/src/Issue/AgileIssueService.php index 50ef5511..85bdfcd1 100644 --- a/src/Issue/AgileIssueService.php +++ b/src/Issue/AgileIssueService.php @@ -11,7 +11,7 @@ class AgileIssueService extends \JiraRestApi\JiraClient private $agileVersion = '1.0'; - public function __construct(ConfigurationInterface $configuration = null, LoggerInterface $logger = null, $path = './') + public function __construct(?ConfigurationInterface $configuration = null, ?LoggerInterface $logger = null, $path = './') { parent::__construct($configuration, $logger, $path); $this->setAPIUri('/rest/agile/'.$this->agileVersion); diff --git a/src/Issue/Comment.php b/src/Issue/Comment.php index b7b0b169..67b2577e 100644 --- a/src/Issue/Comment.php +++ b/src/Issue/Comment.php @@ -18,6 +18,9 @@ class Comment implements \JsonSerializable /** @var string */ public $body; + /** @var string */ + public $renderedBody; + /** @var \JiraRestApi\Issue\Reporter */ public $updateAuthor; diff --git a/src/Issue/CustomField.php b/src/Issue/CustomField.php new file mode 100644 index 00000000..3551c7b2 --- /dev/null +++ b/src/Issue/CustomField.php @@ -0,0 +1,41 @@ +customFields; } - public function addCustomField(string $key, string|int|float|array $value): static + public function addCustomField(string $key, null|string|int|float|array $value): static { $this->customFields[$key] = $value; @@ -355,7 +355,7 @@ public function setParentKeyOrId(string $keyOrId): static return $this; } - public function setParent(Issue $parent): void + public function setParent(?Issue $parent): void { $this->parent = $parent; } diff --git a/src/Issue/IssueSearchResult.php b/src/Issue/IssueSearchResult.php index 3c0cb70c..27b3e9bb 100644 --- a/src/Issue/IssueSearchResult.php +++ b/src/Issue/IssueSearchResult.php @@ -1,4 +1,5 @@ $ids + * + * @return array + */ + public function getWorklogsByIds(array $ids): array + { + $ret = $this->exec('/worklog/list', json_encode(['ids' => $ids]), 'POST'); + + $this->log->debug("getWorklogsByIds res=$ret\n"); + + $worklogsResponse = json_decode($ret, false, 512, JSON_THROW_ON_ERROR); + + $worklogs = array_map(function ($worklog) { + return $this->json_mapper->map($worklog, new Worklog()); + }, $worklogsResponse); + + return $worklogs; + } + /** * add work log to issue. * @@ -822,22 +842,26 @@ public function getPriority(int $priorityId): Priority * Get priority by id. * throws HTTPException if the priority is not found, or the calling user does not have permission or view it. * - * @param int $priorityId Id of priority. + * @param $paramArray array parameters * * @throws \JsonMapper_Exception * @throws JiraException * - * @return Priority priority + * @return CustomFieldSearchResult array of CustomeFiled + * + * @see https://docs.atlassian.com/software/jira/docs/api/REST/9.14.0/#api/2/customFields-getCustomFields */ - public function getCustomFields(int $priorityId): Priority + public function getCustomFields(array $paramArray = []): CustomFieldSearchResult { - $ret = $this->exec("priority/$priorityId", null); + $ret = $this->exec('customFields'.$this->toHttpQueryParameter($paramArray), null); $this->log->info('Result='.$ret); + //\JiraRestApi\Dumper::dd(json_decode($ret, false)); + return $this->json_mapper->map( - json_decode($ret), - new Priority() + json_decode($ret, false), + new CustomFieldSearchResult() ); } diff --git a/src/Issue/IssueType.php b/src/Issue/IssueType.php index 5c3b83dd..ce38adb7 100644 --- a/src/Issue/IssueType.php +++ b/src/Issue/IssueType.php @@ -8,7 +8,7 @@ class IssueType implements \JsonSerializable public string $id; - public ?string $description; + public ?string $description = null; public string $iconUrl; diff --git a/src/Issue/Reporter.php b/src/Issue/Reporter.php index e4d5020f..7322c858 100644 --- a/src/Issue/Reporter.php +++ b/src/Issue/Reporter.php @@ -14,9 +14,9 @@ class Reporter implements \JsonSerializable public string $self; - public ?string $name; + public ?string $name = null; - public ?string $emailAddress; + public ?string $emailAddress = null; public array $avatarUrls; diff --git a/src/Issue/TimeTracking.php b/src/Issue/TimeTracking.php index cc9ec806..bf338da8 100644 --- a/src/Issue/TimeTracking.php +++ b/src/Issue/TimeTracking.php @@ -1,4 +1,5 @@ name = $name; } diff --git a/src/JiraClient.php b/src/JiraClient.php index fd2ee408..6c9c5585 100644 --- a/src/JiraClient.php +++ b/src/JiraClient.php @@ -59,7 +59,7 @@ class JiraClient * * @throws JiraException */ - public function __construct(ConfigurationInterface $configuration = null, LoggerInterface $logger = null, string $path = './') + public function __construct(?ConfigurationInterface $configuration = null, ?LoggerInterface $logger = null, string $path = './') { if ($configuration === null) { if (!file_exists($path.'.env')) { @@ -79,6 +79,9 @@ public function __construct(ConfigurationInterface $configuration = null, Logger // Properties that are annotated with `@var \DateTimeInterface` should result in \DateTime objects being created. $this->json_mapper->classMap['\\'.\DateTimeInterface::class] = \DateTime::class; + // Just class mapping is not enough, bStrictObjectTypeChecking must be set to false. + $this->json_mapper->bStrictObjectTypeChecking = false; + // create logger if ($this->configuration->getJiraLogEnabled()) { if ($logger) { @@ -185,7 +188,7 @@ protected function filterNullVariable(array $haystack): array * * @return string|bool */ - public function exec(string $context, array|string $post_data = null, string $custom_request = null, string $cookieFile = null): string|bool + public function exec(string $context, array|string|null $post_data = null, ?string $custom_request = null, ?string $cookieFile = null): string|bool { $url = $this->createUrlByContext($context); @@ -197,6 +200,8 @@ public function exec(string $context, array|string $post_data = null, string $cu curl_reset($this->curl); $ch = $this->curl; + curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $this->configuration->getTimeout()); + curl_setopt($ch, CURLOPT_TIMEOUT, $this->configuration->getTimeout()); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_URL, $url); @@ -236,7 +241,8 @@ public function exec(string $context, array|string $post_data = null, string $cu curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); } - curl_setopt($ch, CURLOPT_ENCODING, ''); + // remove for avoid https://github.com/php/php-src/issues/14184 + //curl_setopt($ch, CURLOPT_ENCODING, ''); curl_setopt( $ch, @@ -435,7 +441,7 @@ protected function createUrlByContext(string $context): string /** * Add authorize to curl request. */ - protected function authorization(\CurlHandle $ch, array &$curl_http_headers, string $cookieFile = null): void + protected function authorization(\CurlHandle $ch, array &$curl_http_headers, ?string $cookieFile = null): void { // use cookie if ($this->getConfiguration()->isCookieAuthorizationEnabled()) { @@ -484,11 +490,14 @@ public function setAPIUri(string $api_uri): string /** * convert to query array to http query parameter. */ - public function toHttpQueryParameter(array $paramArray): string + public function toHttpQueryParameter(array $paramArray, bool $dropNullKey = true): string { $queryParam = '?'; foreach ($paramArray as $key => $value) { + if ($dropNullKey === true && empty($value)) { + continue; + } $v = null; // some param field(Ex: expand) type is array. @@ -507,7 +516,7 @@ public function toHttpQueryParameter(array $paramArray): string /** * download and save into outDir. */ - public function download(string $url, string $outDir, string $file, string $cookieFile = null): mixed + public function download(string $url, string $outDir, string $file, ?string $cookieFile = null): mixed { $curl_http_header = [ 'Accept: */*', @@ -605,6 +614,11 @@ private function proxyConfigCurlHandle(\CurlHandle $ch): void $password = $this->getConfiguration()->getProxyPassword(); curl_setopt($ch, CURLOPT_PROXYUSERPWD, "$username:$password"); } + + // Set the proxy type for curl, default is CURLPROXY_HTTP (0) + if ($this->getConfiguration()->getProxyType()) { + curl_setopt($ch, CURLOPT_PROXYTYPE, $this->getConfiguration()->getProxyType()); + } } /** diff --git a/src/JiraException.php b/src/JiraException.php index db14260d..d838a725 100644 --- a/src/JiraException.php +++ b/src/JiraException.php @@ -1,4 +1,5 @@ {$propName} = $jsonValue; $object->customFields[$propName] = $jsonValue; } - } else { + } elseif (isset($object->{$propName})) { $object->{$propName} = $jsonValue; } } diff --git a/src/Project/Project.php b/src/Project/Project.php index e66db698..8f8b3cf8 100644 --- a/src/Project/Project.php +++ b/src/Project/Project.php @@ -28,7 +28,7 @@ class Project implements \JsonSerializable /** * Project key. */ - public ?string $key; + public ?string $key = null; /** * Project name. @@ -73,17 +73,17 @@ class Project implements \JsonSerializable */ public $issueTypes; - public ?string $assigneeType; + public ?string $assigneeType = null; public ?array $versions = []; - public ?array $roles; + public ?array $roles = null; public string $url; public string $projectTypeKey; - public ?string $projectTemplateKey; + public ?string $projectTemplateKey = null; public int $avatarId; diff --git a/src/Project/ProjectService.php b/src/Project/ProjectService.php index 997cf650..10da92cf 100644 --- a/src/Project/ProjectService.php +++ b/src/Project/ProjectService.php @@ -65,7 +65,7 @@ public function get($projectIdOrKey): Project * * @param int|string $projectIdOrKey Project Key * - *@throws \JiraRestApi\JiraException + * @throws \JiraRestApi\JiraException * * @return Reporter[] */ @@ -83,7 +83,7 @@ public function getAssignable(int|string $projectIdOrKey): array /** * @param int|string $projectIdOrKey * - *@throws \JiraRestApi\JiraException + * @throws \JiraRestApi\JiraException * * @return IssueType[] */ @@ -103,7 +103,7 @@ public function getStatuses(int|string $projectIdOrKey): array * * @param int|string $projectIdOrKey * - *@throws \JiraRestApi\JiraException + * @throws \JiraRestApi\JiraException * * @return \JiraRestApi\Component\Component[] */ @@ -123,7 +123,7 @@ public function getProjectComponents(int|string $projectIdOrKey): array * * @param int|string $projectIdOrKey * - *@throws JiraException + * @throws JiraException * * @return array * @return array @@ -174,7 +174,7 @@ public function getProjectTypes(): array /** * @param int|string $key * - *@throws \JsonMapper_Exception + * @throws \JsonMapper_Exception * @throws \JiraRestApi\JiraException * * @return ProjectType @@ -196,7 +196,7 @@ public function getProjectType(int|string $key): ProjectType /** * @param int|string $key * - *@throws \JsonMapper_Exception + * @throws \JsonMapper_Exception * @throws \JiraRestApi\JiraException * * @return ProjectType @@ -221,7 +221,7 @@ public function getAccessibleProjectType(int|string $key): ProjectType * @param int|string $projectIdOrKey * @param array $queryParam * - *@throws \JiraRestApi\JiraException + * @throws \JiraRestApi\JiraException * * @return Version[] array of version */ @@ -279,7 +279,7 @@ public function getVersions(string $projectIdOrKey): \ArrayObject * @param int|string $projectIdOrKey * @param string $versionName * - *@throws \JiraRestApi\JiraException + * @throws \JiraRestApi\JiraException * * @return Version version */ @@ -335,7 +335,7 @@ public function createProject(Project $project): Project * * @param Project $project * - *@throws \JsonMapper_Exception + * @throws \JsonMapper_Exception * @throws JiraException * * @return Project @@ -357,7 +357,7 @@ public function updateProject(Project $project, string|int $projectIdOrKey): Pro /** * @param int|string $projectIdOrKey * - *@throws JiraException + * @throws JiraException * * @return string response status * @@ -378,7 +378,7 @@ public function deleteProject(int|string $projectIdOrKey): string * * @param int|string $projectIdOrKey * - *@throws JiraException + * @throws JiraException * * @return string response status * diff --git a/src/RapidCharts/ScopeChangeBurnDownChartService.php b/src/RapidCharts/ScopeChangeBurnDownChartService.php index 3d065269..63409e76 100644 --- a/src/RapidCharts/ScopeChangeBurnDownChartService.php +++ b/src/RapidCharts/ScopeChangeBurnDownChartService.php @@ -12,7 +12,7 @@ class ScopeChangeBurnDownChartService extends \JiraRestApi\JiraClient private $uri = '/rapid/charts/scopechangeburndownchart'; - public function __construct(ConfigurationInterface $configuration = null, LoggerInterface $logger = null, $path = './') + public function __construct(?ConfigurationInterface $configuration = null, ?LoggerInterface $logger = null, $path = './') { parent::__construct($configuration, $logger, $path); $this->setupAPIUri(); diff --git a/src/Request/RequestService.php b/src/Request/RequestService.php index 0db86d6e..47b65019 100644 --- a/src/Request/RequestService.php +++ b/src/Request/RequestService.php @@ -23,7 +23,7 @@ class RequestService extends \JiraRestApi\JiraClient * @throws JiraException * @throws \Exception */ - public function __construct(ConfigurationInterface $configuration = null, LoggerInterface $logger = null, $path = './') + public function __construct(?ConfigurationInterface $configuration = null, ?LoggerInterface $logger = null, $path = './') { parent::__construct($configuration, $logger, $path); $this->setupAPIUri(); diff --git a/src/ServiceDesk/Customer/Customer.php b/src/ServiceDesk/Customer/Customer.php index ffc6057a..9c6036d1 100644 --- a/src/ServiceDesk/Customer/Customer.php +++ b/src/ServiceDesk/Customer/Customer.php @@ -20,7 +20,7 @@ class Customer implements JsonSerializable public string $displayName; public bool $active; public string $timeZone; - public ?CustomerLinks $_links; + public ?CustomerLinks $_links = null; public string $self; public function setLinks($links): void diff --git a/src/ServiceDesk/Request/RequestService.php b/src/ServiceDesk/Request/RequestService.php index 37b419a2..ddae9f17 100644 --- a/src/ServiceDesk/Request/RequestService.php +++ b/src/ServiceDesk/Request/RequestService.php @@ -65,7 +65,7 @@ public function getRequestFromJSON(object $jsonData): Request * * @see https://docs.atlassian.com/jira-servicedesk/REST/3.6.2/#servicedeskapi/request-getCustomerRequestByIdOrKey */ - public function get(string $issueId, array $expandParameters = [], Request $request = null): Request + public function get(string $issueId, array $expandParameters = [], ?Request $request = null): Request { $request = ($request) ?: new Request(); @@ -88,7 +88,7 @@ public function get(string $issueId, array $expandParameters = [], Request $requ * * @see https://docs.atlassian.com/jira-servicedesk/REST/3.6.2/#servicedeskapi/request-getMyCustomerRequests */ - public function getRequestsByCustomer(Customer $customer, array $searchParameters, int $serviceDeskId = null): array + public function getRequestsByCustomer(Customer $customer, array $searchParameters, ?int $serviceDeskId = null): array { $defaultSearchParameters = [ 'requestOwnership' => 'OWNED_REQUESTS', @@ -427,6 +427,26 @@ public function getWorklogById(string $issueIdOrKey, int $workLogId): Worklog ); } + /** + * @param array $ids + * + * @return array + */ + public function getWorklogsByIds(array $ids): array + { + $ret = $this->client->exec('/worklog/list', json_encode(['ids' => $ids]), 'POST'); + + $this->logger->debug("getWorklogsByIds res=$ret\n"); + + $worklogsResponse = json_decode($ret, false, 512, JSON_THROW_ON_ERROR); + + $worklogs = array_map(function ($worklog) { + return $this->jsonMapper->map($worklog, new Worklog()); + }, $worklogsResponse); + + return $worklogs; + } + /** * add work log to issue. * diff --git a/src/ServiceDesk/ServiceDeskClient.php b/src/ServiceDesk/ServiceDeskClient.php index 579dcaab..d8809cfe 100644 --- a/src/ServiceDesk/ServiceDeskClient.php +++ b/src/ServiceDesk/ServiceDeskClient.php @@ -12,8 +12,8 @@ class ServiceDeskClient extends JiraClient { public function __construct( - ConfigurationInterface $configuration = null, - LoggerInterface $logger = null, + ?ConfigurationInterface $configuration = null, + ?LoggerInterface $logger = null, string $path = './' ) { parent::__construct($configuration, $logger, $path); diff --git a/src/Sprint/Sprint.php b/src/Sprint/Sprint.php index d0c69732..15020883 100644 --- a/src/Sprint/Sprint.php +++ b/src/Sprint/Sprint.php @@ -4,7 +4,6 @@ namespace JiraRestApi\Sprint; -use DateTimeInterface; use JiraRestApi\JsonSerializableTrait; class Sprint implements \JsonSerializable @@ -29,8 +28,12 @@ class Sprint implements \JsonSerializable public string $originBoardId; + public string $createdDate; + public string $goal; + public array $issues; + public function setNameAsString(string $sprintName): self { $this->name = $sprintName; @@ -52,17 +55,38 @@ public function setOriginBoardIdAsStringOrInt(string|int $originBoardId): self return $this; } - public function setStartDateAsDateTime(DateTimeInterface $startDate, $format = 'Y-m-d'): static + public function setStartDateAsDateTime(\DateTimeInterface $startDate, string $format = 'Y-m-d'): static { $this->startDate = $startDate->format($format); return $this; } - public function setEndDateAsDateTime(DateTimeInterface $endDate, $format = 'Y-m-d'): static + public function setStartDateAsString(string $startDate): static + { + $this->startDate = $startDate; + + return $this; + } + + public function setEndDateAsDateTime(\DateTimeInterface $endDate, string $format = 'Y-m-d'): static { $this->endDate = $endDate->format($format); return $this; } + + public function setEndDateAsString(string $endDate): static + { + $this->endDate = $endDate; + + return $this; + } + + public function setMoveIssues(array $issues): static + { + $this->issues = $issues; + + return $this; + } } diff --git a/src/Sprint/SprintSearchResult.php b/src/Sprint/SprintSearchResult.php index 3c36d524..7d5611de 100644 --- a/src/Sprint/SprintSearchResult.php +++ b/src/Sprint/SprintSearchResult.php @@ -1,4 +1,5 @@ setAPIUri('/rest/agile/1.0'); @@ -79,4 +79,18 @@ public function createSprint(Sprint $sprint): Sprint new Sprint() ); } + + /** + * @see https://docs.atlassian.com/jira-software/REST/9.11.0/#agile/1.0/sprint-moveIssuesToSprint + */ + public function moveIssues2Sprint(int $sprintId, Sprint $sprint): bool + { + $data = json_encode($sprint); + + $ret = $this->exec($this->uri.'/'.$sprintId.'/issue', $data); + + $this->log->debug('moveIssues2Sprint result='.var_export($ret, true)); + + return $ret; + } } diff --git a/src/User/UserService.php b/src/User/UserService.php index b5b4a19f..21db9704 100644 --- a/src/User/UserService.php +++ b/src/User/UserService.php @@ -65,7 +65,7 @@ public function get(array $paramArray): User * * @param array $paramArray * - *@throws \JsonMapper_Exception + * @throws \JsonMapper_Exception * @throws \JiraRestApi\JiraException * * @return User[] @@ -198,7 +198,7 @@ public function getMyself(): User /** * @param array $paramArray * - *@throws \JsonMapper_Exception + * @throws \JsonMapper_Exception * @throws \JiraRestApi\JiraException * * @return User[] diff --git a/src/Version/VersionService.php b/src/Version/VersionService.php index 17512e6b..fee0ab48 100644 --- a/src/Version/VersionService.php +++ b/src/Version/VersionService.php @@ -35,7 +35,7 @@ public function create($version) return $this->json_mapper->map( json_decode($ret), - new Version() + Version::class ); } @@ -71,7 +71,7 @@ public function get(string $id) return $this->json_mapper->map( json_decode($ret), - new Version() + Version::class ); } @@ -100,7 +100,7 @@ public function update(Version $version): Version return $this->json_mapper->map( json_decode($ret), - new Version() + Version::class ); } diff --git a/test-data/reporter-no-email-address.json b/test-data/reporter-no-email-address.json new file mode 100644 index 00000000..b3a05a60 --- /dev/null +++ b/test-data/reporter-no-email-address.json @@ -0,0 +1,16 @@ +{ + "reporter": { + "self": "https://jira.example.com/rest/api/2/user?username=lesstif", + "name": "lesstif", + "key": "lesstif", + "avatarUrls": { + "48x48": "https://secure.gravatar.com/avatar/9f1705ef1d8c977eba04f00556e02922?d=mm&s=48", + "24x24": "https://secure.gravatar.com/avatar/9f1705ef1d8c977eba04f00556e02922?d=mm&s=24", + "16x16": "https://secure.gravatar.com/avatar/9f1705ef1d8c977eba04f00556e02922?d=mm&s=16", + "32x32": "https://secure.gravatar.com/avatar/9f1705ef1d8c977eba04f00556e02922?d=mm&s=32" + }, + "displayName": "정광섭", + "active": true, + "timeZone": "Asia/Seoul" + } +} \ No newline at end of file diff --git a/tests/BoardTest.php b/tests/BoardTest.php index 4eac9308..76aa113f 100644 --- a/tests/BoardTest.php +++ b/tests/BoardTest.php @@ -41,6 +41,31 @@ public function get_all_boards() : string return $last_board_id; } + /** + * @test + * + * Test we can obtain the paginated board list. + */ + public function get_boards() : string + { + $board_service = new BoardService(); + + $board_list = $board_service->getBoards(); + $this->assertInstanceOf(BoardResult::class, $board_list, 'We receive a board list.'); + + $last_board_id = null; + foreach ($board_list->getBoards() as $board) { + $this->assertInstanceOf(Board::class, $board, 'Each element of the list is a Board instance.'); + $this->assertNotNull($board->self, 'self must not null'); + $this->assertNotNull($board->name, 'name must not null'); + $this->assertNotNull($board->type, 'type must not null'); + + $last_board_id = $board->id; + } + + return $last_board_id; + } + /** * @test * diff --git a/tests/CustomFieldsTest.php b/tests/CustomFieldsTest.php index c0818f2b..400b262a 100644 --- a/tests/CustomFieldsTest.php +++ b/tests/CustomFieldsTest.php @@ -2,6 +2,7 @@ namespace JiraRestApi\Test; +use JiraRestApi\Issue\IssueService; use PHPUnit\Framework\TestCase; use JiraRestApi\Dumper; use JiraRestApi\Field\Field; @@ -10,6 +11,37 @@ class CustomFieldsTest extends TestCase { + /** + * @Test + * + * @return array|string[]|void + */ + public function get_customer_field() + { + try { + $iss = new IssueService(); + + $paramArray = [ + 'startAt' => 1, + 'maxResults' => 50, + 'search' => null, + 'projectIds' => [1, 2, 3], + 'screenIds' => null, + 'types' => null, + + 'sortOrder' => null, + 'sortColumn' => null, + 'lastValueUpdate' => null, + ]; + $customerFieldSearchResult = $iss->getCustomFields($paramArray); + + $this->assertLessThan(1, $customerFieldSearchResult->total); + + } catch (JiraException $e) { + $this->assertTrue(false, 'testSearch Failed : '.$e->getMessage()); + } + } + public function testGetFields() { try { @@ -26,6 +58,7 @@ public function testGetFields() return $matches[0]; }, $ret); + $this->assertTrue(true); return $ids; } catch (JiraException $e) { @@ -49,6 +82,7 @@ public function testGetFieldOptions($ids) Dumper::dump($ret); }catch (JiraException $e) {} } + $this->assertTrue(true); } catch (JiraException $e) { $this->assertTrue(false, 'testGetFieldOptions Failed : '.$e->getMessage()); } @@ -69,6 +103,9 @@ public function testCreateFields() $fieldService = new FieldService(); $ret = $fieldService->create($field); + + $this->assertTrue(true); + Dumper::dump($ret); } catch (JiraException $e) { $this->assertTrue(false, 'Field Create Failed : '.$e->getMessage()); diff --git a/tests/MapperTest.php b/tests/MapperTest.php index a74b5e43..49d02452 100644 --- a/tests/MapperTest.php +++ b/tests/MapperTest.php @@ -1,4 +1,4 @@ -mapper->map( + json_decode($ret), new Reporter() + ); + + $this->assertInstanceOf(Reporter::class, $reporter); + + $this->assertEquals('lesstif@gmail.com', $reporter->emailAddress); + } + } diff --git a/tests/SPrintTest.php b/tests/SPrintTest.php index c05b9c8e..3b3c930d 100644 --- a/tests/SPrintTest.php +++ b/tests/SPrintTest.php @@ -71,9 +71,9 @@ public function get_sprints(int $sprintId) : int * @depends get_sprints * * @param int $sprintId - * @return void + * @return int */ - public function get_issues_in_sprints(int $sprintId) + public function get_issues_in_sprints(int $sprintId) : int { try { $sps = new SprintService(); @@ -82,8 +82,40 @@ public function get_issues_in_sprints(int $sprintId) $this->assertNotNull($sprint); Dumper::dump($sprint); + + return $sprintId; } catch (Exception $e) { $this->fail('testSearch Failed : '.$e->getMessage()); } } + + /** + * @test + * @depends get_issues_in_sprints + * + * @param int $sprintId + * @return int + */ + public function move_issues_to_sprints(int $sprintId) : int + { + try { + $sp = (new Sprint()) + ->setMoveIssues([ + "MOBL-1", + "MOBL-5", + ]) + + ; + + $sps = new SprintService(); + + $sprint = $sps->moveIssues2Sprint($sprintId, $sp); + + $this->assertNotNull($sprint); + + return $sprintId; + } catch (Exception $e) { + $this->fail('move_issues_to_sprints Failed : '.$e->getMessage()); + } + } } \ No newline at end of file diff --git a/tests/ServiceDesk/Request/RequestServiceTest.php b/tests/ServiceDesk/Request/RequestServiceTest.php index 2c587ac5..76e831d0 100644 --- a/tests/ServiceDesk/Request/RequestServiceTest.php +++ b/tests/ServiceDesk/Request/RequestServiceTest.php @@ -369,6 +369,33 @@ public function testGetWorklogById(): void self::assertSame($item->timeSpent, $result->timeSpent); } + public function testGetWorklogsByIds(): void + { + $item1 = new stdClass(); + $item1->id = 25; + $item1->timeSpent = '2 hours'; + + $item2 = new stdClass(); + $item2->id = 50; + $item2->timeSpent = '2 hours'; + + + $items = [ + $item1, + $item2, + ]; + + $this->client->method('exec') + ->with("/worklog/list", json_encode(['ids' => [25, 50]]), 'POST') + ->willReturn(json_encode($items)); + + $result = $this->uut->getWorklogsByIds([25, 50]); + + self::assertSame(2, count($result)); + self::assertSame($item1->timeSpent, $result[0]->timeSpent); + + } + public function testAddWorklog(): void { $item = $this->createWorkflow(25, '2 hours'); diff --git a/tests/WorkLogTest.php b/tests/WorkLogTest.php index a393e44a..2da791ea 100644 --- a/tests/WorkLogTest.php +++ b/tests/WorkLogTest.php @@ -95,6 +95,22 @@ public function testGetWorkLogById($workLogid) } } + /** + * @depends testUpdateWorkLogInIssue + */ + public function testGetWorkLogsByIds($workLogid) + { + try { + $issueService = new IssueService(); + + $worklogs = $issueService->getWorklogsByIds([$workLogid]); + + Dumper::dump($worklogs); + } catch (JiraException $e) { + $this->assertTrue(false, 'testGetWorkLogsByIds Failed : '.$e->getMessage()); + } + } + /** * @depends testUpdateWorkLogInIssue */