From d15fd0b36dd97dff413a920f9ad3b841e10543c0 Mon Sep 17 00:00:00 2001 From: Pig Fang Date: Mon, 12 Aug 2019 15:21:50 +0800 Subject: [PATCH] Refactor plugin system (part 4) --- app/Events/PluginVersionChanged.php | 21 ++++++++++ app/Listeners/CopyPluginAssets.php | 34 +++++++++++++++ app/Providers/EventServiceProvider.php | 6 +++ app/Services/PluginManager.php | 6 +++ tests/ListenersTest/CopyPluginAssetsTest.php | 28 +++++++++++++ tests/ServicesTest/PluginManagerTest.php | 44 +++++++++++++++++++- 6 files changed, 138 insertions(+), 1 deletion(-) create mode 100644 app/Events/PluginVersionChanged.php create mode 100644 app/Listeners/CopyPluginAssets.php create mode 100644 tests/ListenersTest/CopyPluginAssetsTest.php diff --git a/app/Events/PluginVersionChanged.php b/app/Events/PluginVersionChanged.php new file mode 100644 index 00000000..4b5f2be0 --- /dev/null +++ b/app/Events/PluginVersionChanged.php @@ -0,0 +1,21 @@ +plugin = $plugin; + } +} diff --git a/app/Listeners/CopyPluginAssets.php b/app/Listeners/CopyPluginAssets.php new file mode 100644 index 00000000..d74366f3 --- /dev/null +++ b/app/Listeners/CopyPluginAssets.php @@ -0,0 +1,34 @@ +filesystem = $filesystem; + } + + public function handle(\App\Events\PluginVersionChanged $event) + { + $plugin = $event->plugin; + $dir = public_path('plugins/'.$plugin->name); + $this->filesystem->deleteDirectory($dir); + + $this->filesystem->copyDirectory( + $plugin->getPath().DIRECTORY_SEPARATOR.'assets', + $dir.'/assets' + ); + $this->filesystem->copyDirectory( + $plugin->getPath().DIRECTORY_SEPARATOR.'lang', + $dir.'/lang' + ); + } +} diff --git a/app/Providers/EventServiceProvider.php b/app/Providers/EventServiceProvider.php index 10764a40..d4c3cfd0 100644 --- a/app/Providers/EventServiceProvider.php +++ b/app/Providers/EventServiceProvider.php @@ -21,6 +21,12 @@ class EventServiceProvider extends ServiceProvider 'App\Events\TextureDeleting' => [ 'App\Listeners\TextureRemoved', ], + 'App\Events\PluginWasEnabled' => [ + 'App\Listeners\CopyPluginAssets', + ], + 'App\Events\PluginVersionChanged' => [ + 'App\Listeners\CopyPluginAssets', + ], ]; /** diff --git a/app/Services/PluginManager.php b/app/Services/PluginManager.php index 2be38fc5..ca79699d 100644 --- a/app/Services/PluginManager.php +++ b/app/Services/PluginManager.php @@ -97,6 +97,12 @@ class PluginManager $plugin = new Plugin($directory, $manifest); if ($this->enabled->contains('name', $name)) { $plugin->setEnabled(true); + if (Comparator::notEqualTo( + $manifest['version'], + $this->enabled->firstWhere('name', $name)['version'] + )) { + $this->dispatcher->dispatch(new Events\PluginVersionChanged($plugin)); + } } $plugins->put($name, $plugin); }); diff --git a/tests/ListenersTest/CopyPluginAssetsTest.php b/tests/ListenersTest/CopyPluginAssetsTest.php new file mode 100644 index 00000000..d0c0393a --- /dev/null +++ b/tests/ListenersTest/CopyPluginAssetsTest.php @@ -0,0 +1,28 @@ + 'fake']); + + $this->mock(\Illuminate\Filesystem\Filesystem::class, function ($mock) { + $dir = public_path('plugins/fake'); + $mock->shouldReceive('deleteDirectory') + ->with($dir) + ->once(); + + $mock->shouldReceive('copyDirectory') + ->withArgs(['/path'.DIRECTORY_SEPARATOR.'assets', $dir.'/assets']) + ->once(); + + $mock->shouldReceive('copyDirectory') + ->withArgs(['/path'.DIRECTORY_SEPARATOR.'lang', $dir.'/lang']) + ->once(); + }); + + event(new \App\Events\PluginVersionChanged($plugin)); + } +} diff --git a/tests/ServicesTest/PluginManagerTest.php b/tests/ServicesTest/PluginManagerTest.php index 7c9d43d8..b602a3e9 100644 --- a/tests/ServicesTest/PluginManagerTest.php +++ b/tests/ServicesTest/PluginManagerTest.php @@ -2,6 +2,7 @@ namespace Tests; +use Event; use ReflectionClass; use App\Services\PluginManager; use Illuminate\Filesystem\Filesystem; @@ -82,6 +83,48 @@ class PluginManagerTest extends TestCase $manager = $this->rebootPluginManager(app('plugins')); } + public function testDetectVersionChanged() + { + option(['plugins_enabled' => json_encode([['name' => 'mayaka', 'version' => '0.0.0']])]); + Event::fake(); + $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.1.0', + ])); + + $mock->shouldReceive('exists') + ->with('/mayaka/vendor/autoload.php') + ->once() + ->andReturn(false); + $mock->shouldReceive('exists') + ->with('/mayaka/bootstrap.php') + ->once() + ->andReturn(false); + }); + + $manager = $this->rebootPluginManager(app('plugins')); + Event::assertDispatched(\App\Events\PluginVersionChanged::class, function ($event) { + $this->assertEquals('0.1.0', $event->plugin->version); + return true; + }); + + option(['plugins_enabled' => '[]']); + } + public function testLoadComposer() { option(['plugins_enabled' => json_encode([['name' => 'mayaka', 'version' => '0.0.0']])]); @@ -151,7 +194,6 @@ class PluginManagerTest extends TestCase ->with('/mayaka/vendor/autoload.php') ->once() ->andReturn(false); - $mock->shouldReceive('exists') ->with('/mayaka/bootstrap.php') ->once()