Skip to content

Commit 89999fd

Browse files
committed
feature #612 Enable bundles auto-discovery by default (SerheyDolgushev)
This PR was squashed before being merged into the 1.5-dev branch. Discussion ---------- Enable bundles auto-discovery by default Bundles autodiscovery is now enabled for all the packages, but not only for `symfony-bundle` type packages. And it works in the same way as it worked before. PR description before @fabpot review: > 1. Bundles autodiscovery is now enabled for all the packages, but not only for `symfony-bundle` type packages. And it works in the same way as it worked before. It is disabled only when there is `extra.symfony.bundles` configuration in the package (even if this configuration is an empty array). > 2. New `extra.symfony.bundles` package configuration was introduced. It should contain the list of bundles and the environments where those bundles should be enabled. Example: > ``` > "extra": { > "symfony": { > "bundles": { > "VendorName\\BundleName1": ["all"], > "VendorName\\BundleName2": ["dev", "test"] > } > } > } > ``` > Original PR description: >I just do not see any reasons why `ezplatform-bundle` packages couldn't be enabled automatically after the installation (in the same way as `symfony-bundle` packages are). > >Tagging @andrerom here Commits ------- a4bea5a Enable bundles auto-discovery by default
2 parents e4f5a26 + a4bea5a commit 89999fd

File tree

3 files changed

+252
-114
lines changed

3 files changed

+252
-114
lines changed

src/Flex.php

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -444,7 +444,7 @@ function ($value) {
444444
}
445445
$value = strtolower($value[0]);
446446
if (!\in_array($value, ['y', 'n', 'a', 'p'])) {
447-
throw new \InvalidArgumentException('Invalid choice');
447+
throw new \InvalidArgumentException('Invalid choice.');
448448
}
449449

450450
return $value;
@@ -757,18 +757,23 @@ public function fetchRecipes(array $operations): array
757757
}
758758

