From 0c1f907f7d9c789e941f61f5ac4782016b41bcc2 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Sat, 27 May 2017 16:48:37 +0200 Subject: [PATCH 1/8] Autoload package assets --- .../Bootstrap/LoadPackageAssets.php | 28 +++++++++++++ src/Illuminate/Foundation/Console/Kernel.php | 1 + src/Illuminate/Foundation/Http/Kernel.php | 1 + .../Foundation/PackageAssetLoader.php | 39 +++++++++++++++++++ .../FoundationPackageAssetsTest.php | 27 +++++++++++++ .../vendor/package_a/package_a/composer.json | 9 +++++ .../vendor/package_b/package_b/composer.json | 7 ++++ .../vendor/package_c/package_b/composer.json | 8 ++++ 8 files changed, 120 insertions(+) create mode 100644 src/Illuminate/Foundation/Bootstrap/LoadPackageAssets.php create mode 100644 src/Illuminate/Foundation/PackageAssetLoader.php create mode 100644 tests/Foundation/FoundationPackageAssetsTest.php create mode 100644 tests/Foundation/fixtures/vendor/package_a/package_a/composer.json create mode 100644 tests/Foundation/fixtures/vendor/package_b/package_b/composer.json create mode 100644 tests/Foundation/fixtures/vendor/package_c/package_b/composer.json diff --git a/src/Illuminate/Foundation/Bootstrap/LoadPackageAssets.php b/src/Illuminate/Foundation/Bootstrap/LoadPackageAssets.php new file mode 100644 index 000000000000..0dc944bd4e07 --- /dev/null +++ b/src/Illuminate/Foundation/Bootstrap/LoadPackageAssets.php @@ -0,0 +1,28 @@ +get('providers') as $provider) { + $app->register($provider); + } + + AliasLoader::getInstance($assetLoader->get('facades'))->register(); + } +} diff --git a/src/Illuminate/Foundation/Console/Kernel.php b/src/Illuminate/Foundation/Console/Kernel.php index 7c7a1f45acae..6bfea60c3f63 100644 --- a/src/Illuminate/Foundation/Console/Kernel.php +++ b/src/Illuminate/Foundation/Console/Kernel.php @@ -63,6 +63,7 @@ class Kernel implements KernelContract \Illuminate\Foundation\Bootstrap\RegisterFacades::class, \Illuminate\Foundation\Bootstrap\SetRequestForConsole::class, \Illuminate\Foundation\Bootstrap\RegisterProviders::class, + \Illuminate\Foundation\Bootstrap\LoadPackageAssets::class, \Illuminate\Foundation\Bootstrap\BootProviders::class, ]; diff --git a/src/Illuminate/Foundation/Http/Kernel.php b/src/Illuminate/Foundation/Http/Kernel.php index 9a9c4265b83d..45a466f8e5f9 100644 --- a/src/Illuminate/Foundation/Http/Kernel.php +++ b/src/Illuminate/Foundation/Http/Kernel.php @@ -39,6 +39,7 @@ class Kernel implements KernelContract \Illuminate\Foundation\Bootstrap\HandleExceptions::class, \Illuminate\Foundation\Bootstrap\RegisterFacades::class, \Illuminate\Foundation\Bootstrap\RegisterProviders::class, + \Illuminate\Foundation\Bootstrap\LoadPackageAssets::class, \Illuminate\Foundation\Bootstrap\BootProviders::class, ]; diff --git a/src/Illuminate/Foundation/PackageAssetLoader.php b/src/Illuminate/Foundation/PackageAssetLoader.php new file mode 100644 index 000000000000..20e9fec145b4 --- /dev/null +++ b/src/Illuminate/Foundation/PackageAssetLoader.php @@ -0,0 +1,39 @@ +filesystem = $filesystem; + $this->directory = $directory; + } + + public function get($key) + { + $assets = []; + + foreach ($this->filesystem->directories($this->directory) as $vendor) { + foreach ($this->filesystem->directories($vendor) as $package) { + $config = json_decode($this->filesystem->get($package . '/composer.json'), true); + + $assets = array_merge($assets, (array) ($config['extra'][$key] ?? [])); + } + } + + return array_unique($assets); + } +} diff --git a/tests/Foundation/FoundationPackageAssetsTest.php b/tests/Foundation/FoundationPackageAssetsTest.php new file mode 100644 index 000000000000..0216a24716cd --- /dev/null +++ b/tests/Foundation/FoundationPackageAssetsTest.php @@ -0,0 +1,27 @@ +assertEquals($discovery->get('providers'), ['foo', 'bar', 'baz']); + $this->assertEquals($discovery->get('facades'), [ + 'Foo' => 'FooClass', + 'Bar' => 'BarClass', + ]); + } +} diff --git a/tests/Foundation/fixtures/vendor/package_a/package_a/composer.json b/tests/Foundation/fixtures/vendor/package_a/package_a/composer.json new file mode 100644 index 000000000000..e0b13e237e5f --- /dev/null +++ b/tests/Foundation/fixtures/vendor/package_a/package_a/composer.json @@ -0,0 +1,9 @@ +{ + "extra": { + "providers": "foo", + "facades": { + "Foo": "FooClass", + "Bar": "BarClass" + } + } +} diff --git a/tests/Foundation/fixtures/vendor/package_b/package_b/composer.json b/tests/Foundation/fixtures/vendor/package_b/package_b/composer.json new file mode 100644 index 000000000000..2786f0f84908 --- /dev/null +++ b/tests/Foundation/fixtures/vendor/package_b/package_b/composer.json @@ -0,0 +1,7 @@ +{ + "extra": { + "facades": { + "Foo": "FooClass" + } + } +} diff --git a/tests/Foundation/fixtures/vendor/package_c/package_b/composer.json b/tests/Foundation/fixtures/vendor/package_c/package_b/composer.json new file mode 100644 index 000000000000..4c3bc1ef39b3 --- /dev/null +++ b/tests/Foundation/fixtures/vendor/package_c/package_b/composer.json @@ -0,0 +1,8 @@ +{ + "extra": { + "providers": [ + "bar", + "baz" + ] + } +} From f3894d09f6ed1fea4e97f6c4e4b11e0b2fdbd8d9 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Tue, 30 May 2017 00:02:35 +0200 Subject: [PATCH 2/8] Use packages file to cache package providers --- .../Contracts/Foundation/Application.php | 7 +++ src/Illuminate/Foundation/Application.php | 10 ++++ ...ssets.php => RegisterPackageProviders.php} | 7 +-- src/Illuminate/Foundation/ComposerScripts.php | 4 ++ .../Console/ClearCompiledCommand.php | 10 ++-- src/Illuminate/Foundation/Console/Kernel.php | 2 +- src/Illuminate/Foundation/Http/Kernel.php | 2 +- .../Foundation/PackageAssetLoader.php | 60 ++++++++++++++++--- .../FoundationPackageAssetsTest.php | 8 +-- .../vendor/package_a/package_a/composer.json | 6 +- .../vendor/package_b/package_b/composer.json | 7 ++- .../vendor/package_c/package_b/composer.json | 8 --- 12 files changed, 89 insertions(+), 42 deletions(-) rename src/Illuminate/Foundation/Bootstrap/{LoadPackageAssets.php => RegisterPackageProviders.php} (78%) delete mode 100644 tests/Foundation/fixtures/vendor/package_c/package_b/composer.json diff --git a/src/Illuminate/Contracts/Foundation/Application.php b/src/Illuminate/Contracts/Foundation/Application.php index 8a4d412f640f..de47c7470a50 100644 --- a/src/Illuminate/Contracts/Foundation/Application.php +++ b/src/Illuminate/Contracts/Foundation/Application.php @@ -96,4 +96,11 @@ public function booted($callback); * @return string */ public function getCachedServicesPath(); + + /** + * Get the path to the cached packages.php file. + * + * @return string + */ + public function getCachedPackagesPath(); } diff --git a/src/Illuminate/Foundation/Application.php b/src/Illuminate/Foundation/Application.php index f90bc4f93883..5d61475fbbaa 100755 --- a/src/Illuminate/Foundation/Application.php +++ b/src/Illuminate/Foundation/Application.php @@ -838,6 +838,16 @@ public function getCachedServicesPath() return $this->bootstrapPath().'/cache/services.php'; } + /** + * Get the path to the cached services.php file. + * + * @return string + */ + public function getCachedPackagesPath() + { + return $this->bootstrapPath().'/cache/packages.php'; + } + /** * Determine if the application configuration is cached. * diff --git a/src/Illuminate/Foundation/Bootstrap/LoadPackageAssets.php b/src/Illuminate/Foundation/Bootstrap/RegisterPackageProviders.php similarity index 78% rename from src/Illuminate/Foundation/Bootstrap/LoadPackageAssets.php rename to src/Illuminate/Foundation/Bootstrap/RegisterPackageProviders.php index 0dc944bd4e07..7a2ad3851fc3 100644 --- a/src/Illuminate/Foundation/Bootstrap/LoadPackageAssets.php +++ b/src/Illuminate/Foundation/Bootstrap/RegisterPackageProviders.php @@ -3,11 +3,10 @@ namespace Illuminate\Foundation\Bootstrap; use Illuminate\Filesystem\Filesystem; -use Illuminate\Foundation\AliasLoader; use Illuminate\Foundation\PackageAssetLoader; use Illuminate\Contracts\Foundation\Application; -class LoadPackageAssets +class RegisterPackageProviders { /** * Bootstrap the given application. @@ -17,12 +16,10 @@ class LoadPackageAssets */ public function bootstrap(Application $app) { - $assetLoader = new PackageAssetLoader(new Filesystem, base_path('vendor')); + $assetLoader = new PackageAssetLoader(new Filesystem, base_path('vendor'), $app->getCachedPackagesPath()); foreach ($assetLoader->get('providers') as $provider) { $app->register($provider); } - - AliasLoader::getInstance($assetLoader->get('facades'))->register(); } } diff --git a/src/Illuminate/Foundation/ComposerScripts.php b/src/Illuminate/Foundation/ComposerScripts.php index 9b4c1ddebc2a..cf35b99ff9f8 100644 --- a/src/Illuminate/Foundation/ComposerScripts.php +++ b/src/Illuminate/Foundation/ComposerScripts.php @@ -44,5 +44,9 @@ protected static function clearCompiled() if (file_exists($servicesPath = $laravel->getCachedServicesPath())) { @unlink($servicesPath); } + + if (file_exists($packagesPath = $laravel->getCachedPackagesPath())) { + @unlink($packagesPath); + } } } diff --git a/src/Illuminate/Foundation/Console/ClearCompiledCommand.php b/src/Illuminate/Foundation/Console/ClearCompiledCommand.php index 8d87b715e76d..253237b05ae5 100644 --- a/src/Illuminate/Foundation/Console/ClearCompiledCommand.php +++ b/src/Illuminate/Foundation/Console/ClearCompiledCommand.php @@ -27,12 +27,14 @@ class ClearCompiledCommand extends Command */ public function fire() { - $servicesPath = $this->laravel->getCachedServicesPath(); - - if (file_exists($servicesPath)) { + if (file_exists($servicesPath = $this->laravel->getCachedServicesPath())) { @unlink($servicesPath); } - $this->info('The compiled services file has been removed.'); + if (file_exists($packagesPath = $this->laravel->getCachedPackagesPath())) { + @unlink($packagesPath); + } + + $this->info('The compiled services & packages file have been removed.'); } } diff --git a/src/Illuminate/Foundation/Console/Kernel.php b/src/Illuminate/Foundation/Console/Kernel.php index 6bfea60c3f63..1aaac0fba3a8 100644 --- a/src/Illuminate/Foundation/Console/Kernel.php +++ b/src/Illuminate/Foundation/Console/Kernel.php @@ -63,7 +63,7 @@ class Kernel implements KernelContract \Illuminate\Foundation\Bootstrap\RegisterFacades::class, \Illuminate\Foundation\Bootstrap\SetRequestForConsole::class, \Illuminate\Foundation\Bootstrap\RegisterProviders::class, - \Illuminate\Foundation\Bootstrap\LoadPackageAssets::class, + \Illuminate\Foundation\Bootstrap\RegisterPackageProviders::class, \Illuminate\Foundation\Bootstrap\BootProviders::class, ]; diff --git a/src/Illuminate/Foundation/Http/Kernel.php b/src/Illuminate/Foundation/Http/Kernel.php index 45a466f8e5f9..239e9d599862 100644 --- a/src/Illuminate/Foundation/Http/Kernel.php +++ b/src/Illuminate/Foundation/Http/Kernel.php @@ -39,7 +39,7 @@ class Kernel implements KernelContract \Illuminate\Foundation\Bootstrap\HandleExceptions::class, \Illuminate\Foundation\Bootstrap\RegisterFacades::class, \Illuminate\Foundation\Bootstrap\RegisterProviders::class, - \Illuminate\Foundation\Bootstrap\LoadPackageAssets::class, + \Illuminate\Foundation\Bootstrap\RegisterPackageProviders::class, \Illuminate\Foundation\Bootstrap\BootProviders::class, ]; diff --git a/src/Illuminate/Foundation/PackageAssetLoader.php b/src/Illuminate/Foundation/PackageAssetLoader.php index 20e9fec145b4..46d705fa7cbc 100644 --- a/src/Illuminate/Foundation/PackageAssetLoader.php +++ b/src/Illuminate/Foundation/PackageAssetLoader.php @@ -2,6 +2,7 @@ namespace Illuminate\Foundation; +use Exception; use Illuminate\Filesystem\Filesystem; class PackageAssetLoader @@ -9,26 +10,56 @@ class PackageAssetLoader /** * @var \Illuminate\Filesystem\Filesystem */ - private $filesystem; + private $files; /** * @var string */ - private $directory; + private $vendorPath; - public function __construct(Filesystem $filesystem, string $directory) + /** + * @var string|null + */ + private $manifestPath; + + public function __construct(Filesystem $files, string $vendorPath, string $manifestPath = null) { - $this->filesystem = $filesystem; - $this->directory = $directory; + $this->files = $files; + $this->vendorPath = $vendorPath; + $this->manifestPath = $manifestPath; } - public function get($key) + public function get(string $key): array + { + $manifest = []; + + if (file_exists($this->manifestPath)) { + $manifest = json_decode($this->manifestPath, true); + + // If the manifest has a key for the given asset type, + // we'll simply return the assets without loading + // all of the assets again from the packages. + if (isset($manifest[$key])) { + return $manifest[$key]; + } + } + + $manifest[$key] = $this->retrieveAssets($key); + + if ($this->manifestPath) { + $this->writeManifest($manifest); + } + + return $manifest[$key]; + } + + private function retrieveAssets(string $key) { $assets = []; - foreach ($this->filesystem->directories($this->directory) as $vendor) { - foreach ($this->filesystem->directories($vendor) as $package) { - $config = json_decode($this->filesystem->get($package . '/composer.json'), true); + foreach ($this->files->directories($this->vendorPath) as $vendor) { + foreach ($this->files->directories($vendor) as $package) { + $config = json_decode($this->files->get($package . '/composer.json'), true); $assets = array_merge($assets, (array) ($config['extra'][$key] ?? [])); } @@ -36,4 +67,15 @@ public function get($key) return array_unique($assets); } + + private function writeManifest(array $manifest) + { + if (! is_writable(dirname($this->manifestPath))) { + throw new Exception('The bootstrap/cache directory must be present and writable.'); + } + + $this->files->put( + $this->manifestPath, 'assertEquals($discovery->get('providers'), ['foo', 'bar', 'baz']); - $this->assertEquals($discovery->get('facades'), [ - 'Foo' => 'FooClass', - 'Bar' => 'BarClass', - ]); + $this->assertEquals($assetLoader->get('providers'), ['foo', 'bar', 'baz']); } } diff --git a/tests/Foundation/fixtures/vendor/package_a/package_a/composer.json b/tests/Foundation/fixtures/vendor/package_a/package_a/composer.json index e0b13e237e5f..601971cc780c 100644 --- a/tests/Foundation/fixtures/vendor/package_a/package_a/composer.json +++ b/tests/Foundation/fixtures/vendor/package_a/package_a/composer.json @@ -1,9 +1,5 @@ { "extra": { - "providers": "foo", - "facades": { - "Foo": "FooClass", - "Bar": "BarClass" - } + "providers": "foo" } } diff --git a/tests/Foundation/fixtures/vendor/package_b/package_b/composer.json b/tests/Foundation/fixtures/vendor/package_b/package_b/composer.json index 2786f0f84908..4c3bc1ef39b3 100644 --- a/tests/Foundation/fixtures/vendor/package_b/package_b/composer.json +++ b/tests/Foundation/fixtures/vendor/package_b/package_b/composer.json @@ -1,7 +1,8 @@ { "extra": { - "facades": { - "Foo": "FooClass" - } + "providers": [ + "bar", + "baz" + ] } } diff --git a/tests/Foundation/fixtures/vendor/package_c/package_b/composer.json b/tests/Foundation/fixtures/vendor/package_c/package_b/composer.json deleted file mode 100644 index 4c3bc1ef39b3..000000000000 --- a/tests/Foundation/fixtures/vendor/package_c/package_b/composer.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "extra": { - "providers": [ - "bar", - "baz" - ] - } -} From 40a4926d56b0b234c0d4846fd9013139fa4a480b Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Tue, 30 May 2017 00:15:10 +0200 Subject: [PATCH 3/8] Fix getting manifest contents --- src/Illuminate/Foundation/PackageAssetLoader.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Illuminate/Foundation/PackageAssetLoader.php b/src/Illuminate/Foundation/PackageAssetLoader.php index 46d705fa7cbc..96618b11a457 100644 --- a/src/Illuminate/Foundation/PackageAssetLoader.php +++ b/src/Illuminate/Foundation/PackageAssetLoader.php @@ -34,7 +34,7 @@ public function get(string $key): array $manifest = []; if (file_exists($this->manifestPath)) { - $manifest = json_decode($this->manifestPath, true); + $manifest = $this->files->getRequire($this->manifestPath); // If the manifest has a key for the given asset type, // we'll simply return the assets without loading From f483ed4b0d8aceb4e52849e1a4cc7bd121f8ffdf Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Tue, 30 May 2017 00:21:19 +0200 Subject: [PATCH 4/8] Allow users to disable package autoloading --- .../Foundation/Bootstrap/RegisterPackageProviders.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Illuminate/Foundation/Bootstrap/RegisterPackageProviders.php b/src/Illuminate/Foundation/Bootstrap/RegisterPackageProviders.php index 7a2ad3851fc3..4e4b35b7ceac 100644 --- a/src/Illuminate/Foundation/Bootstrap/RegisterPackageProviders.php +++ b/src/Illuminate/Foundation/Bootstrap/RegisterPackageProviders.php @@ -16,6 +16,10 @@ class RegisterPackageProviders */ public function bootstrap(Application $app) { + if (! $app->make('config')->get('app.autoload_package_providers', true)) { + return; + } + $assetLoader = new PackageAssetLoader(new Filesystem, base_path('vendor'), $app->getCachedPackagesPath()); foreach ($assetLoader->get('providers') as $provider) { From 11006d82153c9dea3386566e32c5feec8298995b Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Tue, 30 May 2017 00:23:42 +0200 Subject: [PATCH 5/8] Remove mockery call in test --- tests/Foundation/FoundationPackageAssetsTest.php | 6 ------ 1 file changed, 6 deletions(-) diff --git a/tests/Foundation/FoundationPackageAssetsTest.php b/tests/Foundation/FoundationPackageAssetsTest.php index 2faefd13ab56..9acd7d98fa9b 100644 --- a/tests/Foundation/FoundationPackageAssetsTest.php +++ b/tests/Foundation/FoundationPackageAssetsTest.php @@ -2,18 +2,12 @@ namespace Illuminate\Tests\Foundation; -use Mockery as m; use PHPUnit\Framework\TestCase; use Illuminate\Filesystem\Filesystem; use Illuminate\Foundation\PackageAssetLoader; class FoundationPackageAssetsTest extends TestCase { - public function tearDown() - { - m::close(); - } - public function testAssetLoading() { $assetLoader = new PackageAssetLoader(new Filesystem, __DIR__ . '/fixtures/vendor'); From 9e7ef4ee166d7608557404ed4ef906d2d3ff9641 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Tue, 30 May 2017 10:59:46 +0200 Subject: [PATCH 6/8] Wording --- src/Illuminate/Foundation/Console/ClearCompiledCommand.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Illuminate/Foundation/Console/ClearCompiledCommand.php b/src/Illuminate/Foundation/Console/ClearCompiledCommand.php index 253237b05ae5..0f072d133823 100644 --- a/src/Illuminate/Foundation/Console/ClearCompiledCommand.php +++ b/src/Illuminate/Foundation/Console/ClearCompiledCommand.php @@ -35,6 +35,6 @@ public function fire() @unlink($packagesPath); } - $this->info('The compiled services & packages file have been removed.'); + $this->info('The compiled services & packages files have been removed.'); } } From 0f49665023a17b1c1127fc62fb5abb1ed7d709fd Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Thu, 1 Jun 2017 11:34:56 +0200 Subject: [PATCH 7/8] Fix StyleCI warnings --- src/Illuminate/Foundation/PackageAssetLoader.php | 2 +- tests/Foundation/FoundationPackageAssetsTest.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Illuminate/Foundation/PackageAssetLoader.php b/src/Illuminate/Foundation/PackageAssetLoader.php index 96618b11a457..f4a7f4c6117c 100644 --- a/src/Illuminate/Foundation/PackageAssetLoader.php +++ b/src/Illuminate/Foundation/PackageAssetLoader.php @@ -59,7 +59,7 @@ private function retrieveAssets(string $key) foreach ($this->files->directories($this->vendorPath) as $vendor) { foreach ($this->files->directories($vendor) as $package) { - $config = json_decode($this->files->get($package . '/composer.json'), true); + $config = json_decode($this->files->get($package.'/composer.json'), true); $assets = array_merge($assets, (array) ($config['extra'][$key] ?? [])); } diff --git a/tests/Foundation/FoundationPackageAssetsTest.php b/tests/Foundation/FoundationPackageAssetsTest.php index 9acd7d98fa9b..d8d8db3c9758 100644 --- a/tests/Foundation/FoundationPackageAssetsTest.php +++ b/tests/Foundation/FoundationPackageAssetsTest.php @@ -10,7 +10,7 @@ class FoundationPackageAssetsTest extends TestCase { public function testAssetLoading() { - $assetLoader = new PackageAssetLoader(new Filesystem, __DIR__ . '/fixtures/vendor'); + $assetLoader = new PackageAssetLoader(new Filesystem, __DIR__.'/fixtures/vendor'); $this->assertEquals($assetLoader->get('providers'), ['foo', 'bar', 'baz']); } From 96e609b5706c3989a605e1dc7a5ea87f1ec43cc0 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Thu, 1 Jun 2017 11:49:45 +0200 Subject: [PATCH 8/8] Check first if class exists --- .../Foundation/Bootstrap/RegisterPackageProviders.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Illuminate/Foundation/Bootstrap/RegisterPackageProviders.php b/src/Illuminate/Foundation/Bootstrap/RegisterPackageProviders.php index 4e4b35b7ceac..25ce19ef15a3 100644 --- a/src/Illuminate/Foundation/Bootstrap/RegisterPackageProviders.php +++ b/src/Illuminate/Foundation/Bootstrap/RegisterPackageProviders.php @@ -23,7 +23,9 @@ public function bootstrap(Application $app) $assetLoader = new PackageAssetLoader(new Filesystem, base_path('vendor'), $app->getCachedPackagesPath()); foreach ($assetLoader->get('providers') as $provider) { - $app->register($provider); + if (class_exists($provider)) { + $app->register($provider); + } } } }