diff --git a/.styleci.yml b/.styleci.yml index 6cf29b27..f6dbf717 100644 --- a/.styleci.yml +++ b/.styleci.yml @@ -18,7 +18,6 @@ enabled: - declare_strict_types - dir_constant - empty_loop_body_braces - - function_to_constant - hash_to_slash_comment - integer_literal_case - is_null diff --git a/src/http/ErrorHandler.php b/src/http/ErrorHandler.php index 872e70d0..56df7d3d 100644 --- a/src/http/ErrorHandler.php +++ b/src/http/ErrorHandler.php @@ -119,7 +119,7 @@ public function handleException($exception): Response $this->unregister(); - if (PHP_SAPI !== 'cli') { + if (php_sapi_name() !== 'cli') { $statusCode = 500; if ($exception instanceof HttpException) { diff --git a/tests/http/ErrorHandlerTest.php b/tests/http/ErrorHandlerTest.php index 683f95dd..e339a648 100644 --- a/tests/http/ErrorHandlerTest.php +++ b/tests/http/ErrorHandlerTest.php @@ -5,11 +5,13 @@ namespace yii2\extensions\psrbridge\tests\http; use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\TestWith; use RuntimeException; use Throwable; use yii\base\{Exception, UserException}; use yii\web\HttpException; use yii2\extensions\psrbridge\http\{ErrorHandler, Response}; +use yii2\extensions\psrbridge\tests\support\stub\HTTPFunctions; use yii2\extensions\psrbridge\tests\TestCase; use function str_repeat; @@ -17,6 +19,13 @@ #[Group('http')] final class ErrorHandlerTest extends TestCase { + protected function tearDown(): void + { + HTTPFunctions::reset(); + + parent::tearDown(); + } + public function testHandleExceptionResetsState(): void { $errorHandler = new ErrorHandler(); @@ -97,8 +106,12 @@ public function testHandleExceptionWithGenericException(): void ); } - public function testHandleExceptionWithHttpException(): void + #[TestWith(['apache'])] + #[TestWith(['cli'])] + public function testHandleExceptionWithHttpException(string $sapi): void { + HTTPFunctions::set_sapi($sapi); + $errorHandler = new ErrorHandler(); $errorHandler->discardExistingOutput = false; @@ -116,6 +129,11 @@ public function testHandleExceptionWithHttpException(): void $response->data, 'Should set response data for HTTP exception.', ); + self::assertSame( + $sapi, + HTTPFunctions::php_sapi_name(), + "Should return correct SAPI name '{$sapi}' for 'HttpException'.", + ); } public function testHandleExceptionWithLongMessage(): void diff --git a/tests/support/MockerExtension.php b/tests/support/MockerExtension.php index e4c21b8b..9cd9b5b0 100644 --- a/tests/support/MockerExtension.php +++ b/tests/support/MockerExtension.php @@ -73,6 +73,11 @@ public static function load(): void $line, ), ], + [ + 'namespace' => 'yii2\extensions\psrbridge\http', + 'name' => 'php_sapi_name', + 'function' => static fn(): string => HTTPFunctions::php_sapi_name(), + ], [ 'namespace' => 'yii2\extensions\psrbridge\adapter', 'name' => 'stream_get_contents', diff --git a/tests/support/stub/HTTPFunctions.php b/tests/support/stub/HTTPFunctions.php index 85f9c3a8..4d5f187c 100644 --- a/tests/support/stub/HTTPFunctions.php +++ b/tests/support/stub/HTTPFunctions.php @@ -15,19 +15,20 @@ * Provides controlled replacements for core PHP HTTP header and response functions to facilitate testing of HTTP * emitter and response-related code without actual header output or side effects. * - * This class allows tests to simulate and inspect HTTP header operations, response codes, and output flushing by - * maintaining internal state and exposing methods to manipulate and query that state. + * This class allows tests to simulate and inspect HTTP header operations, response codes, output flushing, + * and SAPI name retrieval by maintaining internal state and exposing methods to manipulate and query that state. * - * It enables validation of emitter logic, header management, and response code handling in isolation from PHP's global - * state. + * It enables validation of emitter logic, header management, response code handling, and SAPI simulation in isolation + * from PHP global state. * * Key features. * - Complete simulation of {@see \header()}, {@see \headers_sent()}, {@see \header_remove()}, {@see \headers_list()}, - * and {@see \http_response_code()} + * {@see \http_response_code()}, and {@see php_sapi_name()} for test reliability. * - Consistent behavior matching PHP's native functions for test reliability. * - File and line tracking for headers_sent simulation. * - Header inspection and manipulation for assertions. * - Simulated output flushing and flush count tracking. + * - SAPI name simulation for emitter and environment testing. * - State reset capability for test isolation and repeatability. * * @copyright Copyright (C) 2025 Terabytesoftw. @@ -67,6 +68,11 @@ final class HTTPFunctions */ private static int $responseCode = 200; + /** + * Tracks the current SAPI name for simulation. + */ + private static string $sapi = 'cli'; + /** * Controls whether stream_get_contents should fail. */ @@ -154,6 +160,11 @@ public static function http_response_code(int|null $response_code = 0): int return self::$responseCode; } + public static function php_sapi_name(): string + { + return self::$sapi; + } + public static function reset(): void { self::$flushedTimes = 0; @@ -162,6 +173,7 @@ public static function reset(): void self::$headersSentFile = ''; self::$headersSentLine = 0; self::$responseCode = 200; + self::$sapi = 'cli'; self::$streamGetContentsShouldFail = false; } @@ -172,6 +184,11 @@ public static function set_headers_sent(bool $value = false, string $file = '', self::$headersSentLine = $line; } + public static function set_sapi(string $sapi): void + { + self::$sapi = $sapi; + } + public static function set_stream_get_contents_should_fail(bool $shouldFail = true): void { self::$streamGetContentsShouldFail = $shouldFail;