diff --git a/src/http/ErrorHandler.php b/src/http/ErrorHandler.php index 56df7d3d..8feb5de6 100644 --- a/src/http/ErrorHandler.php +++ b/src/http/ErrorHandler.php @@ -14,7 +14,6 @@ use function array_diff_key; use function array_flip; use function htmlspecialchars; -use function http_response_code; use function ini_set; /** @@ -120,11 +119,7 @@ public function handleException($exception): Response $this->unregister(); if (php_sapi_name() !== 'cli') { - $statusCode = 500; - - if ($exception instanceof HttpException) { - $statusCode = $exception->statusCode; - } + $statusCode = $exception instanceof HttpException ? $exception->statusCode : 500; http_response_code($statusCode); } diff --git a/tests/http/ErrorHandlerTest.php b/tests/http/ErrorHandlerTest.php index 8a351a64..23010cf6 100644 --- a/tests/http/ErrorHandlerTest.php +++ b/tests/http/ErrorHandlerTest.php @@ -68,6 +68,64 @@ public function testClearOutputCleansAllBuffersInNonTestEnvironment(): void } } + public function testHandleExceptionCallsHttpResponseCodeInNonCliSapi(): void + { + HTTPFunctions::set_sapi('apache2handler'); + + $errorHandler = new ErrorHandler(); + + $errorHandler->discardExistingOutput = false; + + $exception = new Exception('Test exception for non-CLI SAPI'); + + $response = $errorHandler->handleException($exception); + + self::assertSame( + 'apache2handler', + HTTPFunctions::php_sapi_name(), + "Should return 'apache2handler' as the SAPI name when running in non-CLI environment.", + ); + self::assertSame( + 1, + HTTPFunctions::getHttpResponseCodeCalls(), + "Should call 'http_response_code()' exactly once in non-CLI SAPI; call count must be '1'.", + ); + self::assertSame( + 500, + $response->getStatusCode(), + "Should set status code to '500' for Exception in non-CLI SAPI.", + ); + } + + public function testHandleExceptionDoesNotCallHttpResponseCodeInCliSapi(): void + { + HTTPFunctions::set_sapi('cli'); + + $errorHandler = new ErrorHandler(); + + $errorHandler->discardExistingOutput = false; + + $exception = new Exception('Test exception for CLI SAPI'); + + $response = $errorHandler->handleException($exception); + + self::assertSame( + 'cli', + HTTPFunctions::php_sapi_name(), + "Should return 'cli' as the SAPI name when running in CLI environment.", + ); + self::assertSame( + 0, + HTTPFunctions::getHttpResponseCodeCalls(), + "Should not call 'http_response_code()' in CLI SAPI; call count must remain '0'.", + ); + self::assertSame( + 500, + $response->getStatusCode(), + "Should set status code to '500' for Exception in CLI SAPI.", + ); + } + public function testHandleExceptionResetsState(): void { $errorHandler = new ErrorHandler(); diff --git a/tests/support/MockerExtension.php b/tests/support/MockerExtension.php index 9cd9b5b0..d6063970 100644 --- a/tests/support/MockerExtension.php +++ b/tests/support/MockerExtension.php @@ -73,6 +73,13 @@ public static function load(): void $line, ), ], + [ + 'namespace' => 'yii2\extensions\psrbridge\http', + 'name' => 'http_response_code', + 'function' => static fn(int|null $response_code = null): int => HTTPFunctions::http_response_code( + $response_code, + ), + ], [ 'namespace' => 'yii2\extensions\psrbridge\http', 'name' => 'php_sapi_name', diff --git a/tests/support/stub/HTTPFunctions.php b/tests/support/stub/HTTPFunctions.php index 4d5f187c..15dd89c5 100644 --- a/tests/support/stub/HTTPFunctions.php +++ b/tests/support/stub/HTTPFunctions.php @@ -63,6 +63,11 @@ final class HTTPFunctions */ private static int $headersSentLine = 0; + /** + * Tracks the number of times {@see \http_response_code()} was called. + */ + private static int $httpResponseCodeCalls = 0; + /** * Tracks the HTTP response code. */ @@ -96,6 +101,11 @@ public static function getHeader(string $header): array return self::$headers[strtolower($header)] ?? []; } + public static function getHttpResponseCodeCalls(): int + { + return self::$httpResponseCodeCalls; + } + public static function hasHeader(string $header): bool { return array_key_exists(strtolower($header), self::$headers); @@ -153,6 +163,8 @@ public static function headers_sent(mixed &$file = null, mixed &$line = null): b public static function http_response_code(int|null $response_code = 0): int { + self::$httpResponseCodeCalls++; + if ($response_code > 0) { self::$responseCode = $response_code; } @@ -172,6 +184,7 @@ public static function reset(): void self::$headersSent = false; self::$headersSentFile = ''; self::$headersSentLine = 0; + self::$httpResponseCodeCalls = 0; self::$responseCode = 200; self::$sapi = 'cli'; self::$streamGetContentsShouldFail = false;