diff --git a/core/lib/Drupal/Component/Plugin/Factory/DefaultFactory.php b/core/lib/Drupal/Component/Plugin/Factory/DefaultFactory.php index ebada0a..cc64d17 100644 --- a/core/lib/Drupal/Component/Plugin/Factory/DefaultFactory.php +++ b/core/lib/Drupal/Component/Plugin/Factory/DefaultFactory.php @@ -47,10 +47,16 @@ public function __construct(DiscoveryInterface $discovery) { /** * Set the interface used for the plugin. * - * @param string + * @param string $interface * The interface the plugin should have. + * + * @throws \Drupal\Component\Plugin\Exception\PluginException + * Thrown when the interface does not exist. */ public function setInterface($interface) { + if (!interface_exists($interface)) { + throw new PluginException('Invalid/non existing interface passed to setInterface'); + } $this->interface = $interface; } @@ -60,17 +66,29 @@ public function setInterface($interface) { public function createInstance($plugin_id, array $configuration) { $plugin_definition = $this->discovery->getDefinition($plugin_id); $plugin_class = static::getPluginClass($plugin_id, $plugin_definition); + $this->validateInterface($plugin_class, $plugin_id); + return new $plugin_class($configuration, $plugin_id, $plugin_definition); + } + + /** + * Validates the plugin class against the set interface. + * + * @param string $plugin_class + * The class of the plugin to validate. + * @param string $plugin_id + * The plugin ID of the plugin to validate. + * + * @throws \Drupal\Component\Plugin\Exception\PluginException + * Thrown when the plugin class does not match with the set interface. + */ + protected function validateInterface($plugin_class, $plugin_id) { // Validate the interface of the class. if (isset($this->interface)) { - $interfaces = class_implements($plugin_class); - if (!isset($interfaces[$this->interface])) { + if (!is_subclass_of($plugin_class, $this->interface)) { throw new PluginException(sprintf('Plugin (%s) instance class "%s" has to implement interface %s', $plugin_id, $plugin_class, $this->interface)); } } - - - return new $plugin_class($configuration, $plugin_id, $plugin_definition); } /** diff --git a/core/lib/Drupal/Component/Plugin/Factory/ReflectionFactory.php b/core/lib/Drupal/Component/Plugin/Factory/ReflectionFactory.php index 01f300e..9196310 100644 --- a/core/lib/Drupal/Component/Plugin/Factory/ReflectionFactory.php +++ b/core/lib/Drupal/Component/Plugin/Factory/ReflectionFactory.php @@ -6,6 +6,7 @@ namespace Drupal\Component\Plugin\Factory; +use Drupal\Component\Plugin\Exception\PluginException; use ReflectionClass; /** @@ -22,6 +23,7 @@ class ReflectionFactory extends DefaultFactory { public function createInstance($plugin_id, array $configuration) { $plugin_definition = $this->discovery->getDefinition($plugin_id); $plugin_class = static::getPluginClass($plugin_id, $plugin_definition); + $this->validateInterface($plugin_class, $plugin_id); // Lets figure out of there's a constructor for this class and pull // arguments from the $options array if so to populate it. diff --git a/core/lib/Drupal/Core/Plugin/Factory/ContainerFactory.php b/core/lib/Drupal/Core/Plugin/Factory/ContainerFactory.php index 0990565..5fcaab0 100644 --- a/core/lib/Drupal/Core/Plugin/Factory/ContainerFactory.php +++ b/core/lib/Drupal/Core/Plugin/Factory/ContainerFactory.php @@ -6,6 +6,7 @@ namespace Drupal\Core\Plugin\Factory; +use Drupal\Component\Plugin\Exception\PluginException; use Drupal\Component\Plugin\Factory\DefaultFactory; /** @@ -19,11 +20,7 @@ class ContainerFactory extends DefaultFactory { public function createInstance($plugin_id, array $configuration) { $plugin_definition = $this->discovery->getDefinition($plugin_id); $plugin_class = static::getPluginClass($plugin_id, $plugin_definition); - - // If the plugin provides a factory method, pass the container to it. - if (is_subclass_of($plugin_class, 'Drupal\Core\Plugin\ContainerFactoryPluginInterface')) { - return $plugin_class::create(\Drupal::getContainer(), $configuration, $plugin_id, $plugin_definition); - } + $this->validateInterface($plugin_class, $plugin_id); // Otherwise, create the plugin directly. return new $plugin_class($configuration, $plugin_id, $plugin_definition); diff --git a/core/modules/field/lib/Drupal/field/Plugin/Type/Widget/WidgetFactory.php b/core/modules/field/lib/Drupal/field/Plugin/Type/Widget/WidgetFactory.php index 4b7cb6b..94d9682 100644 --- a/core/modules/field/lib/Drupal/field/Plugin/Type/Widget/WidgetFactory.php +++ b/core/modules/field/lib/Drupal/field/Plugin/Type/Widget/WidgetFactory.php @@ -7,6 +7,7 @@ namespace Drupal\field\Plugin\Type\Widget; +use Drupal\Component\Plugin\Exception\PluginException; use Drupal\Component\Plugin\Factory\DefaultFactory; /** @@ -20,6 +21,8 @@ class WidgetFactory extends DefaultFactory { public function createInstance($plugin_id, array $configuration) { $plugin_definition = $this->discovery->getDefinition($plugin_id); $plugin_class = static::getPluginClass($plugin_id, $plugin_definition); + $this->validateInterface($plugin_class, $plugin_id); + return new $plugin_class($plugin_id, $plugin_definition, $configuration['field_definition'], $configuration['settings']); } } diff --git a/core/tests/Drupal/Tests/Component/Plugin/Factory/DefaultPluginFactoryTest.php b/core/tests/Drupal/Tests/Component/Plugin/Factory/DefaultPluginFactoryTest.php deleted file mode 100644 index f3096b9..0000000 --- a/core/tests/Drupal/Tests/Component/Plugin/Factory/DefaultPluginFactoryTest.php +++ /dev/null @@ -1,118 +0,0 @@ - 'Default plugin factory', - 'description' => 'Tests the default plugin factory.', - 'group' => 'Plugin', - ); - } - - /** - * {@inheritdoc} - */ - protected function setUp() { - $this->discovery = $this->getMock('Drupal\Component\Plugin\Discovery\DiscoveryInterface'); - $this->defaultFactory = new DefaultFactory($this->discovery); - } - - /** - * Tests the getPluginClass method. - * - * @see \Drupal\Component\Plugin\DefaultFactory::getPluginClass - * @dataProvider providerTestGetPluginClass - */ - public function testGetPluginClass($plugin_id, $plugin_definition) { - $this->discovery->expects($this->once()) - ->method('getDefinition') - ->with($plugin_id) - ->will($this->returnValue($plugin_definition)); - $this->defaultFactory->setInterface('Drupal\plugin_test\Plugin\plugin_test\fruit\FruitInterface'); - $instance = $this->defaultFactory->createInstance($plugin_id, array()); - - $this->assertInstanceOf($plugin_definition['class'], $instance); - $this->assertInstanceOf('Drupal\plugin_test\Plugin\plugin_test\fruit\FruitInterface', $instance); - } - - /** - * Provides plugin_id/plugin_definition which are valid. - * - * @return array - * An array of plugin IDs and plugin definitions. - * - * @see self::testGetPluginClassWithInvalidInput - */ - public function providerTestGetPluginClass() { - return array( - array('apple', array('class' => '\Drupal\plugin_test\Plugin\plugin_test\fruit\Apple')), - array('banana', array('class' => '\Drupal\plugin_test\Plugin\plugin_test\fruit\Banana')), - ); - } - - - /** - * Tests the getPluginClass method with invalid input. - * - * @expectedException \Drupal\Component\Plugin\Exception\PluginException - * @dataProvider providerTestGetPluginClassWithInvalidInput - */ - public function testGetPluginClassWithInvalidInput($plugin_id, $plugin_definition) { - $this->discovery->expects($this->once()) - ->method('getDefinition') - ->with($plugin_id) - ->will($this->returnValue($plugin_definition)); - $this->defaultFactory->setInterface('Drupal\plugin_test\Plugin\plugin_test\fruit\FruitInterface'); - $this->defaultFactory->createInstance($plugin_id, array()); - } - - /** - * Provides plugin_id/plugin_definitions which are invalid. - * - * @return array - * An array of plugin IDs and plugin definitions. - * - * @see self::testGetPluginClassWithInvalidInput - */ - public function providerTestGetPluginClassWithInvalidInput() { - return array( - // Provide no class definition. - array('rasperry', array()), - // Provide a non existing class. - array('rasperry', array('class' => '\Drupal\plugin_test\Plugin\plugin_test\fruit\Rasperry')), - // Provide a plugin without FruitInterface. - array('orange', array('class' => '\Drupal\plugin_test\Plugin\plugin_test\fruit\Orange')), - ); - } - -}