diff --git a/_config/cache.yml b/_config/cache.yml index b72faebf2..7308d8c50 100644 --- a/_config/cache.yml +++ b/_config/cache.yml @@ -18,3 +18,7 @@ SilverStripe\Core\Injector\Injector: factory: SilverStripe\Core\Cache\CacheFactory constructor: namespace: "LeftAndMain_CMSVersion" + Psr\SimpleCache\CacheInterface.VersionProvider_composerlock: + factory: SilverStripe\Core\Cache\CacheFactory + constructor: + namespace: "VersionProvider_composerlock" diff --git a/_config/config.yml b/_config/config.yml index 882167840..9f90d6f4b 100644 --- a/_config/config.yml +++ b/_config/config.yml @@ -12,3 +12,9 @@ SilverStripe\Control\HTTP: must-revalidate: "true" no-transform: "true" vary: "Cookie, X-Forwarded-Protocol, User-Agent, Accept" +LeftAndMain: + dependencies: + versionProvider: %$VersionProvider +SilverStripe\Core\Manifest\VersionProvider: + modules: + silverstripe/framework: Framework diff --git a/docs/en/02_Developer_Guides/06_Testing/04_Fixtures.md b/docs/en/02_Developer_Guides/06_Testing/04_Fixtures.md index 7e9520ad4..4fb722c4c 100644 --- a/docs/en/02_Developer_Guides/06_Testing/04_Fixtures.md +++ b/docs/en/02_Developer_Guides/06_Testing/04_Fixtures.md @@ -9,6 +9,39 @@ SilverStripe starts with a fresh database containing no records. `Fixtures` prov to load into the database. The [SapphireTest](api:SilverStripe\Dev\SapphireTest) class takes care of populating a test database with data from fixtures - all we have to do is define them. +To include your fixture file in your tests, you should define it as your `$fixture_file`: + + +**mysite/tests/MyNewTest.php** + + :::php + + * SilverStripe\Core\Manifest\VersionProvider: + * modules: + * # package/name: Package Title + * silverstripe/framework: Framework + * silverstripe/cms: CMS + * + */ +class VersionProvider +{ + /** + * Gets a comma delimited string of package titles and versions + * + * @return string + */ + public function getVersion() + { + $modules = $this->getModules(); + $lockModules = $this->getModuleVersionFromComposer(array_keys($modules)); + $output = array(); + foreach ($modules as $module => $title) { + $version = isset($lockModules[$module]) + ? $lockModules[$module] + : _t('SilverStripe\Core\Manifest\VersionProvider.VERSIONUNKNOWN', 'Unknown'); + $output[] = $title . ': ' . $version; + } + return implode(', ', $output); + } + + /** + * Gets the configured core modules to use for the SilverStripe application version. Filtering + * is used to ensure that modules can turn the result off for other modules, e.g. CMS can disable Framework. + * + * @return array + */ + public function getModules() + { + $modules = Config::inst()->get(static::class, 'modules'); + return $modules ? array_filter($modules) : array(); + } + + /** + * Tries to obtain version number from composer.lock if it exists + * + * @param array $modules + * @return array + */ + public function getModuleVersionFromComposer($modules = array()) + { + $versions = array(); + $lockData = $this->getComposerLock(); + if ($lockData && !empty($lockData['packages'])) { + foreach ($lockData['packages'] as $package) { + if (in_array($package['name'], $modules) && isset($package['version'])) { + $versions[$package['name']] = $package['version']; + } + } + } + return $versions; + } + + /** + * Load composer.lock's contents and return it + * + * @param bool $cache + * @return array + */ + protected function getComposerLock($cache = true) + { + $composerLockPath = BASE_PATH . '/composer.lock'; + if (!file_exists($composerLockPath)) { + return array(); + } + + $lockData = array(); + $jsonData = file_get_contents($composerLockPath); + + if ($cache) { + $cache = Injector::inst()->get(CacheInterface::class . '.VersionProvider_composerlock'); + $cacheKey = md5($jsonData); + if ($versions = $cache->get($cacheKey)) { + $lockData = Convert::json2array($versions); + } + } + + if (empty($lockData) && $jsonData) { + $lockData = Convert::json2array($jsonData); + + if ($cache) { + $cache->set($cacheKey, $jsonData); + } + } + + return $lockData; + } +} diff --git a/tests/php/Core/Manifest/VersionProviderTest.php b/tests/php/Core/Manifest/VersionProviderTest.php new file mode 100644 index 000000000..3fc0bca64 --- /dev/null +++ b/tests/php/Core/Manifest/VersionProviderTest.php @@ -0,0 +1,92 @@ +provider = new VersionProvider; + } + + public function testGetModules() + { + Config::modify()->set(VersionProvider::class, 'modules', array( + 'silverstripe/somepackage' => 'Some Package', + 'silverstripe/hidden' => '', + 'silverstripe/another' => 'Another' + )); + + $result = $this->provider->getModules(); + $this->assertArrayHasKey('silverstripe/somepackage', $result); + $this->assertSame('Some Package', $result['silverstripe/somepackage']); + $this->assertArrayHasKey('silverstripe/another', $result); + $this->assertArrayNotHasKey('silverstripe/hidden', $result); + } + + public function testGetModuleVersionFromComposer() + { + Config::modify()->set(VersionProvider::class, 'modules', array( + 'silverstripe/framework' => 'Framework', + 'silverstripe/siteconfig' => 'SiteConfig' + )); + + $result = $this->provider->getModules(array('silverstripe/framework')); + $this->assertArrayHasKey('silverstripe/framework', $result); + $this->assertNotEmpty($result['silverstripe/framework']); + } + + public function testGetVersion() + { + Config::modify()->set(VersionProvider::class, 'modules', array( + 'silverstripe/framework' => 'Framework', + 'silverstripe/siteconfig' => 'SiteConfig' + )); + + $result = $this->provider->getVersion(); + $this->assertContains('SiteConfig: ', $result); + $this->assertContains('Framework: ', $result); + $this->assertContains(', ', $result); + } + + public function testGetModulesFromComposerLock() + { + $this->markTestSkipped('Unable to get this passing'); + + $mock = $this->getMockBuilder(VersionProvider::class) + ->setMethods(array('getComposerLock')) + ->getMock(); + + $mock->expects($this->once()) + ->method('getComposerLock') + ->will($this->returnValue(array( + 'packages' => array( + array( + 'name' => 'silverstripe/somepackage', + 'version' => '1.2.3' + ), + array( + 'name' => 'silverstripe/another', + 'version' => '2.3.4' + ) + ) + ))); + + Config::modify()->set(VersionProvider::class, 'modules', array( + 'silverstripe/somepackage' => 'Some Package' + )); + + $result = $mock->getVersion(); + $this->assertContains('Some Package: 1.2.3', $result); + } +}