Skip to content
Snippets Groups Projects
Commit 2fd6026a authored by Alex Bronstein's avatar Alex Bronstein
Browse files

Issue #2821191 by tim.plunkett, tstoeckler, jibran: Allow object-based plugin...

Issue #2821191 by tim.plunkett, tstoeckler, jibran: Allow object-based plugin definitions to be processed in PluginDependencyTrait
parent f2f688b8
No related branches found
No related tags found
No related merge requests found
<?php
namespace Drupal\Component\Plugin\Definition;
/**
* Provides an interface for a plugin definition that has dependencies.
*/
interface DependentPluginDefinitionInterface {
/**
* Gets the config dependencies of this plugin definition.
*
* @return array
* An array of config dependencies.
*
* @see \Drupal\Core\Plugin\PluginDependencyTrait::calculatePluginDependencies()
*/
public function getConfigDependencies();
/**
* Sets the config dependencies of this plugin definition.
*
* @param array $config_dependencies
* An array of config dependencies.
*
* @return $this
*/
public function setConfigDependencies(array $config_dependencies);
}
<?php
namespace Drupal\Component\Plugin\Definition;
/**
* Provides a trait for a plugin definition that has dependencies.
*/
trait DependentPluginDefinitionTrait {
/**
* The dependencies of this plugin definition.
*
* @var array
*
* @see \Drupal\Core\Config\Entity\ConfigDependencyManager
*/
protected $config_dependencies = [];
/**
* {@inheritdoc}
*/
public function getConfigDependencies() {
return $this->config_dependencies;
}
/**
* {@inheritdoc}
*/
public function setConfigDependencies(array $config_dependencies) {
$this->config_dependencies = $config_dependencies;
return $this;
}
}
......@@ -2,6 +2,8 @@
namespace Drupal\Core\Layout;
use Drupal\Component\Plugin\Definition\DependentPluginDefinitionInterface;
use Drupal\Component\Plugin\Definition\DependentPluginDefinitionTrait;
use Drupal\Component\Plugin\Definition\PluginDefinitionInterface;
use Drupal\Component\Plugin\Definition\PluginDefinition;
......@@ -13,7 +15,9 @@
* experimental modules and development releases of contributed modules.
* See https://www.drupal.org/core/experimental for more information.
*/
class LayoutDefinition extends PluginDefinition implements PluginDefinitionInterface, DerivablePluginDefinitionInterface {
class LayoutDefinition extends PluginDefinition implements PluginDefinitionInterface, DerivablePluginDefinitionInterface, DependentPluginDefinitionInterface {
use DependentPluginDefinitionTrait;
/**
* The name of the deriver of this layout definition, if any.
......@@ -22,15 +26,6 @@ class LayoutDefinition extends PluginDefinition implements PluginDefinitionInter
*/
protected $deriver;
/**
* The dependencies of this layout definition.
*
* @todo Make protected after https://www.drupal.org/node/2821191.
*
* @var array
*/
public $config_dependencies;
/**
* The human-readable name.
*
......@@ -452,31 +447,6 @@ public function setDefaultRegion($default_region) {
return $this;
}
/**
* Gets the config dependencies of this layout definition.
*
* @return array
* An array of config dependencies.
*
* @see \Drupal\Core\Plugin\PluginDependencyTrait::calculatePluginDependencies()
*/
public function getConfigDependencies() {
return $this->config_dependencies;
}
/**
* Sets the config dependencies of this layout definition.
*
* @param array $config_dependencies
* An array of config dependencies.
*
* @return $this
*/
public function setConfigDependencies(array $config_dependencies) {
$this->config_dependencies = $config_dependencies;
return $this;
}
/**
* {@inheritdoc}
*/
......
......@@ -2,6 +2,8 @@
namespace Drupal\Core\Plugin;
use Drupal\Component\Plugin\Definition\DependentPluginDefinitionInterface;
use Drupal\Component\Plugin\Definition\PluginDefinitionInterface;
use Drupal\Component\Plugin\DependentPluginInterface;
use Drupal\Component\Plugin\PluginInspectionInterface;
use Drupal\Core\Entity\DependencyTrait;
......@@ -26,11 +28,21 @@ trait PluginDependencyTrait {
*/
protected function calculatePluginDependencies(PluginInspectionInterface $instance) {
$definition = $instance->getPluginDefinition();
$this->addDependency('module', $definition['provider']);
// Plugins can declare additional dependencies in their definition.
if (isset($definition['config_dependencies'])) {
$this->addDependencies($definition['config_dependencies']);
if ($definition instanceof PluginDefinitionInterface) {
$this->addDependency('module', $definition->getProvider());
if ($definition instanceof DependentPluginDefinitionInterface && $config_dependencies = $definition->getConfigDependencies()) {
$this->addDependencies($config_dependencies);
}
}
elseif (is_array($definition)) {
$this->addDependency('module', $definition['provider']);
// Plugins can declare additional dependencies in their definition.
if (isset($definition['config_dependencies'])) {
$this->addDependencies($definition['config_dependencies']);
}
}
// If a plugin is dependent, calculate its dependencies.
if ($instance instanceof DependentPluginInterface && $plugin_dependencies = $instance->calculateDependencies()) {
$this->addDependencies($plugin_dependencies);
......
......@@ -136,28 +136,17 @@ public function ensureLayout($default_layout_id = 'layout_onecol') {
/**
* Overrides \Drupal\Core\Entity\EntityDisplayBase::calculateDependencies().
*
* @see \Drupal\Core\Plugin\PluginDependencyTrait::calculatePluginDependencies()
*
* @todo Remove once https://www.drupal.org/node/2821191 is resolved.
* Ensure the plugin dependencies are included. Once layouts are no longer
* stored as third party settings, this will be handled by the code in
* \Drupal\Core\Config\Entity\ConfigEntityBase::calculateDependencies() that
* handles \Drupal\Core\Entity\EntityWithPluginCollectionInterface.
*/
public function calculateDependencies() {
parent::calculateDependencies();
// This can be called during uninstallation, so check for a valid ID first.
if ($this->getLayoutId()) {
/** @var \Drupal\Core\Layout\LayoutInterface $layout */
$layout = $this->getLayout();
$definition = $layout->getPluginDefinition();
if (!in_array($definition->getProvider(), ['core', 'component'])) {
$this->addDependency('module', $definition->getProvider());
}
if ($config_dependencies = $definition->getConfigDependencies()) {
$this->addDependencies($config_dependencies);
}
if ($layout_dependencies = $layout->calculateDependencies()) {
$this->addDependencies($layout_dependencies);
}
$this->calculatePluginDependencies($this->getLayout());
}
}
......
<?php
namespace Drupal\Tests\Core\Plugin;
use Drupal\Component\Plugin\Definition\DependentPluginDefinitionInterface;
use Drupal\Component\Plugin\Definition\PluginDefinitionInterface;
use Drupal\Component\Plugin\DependentPluginInterface;
use Drupal\Component\Plugin\PluginInspectionInterface;
use Drupal\Core\Plugin\PluginDependencyTrait;
use Drupal\Tests\UnitTestCase;
use Prophecy\Prophecy\ProphecyInterface;
/**
* @coversDefaultClass \Drupal\Core\Plugin\PluginDependencyTrait
* @group Plugin
*/
class PluginDependencyTraitTest extends UnitTestCase {
/**
* @covers ::calculatePluginDependencies
*
* @dataProvider providerTestCalculatePluginDependencies
*
* @param \Prophecy\Prophecy\ProphecyInterface $plugin
* A prophecy of a plugin instance.
* @param mixed $definition
* A plugin definition.
* @param array $expected
* The expected dependencies.
*/
public function testCalculatePluginDependencies(ProphecyInterface $plugin, $definition, array $expected) {
$test_class = new TestPluginDependency();
$plugin->getPluginDefinition()->willReturn($definition);
$test_class->calculatePluginDependencies($plugin->reveal());
$this->assertEquals($expected, $test_class->getDependencies());
}
/**
* Provides test data for ::testCalculatePluginDependencies().
*/
public function providerTestCalculatePluginDependencies() {
$data = [];
$plugin = $this->prophesize(PluginInspectionInterface::class);
$dependent_plugin = $this->prophesize(PluginInspectionInterface::class)->willImplement(DependentPluginInterface::class);
$dependent_plugin->calculateDependencies()->willReturn([
'module' => ['test_module2'],
]);
$data['dependent_plugin'] = [
$dependent_plugin,
['provider' => 'test_module1'],
[
'module' => [
'test_module1',
'test_module2',
],
],
];
$data['array_with_config_dependencies'] = [
$plugin,
[
'provider' => 'test_module1',
'config_dependencies' => [
'module' => ['test_module2'],
],
],
[
'module' => [
'test_module1',
'test_module2',
],
],
];
$definition = $this->prophesize(PluginDefinitionInterface::class);
$definition->getProvider()->willReturn('test_module1');
$data['object_definition'] = [
$plugin,
$definition->reveal(),
[
'module' => [
'test_module1',
],
],
];
$dependent_definition = $this->prophesize(PluginDefinitionInterface::class)->willImplement(DependentPluginDefinitionInterface::class);
$dependent_definition->getProvider()->willReturn('test_module1');
$dependent_definition->getConfigDependencies()->willReturn(['module' => ['test_module2']]);
$data['dependent_object_definition'] = [
$plugin,
$dependent_definition->reveal(),
[
'module' => [
'test_module1',
'test_module2',
],
],
];
return $data;
}
}
class TestPluginDependency {
use PluginDependencyTrait {
calculatePluginDependencies as public;
}
/**
* @return array[]
*/
public function getDependencies() {
return $this->dependencies;
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment