diff --git a/core/lib/Drupal/Component/Annotation/Plugin.php b/core/lib/Drupal/Component/Annotation/Plugin.php index 790440d112..159f48519f 100644 --- a/core/lib/Drupal/Component/Annotation/Plugin.php +++ b/core/lib/Drupal/Component/Annotation/Plugin.php @@ -33,6 +33,10 @@ class Plugin implements AnnotationInterface { * classed annotations that were used. */ public function __construct($values) { + if (empty($values['id'])) { + throw new \InvalidArgumentException(sprintf('Plugin definition %s does not contain a plugin ID.', get_class())); + } + $reflection = new \ReflectionClass($this); // Only keep actual default values by ignoring NULL values. $defaults = array_filter($reflection->getDefaultProperties(), function ($value) { diff --git a/core/tests/Drupal/Tests/Component/Annotation/PluginTest.php b/core/tests/Drupal/Tests/Component/Annotation/PluginTest.php index d942764005..20d9acbf06 100644 --- a/core/tests/Drupal/Tests/Component/Annotation/PluginTest.php +++ b/core/tests/Drupal/Tests/Component/Annotation/PluginTest.php @@ -11,6 +11,35 @@ */ class PluginTest extends TestCase { + /** + * @covers ::__construct + */ + public function testConstructWithoutIdShouldError() { + if (method_exists($this, 'expectException')) { + $this->expectException(\InvalidArgumentException::class); + } + else { + $this->setExpectedException(\InvalidArgumentException::class); + } + + new Plugin([]); + } + + /** + * @covers ::__construct + * @covers ::parse + * @covers ::get + */ + public function testGetMinimal() { + // Without default properties, we get an almost empty plugin definition. + $plugin = new Plugin([ + 'id' => 'foo', + ]); + $this->assertEquals([ + 'id' => 'foo', + ], $plugin->get()); + } + /** * @covers ::__construct * @covers ::parse @@ -20,15 +49,18 @@ public function testGet() { // Assert all values are accepted through constructor and default value is // used for non existent but defined property. $plugin = new PluginStub([ + 'id' => 'foo', 'foo' => 'bar', 'biz' => [ 'baz' => 'boom', ], 'nestedAnnotation' => new Plugin([ + 'id' => 'bar', 'foo' => 'bar', ]), ]); $this->assertEquals([ + 'id' => 'foo', // This property wasn't in our definition but is defined as a property on // our plugin class. 'defaultProperty' => 'testvalue', @@ -37,20 +69,20 @@ public function testGet() { 'baz' => 'boom', ], 'nestedAnnotation' => [ + 'id' => 'bar', 'foo' => 'bar', ], ], $plugin->get()); - - // Without default properties, we get a completely empty plugin definition. - $plugin = new Plugin([]); - $this->assertEquals([], $plugin->get()); } /** * @covers ::getProvider */ public function testGetProvider() { - $plugin = new Plugin(['provider' => 'example']); + $plugin = new Plugin([ + 'id' => 'foo', + 'provider' => 'example', + ]); $this->assertEquals('example', $plugin->getProvider()); } @@ -58,7 +90,9 @@ public function testGetProvider() { * @covers ::setProvider */ public function testSetProvider() { - $plugin = new Plugin([]); + $plugin = new Plugin([ + 'id' => 'foo', + ]); $plugin->setProvider('example'); $this->assertEquals('example', $plugin->getProvider()); } @@ -75,7 +109,10 @@ public function testGetId() { * @covers ::getClass */ public function testGetClass() { - $plugin = new Plugin(['class' => 'example']); + $plugin = new Plugin([ + 'id' => 'foo', + 'class' => 'example', + ]); $this->assertEquals('example', $plugin->getClass()); } @@ -83,7 +120,9 @@ public function testGetClass() { * @covers ::setClass */ public function testSetClass() { - $plugin = new Plugin([]); + $plugin = new Plugin([ + 'id' => 'foo', + ]); $plugin->setClass('example'); $this->assertEquals('example', $plugin->getClass()); }