diff -u b/core/lib/Drupal/Component/Plugin/Discovery/DerivativeDiscoveryDecorator.php b/core/lib/Drupal/Component/Plugin/Discovery/DerivativeDiscoveryDecorator.php --- b/core/lib/Drupal/Component/Plugin/Discovery/DerivativeDiscoveryDecorator.php +++ b/core/lib/Drupal/Component/Plugin/Discovery/DerivativeDiscoveryDecorator.php @@ -3,7 +3,6 @@ namespace Drupal\Component\Plugin\Discovery; use Drupal\Component\Plugin\Definition\DerivablePluginDefinitionInterface; -use Drupal\Component\Plugin\Definition\PluginDefinitionInterface; use Drupal\Component\Plugin\Exception\InvalidDeriverException; /** @@ -56,7 +55,7 @@ // $base_plugin_id. $plugin_definition = $this->decorated->getDefinition($plugin_id, FALSE); - [$base_plugin_id, $derivative_id] = $this->decodePluginId($plugin_id); + list($base_plugin_id, $derivative_id) = $this->decodePluginId($plugin_id); $base_plugin_definition = $this->decorated->getDefinition($base_plugin_id, $exception_on_invalid); if ($base_plugin_definition) { $deriver = $this->getDeriver($base_plugin_id, $base_plugin_definition); @@ -72,7 +71,7 @@ } // It is vital that derivative plugin definitions contain derivative // plugin IDs. Enforce it here, because not all derivers do it. - $this->setPluginIdsOnDefinition($plugin_definition, $base_plugin_id, $plugin_id); + $this->setPluginIdOnDefinition($plugin_definition, $plugin_id, $base_plugin_id); } } @@ -112,7 +111,7 @@ } // It is vital that derivative plugin definitions contain derivative // plugin IDs. Enforce it here, because not all derivers do it. - $this->setPluginIdsOnDefinition($derivative_plugin_definition, $base_plugin_id, $plugin_id); + $this->setPluginIdOnDefinition($derivative_plugin_definition, $plugin_id, $base_plugin_id); $plugin_definitions[$plugin_id] = $derivative_plugin_definition; } } @@ -234,47 +233,37 @@ /** * Merges a base and derivative definition, taking into account empty values. * - * @param mixed[]|\Drupal\Component\Plugin\Definition\PluginDefinitionInterface $base_plugin_definition + * @param array $base_plugin_definition * The base plugin definition. - * @param mixed[]|\Drupal\Component\Plugin\Definition\MergeablePluginDefinitionInterface $derivative_definition + * @param array $derivative_definition * The derivative plugin definition. * - * @return mixed[]|\Drupal\Component\Plugin\Definition\PluginDefinitionInterface + * @return array * The merged definition. */ protected function mergeDerivativeDefinition($base_plugin_definition, $derivative_definition) { - if (is_array($base_plugin_definition) && is_array($derivative_definition)) { - // Use this definition as defaults if a plugin already defined itself as - // this derivative, but filter out empty values first. - $filtered_base = array_filter($base_plugin_definition); - $derivative_definition = $filtered_base + ($derivative_definition ?: []); - // Add back any empty keys that the derivative didn't have. - return $derivative_definition + $base_plugin_definition; - } - elseif ($derivative_definition instanceof MergeablePluginDefinitionInterface && $base_plugin_definition instanceof PluginDefinitionInterface) { - return $derivative_definition->mergeDefaultDefinition($base_plugin_definition); - } - else { - $base_plugin_definition_type = is_object($base_plugin_definition) ? get_class($base_plugin_definition) : gettype($base_plugin_definition); - $derivative_plugin_definition_type = is_object($derivative_definition) ? get_class($derivative_definition) : gettype($derivative_definition); - throw new \InvalidArgumentException(sprintf('Could not merge base plugin definitions of type %s into derivative plugin definition of type %s. Both must be arrays, or the derivative plugin definition must implement %s and the base plugin definition must implement %s.', $base_plugin_definition_type, $derivative_plugin_definition_type, MergeablePluginDefinitionInterface::class, PluginDefinitionInterface::class)); - } + // Use this definition as defaults if a plugin already defined itself as + // this derivative, but filter out empty values first. + $filtered_base = array_filter($base_plugin_definition); + $derivative_definition = $filtered_base + ($derivative_definition ?: []); + // Add back any empty keys that the derivative didn't have. + return $derivative_definition + $base_plugin_definition; } /** * Sets the plugin ID on a plugin definition. * - * @param string[] $plugin_definition + * @param mixed[]|\Drupal\Component\Plugin\Definition\PluginDefinitionInterface $plugin_definition * The plugin definition. - * @param string $base_plugin_id - * The base plugin id. * @param string $plugin_id * The plugin ID to set. + * @param string $base_plugin_id + * The base plugin ID to set. */ - protected function setPluginIdsOnDefinition(array &$plugin_definition, $base_plugin_id, $plugin_id) { + protected function setPluginIdOnDefinition(&$plugin_definition, $plugin_id, $base_plugin_id) { if (is_array($plugin_definition)) { - $plugin_definition['base_id'] = $base_plugin_id; $plugin_definition['id'] = $plugin_id; + $plugin_definition['base_id'] = $base_plugin_id; } } diff -u b/core/modules/migrate/src/Plugin/migrate/id_map/Sql.php b/core/modules/migrate/src/Plugin/migrate/id_map/Sql.php --- b/core/modules/migrate/src/Plugin/migrate/id_map/Sql.php +++ b/core/modules/migrate/src/Plugin/migrate/id_map/Sql.php @@ -981,7 +981,7 @@ $migration_manager = $this->getMigrationPluginManager(); $migrations = $migration_manager->getDefinitions(); foreach ($migrations as $migration_id => $migration) { - if ($base_id === ($migration['base_id'] ?? NULL)) { + if ($base_id === substr($migration_id, 0, strpos($migration_id, $this::DERIVATIVE_SEPARATOR))) { // Get this derived migration's mapping table and add it to the list // of mapping tables to look in for the highest ID. $stub = $migration_manager->createInstance($migration_id); diff -u b/core/tests/Drupal/Tests/Core/Plugin/Discovery/DerivativeDiscoveryDecoratorTest.php b/core/tests/Drupal/Tests/Core/Plugin/Discovery/DerivativeDiscoveryDecoratorTest.php --- b/core/tests/Drupal/Tests/Core/Plugin/Discovery/DerivativeDiscoveryDecoratorTest.php +++ b/core/tests/Drupal/Tests/Core/Plugin/Discovery/DerivativeDiscoveryDecoratorTest.php @@ -212,6 +212,7 @@ $expected = $definitions['non_container_aware_discovery']; $expected['id'] = 'non_container_aware_discovery:test_discovery_1'; + $expected['base_id'] = 'non_container_aware_discovery'; $this->assertArrayEquals($expected, $returned_definitions['non_container_aware_discovery:test_discovery_1']); } @@ -252,6 +253,7 @@ $expected = $base_definition; $expected['id'] = 'non_container_aware_discovery:test_discovery_1'; + $expected['base_id'] = 'non_container_aware_discovery'; $this->assertArrayEquals($expected, $discovery->getDefinition('non_container_aware_discovery:test_discovery_1')); } only in patch2: unchanged: --- a/core/tests/Drupal/KernelTests/Core/Plugin/DerivativeTest.php +++ b/core/tests/Drupal/KernelTests/Core/Plugin/DerivativeTest.php @@ -19,7 +19,13 @@ class DerivativeTest extends PluginTestBase { */ public function testDerivativeDecorator() { // Ensure that getDefinitions() returns the expected definitions. - $this->assertEqual($this->mockBlockManager->getDefinitions(), $this->mockBlockExpectedDefinitions); + $expected = $this->mockBlockExpectedDefinitions; + $expected['menu:main_menu']['base_id'] = 'menu'; + $expected['menu:navigation']['base_id'] = 'menu'; + $expected['menu:foo']['base_id'] = 'menu'; + $expected['layout']['base_id'] = 'layout'; + $expected['layout:foo']['base_id'] = 'layout'; + $this->assertEquals($this->mockBlockManager->getDefinitions(), $expected); // Ensure that getDefinition() returns the expected definition. foreach ($this->mockBlockExpectedDefinitions as $id => $definition) { only in patch2: unchanged: --- a/core/tests/Drupal/KernelTests/Core/Plugin/InspectionTest.php +++ b/core/tests/Drupal/KernelTests/Core/Plugin/InspectionTest.php @@ -30,6 +30,9 @@ public function testInspection() { foreach (['user_login', 'layout'] as $id) { $plugin = $this->mockBlockManager->createInstance($id); $expected_definition = $this->mockBlockExpectedDefinitions[$id]; + if ($id == 'layout') { + $expected_definition['base_id'] = 'layout'; + } $this->assertIdentical($plugin->getPluginId(), $id); $this->assertIdentical($this->castSafeStrings($this->mockBlockManager->getDefinition($id)), $expected_definition); $this->assertIdentical($this->castSafeStrings($plugin->getPluginDefinition()), $expected_definition);