Refactor plugin system (part 3)

This commit is contained in:
Pig Fang 2019-08-12 14:35:36 +08:00
parent d92e1738dc
commit 18019d85e6
4 changed files with 198 additions and 7 deletions

View File

@ -40,13 +40,13 @@ class PluginServiceProvider extends ServiceProvider
foreach ($plugins->getPlugins() as $plugin) {
if ($plugin->isEnabled()) {
$src_paths[$plugin->getNameSpace()] = $plugin->getPath().'/src';
$src_paths[$plugin->getNamespace()] = $plugin->getPath().'/src';
// Add paths of views
$finder->addNamespace($plugin->getNameSpace(), $plugin->getPath().'/views');
$finder->addNamespace($plugin->getNamespace(), $plugin->getPath().'/views');
}
// Always add paths of translation files for namespace hints
$loader->addNamespace($plugin->getNameSpace(), $plugin->getPath().'/lang');
$loader->addNamespace($plugin->getNamespace(), $plugin->getPath().'/lang');
}
$this->registerPluginCallbackListener();

View File

@ -111,7 +111,7 @@ class Plugin
return $this;
}
public function getNameSpace(): string
public function getNamespace(): string
{
return $this->namespace;
}

View File

@ -103,18 +103,25 @@ class PluginManager
// disable unsatisfied here
$enabled = $plugins->filter(function ($plugin) {
return $plugin->isEnabled();
});
$this->registerAutoload(
$plugins->filter(function ($plugin) {
return $plugin->isEnabled();
})->mapWithKeys(function ($plugin) {
$enabled->mapWithKeys(function ($plugin) {
return [$plugin->namespace => $plugin->getPath().'/src'];
})
);
$this->loadVendor($enabled);
$this->loadViewsAndTranslations($enabled);
$this->loadBootstrapper($enabled);
$this->booted = true;
}
/**
* Register classes autoloading.
*
* @param Collection $paths
*/
protected function registerAutoload($paths)
@ -134,6 +141,54 @@ class PluginManager
});
}
/**
* Load Composer dumped autoload file.
*
* @param Collection $enabled
*/
protected function loadVendor($enabled)
{
$enabled->each(function ($plugin) {
$path = $plugin->getPath().'/vendor/autoload.php';
if ($this->filesystem->exists($path)) {
$this->filesystem->getRequire($path);
}
});
}
/**
* Load views and translations.
*
* @param Collection $enabled
*/
protected function loadViewsAndTranslations($enabled)
{
$translations = $this->app->make('translation.loader');
$view = $this->app->make('view');
$enabled->each(function ($plugin) use (&$translations, &$view) {
$namespace = $plugin->namespace;
$path = $plugin->getPath();
$translations->addNamespace($namespace, $path.'/lang');
$view->addNamespace($namespace, $path.'/views');
});
}
/**
* Load plugin's bootstrapper.
*
* @param Collection $enabled
*/
protected function loadBootstrapper($enabled)
{
$enabled->each(function ($plugin) {
$path = $plugin->getPath().'/bootstrap.php';
if ($this->filesystem->exists($path)) {
$this->app->call($this->filesystem->getRequire($path));
}
});
}
/**
* @return Collection
*/

View File

@ -82,6 +82,142 @@ class PluginManagerTest extends TestCase
$manager = $this->rebootPluginManager(app('plugins'));
}
public function testLoadComposer()
{
option(['plugins_enabled' => json_encode([['name' => 'mayaka', 'version' => '0.0.0']])]);
$this->mock(Filesystem::class, function ($mock) {
$mock->shouldReceive('directories')
->with(base_path('plugins'))
->once()
->andReturn(collect(['/mayaka']));
$mock->shouldReceive('exists')
->with('/mayaka'.DIRECTORY_SEPARATOR.'package.json')
->once()
->andReturn(true);
$mock->shouldReceive('get')
->with('/mayaka'.DIRECTORY_SEPARATOR.'package.json')
->once()
->andReturn(json_encode([
'name' => 'mayaka',
'version' => '0.0.0',
]));
$mock->shouldReceive('exists')
->with('/mayaka/vendor/autoload.php')
->once()
->andReturn(true);
$mock->shouldReceive('getRequire')
->with('/mayaka/vendor/autoload.php')
->once();
$mock->shouldReceive('exists')
->with('/mayaka/bootstrap.php')
->once()
->andReturn(false);
});
$manager = $this->rebootPluginManager(app('plugins'));
option(['plugins_enabled' => '[]']);
}
public function testLoadViewsAndTranslations()
{
option(['plugins_enabled' => json_encode([['name' => 'mayaka', 'version' => '0.0.0']])]);
$this->mock(Filesystem::class, function ($mock) {
$mock->shouldReceive('directories')
->with(base_path('plugins'))
->once()
->andReturn(collect(['/mayaka']));
$mock->shouldReceive('exists')
->with('/mayaka'.DIRECTORY_SEPARATOR.'package.json')
->once()
->andReturn(true);
$mock->shouldReceive('get')
->with('/mayaka'.DIRECTORY_SEPARATOR.'package.json')
->once()
->andReturn(json_encode([
'name' => 'mayaka',
'version' => '0.0.0',
'namespace' => 'Mayaka',
]));
$mock->shouldReceive('exists')
->with('/mayaka/vendor/autoload.php')
->once()
->andReturn(false);
$mock->shouldReceive('exists')
->with('/mayaka/bootstrap.php')
->once()
->andReturn(false);
});
$this->mock('view', function ($mock) {
$mock->shouldReceive('addNamespace')
->withArgs(['Mayaka', '/mayaka/views'])
->once();
});
$this->instance('translation.loader', \Mockery::mock(\App\Services\TranslationLoader::class, function ($mock) {
$mock->shouldReceive('addNamespace')
->withArgs(['Mayaka', '/mayaka/lang'])
->once();
}));
$manager = $this->rebootPluginManager(app('plugins'));
option(['plugins_enabled' => '[]']);
}
public function testLoadBootstrapper()
{
option(['plugins_enabled' => json_encode([['name' => 'mayaka', 'version' => '0.0.0']])]);
$this->mock(Filesystem::class, function ($mock) {
$mock->shouldReceive('directories')
->with(base_path('plugins'))
->once()
->andReturn(collect(['/mayaka']));
$mock->shouldReceive('exists')
->with('/mayaka'.DIRECTORY_SEPARATOR.'package.json')
->once()
->andReturn(true);
$mock->shouldReceive('get')
->with('/mayaka'.DIRECTORY_SEPARATOR.'package.json')
->once()
->andReturn(json_encode([
'name' => 'mayaka',
'version' => '0.0.0',
]));
$mock->shouldReceive('exists')
->with('/mayaka/vendor/autoload.php')
->once()
->andReturn(false);
$mock->shouldReceive('exists')
->with('/mayaka/bootstrap.php')
->once()
->andReturn(true);
$mock->shouldReceive('getRequire')
->with('/mayaka/bootstrap.php')
->once()
->andReturn(function (\Illuminate\Contracts\Events\Dispatcher $events) {
$this->assertTrue(method_exists($events, 'listen'));
});
});
$manager = $this->rebootPluginManager(app('plugins'));
option(['plugins_enabled' => '[]']);
}
public function testRegisterAutoload()
{
$dir = config('plugins.directory');