diff --git a/core/lib/Drupal/Core/Plugin/DefaultPluginManager.php b/core/lib/Drupal/Core/Plugin/DefaultPluginManager.php index 7a1cdac3b32c919be826f7ae4eaef844bd1ac46e..b7b0557a7dcec5a7adcac1156fad101c1c3ec9cb 100644 --- a/core/lib/Drupal/Core/Plugin/DefaultPluginManager.php +++ b/core/lib/Drupal/Core/Plugin/DefaultPluginManager.php @@ -8,7 +8,7 @@ namespace Drupal\Core\Plugin; use Drupal\Component\Plugin\Discovery\CachedDiscoveryInterface; -use Drupal\Component\Plugin\Discovery\DerivativeDiscoveryDecorator; +use Drupal\Core\Plugin\Discovery\ContainerDerivativeDiscoveryDecorator; use Drupal\Component\Plugin\PluginManagerBase; use Drupal\Component\Plugin\PluginManagerInterface; use Drupal\Component\Utility\NestedArray; @@ -98,7 +98,7 @@ class DefaultPluginManager extends PluginManagerBase implements PluginManagerInt public function __construct($subdir, \Traversable $namespaces, $annotation_namespaces = array(), $plugin_definition_annotation_name = 'Drupal\Component\Annotation\Plugin') { $this->subdir = $subdir; $this->discovery = new AnnotatedClassDiscovery($subdir, $namespaces, $annotation_namespaces, $plugin_definition_annotation_name); - $this->discovery = new DerivativeDiscoveryDecorator($this->discovery); + $this->discovery = new ContainerDerivativeDiscoveryDecorator($this->discovery); $this->factory = new ContainerFactory($this); } diff --git a/core/lib/Drupal/Core/Plugin/Discovery/ContainerDerivativeDiscoveryDecorator.php b/core/lib/Drupal/Core/Plugin/Discovery/ContainerDerivativeDiscoveryDecorator.php new file mode 100644 index 0000000000000000000000000000000000000000..fcae2e3f143892996b71438fb2a5766359abaaea --- /dev/null +++ b/core/lib/Drupal/Core/Plugin/Discovery/ContainerDerivativeDiscoveryDecorator.php @@ -0,0 +1,35 @@ +<?php + +/** + * @file + * Contains \Drupal\Core\Plugin\Discovery\ContainerDerivativeDiscoveryDecorator. + */ + +namespace Drupal\Core\Plugin\Discovery; + +use Drupal\Component\Plugin\Discovery\DerivativeDiscoveryDecorator; + +class ContainerDerivativeDiscoveryDecorator extends DerivativeDiscoveryDecorator { + + /** + * {@inheritdoc} + */ + protected function getDerivativeFetcher($base_plugin_id, array $base_definition) { + if (!isset($this->derivativeFetchers[$base_plugin_id])) { + $this->derivativeFetchers[$base_plugin_id] = FALSE; + if (isset($base_definition['derivative'])) { + $class = $base_definition['derivative']; + // If the derivative class provides a factory method, pass the container + // to it. + if (is_subclass_of($class, 'Drupal\Core\Plugin\Discovery\ContainerDerivativeInterface')) { + $this->derivativeFetchers[$base_plugin_id] = $class::create(\Drupal::getContainer(), $base_plugin_id); + } + else { + $this->derivativeFetchers[$base_plugin_id] = new $class($base_plugin_id); + } + } + } + return $this->derivativeFetchers[$base_plugin_id] ?: NULL; + } + +} diff --git a/core/lib/Drupal/Core/Plugin/Discovery/ContainerDerivativeInterface.php b/core/lib/Drupal/Core/Plugin/Discovery/ContainerDerivativeInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..6ba68a68f0ec147be875e771d72db23f4dd49cf2 --- /dev/null +++ b/core/lib/Drupal/Core/Plugin/Discovery/ContainerDerivativeInterface.php @@ -0,0 +1,30 @@ +<?php + +/** + * @file + * Contains \Drupal\Core\Plugin\Discovery\ContainerDerivativeInterface. + */ + +namespace Drupal\Core\Plugin\Discovery; + +use Symfony\Component\DependencyInjection\ContainerInterface; + +/** + * Derivative fetcher interface to pass the container to static create method. + */ +interface ContainerDerivativeInterface { + + /** + * Creates an instance of the derivative fetcher. + * + * @param \Symfony\Component\DependencyInjection\ContainerInterface $container + * The container to pull out services used in the fetcher. + * @param string $plugin_id + * The base plugin ID for the plugin ID. + * + * @return static + * Returns an instance of this fetcher. + */ + public static function create(ContainerInterface $container, $base_plugin_id); + +} diff --git a/core/modules/views/lib/Drupal/views/Plugin/Derivative/ViewsBlock.php b/core/modules/views/lib/Drupal/views/Plugin/Derivative/ViewsBlock.php index 1d243d57eabbce6d37497a4896b456c4bf08487c..d932e5fb5be948721f0e2b411b14686ca8c01c6f 100644 --- a/core/modules/views/lib/Drupal/views/Plugin/Derivative/ViewsBlock.php +++ b/core/modules/views/lib/Drupal/views/Plugin/Derivative/ViewsBlock.php @@ -7,14 +7,16 @@ namespace Drupal\views\Plugin\Derivative; -use Drupal\Component\Plugin\Derivative\DerivativeInterface; +use Drupal\Core\Entity\EntityStorageControllerInterface; +use Drupal\Core\Plugin\Discovery\ContainerDerivativeInterface; +use Symfony\Component\DependencyInjection\ContainerInterface; /** * Provides block plugin definitions for all Views block displays. * * @see \Drupal\views\Plugin\block\block\ViewsBlock */ -class ViewsBlock implements DerivativeInterface { +class ViewsBlock implements ContainerDerivativeInterface { /** * List of derivative definitions. @@ -23,6 +25,43 @@ class ViewsBlock implements DerivativeInterface { */ protected $derivatives = array(); + /** + * The base plugin ID. + * + * @var string + */ + protected $base_plugin_id; + + /** + * The view storage controller. + * + * @var \Drupal\Core\Entity\EntityStorageControllerInterface + */ + protected $viewStorageController; + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container, $base_plugin_id) { + return new static( + $base_plugin_id, + $container->get('plugin.manager.entity')->getStorageController('view') + ); + } + + /** + * Constructs a ViewsBlock object. + * + * @param string $base_plugin_id + * The base plugin ID. + * @param \Drupal\Core\Entity\EntityStorageControllerInterface $view_storage_controller + * The entity storage controller to load views. + */ + public function __construct($base_plugin_id, EntityStorageControllerInterface $view_storage_controller) { + $this->basePluginId = $base_plugin_id; + $this->viewStorageController = $view_storage_controller; + } + /** * Implements \Drupal\Component\Plugin\Derivative\DerivativeInterface::getDerivativeDefinition(). */ @@ -39,7 +78,7 @@ public function getDerivativeDefinition($derivative_id, array $base_plugin_defin */ public function getDerivativeDefinitions(array $base_plugin_definition) { // Check all Views for block displays. - foreach (views_get_all_views() as $view) { + foreach ($this->viewStorageController->loadMultiple() as $view) { // Do not return results for disabled views. if (!$view->status()) { continue; diff --git a/core/tests/Drupal/Tests/Core/Plugin/Discovery/ContainerDerivativeDiscoveryDecoratorTest.php b/core/tests/Drupal/Tests/Core/Plugin/Discovery/ContainerDerivativeDiscoveryDecoratorTest.php new file mode 100644 index 0000000000000000000000000000000000000000..5a53a694569962585e65256ba707b83f6b80d006 --- /dev/null +++ b/core/tests/Drupal/Tests/Core/Plugin/Discovery/ContainerDerivativeDiscoveryDecoratorTest.php @@ -0,0 +1,68 @@ +<?php + +/** + * @file + * Contains \Drupal\Tests\Core\Plugin\Discovery\ContainerDerivativeDiscoveryDecoratorTest. + */ + +namespace Drupal\Tests\Core\Plugin\Discovery; + +use Drupal\Core\Plugin\Discovery\ContainerDerivativeDiscoveryDecorator; +use Drupal\Tests\UnitTestCase; + +/** + * Tests the container aware derivative discovery decorator. + */ +class ContainerDerivativeDiscoveryDecoratorTest extends UnitTestCase { + + /** + * {@inheritdoc} + */ + public static function getInfo() { + return array( + 'name' => 'Container aware derivative discovery decorator.', + 'description' => 'Tests the container aware derivative discovery decorator.', + 'group' => 'Plugin', + ); + } + + /** + * Tests the getDerivativeFetcher method. + * + * @see \Drupal\Core\Plugin\Discovery\ContainerDerivativeDiscoveryDecorator::getDerivativeFetcher(). + */ + public function testGetDerivativeFetcher() { + $example_service = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); + $example_container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder') + ->setMethods(array('get')) + ->getMock(); + $example_container->expects($this->once()) + ->method('get') + ->with($this->equalTo('example_service')) + ->will($this->returnValue($example_service)); + + \Drupal::setContainer($example_container); + + $definitions = array(); + $definitions['container_aware_discovery'] = array( + 'id' => 'container_aware_discovery', + 'derivative' => '\Drupal\Tests\Core\Plugin\Discovery\TestContainerDerivativeDiscovery', + ); + $definitions['non_container_aware_discovery'] = array( + 'id' => 'non_container_aware_discovery', + 'derivative' => '\Drupal\Tests\Core\Plugin\Discovery\TestDerivativeDiscovery', + ); + + $discovery_main = $this->getMock('Drupal\Component\Plugin\Discovery\DiscoveryInterface'); + $discovery_main->expects($this->any()) + ->method('getDefinitions') + ->will($this->returnValue($definitions)); + + $discovery = new ContainerDerivativeDiscoveryDecorator($discovery_main); + $definitions = $discovery->getDefinitions(); + + // Ensure that both the instances from container and non-container test derivatives got added. + $this->assertEquals(4, count($definitions)); + } + +} diff --git a/core/tests/Drupal/Tests/Core/Plugin/Discovery/TestContainerDerivativeDiscovery.php b/core/tests/Drupal/Tests/Core/Plugin/Discovery/TestContainerDerivativeDiscovery.php new file mode 100644 index 0000000000000000000000000000000000000000..88bebf2142dd6a576c96b1df68c4e344c2548786 --- /dev/null +++ b/core/tests/Drupal/Tests/Core/Plugin/Discovery/TestContainerDerivativeDiscovery.php @@ -0,0 +1,35 @@ +<?php + +/** + * @file + * Contains \Drupal\Tests\Core\Plugin\Discovery\TestContainerDerivativeDiscovery. + */ + +namespace Drupal\Tests\Core\Plugin\Discovery; + +use Drupal\Core\Plugin\Discovery\ContainerDerivativeInterface; +use Symfony\Component\DependencyInjection\ContainerInterface; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; + +/** + * Defines container test derivative discovery. + */ +class TestContainerDerivativeDiscovery extends TestDerivativeDiscovery implements ContainerDerivativeInterface { + + /** + * Constructs a TestContainerDerivativeDiscovery object. + * + * @var \Symfony\Component\EventDispatcher\EventDispatcherInterface $example_service + * Some service. + */ + public function __construct(EventDispatcherInterface $example_service) { + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container, $base_plugin_id) { + return new static($container->get('example_service')); + } + +} diff --git a/core/tests/Drupal/Tests/Core/Plugin/Discovery/TestDerivativeDiscovery.php b/core/tests/Drupal/Tests/Core/Plugin/Discovery/TestDerivativeDiscovery.php new file mode 100644 index 0000000000000000000000000000000000000000..d0b8218f47effe283c9ee222b6a3388aa28602fb --- /dev/null +++ b/core/tests/Drupal/Tests/Core/Plugin/Discovery/TestDerivativeDiscovery.php @@ -0,0 +1,36 @@ +<?php + +/** + * @file + * Contains \Drupal\Tests\Core\Plugin\Discovery\TestDiscovery. + */ + +namespace Drupal\Tests\Core\Plugin\Discovery; + +use Drupal\Component\Plugin\Derivative\DerivativeInterface; + +/** + * Defines test derivative discovery. + */ +class TestDerivativeDiscovery implements DerivativeInterface { + + /** + * {@inheritdoc} + */ + public function getDerivativeDefinition($derivative_id, array $base_plugin_definition) { + $definitions = $this->getDerivativeDefinitions($base_plugin_definition); + return $definitions[$derivative_id]; + } + + /** + * {@inheritdoc} + */ + public function getDerivativeDefinitions(array $base_plugin_definition) { + $plugins = array(); + for ($i = 0; $i < 2; $i++) { + $plugins['test_discovery_' . $i] = $base_plugin_definition; + } + return $plugins; + } + +}