diff --git a/.github/wiki b/.github/wiki index 2182ccf4b..077086ae8 160000 --- a/.github/wiki +++ b/.github/wiki @@ -1 +1 @@ -Subproject commit 2182ccf4b9a6ef8dbe0b8ad188df507a9adee909 +Subproject commit 077086ae8cb01397e60d148989955955efbafbda diff --git a/CHANGELOG.md b/CHANGELOG.md index ff50d90d0..6b85dc7d8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Rewrite drifted Git hooks by removing the previous target first, restore the intended `0o755` executable mode, and report unwritable hook replacements cleanly when `.git/hooks` stays locked (#190) - Keep Composer plugin command discovery compatible with consumer environments by moving unsupported Symfony Console named parameters out of command metadata/configuration and by decoupling the custom filesystem wrapper from Composer's bundled Symfony Filesystem signatures (#185) - Keep Composer autoload, Rector, and ECS from traversing nested fixture `vendor` directories when the composer-plugin consumer fixture has installed dependencies (#179) +- Skip LICENSE generation cleanly when a consumer composer manifest omits or leaves the `license` field empty (#227) ## [1.20.0] - 2026-04-23 diff --git a/src/License/Resolver.php b/src/License/Resolver.php index d9301bf62..3073ea71c 100644 --- a/src/License/Resolver.php +++ b/src/License/Resolver.php @@ -47,14 +47,18 @@ final class Resolver implements ResolverInterface /** * Resolves a license identifier to its template filename. * - * @param string $license The license identifier to resolve + * @param string|null $license The license identifier to resolve * * @return string|null The template filename if supported, or null if not */ - public function resolve(string $license): ?string + public function resolve(?string $license): ?string { $normalized = $this->normalize($license); + if (null === $normalized) { + return null; + } + if (! isset(self::SUPPORTED_LICENSES[$normalized])) { return null; } @@ -65,12 +69,18 @@ public function resolve(string $license): ?string /** * Normalizes the license identifier for comparison. * - * @param string $license The license identifier to normalize + * @param string|null $license The license identifier to normalize * - * @return string The normalized license string + * @return string|null The normalized license string, or null when unavailable */ - private function normalize(string $license): string + private function normalize(?string $license): ?string { - return trim($license); + if (null === $license) { + return null; + } + + $license = trim($license); + + return '' === $license ? null : $license; } } diff --git a/src/License/ResolverInterface.php b/src/License/ResolverInterface.php index a1ef7c742..4701d925a 100644 --- a/src/License/ResolverInterface.php +++ b/src/License/ResolverInterface.php @@ -30,9 +30,9 @@ interface ResolverInterface /** * Resolves a license identifier to its template filename. * - * @param string $license The license identifier to resolve + * @param string|null $license The license identifier to resolve * * @return string|null The template filename if supported, or null if not */ - public function resolve(string $license): ?string; + public function resolve(?string $license): ?string; } diff --git a/tests/License/GeneratorTest.php b/tests/License/GeneratorTest.php index 358bcb9d0..70a5f1f75 100644 --- a/tests/License/GeneratorTest.php +++ b/tests/License/GeneratorTest.php @@ -109,6 +109,24 @@ public function generateWithUnsupportedLicenseWillReturnNull(): void self::assertNull($result); } + /** + * @return void + */ + #[Test] + public function generateWithMissingLicenseWillReturnNull(): void + { + $this->composer->getLicense() + ->willReturn(null); + $this->resolver->resolve(null) + ->willReturn(null); + $this->filesystem->dumpFile(Argument::cetera()) + ->shouldNotBeCalled(); + + $result = $this->generator->generate('/tmp/LICENSE'); + + self::assertNull($result); + } + /** * @return void */ diff --git a/tests/License/ResolverTest.php b/tests/License/ResolverTest.php index fb2a1539b..df9b80c5b 100644 --- a/tests/License/ResolverTest.php +++ b/tests/License/ResolverTest.php @@ -65,4 +65,22 @@ public function resolveWithUnknownLicenseWillReturnNull(): void { self::assertNull($this->resolver->resolve('Unknown-License')); } + + /** + * @return void + */ + #[Test] + public function resolveWithMissingLicenseWillReturnNull(): void + { + self::assertNull($this->resolver->resolve(null)); + } + + /** + * @return void + */ + #[Test] + public function resolveWithEmptyLicenseWillReturnNull(): void + { + self::assertNull($this->resolver->resolve(' ')); + } }