From fd35eb1ba8e9b32f3eb5a8378ee374d5ae9a7d2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20FIDRY?= Date: Sat, 28 Apr 2018 14:41:42 +0100 Subject: [PATCH] Fix PHAR minimal requirements When a PHAR is compressed, it also requires the PHP extension `zip`. Closes #164 --- src/Console/Command/Compile.php | 2 +- .../AppRequirementsFactory.php | 15 ++- src/RequirementChecker/RequirementsDumper.php | 8 +- .../AppRequirementsFactoryTest.php | 91 ++++++++++++++++++- 4 files changed, 103 insertions(+), 13 deletions(-) diff --git a/src/Console/Command/Compile.php b/src/Console/Command/Compile.php index 02a9a66a9..1752a1362 100644 --- a/src/Console/Command/Compile.php +++ b/src/Console/Command/Compile.php @@ -432,7 +432,7 @@ private function registerRequirementsChecker(Configuration $config, Box $box, Bu 'Adding requirements checker' ); - $checkFiles = RequirementsDumper::dump($config->getComposerLockDecodedContents()); + $checkFiles = RequirementsDumper::dump($config->getComposerLockDecodedContents(), null !== $config->getCompressionAlgorithm()); foreach ($checkFiles as $fileWithContents) { [$file, $contents] = $fileWithContents; diff --git a/src/RequirementChecker/AppRequirementsFactory.php b/src/RequirementChecker/AppRequirementsFactory.php index bd45920d6..9a0467a2d 100644 --- a/src/RequirementChecker/AppRequirementsFactory.php +++ b/src/RequirementChecker/AppRequirementsFactory.php @@ -33,11 +33,12 @@ final class AppRequirementsFactory * * @return array Serialized configured requirements */ - public static function create(array $composerLockDecodedContents): array + public static function create(array $composerLockDecodedContents, bool $compressed): array { return self::configureExtensionRequirements( self::configurePhpVersionRequirements([], $composerLockDecodedContents), - $composerLockDecodedContents + $composerLockDecodedContents, + $compressed ); } @@ -88,9 +89,9 @@ private static function configurePhpVersionRequirements(array $requirements, arr return $requirements; } - private static function configureExtensionRequirements(array $requirements, array $composerLockContents): array + private static function configureExtensionRequirements(array $requirements, array $composerLockContents, bool $compressed): array { - $extensionRequirements = self::collectExtensionRequirements($composerLockContents); + $extensionRequirements = self::collectExtensionRequirements($composerLockContents, $compressed); foreach ($extensionRequirements as $extension => $packages) { foreach ($packages as $package) { @@ -135,11 +136,15 @@ private static function configureExtensionRequirements(array $requirements, arra * * @return array Associative array containing the list of extensions required */ - private static function collectExtensionRequirements(array $composerLockContents): array + private static function collectExtensionRequirements(array $composerLockContents, bool $compressed): array { $requirements = []; $polyfills = []; + if ($compressed) { + $requirements['zip'] = [self::SELF_PACKAGE]; + } + $platform = $composerLockContents['platform'] ?? []; foreach ($platform as $package => $constraint) { diff --git a/src/RequirementChecker/RequirementsDumper.php b/src/RequirementChecker/RequirementsDumper.php index ec908df07..2e70dec15 100644 --- a/src/RequirementChecker/RequirementsDumper.php +++ b/src/RequirementChecker/RequirementsDumper.php @@ -57,10 +57,10 @@ final class RequirementsDumper /** * @return string[][] */ - public static function dump(array $composerLockDecodedContents): array + public static function dump(array $composerLockDecodedContents, bool $compressed): array { $filesWithContents = [ - self::dumpRequirementsConfig($composerLockDecodedContents), + self::dumpRequirementsConfig($composerLockDecodedContents, $compressed), [self::CHECK_FILE_NAME, self::REQUIREMENTS_CHECKER_TEMPLATE], ]; @@ -80,9 +80,9 @@ public static function dump(array $composerLockDecodedContents): array return $filesWithContents; } - private static function dumpRequirementsConfig(array $composerLockDecodedContents): array + private static function dumpRequirementsConfig(array $composerLockDecodedContents, bool $compressed): array { - $config = AppRequirementsFactory::create($composerLockDecodedContents); + $config = AppRequirementsFactory::create($composerLockDecodedContents, $compressed); return [ '.requirements.php', diff --git a/tests/RequirementChecker/AppRequirementsFactoryTest.php b/tests/RequirementChecker/AppRequirementsFactoryTest.php index fa77a2b8d..98638bc33 100644 --- a/tests/RequirementChecker/AppRequirementsFactoryTest.php +++ b/tests/RequirementChecker/AppRequirementsFactoryTest.php @@ -20,14 +20,14 @@ /** * @coversNothing */ -class AppRequirementsFactoryTest extends TestCase +class pAppRequirementsFactoryTest extends TestCase { /** * @dataProvider provideLockContents */ - public function test_it_can_generate_and_serialized_requirements_from_a_composer_lock_file(string $composerLockContents, array $expected): void + public function test_it_can_generate_and_serialized_requirements_from_a_composer_lock_file(string $composerLockContents, bool $compressed, array $expected): void { - $actual = AppRequirementsFactory::create(json_decode($composerLockContents, true)); + $actual = AppRequirementsFactory::create(json_decode($composerLockContents, true), $compressed); $this->assertSame($expected, $actual); } @@ -36,9 +36,22 @@ public function provideLockContents() { yield 'empty lock file' => [ '{}', + false, [], ]; + yield 'empty lock file (compressed PHAR)' => [ + '{}', + true, + [ + [ + "return \\extension_loaded('zip');", + 'The application requires the extension "zip". Enable it or install a polyfill.', + 'The application requires the extension "zip".', + ], + ], + ]; + yield 'lock file platform requirements' => [ <<<'JSON' { @@ -50,6 +63,7 @@ public function provideLockContents() } JSON , + false, [ [ <<<'PHP' @@ -78,6 +92,51 @@ public function provideLockContents() ], ]; + yield 'lock file platform requirements (compressed PHAR)' => [ + <<<'JSON' +{ + "platform": { + "php": "^7.1", + "ext-phar": "*" + }, + "platform-dev": [] +} +JSON + , + true, + [ + [ + <<<'PHP' +require_once __DIR__.'/../vendor/composer/semver/src/Semver.php'; +require_once __DIR__.'/../vendor/composer/semver/src/VersionParser.php'; +require_once __DIR__.'/../vendor/composer/semver/src/Constraint/ConstraintInterface.php'; +require_once __DIR__.'/../vendor/composer/semver/src/Constraint/EmptyConstraint.php'; +require_once __DIR__.'/../vendor/composer/semver/src/Constraint/MultiConstraint.php'; +require_once __DIR__.'/../vendor/composer/semver/src/Constraint/Constraint.php'; + +return \Composer\Semver\Semver::satisfies( + sprintf('%d.%d.%d', \PHP_MAJOR_VERSION, \PHP_MINOR_VERSION, \PHP_RELEASE_VERSION), + '^7.1' +); + +PHP + , + 'The application requires the version "^7.1" or greater.', + 'The application requires the version "^7.1" or greater.', + ], + [ + "return \\extension_loaded('zip');", + 'The application requires the extension "zip". Enable it or install a polyfill.', + 'The application requires the extension "zip".', + ], + [ + "return \\extension_loaded('phar');", + 'The application requires the extension "phar". Enable it or install a polyfill.', + 'The application requires the extension "phar".', + ], + ], + ]; + yield 'lock file platform dev requirements are ignored' => [ <<<'JSON' { @@ -89,9 +148,31 @@ public function provideLockContents() } JSON , + false, [], ]; + yield 'lock file platform dev requirements are ignored (compressed PHAR)' => [ + <<<'JSON' +{ + "platform": [], + "platform-dev": { + "php": "^7.3", + "ext-json": "*" + } +} +JSON + , + true, + [ + [ + "return \\extension_loaded('zip');", + 'The application requires the extension "zip". Enable it or install a polyfill.', + 'The application requires the extension "zip".', + ], + ], + ]; + yield 'lock file packages requirements' => [ <<<'JSON' { @@ -130,6 +211,7 @@ public function provideLockContents() } JSON , + false, [ [ <<<'PHP' @@ -222,6 +304,7 @@ public function provideLockContents() } JSON , + false, [], ]; @@ -262,6 +345,7 @@ public function provideLockContents() } JSON , + false, [ [ <<<'PHP' @@ -368,6 +452,7 @@ public function provideLockContents() } JSON , + false, [ [ <<<'PHP'