From 37e973b68b25470c88330bcf1454fcd84b795111 Mon Sep 17 00:00:00 2001 From: Sergei Predvoditelev Date: Fri, 30 Oct 2026 11:31:19 +0300 Subject: [PATCH 1/2] Use `http_get_last_response_headers()` in `NativeTransport` on PHP 8.4+ --- CHANGELOG.md | 1 + src/Transport/NativeTransport.php | 15 ++++++++++++--- .../NativeTransport/NativeTransportTest.php | 2 ++ .../NativeTransport/StreamMock/StreamMock.php | 19 +++++++++++++++++-- .../NativeTransport/StreamMock/functions.php | 18 ++++++++++++++++++ 5 files changed, 50 insertions(+), 5 deletions(-) create mode 100644 tests/Transport/NativeTransport/StreamMock/functions.php diff --git a/CHANGELOG.md b/CHANGELOG.md index 2e8289b0..775bf54c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ the original error message. - Enh #229: Replace Psalm with PHPStan for static analysis. - Enh #230: Add PHP 8.6 support. +- Enh #231: Use `http_get_last_response_headers()` in `NativeTransport` on PHP 8.4+. - Bug #227: Throw `InvalidArgumentException` on serialization of rich text that contains an element other than a string, a `RichText` object or an array of them, instead of failing with `TypeError` or silently casting scalars to strings. diff --git a/src/Transport/NativeTransport.php b/src/Transport/NativeTransport.php index 927bbece..9e0774e8 100644 --- a/src/Transport/NativeTransport.php +++ b/src/Transport/NativeTransport.php @@ -93,7 +93,11 @@ static function (int $errorNumber, string $errorString): bool { */ private function send(string $url, array $options): ApiResponse { - global $http_response_header; + if (PHP_VERSION_ID < 80400) { + // The variable name is dynamic to avoid the deprecation of `$http_response_header` in PHP 8.5+. + $headersVariableName = 'http_response_header'; + global ${$headersVariableName}; + } $options['ignore_errors'] = true; @@ -114,12 +118,17 @@ static function (int $errorNumber, string $errorString): bool { } /** - * @var non-empty-list $http_response_header + * @var non-empty-list $headers We throw an exception on error, so the response is received and headers + * contain at least the status line. + * @see https://www.php.net/manual/function.http-get-last-response-headers.php * @see https://www.php.net/manual/reserved.variables.httpresponseheader.php */ + $headers = PHP_VERSION_ID < 80400 + ? ${$headersVariableName} + : http_get_last_response_headers(); return new ApiResponse( - $this->parseStatusCode($http_response_header), + $this->parseStatusCode($headers), $body, ); } diff --git a/tests/Transport/NativeTransport/NativeTransportTest.php b/tests/Transport/NativeTransport/NativeTransportTest.php index cf92f826..0a056763 100644 --- a/tests/Transport/NativeTransport/NativeTransportTest.php +++ b/tests/Transport/NativeTransport/NativeTransportTest.php @@ -20,6 +20,8 @@ use function PHPUnit\Framework\assertTrue; use function sprintf; +require_once __DIR__ . '/StreamMock/functions.php'; + final class NativeTransportTest extends TestCase { public function testGet(): void diff --git a/tests/Transport/NativeTransport/StreamMock/StreamMock.php b/tests/Transport/NativeTransport/StreamMock/StreamMock.php index 76b7af8a..b2fe8a5f 100644 --- a/tests/Transport/NativeTransport/StreamMock/StreamMock.php +++ b/tests/Transport/NativeTransport/StreamMock/StreamMock.php @@ -25,6 +25,11 @@ final class StreamMock private int $position = 0; + /** + * @var list|null + */ + private static ?array $lastResponseHeaders = null; + /** * @var resource */ @@ -73,6 +78,7 @@ public static function enable(array $responseHeaders = [], string $responseBody if (file_exists(self::REQUEST_FILE)) { unlink(self::REQUEST_FILE); } + self::$lastResponseHeaders = null; stream_wrapper_unregister('http'); stream_wrapper_register('http', self::class, STREAM_IS_URL); @@ -84,6 +90,7 @@ public static function enable(array $responseHeaders = [], string $responseBody public static function disable(): ?array { stream_wrapper_restore('http'); + self::$lastResponseHeaders = null; if (!file_exists(self::REQUEST_FILE)) { return null; @@ -143,10 +150,18 @@ public function stream_stat(): array return []; } + /** + * @return list|null + */ + public static function getLastResponseHeaders(): ?array + { + return self::$lastResponseHeaders; + } + public function stream_close(): void { - global $http_response_header; - $http_response_header = $this->config['responseHeaders']; + self::$lastResponseHeaders = $this->config['responseHeaders']; + $GLOBALS['http_response_header'] = $this->config['responseHeaders']; } private static function readFile(string $path): string diff --git a/tests/Transport/NativeTransport/StreamMock/functions.php b/tests/Transport/NativeTransport/StreamMock/functions.php new file mode 100644 index 00000000..af3a1ab0 --- /dev/null +++ b/tests/Transport/NativeTransport/StreamMock/functions.php @@ -0,0 +1,18 @@ +|null + */ +function http_get_last_response_headers(): ?array +{ + return StreamMock::getLastResponseHeaders() ?? \http_get_last_response_headers(); +} From f1264ab2729a9841a40f16849667def25475d4a0 Mon Sep 17 00:00:00 2001 From: Sergei Predvoditelev Date: Fri, 30 Oct 2026 11:35:17 +0300 Subject: [PATCH 2/2] fix --- tests/Transport/NativeTransport/StreamMock/functions.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Transport/NativeTransport/StreamMock/functions.php b/tests/Transport/NativeTransport/StreamMock/functions.php index af3a1ab0..fdb1591c 100644 --- a/tests/Transport/NativeTransport/StreamMock/functions.php +++ b/tests/Transport/NativeTransport/StreamMock/functions.php @@ -14,5 +14,5 @@ */ function http_get_last_response_headers(): ?array { - return StreamMock::getLastResponseHeaders() ?? \http_get_last_response_headers(); + return StreamMock::getLastResponseHeaders(); }