From ebdc00ac2015c2e3058097a3ed799411a263acad Mon Sep 17 00:00:00 2001 From: Derrick Austin Date: Thu, 4 Jun 2026 17:02:40 -0500 Subject: [PATCH 1/2] fix: resolve PHP 8.4/8.5 deprecations in HttpAsset and BasePhpFormulaLoader MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A full PHPUnit run under PHP 8.4 and 8.5 (error_reporting=-1) surfaced two deprecations originating in the library's own src/: - HttpAsset::getLastModified() — the predefined locally scoped $http_response_header variable is deprecated in PHP 8.5. The existing function_exists('http_get_last_response_headers') shim does not suppress it: the notice is emitted at compile time from the bare variable read (verified via `php -l`, which executes nothing yet still emits it), so a runtime guard can never silence it. Reading it through the null-coalescing operator (`$http_response_header ?? []`) compiles to a non-deprecated fetch, keeping the pre-8.4 fallback working while emitting nothing on 8.5. `?? []` (not null) keeps the subsequent foreach safe. composer still pins php ^7.3 || ^8.0, so the legacy branch cannot be removed outright yet. - BasePhpFormulaLoader::processCall() — shell_exec() returns string|false|null, and passing null to unserialize()'s non-nullable string parameter is deprecated in PHP 8.4+. Guard with is_string(); the array() fallback is behaviour-identical to the previous unserialize(false) === false path. Also add the missing `use Assetic\Contracts\Filter\FilterInterface;` to CssImportFilter so the constructor's ?FilterInterface type hint resolves to the real interface instead of a non-existent Assetic\Filter\FilterInterface (a latent Error on any PHP version when a non-null filter is passed). Verified: zero project-src deprecations on PHP 8.4.14 and 8.5.5; the test suite remains green (HttpAsset, FormulaLoader and CssImportFilter tests all pass). --- src/Assetic/Asset/HttpAsset.php | 8 +++++--- src/Assetic/Factory/Loader/BasePhpFormulaLoader.php | 3 ++- src/Assetic/Filter/CssImportFilter.php | 1 + 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/Assetic/Asset/HttpAsset.php b/src/Assetic/Asset/HttpAsset.php index bf8b9ba..5a507f9 100644 --- a/src/Assetic/Asset/HttpAsset.php +++ b/src/Assetic/Asset/HttpAsset.php @@ -58,11 +58,13 @@ public function load(?FilterInterface $additionalFilter = null) public function getLastModified() { if (false !== @file_get_contents($this->sourceUrl, false, stream_context_create(array('http' => array('method' => 'HEAD'))))) { - // TODO: $http_response_header deprecated since PHP 8.5 - // Remove when min PHP >= 8.4 and use http_get_last_response_headers() directly + // http_get_last_response_headers() was added in PHP 8.4; older versions fall back + // to the predefined $http_response_header. The `?? []` coalescing read avoids the + // PHP 8.5 deprecation of that variable: a bare read is flagged at compile time, + // a coalescing read is not. Drop the fallback once the minimum PHP version is >= 8.4. $headers = function_exists('http_get_last_response_headers') ? http_get_last_response_headers() - : $http_response_header; + : ($http_response_header ?? []); foreach ($headers as $header) { if (0 === stripos($header, 'Last-Modified: ')) { list(, $mtime) = explode(':', $header, 2); diff --git a/src/Assetic/Factory/Loader/BasePhpFormulaLoader.php b/src/Assetic/Factory/Loader/BasePhpFormulaLoader.php index 75e039f..5297374 100644 --- a/src/Assetic/Factory/Loader/BasePhpFormulaLoader.php +++ b/src/Assetic/Factory/Loader/BasePhpFormulaLoader.php @@ -105,7 +105,8 @@ private function processCall($call, array $protoOptions = []) $call, 'echo serialize($_call);', ))); - $args = unserialize(shell_exec('php ' . escapeshellarg($tmp))); + $output = shell_exec('php ' . escapeshellarg($tmp)); + $args = is_string($output) ? unserialize($output) : array(); unlink($tmp); $inputs = isset($args[0]) ? self::argumentToArray($args[0]) : []; diff --git a/src/Assetic/Filter/CssImportFilter.php b/src/Assetic/Filter/CssImportFilter.php index 882ab7a..a7abc2f 100644 --- a/src/Assetic/Filter/CssImportFilter.php +++ b/src/Assetic/Filter/CssImportFilter.php @@ -7,6 +7,7 @@ use Assetic\Asset\HttpAsset; use Assetic\Factory\AssetFactory; use Assetic\Contracts\Filter\DependencyExtractorInterface; +use Assetic\Contracts\Filter\FilterInterface; /** * Inlines imported stylesheets. From 49783b75e5643762bca6077700a841c0c1aee8a3 Mon Sep 17 00:00:00 2001 From: Luke Towers Date: Thu, 4 Jun 2026 15:49:44 -0700 Subject: [PATCH 2/2] Apply suggestion from @jaxwilko Co-authored-by: Jack Wilkinson <31214002+jaxwilko@users.noreply.github.com> --- src/Assetic/Factory/Loader/BasePhpFormulaLoader.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Assetic/Factory/Loader/BasePhpFormulaLoader.php b/src/Assetic/Factory/Loader/BasePhpFormulaLoader.php index 5297374..4c2bf86 100644 --- a/src/Assetic/Factory/Loader/BasePhpFormulaLoader.php +++ b/src/Assetic/Factory/Loader/BasePhpFormulaLoader.php @@ -106,7 +106,7 @@ private function processCall($call, array $protoOptions = []) 'echo serialize($_call);', ))); $output = shell_exec('php ' . escapeshellarg($tmp)); - $args = is_string($output) ? unserialize($output) : array(); + $args = is_string($output) ? unserialize($output) : []; unlink($tmp); $inputs = isset($args[0]) ? self::argumentToArray($args[0]) : [];