Problem/Motivation

PluginManagerBase:

  public function getInstance(array $options) {
    return $this->mapper->getInstance($options);
  }

Try drush ev '\Drupal::service("plugin.manager.action")->getInstance([])' and you will get

PHP Fatal error: Call to a member function getInstance() on null in /home/chx/www/d8/core/lib/Drupal/Component/Plugin/PluginManagerBase.php on line 97

By no means this is just the action manager. There are only 7 plugin managers overriding this, all the others will get this.

Proposed resolution

As a quick placebo, implement a MapperInterface class which throws an exception and set that as the default mapper in PluginManagerBase. That still leads to a fatal but it's less mysterious and more catchable.

Remaining tasks

User interface changes

API changes

Data model changes

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

chx created an issue. See original summary.

dawehner’s picture

IMHO we could implement a basic implementation which calls out to createInstance() if possible (when the ID is set).

tim.plunkett’s picture

Xano’s picture

IMHO we could implement a basic implementation which calls out to createInstance() if possible (when the ID is set).

This is not doable. We don't know anything about the structure of $options. Writing code that pretends we know this, is just giving a bad example.

This patch implements @chx's original suggestion, and slightly improves the documentation on PluginManagerBase.

tim.plunkett’s picture

Priority: Major » Normal

Sure, I think that's an improvement. But it's not a major bug.

chx’s picture

PluginManagerInterface::class, what about get_called_class() ?

tim.plunkett’s picture