759759
$noRecipe = !isset($manifests[$name]) || (isset($manifests[$name]['not_installable']) && $manifests[$name]['not_installable']);
760-
if ($noRecipe && 'symfony-bundle' === $package->getType()) {
761-
$manifest = [];
762-
$bundle = new SymfonyBundle($this->composer, $package, $job);
760+
if ($noRecipe) {
761+
$bundles = [];
762+
763763
if (null === $devPackages) {
764764
$devPackages = array_column($this->composer->getLocker()->getLockData()['packages-dev'], 'name');
765765
}
766766
$envs = \in_array($name, $devPackages) ? ['dev', 'test'] : ['all'];
767-
foreach ($bundle->getClassNames() as $class) {
768-
$manifest['manifest']['bundles'][$class] = $envs;
767+
$bundle = new SymfonyBundle($this->composer, $package, $job);
768+
foreach ($bundle->getClassNames() as $bundleClass) {
769+
$bundles[$bundleClass] = $envs;
769770
}
770-
if ($manifest) {
771-
$manifest['origin'] = sprintf('%s:%s@auto-generated recipe', $name, $package->getPrettyVersion());
771+
772+
if ($bundles) {
773+
$manifest = [
774+
'origin' => sprintf('%s:%s@auto-generated recipe', $name, $package->getPrettyVersion()),
775+
'manifest' => ['bundles' => $bundles],
776+
];
772777
$recipes[$name] = new Recipe($package, $name, $job, $manifest);
773778
}
774779
}

tests/FlexTest.php

Lines changed: 226 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
namespace Symfony\Flex\Tests;
1313

1414
use Composer\Composer;
15+
use Composer\Config;
1516
use Composer\DependencyResolver\Operation\InstallOperation;
1617
use Composer\Factory;
1718
use Composer\Installer\PackageEvent;
@@ -37,10 +38,6 @@ class FlexTest extends TestCase
3738
{
3839
public function testPostInstall()
3940
{
40-
$package = new Package('dummy/dummy', '1.0.0', '1.0.0');
41-
$event = $this->getMockBuilder(PackageEvent::class)->disableOriginalConstructor()->getMock();
42-
$event->expects($this->any())->method('getOperation')->willReturn(new InstallOperation($package));
43-
4441
$data = [
4542
'manifests' => [
4643
'dummy/dummy' => [
@@ -61,40 +58,14 @@ public function testPostInstall()
6158
],
6259
];
6360

64-
$configurator = $this->getMockBuilder(Configurator::class)->disableOriginalConstructor()->getMock();
65-
$configurator->expects($this->once())->method('install')->with($this->equalTo(new Recipe($package, 'dummy/dummy', 'install', $data['manifests']['dummy/dummy'], $data['locks']['dummy/dummy'])));
66-
67-
$downloader = $this->getMockBuilder(Downloader::class)->disableOriginalConstructor()->getMock();
68-
$downloader->expects($this->once())->method('getRecipes')->willReturn($data);
69-
$downloader->expects($this->once())->method('isEnabled')->willReturn(true);
70-
7161
$io = new BufferIO('', OutputInterface::VERBOSITY_VERBOSE);
72-
$locker = $this->getMockBuilder(Locker::class)->disableOriginalConstructor()->getMock();
73-
$locker->expects($this->any())->method('getLockData')->willReturn(['content-hash' => 'random']);
74-
75-
$package = $this->getMockBuilder(RootPackageInterface::class)->disableOriginalConstructor()->getMock();
76-
$package->expects($this->any())->method('getExtra')->willReturn(['symfony' => ['allow-contrib' => true]]);
77-
78-
$lock = $this->getMockBuilder(Lock::class)->disableOriginalConstructor()->getMock();
79-
$lock->expects($this->any())->method('has')->willReturn(false);
80-
81-
$flex = \Closure::bind(function () use ($configurator, $downloader, $io, $locker, $package, $lock) {
82-
$flex = new Flex();
83-
$flex->composer = new Composer();
84-
$flex->composer->setLocker($locker);
85-
$flex->composer->setPackage($package);
86-
$flex->io = $io;
87-
$flex->configurator = $configurator;
88-
$flex->downloader = $downloader;
89-
$flex->runningCommand = function () {
90-
};
91-
$flex->options = new Options(['config-dir' => 'config', 'var-dir' => 'var']);
92-
$flex->lock = $lock;
62+
$package = new Package('dummy/dummy', '1.0.0', '1.0.0');
63+
$recipe = new Recipe($package, 'dummy/dummy', 'install', $data['manifests']['dummy/dummy'], $data['locks']['dummy/dummy']);
9364

94-
return $flex;
95-
}, null, Flex::class)->__invoke();
96-
$flex->record($event);
97-
$flex->install($this->getMockBuilder(Event::class)->disableOriginalConstructor()->getMock());
65+
$rootPackage = $this->mockRootPackage(['symfony' => ['allow-contrib' => true]]);
66+
$flex = $this->mockFlex($io, $rootPackage, $recipe, $data);
67+
$flex->record($this->mockPackageEvent($package));
68+
$flex->install($this->mockFlexEvent());
9869

9970
$expected = [
10071
'',
@@ -124,22 +95,230 @@ public function testPostInstall()
12495
public function testActivateLoadsClasses()
12596
{
12697
$io = new BufferIO('', OutputInterface::VERBOSITY_VERBOSE);
127-
$composer = new Composer();
128-
$composer->setConfig(Factory::createConfig($io));
129-
$package = $this->getMockBuilder(RootPackageInterface::class)->disableOriginalConstructor()->getMock();
130-
$package->method('getExtra')->willReturn(['symfony' => ['allow-contrib' => true]]);
98+
99+
$package = $this->mockRootPackage(['symfony' => ['allow-contrib' => true]]);
131100
$package->method('getRequires')->willReturn([new Link('dummy', 'symfony/flex')]);
132-
$composer->setPackage($package);
133-
$localRepo = $this->getMockBuilder(WritableRepositoryInterface::class)->disableOriginalConstructor()->getMock();
134-
$manager = $this->getMockBuilder(RepositoryManager::class)->disableOriginalConstructor()->getMock();
135-
$manager->expects($this->once())
136-
->method('getLocalRepository')
137-
->willReturn($localRepo);
138-
$composer->setRepositoryManager($manager);
101+
102+
$composer = $this->mockComposer($this->mockLocker(), $package, Factory::createConfig($io));
103+
$composer->setRepositoryManager($this->mockManager());
139104

140105
$flex = new Flex();
141106
$flex->activate($composer, $io);
142107

143108
$this->assertTrue(class_exists(Response::class, false));
144109
}
110+
111+
/**
112+
* @dataProvider getPackagesForAutoDiscovery
113+
*/
114+
public function testBundlesAutoDiscovery(Package $package, array $expectedManifest)
115+
{
116+
$io = new BufferIO('', OutputInterface::VERBOSITY_VERBOSE);
117+
118+
$recipe = null;
119+
if (\count($expectedManifest)) {
120+
$recipe = new Recipe($package, $package->getName(), 'install', $expectedManifest);
121+
}
122+
123+
$devPackages = $package->isDev() ? [['name' => $package->getName()]] : [];
124+
125+
$rootPackage = $this->mockRootPackage($package->getExtra());
126+
$flex = $this->mockFlex($io, $rootPackage, $recipe, [], ['packages-dev' => $devPackages]);
127+
$flex->record($this->mockPackageEvent($package));
128+
$flex->install($this->mockFlexEvent());
129+
}
130+
131+
public function getPackagesForAutoDiscovery(): array
132+
{
133+
$return = [];
134+
135+
$versions = ['1.0', '2.0-dev'];
136+
$packages = self::getTestPackages();
137+
138+
foreach ($packages as $name => $info) {
139+
foreach ($versions as $version) {
140+
$package = new Package($name, $version, $version);
141+
$package->setAutoload($info['autoload']);
142+
if (isset($info['type'])) {
143+
$package->setType($info['type']);
144+
}
145+
146+
$expectedManifest = [
147+
'origin' => sprintf('%s:%s@auto-generated recipe', $package->getName(),
148+
$package->getPrettyVersion()),
149+
'manifest' => ['bundles' => []],
150+
];
151+
152+
$envs = $package->isDev() ? ['dev', 'test'] : ['all'];
153+
foreach ($info['bundles'] as $bundle) {
154+
$expectedManifest['manifest']['bundles'][$bundle] = $envs;
155+
}
156+
157+
$return[] = [$package, $expectedManifest];
158+
}
159+
}
160+
161+
return $return;
162+
}
163+
164+
public static function getTestPackages(): array
165+
{
166+
return [
167+
'symfony/debug-bundle' => [
168+
'autoload' => ['psr-4' => ['Symfony\\Bundle\\DebugBundle\\' => '']],
169+
'bundles' => ['Symfony\\Bundle\\DebugBundle\\DebugBundle'],
170+
],
171+
'symfony/dummy' => [
172+
'autoload' => ['psr-4' => ['Symfony\\Bundle\\FirstDummyBundle\\' => 'FirstDummyBundle/', 'Symfony\\Bundle\\SecondDummyBundle\\' => 'SecondDummyBundle/']],
173+
'bundles' => ['Symfony\\Bundle\\FirstDummyBundle\\FirstDummyBundle', 'Symfony\\Bundle\\SecondDummyBundle\\SecondDummyBundle'],
174+
],
175+
'doctrine/doctrine-cache-bundle' => [
176+
'autoload' => ['psr-4' => ['Doctrine\\Bundle\\DoctrineCacheBundle\\' => '']],
177+
'bundles' => ['Doctrine\\Bundle\\DoctrineCacheBundle\\DoctrineCacheBundle'],
178+
],
179+
'eightpoints/guzzle-bundle' => [
180+
'autoload' => ['psr-0' => ['EightPoints\\Bundle\\GuzzleBundle' => '']],
181+
'bundles' => ['EightPoints\\Bundle\\GuzzleBundle\\GuzzleBundle'],
182+
],
183+
'easycorp/easy-security-bundle' => [
184+
'autoload' => ['psr-4' => ['EasyCorp\\Bundle\\EasySecurityBundle\\' => '']],
185+
'bundles' => ['EasyCorp\\Bundle\\EasySecurityBundle\\EasySecurityBundle'],
186+
],
187+
'symfony-cmf/routing-bundle' => [
188+
'autoload' => ['psr-4' => ['Symfony\\Cmf\\Bundle\\RoutingBundle\\' => '']],
189+
'bundles' => ['Symfony\\Cmf\\Bundle\\RoutingBundle\\CmfRoutingBundle'],
190+
],
191+
'easycorp/easy-deploy-bundle' => [
192+
'autoload' => ['psr-4' => ['EasyCorp\\Bundle\\EasyDeployBundle\\' => 'src/']],
193+
'bundles' => ['EasyCorp\\Bundle\\EasyDeployBundle\\EasyDeployBundle'],
194+
],
195+
'easycorp/easy-deploy-bundle' => [
196+
'autoload' => ['psr-4' => ['EasyCorp\\Bundle\\EasyDeployBundle\\' => ['src', 'tests']]],
197+
'bundles' => ['EasyCorp\\Bundle\\EasyDeployBundle\\EasyDeployBundle'],
198+
],
199+
'web-token/jwt-bundle' => [
200+
'autoload' => ['psr-4' => ['Jose\\Bundle\\JoseFramework\\' => ['']]],
201+
'bundles' => ['Jose\\Bundle\\JoseFramework\\JoseFrameworkBundle'],
202+
],
203+
'sylius/shop-api-plugin' => [
204+
'autoload' => ['psr-4' => ['Sylius\\ShopApiPlugin\\' => 'src/']],
205+
'bundles' => ['Sylius\\ShopApiPlugin\\ShopApiPlugin'],
206+
'type' => 'sylius-plugin',
207+
],
208+
'dunglas/sylius-acme-plugin' => [
209+
'autoload' => ['psr-4' => ['Dunglas\\SyliusAcmePlugin\\' => 'src/']],
210+
'bundles' => ['Dunglas\\SyliusAcmePlugin\\DunglasSyliusAcmePlugin'],
211+
'type' => 'sylius-plugin',
212+
],
213+
];
214+
}
215+
216+
private function mockPackageEvent(Package $package): PackageEvent
217+
{
218+
$event = $this->getMockBuilder(PackageEvent::class, ['getOperation'])->disableOriginalConstructor()->getMock();
219+
$event->expects($this->any())->method('getOperation')->willReturn(new InstallOperation($package));
220+
221+
return $event;
222+
}
223+
224+
private function mockConfigurator(Recipe $recipe = null): Configurator
225+
{
226+
$configurator = $this->getMockBuilder(Configurator::class)->disableOriginalConstructor()->getMock();
227+
228+
if ($recipe) {
229+
$configurator->expects($this->once())->method('install')->with($this->equalTo($recipe));
230+
}
231+
232+
return $configurator;
233+
}
234+
235+
private function mockDownloader(array $recipes = []): Downloader
236+
{
237+
$downloader = $this->getMockBuilder(Downloader::class)->disableOriginalConstructor()->getMock();
238+
239+
$downloader->expects($this->once())->method('getRecipes')->willReturn($recipes);
240+
$downloader->expects($this->once())->method('isEnabled')->willReturn(true);
241+
242+
return $downloader;
243+
}
244+
245+
private function mockLocker(array $lockData = []): Locker
246+
{
247+
$locker = $this->getMockBuilder(Locker::class)->disableOriginalConstructor()->getMock();
248+
249+
$lockData = array_merge(['content-hash' => 'random', 'packages-dev' => []], $lockData);
250+
$locker->expects($this->any())->method('getLockData')->willReturn($lockData);
251+
252+
return $locker;
253+
}
254+
255+
private function mockComposer(Locker $locker, RootPackageInterface $package, Config $config = null): Composer
256+
{
257+
if (null === $config) {
258+
$config = $this->getMockBuilder(Config::class)->getMock();
259+
$config->expects($this->any())->method('get')->willReturn(__DIR__.'/Fixtures/vendor');
260+
}
261+
262+
$composer = new Composer();
263+
$composer->setConfig($config);
264+
$composer->setLocker($locker);
265+
$composer->setPackage($package);
266+
267+
return $composer;
268+
}
269+
270+
private function mockRootPackage(array $extraData = []): RootPackageInterface
271+
{
272+
$package = $this->getMockBuilder(RootPackageInterface::class)->disableOriginalConstructor()->getMock();
273+
274+
$package->expects($this->any())->method('getExtra')->willReturn($extraData);
275+
276+
return $package;
277+
}
278+
279+
private function mockLock(): Lock
280+
{
281+
$lock = $this->getMockBuilder(Lock::class)->disableOriginalConstructor()->getMock();
282+
$lock->expects($this->any())->method('has')->willReturn(false);
283+
284+
return $lock;
285+
}
286+
287+
private function mockFlexEvent(): Event
288+
{
289+
return $this->getMockBuilder(Event::class)->disableOriginalConstructor()->getMock();
290+
}
291+
292+
private function mockManager(): RepositoryManager
293+
{
294+
$manager = $this->getMockBuilder(RepositoryManager::class)->disableOriginalConstructor()->getMock();
295+
296+
$localRepo = $this->getMockBuilder(WritableRepositoryInterface::class)->disableOriginalConstructor()->getMock();
297+
$manager->expects($this->once())->method('getLocalRepository')->willReturn($localRepo);
298+
299+
return $manager;
300+
}
301+
302+
private function mockFlex(BufferIO $io, RootPackageInterface $package, Recipe $recipe = null, array $recipes = [], array $lockerData = []): Flex
303+
{
304+
$composer = $this->mockComposer($this->mockLocker($lockerData), $package);
305+
306+
$configurator = $this->mockConfigurator($recipe);
307+
$downloader = $this->mockDownloader($recipes);
308+
$lock = $this->mockLock();
309+
310+
return \Closure::bind(function () use ($composer, $io, $configurator, $downloader, $lock) {
311+
$flex = new Flex();
312+
$flex->composer = $composer;
313+
$flex->io = $io;
314+
$flex->configurator = $configurator;
315+
$flex->downloader = $downloader;
316+
$flex->runningCommand = function () {
317+
};
318+
$flex->options = new Options(['config-dir' => 'config', 'var-dir' => 'var']);
319+
$flex->lock = $lock;
320+
321+
return $flex;
322+
}, null, Flex::class)->__invoke();
323+
}
145324
}

0 commit comments

Comments
 (0)