From 55463c9ef0e4c3e24a08a7c3c40c2ca12b087feb Mon Sep 17 00:00:00 2001 From: Dave Long <dave@longwaveconsulting.com> Date: Fri, 10 May 2024 16:36:36 +0100 Subject: [PATCH] Issue #3445950 by alexpott, tim.plunkett: \Drupal\Core\Plugin\DefaultLazyPluginCollection::setInstanceConfiguration() assumes that $configuration results in the same plugin instance (cherry picked from commit 926d069c2cf47fa251f5f5a51dd51d75027f53d6) --- .../Plugin/DefaultLazyPluginCollection.php | 11 +++++++ .../DefaultLazyPluginCollectionTest.php | 31 +++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/core/lib/Drupal/Core/Plugin/DefaultLazyPluginCollection.php b/core/lib/Drupal/Core/Plugin/DefaultLazyPluginCollection.php index e420dfc15052..9371de650a92 100644 --- a/core/lib/Drupal/Core/Plugin/DefaultLazyPluginCollection.php +++ b/core/lib/Drupal/Core/Plugin/DefaultLazyPluginCollection.php @@ -156,6 +156,17 @@ public function setConfiguration(array $configuration) { * The plugin configuration to set. */ public function setInstanceConfiguration($instance_id, array $configuration) { + if ( + isset($this->pluginInstances[$instance_id]) && + isset($configuration[$this->pluginKey]) && + isset($this->configurations[$instance_id][$this->pluginKey]) && + $configuration[$this->pluginKey] !== $this->configurations[$instance_id][$this->pluginKey] + ) { + // If the plugin has already been instantiated by the configuration was + // for a different plugin then we need to unset the instantiated plugin. + unset($this->pluginInstances[$instance_id]); + } + $this->configurations[$instance_id] = $configuration; $instance = $this->get($instance_id); if ($instance instanceof ConfigurableInterface) { diff --git a/core/tests/Drupal/Tests/Core/Plugin/DefaultLazyPluginCollectionTest.php b/core/tests/Drupal/Tests/Core/Plugin/DefaultLazyPluginCollectionTest.php index 71b67e43171d..a4b9e379caa9 100644 --- a/core/tests/Drupal/Tests/Core/Plugin/DefaultLazyPluginCollectionTest.php +++ b/core/tests/Drupal/Tests/Core/Plugin/DefaultLazyPluginCollectionTest.php @@ -168,6 +168,37 @@ public function testSetInstanceConfiguration() { $this->assertSame($expected, $config['cherry']); } + /** + * Tests plugin instances are changed if the configuration plugin key changes. + * + * @covers ::setInstanceConfiguration + */ + public function testSetInstanceConfigurationPluginChange() { + $configurable_plugin = $this->prophesize(ConfigurableInterface::class); + $configurable_config = ['id' => 'configurable', 'foo' => 'bar']; + $configurable_plugin->getConfiguration()->willReturn($configurable_config); + + $nonconfigurable_plugin = $this->prophesize(PluginInspectionInterface::class); + $nonconfigurable_config = ['id' => 'non-configurable', 'baz' => 'qux']; + $nonconfigurable_plugin->configuration = $nonconfigurable_config; + + $configurations = [ + 'instance' => $configurable_config, + ]; + + $plugin_manager = $this->prophesize(PluginManagerInterface::class); + $plugin_manager->createInstance('configurable', $configurable_config)->willReturn($configurable_plugin->reveal()); + $plugin_manager->createInstance('non-configurable', $nonconfigurable_config)->willReturn($nonconfigurable_plugin->reveal()); + + $collection = new DefaultLazyPluginCollection($plugin_manager->reveal(), $configurations); + $this->assertInstanceOf(ConfigurableInterface::class, $collection->get('instance')); + + // Ensure changing the instance to a different plugin via + // setInstanceConfiguration() results in a different plugin instance. + $collection->setInstanceConfiguration('instance', $nonconfigurable_config); + $this->assertNotInstanceOf(ConfigurableInterface::class, $collection->get('instance')); + } + /** * @covers ::count */ -- GitLab