From 4b8f4861e0205435f166926fdd5732f0b5ab89f8 Mon Sep 17 00:00:00 2001 From: Bohdan Date: Mon, 4 Sep 2023 14:57:26 +0300 Subject: [PATCH 01/33] add fix for nullable parent prop in IssueField (#516) Co-authored-by: tokmanb --- src/Issue/IssueField.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Issue/IssueField.php b/src/Issue/IssueField.php index 2b498b28..aaa80110 100644 --- a/src/Issue/IssueField.php +++ b/src/Issue/IssueField.php @@ -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; } From 0601219e8a545665c9371b2ed1b521fc58143016 Mon Sep 17 00:00:00 2001 From: KwangSeob Jeong Date: Mon, 4 Sep 2023 20:59:26 +0900 Subject: [PATCH 02/33] Apply fixes from StyleCI (#517) [ci skip] [skip ci] Co-authored-by: StyleCI Bot --- src/Project/ProjectService.php | 22 +++++++++++----------- src/User/UserService.php | 4 ++-- 2 files changed, 13 insertions(+), 13 deletions(-) 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/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[] From 6d186c0581e8a560bda35ec42e767290a6137e07 Mon Sep 17 00:00:00 2001 From: "R. Leroi" Date: Wed, 6 Sep 2023 14:42:00 +0200 Subject: [PATCH 03/33] Add cURL proxy type configuration (#519) --- src/Configuration/AbstractConfiguration.php | 10 ++++++++++ src/Configuration/ConfigurationInterface.php | 5 +++++ src/Configuration/DotEnvConfiguration.php | 1 + src/JiraClient.php | 5 +++++ 4 files changed, 21 insertions(+) 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/ConfigurationInterface.php b/src/Configuration/ConfigurationInterface.php index 196360bc..e3c41999 100644 --- a/src/Configuration/ConfigurationInterface.php +++ b/src/Configuration/ConfigurationInterface.php @@ -96,6 +96,11 @@ public function getProxyServer(): ?string; */ public function getProxyPort(): ?string; + /** + * Proxy type. + */ + public function getProxyType(): ?int; + /** * Proxy user. */ diff --git a/src/Configuration/DotEnvConfiguration.php b/src/Configuration/DotEnvConfiguration.php index 0aae17d0..d26a469c 100644 --- a/src/Configuration/DotEnvConfiguration.php +++ b/src/Configuration/DotEnvConfiguration.php @@ -37,6 +37,7 @@ public function __construct(string $path = '.') $this->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/JiraClient.php b/src/JiraClient.php index fd2ee408..0e055f54 100644 --- a/src/JiraClient.php +++ b/src/JiraClient.php @@ -605,6 +605,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()); + } } /** From 35be23fe1762048e0af16a9b4e9faa3227bf57d0 Mon Sep 17 00:00:00 2001 From: Maddin <9324423+reinfi@users.noreply.github.com> Date: Wed, 6 Sep 2023 14:42:55 +0200 Subject: [PATCH 04/33] Set types correctly for Version class (#518) * add default values to properties not sent * release date is nullable * name cannot be nullable --------- Co-authored-by: martin.reinfandt --- src/Issue/Version.php | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Issue/Version.php b/src/Issue/Version.php index eb3b23a6..8c06b8f4 100644 --- a/src/Issue/Version.php +++ b/src/Issue/Version.php @@ -11,25 +11,25 @@ class Version implements \JsonSerializable public string $id; // Version name: ex: 4.2.3 - public ?string $name; + public string $name; // version description: ex; improvement performance - public ?string $description; + public ?string $description = null; public bool $archived; public bool $released; - public string $releaseDate; + public ?string $releaseDate = null; - public bool $overdue; + public bool $overdue = false; - public ?string $userReleaseDate; + public ?string $userReleaseDate = null; public int $projectId; - public ?string $startDate; - public ?string $userStartDate; + public ?string $startDate = null; + public ?string $userStartDate = null; public function __construct($name = null) { From 25f83be157631b875e9f8bfe4dc7032e90adbae6 Mon Sep 17 00:00:00 2001 From: KwangSeob Jeong Date: Wed, 27 Sep 2023 00:02:44 +0900 Subject: [PATCH 05/33] fixed #522 avoiding $emailAddress property accessed before initialization error. --- src/Issue/Reporter.php | 2 +- test-data/reporter-no-email-address.json | 16 ++++++++++++++++ tests/MapperTest.php | 15 ++++++++++++++- 3 files changed, 31 insertions(+), 2 deletions(-) create mode 100644 test-data/reporter-no-email-address.json diff --git a/src/Issue/Reporter.php b/src/Issue/Reporter.php index e4d5020f..c639118b 100644 --- a/src/Issue/Reporter.php +++ b/src/Issue/Reporter.php @@ -16,7 +16,7 @@ class Reporter implements \JsonSerializable public ?string $name; - public ?string $emailAddress; + public ?string $emailAddress = null; public array $avatarUrls; 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/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); + } + } From 1306db5e8c4041fe0ff296b2fa30809618b192b3 Mon Sep 17 00:00:00 2001 From: Maddin <9324423+reinfi@users.noreply.github.com> Date: Tue, 26 Sep 2023 17:07:29 +0200 Subject: [PATCH 06/33] Fix constructor for Version class (#521) * add default values to properties not sent * release date is nullable * name cannot be nullable * adjust constructor of version so name can only be a string * require a minimum of latest version of json mapper to support class-string syntax --------- Co-authored-by: martin.reinfandt --- composer.json | 2 +- src/Issue/Version.php | 2 +- src/Version/VersionService.php | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) 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/Issue/Version.php b/src/Issue/Version.php index 8c06b8f4..30b57ed1 100644 --- a/src/Issue/Version.php +++ b/src/Issue/Version.php @@ -31,7 +31,7 @@ class Version implements \JsonSerializable public ?string $startDate = null; public ?string $userStartDate = null; - public function __construct($name = null) + public function __construct(string $name) { $this->name = $name; } 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 ); } From 8ce2cfe877f8a0cbd41acf6bd8c6532dca2936bf Mon Sep 17 00:00:00 2001 From: KwangSeob Jeong Date: Sun, 1 Oct 2023 23:39:07 +0900 Subject: [PATCH 07/33] - implemented Move issues to Sprint - fixed #523 added createdDate property --- src/Sprint/Sprint.php | 30 +++++++++++++++++++++++++++--- src/Sprint/SprintService.php | 14 ++++++++++++++ tests/SPrintTest.php | 36 ++++++++++++++++++++++++++++++++++-- 3 files changed, 75 insertions(+), 5 deletions(-) diff --git a/src/Sprint/Sprint.php b/src/Sprint/Sprint.php index d0c69732..d0cc91c3 100644 --- a/src/Sprint/Sprint.php +++ b/src/Sprint/Sprint.php @@ -29,8 +29,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; @@ -51,18 +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/SprintService.php b/src/Sprint/SprintService.php index c2e6bb23..a91b7dc0 100644 --- a/src/Sprint/SprintService.php +++ b/src/Sprint/SprintService.php @@ -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/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 From 69dfc133b0b84c8206cc59b3e8af35f7b8c668b0 Mon Sep 17 00:00:00 2001 From: KwangSeob Jeong Date: Sun, 1 Oct 2023 23:43:05 +0900 Subject: [PATCH 08/33] Apply fixes from StyleCI (#524) [ci skip] [skip ci] Co-authored-by: StyleCI Bot --- src/Sprint/Sprint.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Sprint/Sprint.php b/src/Sprint/Sprint.php index d0cc91c3..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 @@ -55,6 +54,7 @@ public function setOriginBoardIdAsStringOrInt(string|int $originBoardId): self return $this; } + public function setStartDateAsDateTime(\DateTimeInterface $startDate, string $format = 'Y-m-d'): static { $this->startDate = $startDate->format($format); From d375c35cc96896898673a70b893111f552fca59e Mon Sep 17 00:00:00 2001 From: KwangSeob Jeong Date: Sun, 24 Mar 2024 21:30:52 +0900 Subject: [PATCH 09/33] fixed #526 I've implemented getting customField action. --- src/Issue/CustomField.php | 41 +++++++++++++++++++++++++++ src/Issue/CustomFieldSearchResult.php | 24 ++++++++++++++++ src/Issue/IssueService.php | 16 +++++++---- src/JiraClient.php | 5 +++- tests/CustomFieldsTest.php | 37 ++++++++++++++++++++++++ 5 files changed, 116 insertions(+), 7 deletions(-) create mode 100644 src/Issue/CustomField.php create mode 100644 src/Issue/CustomFieldSearchResult.php diff --git a/src/Issue/CustomField.php b/src/Issue/CustomField.php new file mode 100644 index 00000000..15308904 --- /dev/null +++ b/src/Issue/CustomField.php @@ -0,0 +1,41 @@ +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/JiraClient.php b/src/JiraClient.php index 0e055f54..44de49b2 100644 --- a/src/JiraClient.php +++ b/src/JiraClient.php @@ -484,11 +484,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. 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()); From db8b8d0a8b1aaf30cfe9872633d5e43056f4d7de Mon Sep 17 00:00:00 2001 From: flack Date: Sun, 24 Mar 2024 13:31:56 +0100 Subject: [PATCH 10/33] Allow null values (#527) e.g. to remove a previous selection from a checkbox field --- src/Issue/IssueField.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Issue/IssueField.php b/src/Issue/IssueField.php index aaa80110..88779d95 100644 --- a/src/Issue/IssueField.php +++ b/src/Issue/IssueField.php @@ -150,7 +150,7 @@ public function getCustomFields(): ?array return $this->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; From 387c4ab5eaf4c3b871d013076be3838e2128ae5e Mon Sep 17 00:00:00 2001 From: KwangSeob Jeong Date: Sun, 24 Mar 2024 23:35:53 +0900 Subject: [PATCH 11/33] Apply fixes from StyleCI (#529) [ci skip] [skip ci] Co-authored-by: StyleCI Bot --- src/Issue/CustomField.php | 2 +- src/Issue/CustomFieldSearchResult.php | 2 +- src/Issue/IssueService.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Issue/CustomField.php b/src/Issue/CustomField.php index 15308904..3551c7b2 100644 --- a/src/Issue/CustomField.php +++ b/src/Issue/CustomField.php @@ -38,4 +38,4 @@ public function jsonSerialize(): mixed { return array_filter(get_object_vars($this)); } -} \ No newline at end of file +} diff --git a/src/Issue/CustomFieldSearchResult.php b/src/Issue/CustomFieldSearchResult.php index 35dac9ba..5fac7a35 100644 --- a/src/Issue/CustomFieldSearchResult.php +++ b/src/Issue/CustomFieldSearchResult.php @@ -21,4 +21,4 @@ public function jsonSerialize(): mixed { return array_filter(get_object_vars($this)); } -} \ No newline at end of file +} diff --git a/src/Issue/IssueService.php b/src/Issue/IssueService.php index 559d6352..68d3049e 100644 --- a/src/Issue/IssueService.php +++ b/src/Issue/IssueService.php @@ -833,7 +833,7 @@ public function getPriority(int $priorityId): Priority */ public function getCustomFields(array $paramArray = []): CustomFieldSearchResult { - $ret = $this->exec("customFields".$this->toHttpQueryParameter($paramArray), null); + $ret = $this->exec('customFields'.$this->toHttpQueryParameter($paramArray), null); $this->log->info('Result='.$ret); From 83d4f8daf973c1ebda6775171b7651ef85c36723 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dillenbourg=20J=C3=A9r=C3=A9my?= Date: Mon, 22 Apr 2024 14:20:44 +0200 Subject: [PATCH 12/33] Ensure property exist before assignation (#531) --- src/JsonMapperHelper.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/JsonMapperHelper.php b/src/JsonMapperHelper.php index 355867f5..4f736bdc 100644 --- a/src/JsonMapperHelper.php +++ b/src/JsonMapperHelper.php @@ -21,7 +21,7 @@ public static function setUndefinedProperty($object, $propName, $jsonValue) $object->{$propName} = $jsonValue; $object->customFields[$propName] = $jsonValue; } - } else { + } elseif (isset($object->{$propName})) { $object->{$propName} = $jsonValue; } } From fb62c0e41bc17ebf0d279b20900d1ebc9fa869e1 Mon Sep 17 00:00:00 2001 From: Peter Majmesku Date: Mon, 22 Apr 2024 15:19:06 +0200 Subject: [PATCH 13/33] Introduce timeout to cURL exec from .env file (#533) * Changed project name * Can we use the original project name? * feat: #WPLZ-166 - introduce timeout --------- Co-authored-by: Peter Majmesku --- src/JiraClient.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/JiraClient.php b/src/JiraClient.php index 44de49b2..e19f9d60 100644 --- a/src/JiraClient.php +++ b/src/JiraClient.php @@ -197,6 +197,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); From e01f5430bd003fcc1b0c19ec510a79f26b90cd04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Lipensk=C3=BD?= <85517608+ppacz@users.noreply.github.com> Date: Mon, 16 Sep 2024 12:10:13 +0200 Subject: [PATCH 14/33] feat: added endpoint to find workload by ID (#537) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Tomáš Lipenský --- src/ServiceDesk/Request/RequestService.php | 20 ++++++++++++++ .../Request/RequestServiceTest.php | 27 +++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/src/ServiceDesk/Request/RequestService.php b/src/ServiceDesk/Request/RequestService.php index 37b419a2..33cafcfd 100644 --- a/src/ServiceDesk/Request/RequestService.php +++ b/src/ServiceDesk/Request/RequestService.php @@ -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/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'); From 087718a85b754378f6dd88b5ef499fc4eeed40a2 Mon Sep 17 00:00:00 2001 From: Nick Poulos Date: Mon, 16 Sep 2024 06:52:08 -0400 Subject: [PATCH 15/33] Add New Method for Returning Board List With Offset/Paginated Results (#535) * Create BoardResult.php - Create a new class to hold the entire result data of the response returned from the "/rest/agile/1.0/board" endpoint - The approach is very similar to how the existing IssueService->search() function works already * Update BoardService.php - Instead of updating the existing getAllBoards() method and create a breaking change, I introduced a new method getBoards() - This method calls to the same "/rest/agile/1.0/board" endpoint as getAllBoards() but it maps the value into the newly created BoardResult class rather than ArrayObject. - This allows the developer to determine if there are more results past the initial 50 on the first page, and get additional pages if necessary * Update BoardTest.php - Created a new test method which performs the same test as the get_all_boards() test but using the updated result object instead * Update README.md Add information about how to use the new getBoards() method to retrieve the entire list of board results * Add periods to end of comments Added these in order to pass StyleCI PR checks * Rename BoardResult to more generic PaginatedResult I realized other methods in BoardService also did not have proper pagination built in. We will reuse this class in a more generic way for other methods such as getSprintsForBoard() * Update BoardService.php - Update our new getBoards() method to return PaginatedResult instead of BoardResult - Add new method getSprintsForBoard() which has support for pagination and uses PaginatedResult --- README.md | 37 ++++++++++ src/Board/BoardService.php | 47 +++++++++++++ src/Board/PaginatedResult.php | 129 ++++++++++++++++++++++++++++++++++ tests/BoardTest.php | 25 +++++++ 4 files changed, 238 insertions(+) create mode 100644 src/Board/PaginatedResult.php 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/src/Board/BoardService.php b/src/Board/BoardService.php index 07a94179..8c7c0ae9 100644 --- a/src/Board/BoardService.php +++ b/src/Board/BoardService.php @@ -46,6 +46,29 @@ public function getBoardList($paramArray = []): ?\ArrayObject } } + /** + * Get list of boards with paginated results. + * + * @param array $paramArray + * + * @return PaginatedResult|null array of Board class + *@throws \JiraRestApi\JiraException + * + */ + 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 +145,30 @@ 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..c3339aab --- /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/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 * From 06c20a4b6ff263cbbeb90b270f49ac8e697e320f Mon Sep 17 00:00:00 2001 From: KwangSeob Jeong Date: Mon, 16 Sep 2024 20:00:42 +0900 Subject: [PATCH 16/33] fixed #536, #534 --- src/JiraClient.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/JiraClient.php b/src/JiraClient.php index e19f9d60..b238f36d 100644 --- a/src/JiraClient.php +++ b/src/JiraClient.php @@ -238,7 +238,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, From 2d5e7c53556ebe4cca79b233dca51e5316949ce8 Mon Sep 17 00:00:00 2001 From: Victor Date: Sat, 5 Apr 2025 14:47:32 +0200 Subject: [PATCH 17/33] Set default to null for all nullable properties (#545) --- src/Component/Component.php | 2 +- src/Issue/Issue.php | 16 ++++++------- src/Issue/IssueField.php | 34 +++++++++++++-------------- src/Issue/IssueType.php | 2 +- src/Issue/Reporter.php | 2 +- src/Project/Project.php | 8 +++---- src/ServiceDesk/Customer/Customer.php | 2 +- 7 files changed, 33 insertions(+), 33 deletions(-) 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/Issue/Issue.php b/src/Issue/Issue.php index e6616ab0..2793be12 100644 --- a/src/Issue/Issue.php +++ b/src/Issue/Issue.php @@ -7,7 +7,7 @@ class Issue implements \JsonSerializable /** * return only if Project query by key(not id). */ - public ?string $expand; + public ?string $expand = null; public string $self; @@ -17,19 +17,19 @@ class Issue implements \JsonSerializable public IssueField $fields; - public ?array $renderedFields; + public ?array $renderedFields = null; - public ?array $names; + public ?array $names = null; - public ?array $schema; + public ?array $schema = null; - public ?array $transitions; + public ?array $transitions = null; - public ?array $operations; + public ?array $operations = null; - public ?array $editmeta; + public ?array $editmeta = null; - public ?ChangeLog $changelog; + public ?ChangeLog $changelog = null; #[\ReturnTypeWillChange] public function jsonSerialize(): array diff --git a/src/Issue/IssueField.php b/src/Issue/IssueField.php index 88779d95..ee3e72b8 100644 --- a/src/Issue/IssueField.php +++ b/src/Issue/IssueField.php @@ -18,11 +18,11 @@ class IssueField implements \JsonSerializable public ?TimeTracking $timeTracking = null; - public ?IssueType $issuetype; + public ?IssueType $issuetype = null; public ?Reporter $reporter = null; - public ?DateTimeInterface $created; + public ?DateTimeInterface $created = null; public ?DateTimeInterface $updated = null; @@ -36,7 +36,7 @@ class IssueField implements \JsonSerializable public Project $project; - public ?string $environment; + public ?string $environment = null; /* @var \JiraRestApi\Issue\Component[] This property must don't describe the type feature for JSON deserialized. */ public $components; @@ -45,15 +45,15 @@ class IssueField implements \JsonSerializable public object $votes; - public ?object $resolution; + public ?object $resolution = null; public array $fixVersions; - public ?Reporter $creator; + public ?Reporter $creator = null; - public ?object $watches; + public ?object $watches = null; - public ?object $worklog; + public ?object $worklog = null; public ?Reporter $assignee = null; @@ -63,13 +63,13 @@ class IssueField implements \JsonSerializable /** @var \JiraRestApi\Issue\Attachment[] */ public $attachment; - public ?string $aggregatetimespent; + public ?string $aggregatetimespent = null; - public ?string $timeestimate; + public ?string $timeestimate = null; - public ?string $aggregatetimeoriginalestimate; + public ?string $aggregatetimeoriginalestimate = null; - public ?string $resolutiondate; + public ?string $resolutiondate = null; public ?DateTimeInterface $duedate = null; @@ -82,20 +82,20 @@ class IssueField implements \JsonSerializable public int $workratio; - public ?object $aggregatetimeestimate; + public ?object $aggregatetimeestimate = null; - public ?object $aggregateprogress; + public ?object $aggregateprogress = null; - public ?object $lastViewed; + public ?object $lastViewed = null; - public ?object $timeoriginalestimate; + public ?object $timeoriginalestimate = null; /** @var object|null */ public $parent; - public ?array $customFields; + public ?array $customFields = null; - public ?SecurityScheme $security; + public ?SecurityScheme $security = null; public function __construct($updateIssue = false) { 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 c639118b..7322c858 100644 --- a/src/Issue/Reporter.php +++ b/src/Issue/Reporter.php @@ -14,7 +14,7 @@ class Reporter implements \JsonSerializable public string $self; - public ?string $name; + public ?string $name = null; public ?string $emailAddress = null; 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/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 From 7dc9fe2d7f05f33a98a251e4066c2bf8a9852242 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Lipensk=C3=BD?= <85517608+ppacz@users.noreply.github.com> Date: Sat, 5 Apr 2025 14:49:20 +0200 Subject: [PATCH 18/33] feat: endpoint to find workloads by IDs (#538) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Tomáš Lipenský --- src/Issue/IssueService.php | 20 ++++++++++++++++++++ tests/WorkLogTest.php | 16 ++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/src/Issue/IssueService.php b/src/Issue/IssueService.php index 68d3049e..88afa872 100644 --- a/src/Issue/IssueService.php +++ b/src/Issue/IssueService.php @@ -700,6 +700,26 @@ public function getWorklogById(string $issueIdOrKey, int $workLogId): Worklog ); } + /** + * @param array $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. * 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 */ From d203e9c691714ce56d3aa0c273713ecb90987c31 Mon Sep 17 00:00:00 2001 From: Armino Popp Date: Sat, 5 Apr 2025 15:49:38 +0300 Subject: [PATCH 19/33] Update Comment.php (#539) On PHP >= 8.2 Allow comment to have renderedBody property correctly set upon deserialization. --- src/Issue/Comment.php | 3 +++ 1 file changed, 3 insertions(+) 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; From 21331c481a3c22237c6e2ba14bc398204b7b4377 Mon Sep 17 00:00:00 2001 From: Evgeny Mazovetskiy Date: Sat, 5 Apr 2025 14:49:54 +0200 Subject: [PATCH 20/33] disable strict object type check in JsonMapper (#541) Since version 5 of the JsonMapper the property bStrictObjectTypeChecking is true by default. This causes error when mapping string dates to DateTimeInterface. This fix sets the property to false. --- src/JiraClient.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/JiraClient.php b/src/JiraClient.php index b238f36d..348fb4bc 100644 --- a/src/JiraClient.php +++ b/src/JiraClient.php @@ -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) { From 46b20408c34138615acbdd58a86b8b624d864d0c Mon Sep 17 00:00:00 2001 From: Heiko Griga <81759879+hgriga@users.noreply.github.com> Date: Sat, 5 Apr 2025 14:50:11 +0200 Subject: [PATCH 21/33] Set default values for changelog + fixVersions (#543) * set default value for changelog * set default value for fixVersions --- src/Issue/IssueField.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Issue/IssueField.php b/src/Issue/IssueField.php index ee3e72b8..8f96bcaf 100644 --- a/src/Issue/IssueField.php +++ b/src/Issue/IssueField.php @@ -47,7 +47,7 @@ class IssueField implements \JsonSerializable public ?object $resolution = null; - public array $fixVersions; + public array $fixVersions = []; public ?Reporter $creator = null; From a6a96c02023c73e915a2e4f31f1e2beefa1f64c1 Mon Sep 17 00:00:00 2001 From: KwangSeob Jeong Date: Sat, 5 Apr 2025 22:08:01 +0900 Subject: [PATCH 22/33] Apply fixes from StyleCI (#546) [ci skip] [skip ci] Co-authored-by: StyleCI Bot --- src/Auth/AuthService.php | 2 +- src/Board/BoardService.php | 9 ++++++--- src/Board/PaginatedResult.php | 2 +- src/Configuration/ArrayConfiguration.php | 1 + src/Configuration/ConfigurationInterface.php | 1 + src/Epic/EpicService.php | 2 +- src/Issue/AgileIssueService.php | 2 +- src/Issue/IssueSearchResult.php | 1 + src/Issue/TimeTracking.php | 1 + src/JiraClient.php | 8 ++++---- src/JiraException.php | 3 ++- src/RapidCharts/ScopeChangeBurnDownChartService.php | 2 +- src/Request/RequestService.php | 2 +- src/ServiceDesk/Request/RequestService.php | 4 ++-- src/ServiceDesk/ServiceDeskClient.php | 4 ++-- src/Sprint/SprintSearchResult.php | 1 + src/Sprint/SprintService.php | 2 +- 17 files changed, 28 insertions(+), 19 deletions(-) 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 8c7c0ae9..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); @@ -51,13 +51,14 @@ public function getBoardList($paramArray = []): ?\ArrayObject * * @param array $paramArray * - * @return PaginatedResult|null array of Board class - *@throws \JiraRestApi\JiraException + * @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()), @@ -65,6 +66,7 @@ public function getBoards($paramArray = []): ?PaginatedResult ); } catch (\JsonException $exception) { $this->log->error("Response cannot be decoded from json\nException: {$exception->getMessage()}"); + return null; } } @@ -165,6 +167,7 @@ public function getSprintsForBoard($boardId, $paramArray = []): ?PaginatedResult ); } catch (\JsonException $exception) { $this->log->error("Response cannot be decoded from json\nException: {$exception->getMessage()}"); + return null; } } diff --git a/src/Board/PaginatedResult.php b/src/Board/PaginatedResult.php index c3339aab..62f62f40 100644 --- a/src/Board/PaginatedResult.php +++ b/src/Board/PaginatedResult.php @@ -3,7 +3,7 @@ namespace JiraRestApi\Board; /** - * Paginated Result object for BoardService + * Paginated Result object for BoardService. */ class PaginatedResult { 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 @@ 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/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 @@ createUrlByContext($context); @@ -441,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()) { @@ -516,7 +516,7 @@ public function toHttpQueryParameter(array $paramArray, bool $dropNullKey = true /** * 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: */*', 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 @@ 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/Request/RequestService.php b/src/ServiceDesk/Request/RequestService.php index 33cafcfd..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', 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/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'); From bf69b91d1c1cffd76e866c183b63da124b985ac2 Mon Sep 17 00:00:00 2001 From: Oleg Poludnenko Date: Sat, 20 Sep 2025 07:48:48 +0300 Subject: [PATCH 23/33] Field 'fixVersions' cannot be set. It is not on the appropriate screen, or unknown (#548) https://github.com/lesstif/php-jira-rest-client/issues/547 --- src/Issue/IssueField.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Issue/IssueField.php b/src/Issue/IssueField.php index 8f96bcaf..3a74424b 100644 --- a/src/Issue/IssueField.php +++ b/src/Issue/IssueField.php @@ -114,7 +114,7 @@ public function __construct($updateIssue = false) public function jsonSerialize(): mixed { $vars = array_filter(get_object_vars($this), function ($var) { - return !is_null($var); + return !empty($var); }); // if assignee property has empty value then remove it. From 0289d7732a7fb993bb79c88ad88f5c1b18e19d85 Mon Sep 17 00:00:00 2001 From: johanib <60608181+johanib@users.noreply.github.com> Date: Sat, 20 Sep 2025 06:49:07 +0200 Subject: [PATCH 24/33] Fix ["JSON property \"expand\" in class \"JiraRestApi\\Issue\\IssueSearchResult\" must not be NULL"] (#549) --- src/Issue/IssueSearchResult.php | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/Issue/IssueSearchResult.php b/src/Issue/IssueSearchResult.php index 27b3e9bb..9ba8bd47 100644 --- a/src/Issue/IssueSearchResult.php +++ b/src/Issue/IssueSearchResult.php @@ -17,7 +17,7 @@ class IssueSearchResult /** * @var string */ - public $expand; + public ?string $expand = null; /** * @var int @@ -114,17 +114,14 @@ public function getIssue($ndx) } /** - * @return string + * @return ?string */ public function getExpand() { return $this->expand; } - /** - * @param string $expand - */ - public function setExpand($expand) + public function setExpand(?string $expand) { $this->expand = $expand; } From 18f2ab931ec5bd1f652e8ecfcf4f372765239f5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A1n=20Hamr=C3=A1k?= Date: Sat, 20 Sep 2025 06:49:20 +0200 Subject: [PATCH 25/33] Support netresearch/jsonmapper ^5.0 (#551) * Support netresearch/jsonmapper ^5.0 * codefactor fix --- composer.json | 6 +-- src/JiraClient.php | 64 ++++++++++++++++++----------- src/ServiceDesk/Request/Request.php | 7 ++++ 3 files changed, 48 insertions(+), 29 deletions(-) diff --git a/composer.json b/composer.json index 58cc2c0e..89cf5176 100644 --- a/composer.json +++ b/composer.json @@ -7,10 +7,8 @@ "php": "^8.0", "ext-curl": "*", "ext-json": "*", - "netresearch/jsonmapper": "^4.2", - "monolog/monolog": "^2.0|^3.0" - }, - "suggest": { + "netresearch/jsonmapper": "^4.2|^5.0", + "monolog/monolog": "^2.0|^3.0", "vlucas/phpdotenv": "^5.0|^6.0" }, "require-dev": { diff --git a/src/JiraClient.php b/src/JiraClient.php index 6c9c5585..02a7dd52 100644 --- a/src/JiraClient.php +++ b/src/JiraClient.php @@ -73,6 +73,13 @@ public function __construct(?ConfigurationInterface $configuration = null, ?Logg $this->json_mapper = new \JsonMapper(); + // Adjust settings for JsonMapper v5.0 BC + if (property_exists($this->json_mapper, 'bStrictNullTypesInArrays')) { + $this->json_mapper->bStrictNullTypesInArrays = false; // if you want to allow nulls in arrays + } + $this->json_mapper->bStrictNullTypes = false; // if you want to allow nulls + $this->json_mapper->bStrictObjectTypeChecking = false; // if you want to disable strict type checking + // Fix "\JiraRestApi\JsonMapperHelper::class" syntax error, unexpected 'class' (T_CLASS), expecting identifier (T_STRING) or variable (T_VARIABLE) or '{' or '$' $this->json_mapper->undefinedPropertyHandler = [new \JiraRestApi\JsonMapperHelper(), 'setUndefinedProperty']; @@ -198,31 +205,7 @@ public function exec(string $context, array|string|null $post_data = null, ?stri $this->log->info("Curl $custom_request: $url JsonData=".json_encode($post_data, JSON_UNESCAPED_UNICODE)); } - 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); - - // post_data - if (!is_null($post_data)) { - // PUT REQUEST - if (!is_null($custom_request) && $custom_request == 'PUT') { - curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT'); - curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data); - } - if (!is_null($custom_request) && $custom_request == 'DELETE') { - curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'DELETE'); - } else { - curl_setopt($ch, CURLOPT_POST, true); - curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data); - } - } else { - if (!is_null($custom_request) && $custom_request == 'DELETE') { - curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'DELETE'); - } - } + $ch = $this->prepareCurlRequest($url, $post_data, $custom_request); // save HTTP Headers $curl_http_headers = [ @@ -621,6 +604,37 @@ private function proxyConfigCurlHandle(\CurlHandle $ch): void } } + private function prepareCurlRequest(string $url, array|string|null $post_data = null, ?string $custom_request = null) + { + 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); + + // post_data + if (!is_null($post_data)) { + // PUT REQUEST + if (!is_null($custom_request) && $custom_request == 'PUT') { + curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT'); + curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data); + } + if (!is_null($custom_request) && $custom_request == 'DELETE') { + curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'DELETE'); + } else { + curl_setopt($ch, CURLOPT_POST, true); + curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data); + } + } else { + if (!is_null($custom_request) && $custom_request == 'DELETE') { + curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'DELETE'); + } + } + + return $ch; + } + /** * setting REST API url to V2. * diff --git a/src/ServiceDesk/Request/Request.php b/src/ServiceDesk/Request/Request.php index 3476520a..bc86923d 100644 --- a/src/ServiceDesk/Request/Request.php +++ b/src/ServiceDesk/Request/Request.php @@ -125,6 +125,13 @@ private function map(object $data, object $target) { $mapper = new JsonMapper(); + // Adjust settings for JsonMapper v5.0 BC + if (property_exists($mapper, 'bStrictNullTypesInArrays')) { + $mapper->bStrictNullTypesInArrays = false; // if you want to allow nulls in arrays + } + $mapper->bStrictNullTypes = false; // if you want to allow nulls + $mapper->bStrictObjectTypeChecking = false; // if you want to disable strict type checking + return $mapper->map( $data, $target From 2e79233627ec666dc1693576ff3a82a42b542882 Mon Sep 17 00:00:00 2001 From: Tuen Lee Date: Sat, 20 Sep 2025 06:53:17 +0200 Subject: [PATCH 26/33] fix deprecated search to search/jql (#554) Co-authored-by: Tuen Lee Co-authored-by: KwangSeob Jeong --- src/Issue/IssueBulkResult.php | 82 +++++++++++++++++++++++++++++++++ src/Issue/IssueSearchResult.php | 50 ++++---------------- src/Issue/IssueService.php | 27 +++++------ 3 files changed, 104 insertions(+), 55 deletions(-) create mode 100644 src/Issue/IssueBulkResult.php diff --git a/src/Issue/IssueBulkResult.php b/src/Issue/IssueBulkResult.php new file mode 100644 index 00000000..804ed69d --- /dev/null +++ b/src/Issue/IssueBulkResult.php @@ -0,0 +1,82 @@ +issueErrors; + } + + /** + * @param array $issueErrors + */ + public function setIssueErrors($issueErrors) + { + $this->issueErrors = $issueErrors; + } + + /** + * @return Issue[] + */ + public function getIssues() + { + return $this->issues; + } + + /** + * @param Issue[] $issues + */ + public function setIssues($issues) + { + $this->issues = $issues; + } + + /** + * @param int $ndx + * + * @return Issue + */ + public function getIssue($ndx) + { + return $this->issues[$ndx]; + } + + /** + * @return string + */ + public function getExpand() + { + return $this->expand; + } + + /** + * @param string $expand + */ + public function setExpand($expand) + { + $this->expand = $expand; + } +} \ No newline at end of file diff --git a/src/Issue/IssueSearchResult.php b/src/Issue/IssueSearchResult.php index 9ba8bd47..628267ca 100644 --- a/src/Issue/IssueSearchResult.php +++ b/src/Issue/IssueSearchResult.php @@ -1,5 +1,4 @@ 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() + public function getNextPageToken() { - return $this->total; + return $this->nextPageToken; } /** - * @param int $total + * @param string $nextPageToken */ - public function setTotal($total) + public function setNextPageToken($nextPageToken) { - $this->total = $total; + $this->nextPageToken = $nextPageToken; } /** @@ -116,7 +82,7 @@ public function getIssue($ndx) /** * @return ?string */ - public function getExpand() + public function getExpand() : ?$string { return $this->expand; } diff --git a/src/Issue/IssueService.php b/src/Issue/IssueService.php index 88afa872..9f681506 100644 --- a/src/Issue/IssueService.php +++ b/src/Issue/IssueService.php @@ -534,25 +534,26 @@ public function transition($issueIdOrKey, $transition): ?string * * @return IssueSearchResult */ - public function search(string $jql, int $startAt = 0, int $maxResults = 15, array $fields = [], array $expand = [], bool $validateQuery = true): IssueSearchResult + public function search(string $jql, string $nextPageToken = '', int $maxResults = 50, array $fields = [], string $expand = '', array $reconcileIssues = []): IssueBulkResult { - $data = json_encode([ - 'jql' => $jql, - 'startAt' => $startAt, - 'maxResults' => $maxResults, - 'fields' => $fields, - 'expand' => $expand, - 'validateQuery' => $validateQuery, - ]); + $data = [ + 'jql' => $jql, + 'maxResults' => $maxResults, + 'fields' => $fields, + 'expand' => $expand, + 'reconcileIssues' => $reconcileIssues, + ]; - $ret = $this->exec('search', $data, 'POST'); - $json = json_decode($ret); + if ($nextPageToken) { + $data['nextPageToken'] = $nextPageToken; + } - $result = null; + $ret = $this->exec('search//jql', json_encode($data), 'POST'); + $json = json_decode($ret); $result = $this->json_mapper->map( $json, - new IssueSearchResult() + new IssueBulkResult() ); return $result; From ad68956e8384c5563b1c74f3e71e9befdb4290fe Mon Sep 17 00:00:00 2001 From: Stephan Maximilian Huber Date: Sun, 21 Sep 2025 16:57:50 +0200 Subject: [PATCH 27/33] Draft: Fix search (#555) * Fix PHP syntax error * Use correct result class for returning results from search We need to switch back to IssueSearchResult, as it contains sthe nextPageToken which is required for paged searches. * Add searchApproximateCount as the new search endpoint does not provide that info anymore --- src/Issue/IssueSearchResult.php | 3 ++- src/Issue/IssueService.php | 33 +++++++++++++++++++++++--- src/Issue/JQLCountResult.php | 42 +++++++++++++++++++++++++++++++++ 3 files changed, 74 insertions(+), 4 deletions(-) create mode 100644 src/Issue/JQLCountResult.php diff --git a/src/Issue/IssueSearchResult.php b/src/Issue/IssueSearchResult.php index 628267ca..9b9fafad 100644 --- a/src/Issue/IssueSearchResult.php +++ b/src/Issue/IssueSearchResult.php @@ -1,4 +1,5 @@ expand; } diff --git a/src/Issue/IssueService.php b/src/Issue/IssueService.php index 9f681506..15dd07e8 100644 --- a/src/Issue/IssueService.php +++ b/src/Issue/IssueService.php @@ -534,7 +534,7 @@ public function transition($issueIdOrKey, $transition): ?string * * @return IssueSearchResult */ - public function search(string $jql, string $nextPageToken = '', int $maxResults = 50, array $fields = [], string $expand = '', array $reconcileIssues = []): IssueBulkResult + public function search(string $jql, string $nextPageToken = '', int $maxResults = 50, array $fields = [], string $expand = '', array $reconcileIssues = []): IssueSearchResult { $data = [ 'jql' => $jql, @@ -548,12 +548,39 @@ public function search(string $jql, string $nextPageToken = '', int $maxResults $data['nextPageToken'] = $nextPageToken; } - $ret = $this->exec('search//jql', json_encode($data), 'POST'); + $ret = $this->exec('search/jql', json_encode($data), 'POST'); $json = json_decode($ret); $result = $this->json_mapper->map( $json, - new IssueBulkResult() + new IssueSearchResult() + ); + + return $result; + } + + /** + * Get an approximate count of issues that match a JQL query. + * + * @param string $jql The JQL query string + * + * @throws \JsonMapper_Exception + * @throws JiraException + * + * @return JQLCountResult + */ + public function searchApproximateCount(string $jql): JQLCountResult + { + $data = [ + 'jql' => $jql, + ]; + + $ret = $this->exec('search/approximate-count', json_encode($data), 'POST'); + $json = json_decode($ret); + + $result = $this->json_mapper->map( + $json, + new JQLCountResult() ); return $result; diff --git a/src/Issue/JQLCountResult.php b/src/Issue/JQLCountResult.php new file mode 100644 index 00000000..78209469 --- /dev/null +++ b/src/Issue/JQLCountResult.php @@ -0,0 +1,42 @@ +count; + } + + /** + * Set the count of issues. + * + * @param int $count + */ + public function setCount(int $count): void + { + $this->count = $count; + } + + #[\ReturnTypeWillChange] + public function jsonSerialize(): array + { + return [ + 'count' => $this->count + ]; + } +} From a055ce7a12740b772eb1f93beca7dcd50a5257f0 Mon Sep 17 00:00:00 2001 From: KwangSeob Jeong Date: Mon, 22 Sep 2025 00:22:29 +0900 Subject: [PATCH 28/33] Apply fixes from StyleCI (#556) [ci skip] [skip ci] Co-authored-by: StyleCI Bot --- src/Issue/IssueBulkResult.php | 2 +- src/Issue/JQLCountResult.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Issue/IssueBulkResult.php b/src/Issue/IssueBulkResult.php index 804ed69d..96debcd7 100644 --- a/src/Issue/IssueBulkResult.php +++ b/src/Issue/IssueBulkResult.php @@ -79,4 +79,4 @@ public function setExpand($expand) { $this->expand = $expand; } -} \ No newline at end of file +} diff --git a/src/Issue/JQLCountResult.php b/src/Issue/JQLCountResult.php index 78209469..aa748028 100644 --- a/src/Issue/JQLCountResult.php +++ b/src/Issue/JQLCountResult.php @@ -36,7 +36,7 @@ public function setCount(int $count): void public function jsonSerialize(): array { return [ - 'count' => $this->count + 'count' => $this->count, ]; } } From 27d379f7d15e2e56f54451405e4b37f2a580569b Mon Sep 17 00:00:00 2001 From: Katharina <42220355+peechyfloof@users.noreply.github.com> Date: Sun, 12 Oct 2025 12:53:12 +0200 Subject: [PATCH 29/33] Fix incorrect endpoint path for JQL search (#561) --- src/Issue/IssueService.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Issue/IssueService.php b/src/Issue/IssueService.php index 15dd07e8..16c74d4c 100644 --- a/src/Issue/IssueService.php +++ b/src/Issue/IssueService.php @@ -548,7 +548,7 @@ public function search(string $jql, string $nextPageToken = '', int $maxResults $data['nextPageToken'] = $nextPageToken; } - $ret = $this->exec('search/jql', json_encode($data), 'POST'); + $ret = $this->exec('/search/jql', json_encode($data), 'POST'); $json = json_decode($ret); $result = $this->json_mapper->map( From 4231809f550700f4f165ea40693991f2f26f0509 Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Sun, 12 Oct 2025 12:53:45 +0200 Subject: [PATCH 30/33] Remove unnecessary files from releases (#557) --- .gitattributes | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..5ad5c264 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,7 @@ +/tests-data export-ignore +/tests export-ignore + +/.* export-ignore +/phpstan-baseline.neon export-ignore +/phpstan-baseline.neon.dist export-ignore +/phpunit.xml export-ignore From b519738a3aa7224b7347267d8448536660cb96e7 Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Sun, 12 Oct 2025 12:54:10 +0200 Subject: [PATCH 31/33] next page token can be null (#559) --- src/Issue/IssueSearchResult.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Issue/IssueSearchResult.php b/src/Issue/IssueSearchResult.php index 9b9fafad..a714a1a6 100644 --- a/src/Issue/IssueSearchResult.php +++ b/src/Issue/IssueSearchResult.php @@ -39,7 +39,7 @@ class IssueSearchResult public $issues; /** - * @return int + * @return string|null */ public function getNextPageToken() { From b558e74b16bc8c42a74a2655f7064cd3a3874c39 Mon Sep 17 00:00:00 2001 From: Lee Rowlands Date: Sun, 12 Oct 2025 20:55:32 +1000 Subject: [PATCH 32/33] fix(Issue): Fix issue search (#560) Co-authored-by: KwangSeob Jeong From 68cc07a9b188c7ac7932e9be4074dd9169bfa451 Mon Sep 17 00:00:00 2001 From: Petr Kovalev Date: Sun, 12 Oct 2025 15:56:08 +0500 Subject: [PATCH 33/33] Fix: createUrlByContext (#563) --- src/JiraClient.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/JiraClient.php b/src/JiraClient.php index 02a7dd52..86b4db7d 100644 --- a/src/JiraClient.php +++ b/src/JiraClient.php @@ -418,7 +418,7 @@ protected function createUrlByContext(string $context): string { $host = $this->getConfiguration()->getJiraHost(); - return $host.$this->api_uri.'/'.preg_replace('/\//', '', $context, 1); + return $host.$this->api_uri.'/'.preg_replace('/^\//', '', $context, 1); } /**