Skip to content

Commit 817de1d

Browse files
committed
Add PSR-4 autoload paths for app plugins.
This change avoids having to update the app's composer.json to add autoload paths for app plugins under the "plugins" folder.
1 parent 67f6c34 commit 817de1d

2 files changed

Lines changed: 100 additions & 1 deletion

File tree

src/Plugin.php

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,55 @@ public static function getSubscribedEvents()
4242
{
4343
return [
4444
'post-autoload-dump' => 'postAutoloadDump',
45+
'pre-autoload-dump' => 'preAutoloadDump',
4546
];
4647
}
4748

49+
/**
50+
* Add PSR-4 autoload paths for app plugins.
51+
*
52+
* @param \Composer\Script\Event $event
53+
* @return void
54+
*/
55+
public function preAutoloadDump(Event $event): void
56+
{
57+
$package = $event->getComposer()->getPackage();
58+
$autoload = $package->getAutoload();
59+
$devAutoload = $package->getDevAutoload();
60+
61+
$extra = $package->getExtra();
62+
if (empty($extra['plugin-paths'])) {
63+
$extra['plugin-paths'] = ['plugins'];
64+
}
65+
66+
$root = dirname(realpath($event->getComposer()->getConfig()->get('vendor-dir')));
67+
foreach ($extra['plugin-paths'] as $pluginsPath) {
68+
foreach (new DirectoryIterator($root . '/' . $pluginsPath) as $fileInfo) {
69+
if (!$fileInfo->isDir() || $fileInfo->isDot()) {
70+
continue;
71+
}
72+
73+
$folderName = $fileInfo->getFilename();
74+
if ($folderName[0] === '.') {
75+
continue;
76+
}
77+
78+
$pluginNamespace = $folderName . '\\';
79+
$pluginTestNamespace = $folderName . '\\Test\\';
80+
$path = $pluginsPath . '/' . $folderName . '/';
81+
if (!isset($autoload['psr-4'][$pluginNamespace])) {
82+
$autoload['psr-4'][$pluginNamespace] = $path . 'src';
83+
}
84+
if (!isset($devAutoload['psr-4'][$pluginTestNamespace])) {
85+
$devAutoload['psr-4'][$pluginTestNamespace] = $path . 'tests';
86+
}
87+
}
88+
}
89+
90+
$package->setAutoload($autoload);
91+
$package->setDevAutoload($devAutoload);
92+
}
93+
4894
/**
4995
* Called whenever composer (re)generates the autoloader.
5096
*

tests/TestCase/PluginTest.php

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@
88
use Composer\Config;
99
use Composer\IO\IOInterface;
1010
use Composer\Package\Package;
11+
use Composer\Package\RootPackage;
1112
use Composer\Repository\RepositoryManager;
13+
use Composer\Script\Event;
1214
use Composer\Util\HttpDownloader;
1315
use PHPUnit\Framework\TestCase;
1416

@@ -67,7 +69,9 @@ public function setUp(): void
6769
$this->composer = new Composer();
6870
$config = new Config();
6971
$config->merge([
70-
'vendor-dir' => $this->path . '/vendor',
72+
'config' => [
73+
'vendor-dir' => $this->path . '/vendor',
74+
],
7175
]);
7276

7377
$this->composer->setConfig($config);
@@ -109,6 +113,7 @@ public function testGetSubscribedEvents()
109113
{
110114
$expected = [
111115
'post-autoload-dump' => 'postAutoloadDump',
116+
'pre-autoload-dump' => 'preAutoloadDump',
112117
];
113118

114119
$this->assertSame($expected, $this->plugin->getSubscribedEvents());
@@ -120,6 +125,54 @@ public function testGetConfigFilePath()
120125
$this->assertFileExists(dirname($path));
121126
}
122127

128+
public function testPreAutoloadDump()
129+
{
130+
$package = new RootPackage('App', '1.0.0', '1.0.0');
131+
$package->setExtra([
132+
'plugin-paths' => [
133+
'app_plugins',
134+
'plugins',
135+
],
136+
]);
137+
$package->setAutoload([
138+
'psr-4' => [
139+
'Foo\\' => 'xyz/Foo/src',
140+
],
141+
]);
142+
$package->setDevAutoload([
143+
'psr-4' => [
144+
'Foo\Test\\' => 'xyz/Foo/tests',
145+
],
146+
]);
147+
$this->composer->setPackage($package);
148+
149+
$event = new Event('', $this->composer, $this->io);
150+
151+
$this->plugin->preAutoloadDump($event);
152+
153+
$expected = [
154+
'psr-4' => [
155+
'Foo\\' => 'xyz/Foo/src',
156+
'Fee\\' => 'plugins/Fee/src',
157+
'Fum\\' => 'plugins/Fum/src',
158+
'Foe\\' => 'plugins/Foe/src',
159+
'Bar\\' => 'app_plugins/Bar/src',
160+
],
161+
];
162+
$this->assertEquals($expected, $package->getAutoload());
163+
164+
$expected = [
165+
'psr-4' => [
166+
'Foo\Test\\' => 'xyz/Foo/tests',
167+
'Fee\Test\\' => 'plugins/Fee/tests',
168+
'Fum\Test\\' => 'plugins/Fum/tests',
169+
'Foe\Test\\' => 'plugins/Foe/tests',
170+
'Bar\Test\\' => 'app_plugins/Bar/tests',
171+
],
172+
];
173+
$this->assertEquals($expected, $package->getDevAutoload());
174+
}
175+
123176
public function testGetPrimaryNamespace()
124177
{
125178
$autoload = [

0 commit comments

Comments
 (0)