From a53301f6739534841a8946d050344c9cf5c082ad Mon Sep 17 00:00:00 2001 From: Loz Calver Date: Mon, 15 Apr 2024 16:59:59 +0100 Subject: [PATCH] FIX: OutOfBoundsException when recipe-core isn't installed (fixes #11197) --- src/Core/Manifest/VersionProvider.php | 3 +++ .../php/Core/Manifest/VersionProviderTest.php | 21 +++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/src/Core/Manifest/VersionProvider.php b/src/Core/Manifest/VersionProvider.php index 65cfc7376..4a0d4b48e 100644 --- a/src/Core/Manifest/VersionProvider.php +++ b/src/Core/Manifest/VersionProvider.php @@ -189,6 +189,9 @@ class VersionProvider { $versions = []; foreach ($modules as $module) { + if (!InstalledVersions::isInstalled($module)) { + continue; + } $versions[$module] = InstalledVersions::getPrettyVersion($module); } return $versions; diff --git a/tests/php/Core/Manifest/VersionProviderTest.php b/tests/php/Core/Manifest/VersionProviderTest.php index 9e585f5ea..7b7959a9c 100644 --- a/tests/php/Core/Manifest/VersionProviderTest.php +++ b/tests/php/Core/Manifest/VersionProviderTest.php @@ -102,6 +102,27 @@ class VersionProviderTest extends SapphireTest $this->assertStringNotContainsString('Framework: 1.2.3', $result); } + public function testGetModuleVersionWhenPackageMayNotBeInstalled() + { + if (!class_exists(VersionParser::class)) { + $this->markTestSkipped('This test requires composer/semver to be installed'); + } + $provider = $this->getProvider(); + // VersionProvider::getModuleVersion() will loop over the modules defined in the "modules" config value, which + // may sometimes include packages that are optional (e.g. recipe-core). This tests that the version can still + // be found even if non-existent modules are encountered + Config::modify()->set(VersionProvider::class, 'modules', [ + 'this/module/cannot/possibly/exist' => 'Oopsies', + 'silverstripe/framework' => 'Framework', + 'silverstripe/another-module-that-does-not-exist' => 'Sapphire', + ]); + $moduleVersion = $provider->getModuleVersion('silverstripe/framework'); + $parser = new VersionParser(); + $this->assertIsString($parser->normalize($moduleVersion), "Expected a valid semver but got $moduleVersion"); + $result = $provider->getVersion(); + $this->assertStringNotContainsString('Framework: 1.2.3', $result); + } + private function clearCache() { $cache = Injector::inst()->get(CacheInterface::class . '.VersionProvider');