diff --git a/src/Redmine/Api/Issue.php b/src/Redmine/Api/Issue.php index 7319b364..eb481235 100644 --- a/src/Redmine/Api/Issue.php +++ b/src/Redmine/Api/Issue.php @@ -8,6 +8,7 @@ use Redmine\Exception; use Redmine\Exception\SerializerException; use Redmine\Exception\UnexpectedResponseException; +use Redmine\Future; use Redmine\Http\HttpClient; use Redmine\Http\HttpFactory; use Redmine\Serializer\JsonSerializer; @@ -254,8 +255,12 @@ public function create(array $params = []) $body = $this->lastResponse->getContent(); - if ($body === '') { - return $body; + if ($this->lastResponse->getStatusCode() !== 201) { + if (!Future::isForwardCompatibilityEnabled() && $body === '') { + return $body; + } + + throw UnexpectedResponseException::create($this->lastResponse); } return new SimpleXMLElement($body); diff --git a/src/Redmine/Client/ClientApiTrait.php b/src/Redmine/Client/ClientApiTrait.php index c0e71859..f18885ad 100644 --- a/src/Redmine/Client/ClientApiTrait.php +++ b/src/Redmine/Client/ClientApiTrait.php @@ -4,6 +4,7 @@ use Redmine\Api; use Redmine\Exception\InvalidApiNameException; +use Redmine\Future; /** * Provide API instantiation to clients. @@ -60,6 +61,11 @@ public function getApi(string $name): Api return $this->apiInstances[$name]; } + public function enableFutureMode(): void + { + Future::enableForwardCompatibility(); + } + private function isUploadCall(string $path): bool { $path = strtolower($path); diff --git a/src/Redmine/Future.php b/src/Redmine/Future.php new file mode 100644 index 00000000..a4e9b61c --- /dev/null +++ b/src/Redmine/Future.php @@ -0,0 +1,28 @@ +assertSame('', $return); } + public function testCreateWithIncorrectStatusCodeThrowsException(): void + { + $client = AssertingHttpClient::create( + $this, + [ + 'POST', + '/issues.xml', + 'application/xml', + '', + 500, + '', + '', + ], + ); + + // Create the object under test + $api = Issue::fromHttpClient($client); + + $this->expectException(UnexpectedResponseException::class); + + try { + Future::enableForwardCompatibility(); + + $api->create([]); + } finally { + Future::disableForwardCompatibility(); + } + } + public function testCreateWithHttpClientRetrievesIssueStatusId(): void { $client = AssertingHttpClient::create( @@ -279,7 +310,7 @@ public function testCreateWithHttpClientRetrievesIssueStatusId(): void '/issues.xml', 'application/xml', '123', - 200, + 201, 'application/xml', '', ], @@ -316,7 +347,7 @@ public function testCreateWithHttpClientRetrievesProjectId(): void '/issues.xml', 'application/xml', '3', - 200, + 201, 'application/xml', '', ], @@ -353,7 +384,7 @@ public function testCreateWithHttpClientRetrievesIssueCategoryId(): void '/issues.xml', 'application/xml', '345', - 200, + 201, 'application/xml', '', ], @@ -390,7 +421,7 @@ public function testCreateWithHttpClientRetrievesTrackerId(): void '/issues.xml', 'application/xml', '9', - 200, + 201, 'application/xml', '', ], @@ -427,7 +458,7 @@ public function testCreateWithHttpClientRetrievesUserId(): void '/issues.xml', 'application/xml', '65', - 200, + 201, 'application/xml', '', ], @@ -513,7 +544,7 @@ public function testCreateWithClientCleansParameters(): void 5 XML, - 200, + 201, 'application/xml', '', ], diff --git a/tests/Unit/Api/IssueTest.php b/tests/Unit/Api/IssueTest.php index 1e112f25..695e5b04 100644 --- a/tests/Unit/Api/IssueTest.php +++ b/tests/Unit/Api/IssueTest.php @@ -276,6 +276,9 @@ public function testCreateWithClientCleansParameters(): void $legacyClient->expects($this->exactly(1)) ->method('getLastResponseContentType') ->willReturn('application/xml'); + $legacyClient->expects($this->exactly(1)) + ->method('getLastResponseStatusCode') + ->willReturn(201); // Create the object under test $api = new Issue($legacyClient); diff --git a/tests/Unit/Client/NativeCurlClient/EnableFutureModeTest.php b/tests/Unit/Client/NativeCurlClient/EnableFutureModeTest.php new file mode 100644 index 00000000..daff3a28 --- /dev/null +++ b/tests/Unit/Client/NativeCurlClient/EnableFutureModeTest.php @@ -0,0 +1,29 @@ +enableFutureMode(); + + self::assertTrue(Future::isForwardCompatibilityEnabled()); + + Future::disableForwardCompatibility(); + } +} diff --git a/tests/Unit/Client/Psr18Client/EnableFutureModeTest.php b/tests/Unit/Client/Psr18Client/EnableFutureModeTest.php new file mode 100644 index 00000000..a77f27c9 --- /dev/null +++ b/tests/Unit/Client/Psr18Client/EnableFutureModeTest.php @@ -0,0 +1,35 @@ +createStub(ClientInterface::class), + $this->createStub(RequestFactoryInterface::class), + $this->createStub(StreamFactoryInterface::class), + '', + '', + ); + $client->enableFutureMode(); + + self::assertTrue(Future::isForwardCompatibilityEnabled()); + + Future::disableForwardCompatibility(); + } +} diff --git a/tests/Unit/FutureTest.php b/tests/Unit/FutureTest.php new file mode 100644 index 00000000..1b15e8cf --- /dev/null +++ b/tests/Unit/FutureTest.php @@ -0,0 +1,32 @@ +