diff --git a/ext/standard/ModuleRegistry.php b/ext/standard/ModuleRegistry.php index 611d38eb381..9b9397b212e 100644 --- a/ext/standard/ModuleRegistry.php +++ b/ext/standard/ModuleRegistry.php @@ -278,6 +278,7 @@ private static function functionBelongsToLogicalExtension(string $functionName, 'readline' => str_starts_with($functionName, 'readline'), 'bcmath' => str_starts_with($functionName, 'bc'), 'openssl' => str_starts_with($functionName, 'openssl_'), + 'zip' => str_starts_with($functionName, 'zip_'), default => false, }; } diff --git a/ext/zip/Module.php b/ext/zip/Module.php index 436f99d6887..581e91e6d8c 100644 --- a/ext/zip/Module.php +++ b/ext/zip/Module.php @@ -8,9 +8,11 @@ use PHPCompiler\Runtime; /** - * zip extension module entry (php-src ext/zip/php_zip.c; issues #5869, #3337, #6370). + * zip extension module entry (php-src ext/zip/php_zip.c; issues #5869, #3337, #6370, #18137). * - * ZipArchive uses pure-PHP store engine ({@see ZipEngine}); procedural zip_* API in {@see VmZipProcedural}. + * Register under {@see standard}; advertise logical {@code zip} extension, ZipArchive, and + * zip_* procedural API when {@see ZipExtensionPolicy::advertisesExtension()} — withheld on + * reference profile (Zend 8.2 harness has no ext/zip). */ class Module extends ModuleAbstract { @@ -22,7 +24,19 @@ public function init(Runtime $runtime): void public function getExtensionName(): string { - return 'zip'; + return 'standard'; + } + + /** + * @return list + */ + public function getAdditionalExtensionNames(): array + { + if (!ZipExtensionPolicy::advertisesExtension()) { + return []; + } + + return ['zip']; } public function getFunctions(): array diff --git a/ext/zip/ZipExtensionPolicy.php b/ext/zip/ZipExtensionPolicy.php index 34618373686..5af17ec9be2 100644 --- a/ext/zip/ZipExtensionPolicy.php +++ b/ext/zip/ZipExtensionPolicy.php @@ -4,15 +4,19 @@ namespace PHPCompiler\ext\zip; +use PHPCompiler\CompilerVersion; + /** - * ext/zip surface advertisement — php-src ext/zip/php_zip.c (#11676, #3337). + * ext/zip surface advertisement — php-src ext/zip/php_zip.c (#11676, #18137, #3337). * - * Pure-PHP ZipArchive ({@see VmZipArchive}) registers when the zip module loads. + * Pure-PHP ZipArchive ({@see VmZipArchive}) and zip_* procedural API stay compiled in-tree but + * are withheld from extension_loaded() and class_exists() on the reference profile until + * {@see CompilerVersion::supportsZip()}. */ final class ZipExtensionPolicy { public static function advertisesExtension(): bool { - return class_exists(VmZipArchive::class); + return CompilerVersion::supportsZip(); } } diff --git a/lib/CompilerVersion.php b/lib/CompilerVersion.php index 44d409967fa..fab926df7fe 100644 --- a/lib/CompilerVersion.php +++ b/lib/CompilerVersion.php @@ -2284,6 +2284,17 @@ public static function supportsMsgpack(): bool return version_compare(self::languageProfileVersion(), '8.4.0', '>='); } + /** + * ext/zip via pure PHP {@see \PHPCompiler\ext\zip\VmZipArchive} — withheld on reference profile (#18137, #11676). + * + * Gated on stable 8.4.0 / {@see languageProfileVersion()} so 8.4.0-dev reference profile matches Zend 8.2 + * phantom gate (host ext-zip absent). Enable forward profile via `PHP_COMPILER_PROFILE=8.4`. + */ + public static function supportsZip(): bool + { + return version_compare(self::languageProfileVersion(), '8.4.0', '>='); + } + /** * ext/brotli via pure PHP {@see \PHPCompiler\ext\brotli\VmBrotliNative} — withheld on reference profile (#17563). * diff --git a/test/compliance/JITTest.php b/test/compliance/JITTest.php index df0c3641f1b..d3176b91da5 100755 --- a/test/compliance/JITTest.php +++ b/test/compliance/JITTest.php @@ -634,6 +634,12 @@ public static function providePHPTests(): \Generator && !str_contains($name, 'extension_loaded_msgpack')) { continue; } + if (!CompilerVersion::supportsZip() + && (str_contains($name, 'zip') + || str_contains($name, 'ziparchive')) + && !str_contains($name, 'extension_loaded_zip')) { + continue; + } if (!CompilerVersion::supportsUri() && str_contains($name, 'uri_rfc3986') && !str_contains($name, 'uri_phantom')) { diff --git a/test/compliance/VMTest.php b/test/compliance/VMTest.php index 857b811ab16..efe102db67f 100755 --- a/test/compliance/VMTest.php +++ b/test/compliance/VMTest.php @@ -521,6 +521,12 @@ public static function providePHPTests(): \Generator && !str_contains($name, 'extension_loaded_msgpack')) { continue; } + if (!CompilerVersion::supportsZip() + && (str_contains($name, 'zip') + || str_contains($name, 'ziparchive')) + && !str_contains($name, 'extension_loaded_zip')) { + continue; + } if (!CompilerVersion::supportsUri() && str_contains($name, 'uri_rfc3986') && !str_contains($name, 'uri_phantom')) { diff --git a/test/compliance/cases/stdlib/extension_loaded_zip_phantom.phpt b/test/compliance/cases/stdlib/extension_loaded_zip_phantom.phpt index e2d0716227f..c16b12df264 100644 --- a/test/compliance/cases/stdlib/extension_loaded_zip_phantom.phpt +++ b/test/compliance/cases/stdlib/extension_loaded_zip_phantom.phpt @@ -1,13 +1,15 @@ --TEST-- -stdlib extension_loaded('zip') true with pure-PHP ZipArchive (#3337, ext/zip/php_zip.c) +stdlib extension_loaded('zip') withheld on reference profile (#18137, ext/zip/php_zip.c) --FILE--