diff --git a/app/Http/Controllers/MarketController.php b/app/Http/Controllers/MarketController.php index 5563b33c..62b66f84 100644 --- a/app/Http/Controllers/MarketController.php +++ b/app/Http/Controllers/MarketController.php @@ -84,7 +84,7 @@ class MarketController extends Controller $url = $metadata['dist']['url']; $filename = Arr::last(explode('/', $url)); - $pluginsDir = $manager->getPluginsDir(); + $pluginsDir = $manager->getPluginsDirs()->first(); $path = storage_path("packages/$name".'_'.$metadata['version'].'.zip'); try { diff --git a/app/Services/PluginManager.php b/app/Services/PluginManager.php index 3cc76e4c..916cabe5 100644 --- a/app/Services/PluginManager.php +++ b/app/Services/PluginManager.php @@ -83,7 +83,11 @@ class PluginManager }); $plugins = collect(); - collect($this->filesystem->directories($this->getPluginsDir())) + $this->getPluginsDirs() + ->flatMap(function ($directory) { + return $this->filesystem->directories($directory); + }) + ->unique() ->filter(function ($directory) { return $this->filesystem->exists($directory.DIRECTORY_SEPARATOR.'package.json'); }) @@ -365,10 +369,18 @@ class PluginManager /** * The plugins path. * - * @return string + * @return Collection */ - public function getPluginsDir() + public function getPluginsDirs() { - return config('plugins.directory') ? realpath(config('plugins.directory')) : base_path('plugins'); + $config = config('plugins.directory'); + if ($config) { + return collect(preg_split('/,\s*/', $config)) + ->map(function ($directory) { + return realpath($directory) ?: $directory; + }); + } else { + return collect([base_path('plugins')]); + } } } diff --git a/tests/ServicesTest/PluginManagerTest.php b/tests/ServicesTest/PluginManagerTest.php index 3c2f0af1..bc73f752 100644 --- a/tests/ServicesTest/PluginManagerTest.php +++ b/tests/ServicesTest/PluginManagerTest.php @@ -496,4 +496,37 @@ class PluginManagerTest extends TestCase $this->expectExceptionMessage('No such plugin.'); plugin_assets('nope', 'relative'); } + + public function testReadMultipleDirectories() + { + $old = config('plugins.directory'); + config(['plugins.directory' => '/kumiko,/reina']); + + $this->mock(Filesystem::class, function ($mock) { + $mock->shouldReceive('directories') + ->with('/kumiko') + ->once() + ->andReturn(collect(['/a', '/b'])); + $mock->shouldReceive('directories') + ->with('/reina') + ->once() + ->andReturn(collect(['/b', '/c'])); + + $mock->shouldReceive('exists') + ->with('/a'.DIRECTORY_SEPARATOR.'package.json') + ->once() + ->andReturn(false); + $mock->shouldReceive('exists') + ->with('/b'.DIRECTORY_SEPARATOR.'package.json') + ->once() + ->andReturn(false); + $mock->shouldReceive('exists') + ->with('/c'.DIRECTORY_SEPARATOR.'package.json') + ->once() + ->andReturn(false); + }); + app('plugins')->all(); + + config(['plugins.directory' => $old]); + } }