diff --git a/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php b/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php index 8a88367c0f..cfa12b9bd3 100644 --- a/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php +++ b/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php @@ -521,7 +521,7 @@ public function onDependencyRemoval(array $dependencies) { $plugin_configuration_changed = $this->onPluginDependencyRemoval($collection_group, $instance); } // If there are unresolved deleted dependencies left, allow the - // config entity make a final decision. + // config entity to make a final decision. if ($this->getPluginRemovedDependencies($instance->calculateDependencies(), $dependencies)) { $plugin_configuration_changed = $this->onUnresolvedPluginDependencyRemoval($collection_group, $instance); } diff --git a/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityBaseUnitTest.php b/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityBaseUnitTest.php index ebe7452ddb..6b067b26b2 100644 --- a/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityBaseUnitTest.php +++ b/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityBaseUnitTest.php @@ -8,6 +8,7 @@ namespace Drupal\Tests\Core\Config\Entity; use Drupal\Component\Plugin\PluginBase; +use Drupal\Component\Plugin\PluginInspectionInterface; use Drupal\Component\Plugin\PluginManagerInterface; use Drupal\Core\DependencyInjection\ContainerBuilder; use Drupal\Core\Language\Language; @@ -275,28 +276,51 @@ public function providerCalculateDependenciesWithPluginCollections() { * * @dataProvider providerOnDependencyRemovalWithPluginCollections */ - public function testOnDependencyRemovalWithPluginCollections($dependencies_removed) { + public function testOnDependencyRemovalWithPluginCollections( + array $first_pass_dependencies, + array $second_pass_dependencies, + $plugin_on_dependency_removal, + $entity_on_plugin_dependency_removal, + $entity_on_unresolved_plugin_dependency_removal, + $expectation + ) { // Create an entity with a plugin to test. $instance = $this->getMockBuilder('Drupal\Tests\Core\Plugin\Fixtures\TestConfigurablePlugin') ->setConstructorArgs([[], $this->randomMachineName(), ['provider' => 'foo']]) - ->setMethods(['onDependencyRemoval']) + ->setMethods(['onDependencyRemoval', 'calculateDependencies']) ->getMock(); // A simple onDependencyRemoval which indicates if the plugin was able to // remove dependencies or not. $instance ->expects($this->exactly(1)) ->method('onDependencyRemoval') - ->willReturn($dependencies_removed); - - $this->entity = $this->getMockEntityWithPluginCollection($instance); - - // Ensure the entities onDependencyRemoval method propagates removal of - // dependencies to the plugin. The actual dependencies used here do not - // matter because each plugins dependency management will need to be - // individually tested, this simply ensures that the plugin was given the - // chance to act. - $changed = $this->entity->onDependencyRemoval([]); - $this->assertEquals($dependencies_removed, $changed); + ->willReturn($plugin_on_dependency_removal); + $instance + ->expects($this->at(0)) + ->method('calculateDependencies') + ->willReturn($first_pass_dependencies); + $instance + // @todo: Find out when is called in between (when occurs call #1)? + ->expects($this->at(2)) + ->method('calculateDependencies') + ->willReturn($second_pass_dependencies); + + + $entity = $this->getMockEntityWithPluginCollection($instance); + $entity->expects($this->any()) + ->method('onPluginDependencyRemoval') + ->willReturn($entity_on_plugin_dependency_removal); + $entity->expects($this->any()) + ->method('onUnresolvedPluginDependencyRemoval') + ->willReturn($entity_on_unresolved_plugin_dependency_removal); + + $changed = $entity->onDependencyRemoval([ + 'config' => [ + 'bar' => NULL, + 'baz' => NULL, + ], + ]); + $this->assertEquals($expectation, $changed); } /** @@ -304,10 +328,99 @@ public function testOnDependencyRemovalWithPluginCollections($dependencies_remov */ public function providerOnDependencyRemovalWithPluginCollections() { return [ - 'Plugin removed dependencies' => [ + // The plugin fixes all the dependencies in ::onDependencyRemoval(). + [ + // Plugin ::calculateDependencies() return on 1st pass. + ['config' => ['bar', 'baz']], + // Plugin calculateDependencies() return on 2nd pass. + [], + // Plugin ::onDependencyRemoval() return. + TRUE, + // Entity ::onPluginDependencyRemoval() return. + TRUE, + // Entity ::onUnresolvedPluginDependencyRemoval() return. + NULL, + // Expectation for ConfigEntityInterface::onDependencyRemoval(). TRUE, ], - 'Plugin did not remove dependencies' => [ + // The plugin is not able to fix dependencies in ::onDependencyRemoval() + // and the entity don't act on unresolved dependencies. + [ + // Plugin ::calculateDependencies() return on 1st pass. + ['config' => ['bar', 'baz']], + // Plugin calculateDependencies() return on 2nd pass. + ['config' => ['bar', 'baz']], + // Plugin ::onDependencyRemoval() return. + FALSE, + // Entity ::onPluginDependencyRemoval() return. + TRUE, + // Entity ::onUnresolvedPluginDependencyRemoval() return. + FALSE, + // Expectation for ConfigEntityInterface::onDependencyRemoval(). + FALSE, + ], + // The plugin is not able to fix dependencies in ::onDependencyRemoval() + // but the entity acts on unresolved dependencies. + [ + // Plugin ::calculateDependencies() return on 1st pass. + ['config' => ['bar', 'baz']], + // Plugin calculateDependencies() return on 2nd pass. + ['config' => ['bar', 'baz']], + // Plugin ::onDependencyRemoval() return. + FALSE, + // Entity ::onPluginDependencyRemoval() return. + TRUE, + // Entity ::onUnresolvedPluginDependencyRemoval() return. + TRUE, + // Expectation for ConfigEntityInterface::onDependencyRemoval(). + TRUE, + ], + // The plugin fixes all the dependencies in ::onDependencyRemoval() but + // the entity fail to apply changes in ::onPluginDependencyRemoval(). + [ + // Plugin ::calculateDependencies() return on 1st pass. + ['config' => ['bar', 'baz']], + // Plugin calculateDependencies() return on 2nd pass. + [], + // Plugin ::onDependencyRemoval() return. + TRUE, + // Entity ::onPluginDependencyRemoval() return. + FALSE, + // Entity ::onUnresolvedPluginDependencyRemoval() return. + FALSE, + // Expectation for ConfigEntityInterface::onDependencyRemoval(). + FALSE, + ], + // The plugin fixes only one dependency from two but the entity takes + // action and resolves in ::onUnresolvedPluginDependencyRemoval(). + [ + // Plugin ::calculateDependencies() return on 1st pass. + ['config' => ['bar', 'baz']], + // Plugin calculateDependencies() return on 2nd pass. + ['config' => ['baz']], + // Plugin ::onDependencyRemoval() return. + TRUE, + // Entity ::onPluginDependencyRemoval() return. + TRUE, + // Entity ::onUnresolvedPluginDependencyRemoval() return. + TRUE, + // Expectation for ConfigEntityInterface::onDependencyRemoval(). + TRUE, + ], + // The plugin fixes only one dependency from two and the entity is not + // able to resolve the other in ::onUnresolvedPluginDependencyRemoval(). + [ + // Plugin ::calculateDependencies() return on 1st pass. + ['config' => ['bar', 'baz']], + // Plugin calculateDependencies() return on 2nd pass. + ['config' => ['baz']], + // Plugin ::onDependencyRemoval() return. + TRUE, + // Entity ::onPluginDependencyRemoval() return. + TRUE, + // Entity ::onUnresolvedPluginDependencyRemoval() return. + FALSE, + // Expectation for ConfigEntityInterface::onDependencyRemoval(). FALSE, ], ]; @@ -326,7 +439,7 @@ protected function getMockEntityWithPluginCollection(PluginBase $plugin) { $values = array(); $entity = $this->getMockBuilder('\Drupal\Tests\Core\Config\Entity\Fixtures\ConfigEntityBaseWithPluginCollections') ->setConstructorArgs(array($values, $this->entityTypeId)) - ->setMethods(array('getPluginCollections')) + ->setMethods(array('getPluginCollections', 'onPluginDependencyRemoval', 'onUnresolvedPluginDependencyRemoval')) ->getMock(); // Create a plugin collection to contain the instance. @@ -685,4 +798,18 @@ public function getPluginCollections() { return ['the_plugin_collection_config' => $this->pluginCollection]; } + /** + * {@inheritdoc} + */ + public function onPluginDependencyRemoval($collection_group, PluginInspectionInterface $plugin) { + return FALSE; + } + + /** + * {@inheritdoc} + */ + public function onUnresolvedPluginDependencyRemoval($collection_group, PluginInspectionInterface $plugin) { + return FALSE; + } + } diff --git a/core/tests/Drupal/Tests/Core/Config/Entity/Fixtures/ConfigEntityBaseWithPluginCollections.php b/core/tests/Drupal/Tests/Core/Config/Entity/Fixtures/ConfigEntityBaseWithPluginCollections.php index 6dc9d9817e..3da68e467b 100644 --- a/core/tests/Drupal/Tests/Core/Config/Entity/Fixtures/ConfigEntityBaseWithPluginCollections.php +++ b/core/tests/Drupal/Tests/Core/Config/Entity/Fixtures/ConfigEntityBaseWithPluginCollections.php @@ -3,7 +3,7 @@ namespace Drupal\Tests\Core\Config\Entity\Fixtures; use Drupal\Core\Config\Entity\ConfigEntityBase; -use Drupal\Core\Entity\EntityWithPluginCollectionInterface; +use Drupal\Core\Entity\EntityWithDependentPluginCollectionInterface; /** * Enables testing of dependency calculation. @@ -11,5 +11,5 @@ * @see \Drupal\Tests\Core\Config\Entity\ConfigEntityBaseUnitTest::testCalculateDependenciesWithPluginCollections() * @see \Drupal\Core\Config\Entity\ConfigEntityBase::calculateDependencies() */ -abstract class ConfigEntityBaseWithPluginCollections extends ConfigEntityBase implements EntityWithPluginCollectionInterface { +abstract class ConfigEntityBaseWithPluginCollections extends ConfigEntityBase implements EntityWithDependentPluginCollectionInterface { }