Browse Source

Change how plugin collection is used by an application.

Instead of fetching the singleton instance from the Plugin class the
app now creates it's own collection instance and sets it as the singleton.

This provides better app state isolation when running integration tests.
ADmad 2 years ago
parent
commit
bd231aff03

+ 11 - 0
src/Core/Plugin.php

@@ -129,4 +129,15 @@ class Plugin
     {
     {
         return static::$plugins ??= new PluginCollection();
         return static::$plugins ??= new PluginCollection();
     }
     }
+
+    /**
+     * Set the shared plugin collection.
+     *
+     * @param \Cake\Core\PluginCollection $collection
+     * @return void
+     */
+    public static function setCollection(PluginCollection $collection): void
+    {
+        static::$plugins = $collection;
+    }
 }
 }

+ 21 - 0
src/Core/TestSuite/ContainerStubTrait.php

@@ -56,6 +56,8 @@ trait ContainerStubTrait
      */
      */
     private array $containerServices = [];
     private array $containerServices = [];
 
 
+    protected array $pluginsToLoad = [];
+
     /**
     /**
      * Configure the application class to use in integration tests.
      * Configure the application class to use in integration tests.
      *
      *
@@ -71,6 +73,17 @@ trait ContainerStubTrait
     }
     }
 
 
     /**
     /**
+     * Plugins to load after the app instance is created.
+     *
+     * @param array $plugins
+     * @return void
+     */
+    public function pluginsToLoad(array $plugins): void
+    {
+        $this->pluginsToLoad = $plugins;
+    }
+
+    /**
      * Create an application instance.
      * Create an application instance.
      *
      *
      * Uses the configuration set in `configApplication()`.
      * Uses the configuration set in `configApplication()`.
@@ -95,6 +108,14 @@ trait ContainerStubTrait
             $app->getEventManager()->on('Application.buildContainer', [$this, 'modifyContainer']);
             $app->getEventManager()->on('Application.buildContainer', [$this, 'modifyContainer']);
         }
         }
 
 
+        foreach ($this->pluginsToLoad as $pluginName => $config) {
+            if (is_array($config)) {
+                $app->addPlugin($pluginName, $config);
+            } else {
+                $app->addPlugin($config);
+            }
+        }
+
         return $app;
         return $app;
     }
     }
 
 

+ 2 - 1
src/Http/BaseApplication.php

@@ -107,9 +107,10 @@ abstract class BaseApplication implements
         ?ControllerFactoryInterface $controllerFactory = null
         ?ControllerFactoryInterface $controllerFactory = null
     ) {
     ) {
         $this->configDir = rtrim($configDir, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
         $this->configDir = rtrim($configDir, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
-        $this->plugins = Plugin::getCollection();
+        $this->plugins = new PluginCollection();
         $this->_eventManager = $eventManager ?: EventManager::instance();
         $this->_eventManager = $eventManager ?: EventManager::instance();
         $this->controllerFactory = $controllerFactory;
         $this->controllerFactory = $controllerFactory;
+        Plugin::setCollection($this->plugins);
     }
     }
 
 
     /**
     /**

+ 1 - 1
tests/TestCase/Command/I18nExtractCommandTest.php

@@ -273,7 +273,7 @@ class I18nExtractCommandTest extends TestCase
      */
      */
     public function testExtractVendorPrefixedPlugin(): void
     public function testExtractVendorPrefixedPlugin(): void
     {
     {
-        $this->loadPlugins(['Company/TestPluginThree']);
+        $this->pluginsToLoad(['Company/TestPluginThree']);
 
 
         $this->exec(
         $this->exec(
             'i18n extract ' .
             'i18n extract ' .

+ 10 - 10
tests/TestCase/Command/PluginAssetsCommandsTest.php

@@ -76,7 +76,7 @@ class PluginAssetsCommandsTest extends TestCase
      */
      */
     public function testSymlink(): void
     public function testSymlink(): void
     {
     {
-        $this->loadPlugins(['TestPlugin' => ['routes' => false], 'Company/TestPluginThree']);
+        $this->pluginsToLoad(['TestPlugin' => ['routes' => false], 'Company/TestPluginThree']);
 
 
         $this->exec('plugin assets symlink');
         $this->exec('plugin assets symlink');
         $this->assertExitCode(CommandInterface::CODE_SUCCESS);
         $this->assertExitCode(CommandInterface::CODE_SUCCESS);
@@ -92,7 +92,7 @@ class PluginAssetsCommandsTest extends TestCase
 
 
     public function testSymlinkWhenVendorDirectoryExists(): void
     public function testSymlinkWhenVendorDirectoryExists(): void
     {
     {
-        $this->loadPlugins(['Company/TestPluginThree']);
+        $this->pluginsToLoad(['Company/TestPluginThree']);
 
 
         mkdir($this->wwwRoot . 'company');
         mkdir($this->wwwRoot . 'company');
 
 
@@ -109,7 +109,7 @@ class PluginAssetsCommandsTest extends TestCase
      */
      */
     public function testSymlinkWhenTargetAlreadyExits(): void
     public function testSymlinkWhenTargetAlreadyExits(): void
     {
     {
-        $this->loadPlugins(['TestTheme']);
+        $this->pluginsToLoad(['TestTheme']);
 
 
         $output = new StubConsoleOutput();
         $output = new StubConsoleOutput();
         $io = Mockery::mock(ConsoleIo::class, [$output, $output, null, null])->makePartial();
         $io = Mockery::mock(ConsoleIo::class, [$output, $output, null, null])->makePartial();
@@ -134,7 +134,7 @@ class PluginAssetsCommandsTest extends TestCase
      */
      */
     public function testForPluginWithoutWebroot(): void
     public function testForPluginWithoutWebroot(): void
     {
     {
-        $this->loadPlugins(['TestPluginTwo']);
+        $this->pluginsToLoad(['TestPluginTwo']);
 
 
         $this->exec('plugin assets symlink');
         $this->exec('plugin assets symlink');
         $this->assertFileDoesNotExist($this->wwwRoot . 'test_plugin_two');
         $this->assertFileDoesNotExist($this->wwwRoot . 'test_plugin_two');
@@ -145,7 +145,7 @@ class PluginAssetsCommandsTest extends TestCase
      */
      */
     public function testSymlinkingSpecifiedPlugin(): void
     public function testSymlinkingSpecifiedPlugin(): void
     {
     {
-        $this->loadPlugins(['TestPlugin' => ['routes' => false], 'Company/TestPluginThree']);
+        $this->pluginsToLoad(['TestPlugin' => ['routes' => false], 'Company/TestPluginThree']);
 
 
         $this->exec('plugin assets symlink TestPlugin');
         $this->exec('plugin assets symlink TestPlugin');
 
 
@@ -162,7 +162,7 @@ class PluginAssetsCommandsTest extends TestCase
      */
      */
     public function testCopy(): void
     public function testCopy(): void
     {
     {
-        $this->loadPlugins(['TestPlugin' => ['routes' => false], 'Company/TestPluginThree']);
+        $this->pluginsToLoad(['TestPlugin' => ['routes' => false], 'Company/TestPluginThree']);
 
 
         $this->exec('plugin assets copy');
         $this->exec('plugin assets copy');
 
 
@@ -180,7 +180,7 @@ class PluginAssetsCommandsTest extends TestCase
      */
      */
     public function testCopyOverwrite(): void
     public function testCopyOverwrite(): void
     {
     {
-        $this->loadPlugins(['TestPlugin' => ['routes' => false]]);
+        $this->pluginsToLoad(['TestPlugin' => ['routes' => false]]);
 
 
         $this->exec('plugin assets copy');
         $this->exec('plugin assets copy');
 
 
@@ -207,7 +207,7 @@ class PluginAssetsCommandsTest extends TestCase
      */
      */
     public function testRemoveSymlink(): void
     public function testRemoveSymlink(): void
     {
     {
-        $this->loadPlugins(['TestPlugin' => ['routes' => false], 'Company/TestPluginThree']);
+        $this->pluginsToLoad(['TestPlugin' => ['routes' => false], 'Company/TestPluginThree']);
 
 
         mkdir($this->wwwRoot . 'company');
         mkdir($this->wwwRoot . 'company');
 
 
@@ -230,7 +230,7 @@ class PluginAssetsCommandsTest extends TestCase
      */
      */
     public function testRemoveFolder(): void
     public function testRemoveFolder(): void
     {
     {
-        $this->loadPlugins(['TestPlugin' => ['routes' => false], 'Company/TestPluginThree']);
+        $this->pluginsToLoad(['TestPlugin' => ['routes' => false], 'Company/TestPluginThree']);
 
 
         $this->exec('plugin assets copy');
         $this->exec('plugin assets copy');
 
 
@@ -250,7 +250,7 @@ class PluginAssetsCommandsTest extends TestCase
      */
      */
     public function testOverwrite(): void
     public function testOverwrite(): void
     {
     {
-        $this->loadPlugins(['TestPlugin' => ['routes' => false], 'Company/TestPluginThree']);
+        $this->pluginsToLoad(['TestPlugin' => ['routes' => false], 'Company/TestPluginThree']);
 
 
         $path = $this->wwwRoot . 'test_plugin';
         $path = $this->wwwRoot . 'test_plugin';
 
 

+ 1 - 13
tests/TestCase/Console/Command/HelpCommandTest.php

@@ -18,9 +18,6 @@ namespace Cake\Test\TestCase\Console\Command;
 
 
 use Cake\Console\CommandInterface;
 use Cake\Console\CommandInterface;
 use Cake\Console\TestSuite\ConsoleIntegrationTestTrait;
 use Cake\Console\TestSuite\ConsoleIntegrationTestTrait;
-use Cake\Core\Plugin;
-use Cake\Http\BaseApplication;
-use Cake\Http\MiddlewareQueue;
 use Cake\TestSuite\TestCase;
 use Cake\TestSuite\TestCase;
 
 
 /**
 /**
@@ -37,16 +34,7 @@ class HelpCommandTest extends TestCase
     {
     {
         parent::setUp();
         parent::setUp();
         $this->setAppNamespace();
         $this->setAppNamespace();
-        Plugin::getCollection()->clear();
-
-        $app = new class ('') extends BaseApplication
-        {
-            public function middleware(MiddlewareQueue $middlewareQueue): MiddlewareQueue
-            {
-                return $middlewareQueue;
-            }
-        };
-        $app->addPlugin('TestPlugin');
+        $this->pluginsToLoad(['TestPlugin']);
     }
     }
 
 
     /**
     /**

+ 1 - 1
tests/TestCase/Routing/AssetTest.php

@@ -229,7 +229,7 @@ class AssetTest extends TestCase
     public function testAssetTimestampPluginsAndThemes(): void
     public function testAssetTimestampPluginsAndThemes(): void
     {
     {
         Configure::write('Asset.timestamp', 'force');
         Configure::write('Asset.timestamp', 'force');
-        $this->loadPlugins(['TestPlugin', 'Company/TestPluginThree']);
+        $this->loadPlugins(['TestTheme', 'TestPlugin', 'Company/TestPluginThree']);
 
 
         $result = Asset::assetTimestamp('/test_plugin/css/test_plugin_asset.css');
         $result = Asset::assetTimestamp('/test_plugin/css/test_plugin_asset.css');
         $this->assertMatchesRegularExpression('#/test_plugin/css/test_plugin_asset.css\?[0-9]+$#', $result, 'Missing timestamp plugin');
         $this->assertMatchesRegularExpression('#/test_plugin/css/test_plugin_asset.css\?[0-9]+$#', $result, 'Missing timestamp plugin');

+ 1 - 1
tests/TestCase/View/Helper/UrlHelperTest.php

@@ -333,7 +333,7 @@ class UrlHelperTest extends TestCase
     public function testAssetTimestampPluginsAndThemes(): void
     public function testAssetTimestampPluginsAndThemes(): void
     {
     {
         Configure::write('Asset.timestamp', 'force');
         Configure::write('Asset.timestamp', 'force');
-        $this->loadPlugins(['TestPlugin']);
+        $this->loadPlugins(['TestTheme', 'TestPlugin']);
 
 
         $result = $this->Helper->assetTimestamp('/test_plugin/css/test_plugin_asset.css');
         $result = $this->Helper->assetTimestamp('/test_plugin/css/test_plugin_asset.css');
         $this->assertMatchesRegularExpression('#/test_plugin/css/test_plugin_asset.css\?[0-9]+$#', $result, 'Missing timestamp plugin');
         $this->assertMatchesRegularExpression('#/test_plugin/css/test_plugin_asset.css\?[0-9]+$#', $result, 'Missing timestamp plugin');