+++ b/core/lib/Drupal/Component/Plugin/PluginManagerBase.php
@@ -94,7 +94,7 @@ public function createInstance($plugin_id, array $configuration = array()) {
+    throw new \Exception(sprintf('This method is not implemented. It must remain on %s for backwards compatibility. See %s.', PluginManagerInterface::class, 'https://www.drupal.org/node/1894130'));

static::class could work, but I assume you meant PluginManagerInterface::class because that's where the docs live?

Wim Leers’s picture

Wim Leers’s picture

Marked #2579235: Resource plugin manager needlessly calls wrong method to instantiate plugins and #2503355: Remove ResourcePluginManager::getInstance() as duplicates of this. Note that we should also remove \Drupal\rest\Plugin\Type\ResourcePluginManager::getInstance() as part of this, i.e. the changes in #2579235: Resource plugin manager needlessly calls wrong method to instantiate plugins should be included here.

Version: 8.0.x-dev » 8.1.x-dev

Drupal 8.0.6 was released on April 6 and is the final bugfix release for the Drupal 8.0.x series. Drupal 8.0.x will not receive any further development aside from security fixes. Drupal 8.1.0-rc1 is now available and sites should prepare to update to 8.1.0.

Bug reports should be targeted against the 8.1.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.2.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Wim Leers’s picture

Still a problem.

Xano’s picture

Version: 8.1.x-dev » 8.2.x-dev
Status: Needs work » Needs review
FileSize
879 bytes
1 KB

PluginManagerInterface::class, what about get_called_class() ?

static::class could work, but I assume you meant PluginManagerInterface::class because that's where the docs live?

I hardcoded the class name exactly for that reason. I have updated the message a little to clear up the confusion.

Marked #2579235: Resource plugin manager needlessly calls wrong method to instantiate plugins and #2503355: Remove ResourcePluginManager::getInstance() as duplicates of this. Note that we should also remove \Drupal\rest\Plugin\Type\ResourcePluginManager::getInstance() as part of this, i.e. the changes in #2579235: Resource plugin manager needlessly calls wrong method to instantiate plugins should be included here.

@Wim Leers: in #2503355-16: Remove ResourcePluginManager::getInstance() you said removing it breaks BC, which I agree with, so I think we should keep it as it is.

twistor’s picture

Should we use BadMethodCallException?

dawehner’s picture

IN my world it seems that getInstance is something which would be deprecated and removed from the generic interface in D9. Conceptually getInstance() requires domain specific knowledge and just, as we see here, be implemented in a generic way. Given that, adding domain specific methods onto plugin managers seems to be the next logical step in a future design.

Xano’s picture

@dawehner: Are you suggesting we do that in follow-up issues?

Version: 8.2.x-dev » 8.3.x-dev

Drupal 8.2.0-beta1 was released on August 3, 2016, which means new developments and disruptive changes should now be targeted against the 8.3.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.3.x-dev » 8.4.x-dev

Drupal 8.3.0-alpha1 will be released the week of January 30, 2017, which means new developments and disruptive changes should now be targeted against the 8.4.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.4.x-dev » 8.5.x-dev

Drupal 8.4.0-alpha1 will be released the week of July 31, 2017, which means new developments and disruptive changes should now be targeted against the 8.5.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.5.x-dev » 8.6.x-dev

Drupal 8.5.0-alpha1 will be released the week of January 17, 2018, which means new developments and disruptive changes should now be targeted against the 8.6.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

andypost’s picture

Issue tags: +@deprecated
borisson_’s picture

I'm not sure if we should add the exception in code like that or we should add a trigger error like we usually do. This is something that's really broken.

dawehner’s picture

+++ b/core/lib/Drupal/Component/Plugin/PluginManagerBase.php
@@ -89,7 +89,7 @@ public function createInstance($plugin_id, array $configuration = array()) {
   public function getInstance(array $options) {
-    return $this->mapper->getInstance($options);
+    throw new \Exception(sprintf('This method is not implemented. It must remain on %s for backwards compatibility with %s. See %s.', static::class, PluginManagerInterface::class, 'https://www.drupal.org/node/1894130'));
   }
 

Shouldn't we check the mapper first?

Version: 8.6.x-dev » 8.7.x-dev

Drupal 8.6.0-alpha1 will be released the week of July 16, 2018, which means new developments and disruptive changes should now be targeted against the 8.7.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

jhedstrom’s picture

Status: Needs review » Needs work

NW for #21 and #22.

Xano’s picture

Status: Needs work » Needs review
FileSize
923 bytes
994 bytes

I'm not sure if we should add the exception in code like that or we should add a trigger error like we usually do. This is something that's really broken.

Is that different from just allowing the current code to trigger a fatal error? Do we want to allow continued code execution?

This patch implements the feedback from #13 and #22. I also replaced the URL to the other issue with the URL to the change record I just created. I used the term "discouraged" since I don't think we can fully deprecate this (on account of MapperInterface being meh, but not actually deprecated), but perhaps we can improve the wording over time :)

borisson_’s picture

Status: Needs review » Reviewed & tested by the community

That's a reasonable explenation, this is a lot better than the generic error that previously happened.

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 25: drupal_2625554_25.patch, failed testing. View results

Xano’s picture

Status: Needs work » Reviewed & tested by the community

Re-testing since this looks like an infra failure.

alexpott’s picture

Status: Reviewed & tested by the community » Needs work
Issue tags: +Needs tests

The exception can be tested and then we can be sure the the helpful information of which class is pointed out. Also linking to an issue in the exception message feels odd. Is there not something better we can say / link to?

Xano’s picture

Status: Needs work » Needs review
Issue tags: -Needs tests
FileSize
3.37 KB
3.54 KB
longwave’s picture

+++ b/core/tests/Drupal/Tests/Component/Plugin/PluginManagerBaseTest.php
@@ -90,4 +93,37 @@ public function testCreateInstanceFallback() {
+      ->wilLReturn($instance);

Shift key error in wilLReturn.

alexpott’s picture

Status: Needs review » Needs work
+++ b/core/tests/Drupal/Tests/Component/Plugin/PluginManagerBaseTest.php
@@ -90,4 +93,37 @@ public function testCreateInstanceFallback() {
+   * @expectedException \BadMethodCallException

We don't use this annotation any more.

googletorp’s picture

Fixed issues raised from #31 and #32

Status: Needs review » Needs work

The last submitted patch, 33: 2625554-33.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

googletorp’s picture

Add missing PhpunitCompatibilityTrait from 33.

Status: Needs review » Needs work

The last submitted patch, 35: 2625554-35.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

googletorp’s picture

Status: Needs work » Needs review
FileSize
3.95 KB

Finally dawned on me, that test errors are due to issue with the way I created the patch, where the new file with StubPluginManagerBaseWithMapper was missing in the diff, should hopefully work now.

borisson_’s picture

Status: Needs review » Reviewed & tested by the community

All issues that were raised are fixed now, to RTBC this goes.

alexpott’s picture

Status: Reviewed & tested by the community » Needs work
  1. +++ b/core/lib/Drupal/Component/Plugin/PluginManagerBase.php
    @@ -104,6 +104,9 @@ protected function handlePluginNotFound($plugin_id, array $configuration) {
    +      throw new \BadMethodCallException(sprintf('%s does not implement this method, unless %s::$mapper is set.', static::class, static::class));
    

    Hmmm re-reading this exception message gives me pause. The method is definitely implemented. I think better language would be does not support this method

  2. +++ b/core/tests/Drupal/Tests/Component/Plugin/PluginManagerBaseTest.php
    @@ -11,6 +15,8 @@
    +  use PhpunitCompatibilityTrait;
    

    Let's not use this trait in component code. Every where in component tests we do an if. This introduces a dependency on Drupal's test code that we don't want.

longwave’s picture

borisson_’s picture

Status: Needs review » Reviewed & tested by the community

The remarks in #39 were fixed.

googletorp’s picture

+1 Would have done this myself, just not had the time for it. This should be RTBC.

alexpott’s picture

Status: Reviewed & tested by the community » Fixed

Committed and pushed 56554f5da5 to 8.7.x and e863ce259a to 8.6.x. Thanks!

Backported to 8.6.x since, whilst this does throw a new exception, it is only in the case that would have errored already and the new error is more helpful.

diff --git a/core/tests/Drupal/Tests/Component/Plugin/PluginManagerBaseTest.php b/core/tests/Drupal/Tests/Component/Plugin/PluginManagerBaseTest.php
index 3bf99abb5b..2bad780dbc 100644
--- a/core/tests/Drupal/Tests/Component/Plugin/PluginManagerBaseTest.php
+++ b/core/tests/Drupal/Tests/Component/Plugin/PluginManagerBaseTest.php
@@ -4,7 +4,6 @@
 
 use Drupal\Component\Plugin\Exception\PluginNotFoundException;
 use Drupal\Component\Plugin\Mapper\MapperInterface;
-use Drupal\Component\Plugin\PluginInspectionInterface;
 use Drupal\Component\Plugin\PluginManagerBase;
 use PHPUnit\Framework\TestCase;
 

Fixed unused use on commit.

  • alexpott committed 56554f5 on 8.7.x
    Issue #2625554 by Xano, googletorp, longwave, borisson_, dawehner, tim....

  • alexpott committed e863ce2 on 8.6.x
    Issue #2625554 by Xano, googletorp, longwave, borisson_, dawehner, tim....

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.

quietone’s picture

publish change record