Problem/Motivation

DefaultSingleLazyPluginCollection should not be able to call createInstance() with a NULL instance ID.

Proposed resolution

Check before instantiating.

Remaining tasks

review/commit

User interface changes

no

API changes

no

Data model changes

no

CommentFileSizeAuthor
#58 2853234-58.patch5.71 KBandypost
#58 interdiff.txt1014 bytesandypost
#56 2853234-56.patch5.7 KBandypost
#56 interdiff.txt3.81 KBandypost
#55 interdiff_52-55.txt3.31 KBsahil.goyal
#55 2853234-55.patch8.94 KBsahil.goyal
#53 2853234-53.patch6.42 KBRishabh Vishwakarma
#52 2853234-52.patch5.68 KBRishabh Vishwakarma
#50 interdiff_42_50.txt3.78 KBRishabh Vishwakarma
#50 2853234-50.patch5.68 KBRishabh Vishwakarma
#42 2853234-42.patch5.72 KBandypost
#42 interdiff.txt4.25 KBandypost
#41 2853234-41.patch5.22 KBsmustgrave
#41 interdiff-38-41.txt856 bytessmustgrave
#38 2853234-38.patch5.24 KBsmustgrave
#34 2853234-34.patch17.78 KBsmustgrave
#34 interdiff-31-34.txt15.17 KBsmustgrave
#31 2853234-31.patch5.63 KBsmustgrave
#31 interdiff-28-31.txt3.38 KBsmustgrave
#28 2853234-28.patch5.53 KBsmustgrave
#28 interdiff-20-28.txt824 bytessmustgrave
#27 2853234-27.patch5.75 KBsmustgrave
#27 interdiff-20-27.txt824 bytessmustgrave
#20 2853234-plugin-20-interdiff.txt1.87 KBtim.plunkett
#20 2853234-plugin-20.patch5.33 KBtim.plunkett
#18 2853234-plugin-18-interdiff.txt1.87 KBtim.plunkett
#18 2853234-plugin-18.patch5.28 KBtim.plunkett
#16 2853234-plugin-16-interdiff.txt1002 bytestim.plunkett
#16 2853234-plugin-16.patch3.22 KBtim.plunkett
#7 2853234-plugin-7.patch3.02 KBtim.plunkett
#7 2853234-plugin-7-interdiff.txt4.09 KBtim.plunkett
#2 2853234-plugin-2-PASS.patch2.78 KBtim.plunkett
#2 2853234-plugin-2-FAIL.patch1.34 KBtim.plunkett
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

tim.plunkett created an issue. See original summary.

tim.plunkett’s picture

slashrsm’s picture

Ran into this while working on #2831274: Bring Media entity module to core as Media module (see my comment #305 on that issue for more info).

Patch looks good to me, but would be great if someone that is more familiar with the plugin system would check it too.

The last submitted patch, 2: 2853234-plugin-2-FAIL.patch, failed testing.

dawehner’s picture

Status: Needs review » Reviewed & tested by the community

This makes sense for me.

effulgentsia’s picture

Status: Reviewed & tested by the community » Needs review

In DefaultSingleLazyPluginCollection, the PHPDoc for $instanceId; is @var string, and for the $instance_id parameter in __construct() is @param string $instance_id. So I think if we want to allow for NULL, we should update those docs. Alternatively, maybe we should throw an exception in __construct() and/or addInstanceId() if it's NULL?

tim.plunkett’s picture

Okay, rethinking this in light of:

What we'd want to happen if we were writing this as a new API
What needs to be done to preserve full BC

Once the object is constructed, internal code should be able to rely on $this->instanceId being a string as it is supposed to be.
So I don't think we should add any type checking on the internal property.

Ideally we would trigger an error for anyone passing in NULL, but that's blocked on #2575081: [policy, no patch] Use E_USER_DEPRECATED in Drupal 8 minor releases

I expanded the test coverage, the newly added case would have also failed in 8.2.x and before, and is unrelated to the recent other changes.

joachim’s picture

Looks good to me, except for:

+++ b/core/lib/Drupal/Core/Plugin/DefaultSingleLazyPluginCollection.php
@@ -31,7 +31,7 @@ class DefaultSingleLazyPluginCollection extends LazyPluginCollection {
-  protected $configuration;
+  protected $configuration = [];

This doesn't look like a related change.

tim.plunkett’s picture

+++ b/core/lib/Drupal/Core/Plugin/DefaultSingleLazyPluginCollection.php
@@ -31,7 +31,7 @@ class DefaultSingleLazyPluginCollection extends LazyPluginCollection {
-  protected $configuration;
+  protected $configuration = [];

@@ -52,7 +52,12 @@ class DefaultSingleLazyPluginCollection extends LazyPluginCollection {
-    $this->addInstanceId($instance_id, $configuration);
+
+    // @todo Replace this check with a deprecation error:
+    //   https://www.drupal.org/node/2575081.
+    if ($instance_id !== NULL) {
+      $this->addInstanceId($instance_id, $configuration);
+    }

Before we always instantiated $this->configuration in the constructor via the addInstanceId call.

Now since that won't always be called, we need to ensure it is an array. Also, since it's not documented as array|null, this is correct anyway.

joachim’s picture

Status: Needs review » Reviewed & tested by the community

Thanks for the explanation!

In which case, I'd say this is ready.

alexpott’s picture

Status: Reviewed & tested by the community » Needs work
Issue tags: +Needs change record
+++ b/core/lib/Drupal/Core/Plugin/DefaultSingleLazyPluginCollection.php
@@ -52,7 +52,12 @@ class DefaultSingleLazyPluginCollection extends LazyPluginCollection {
-    $this->addInstanceId($instance_id, $configuration);
+
+    // @todo Replace this check with a deprecation error:
+    //   https://www.drupal.org/node/2575081.
+    if ($instance_id !== NULL) {
+      $this->addInstanceId($instance_id, $configuration);
+    }

I think given that we're planning to put a deprecation notice here we should consider doing that in this issue. Because with this change now addInstance is not called on every instantiation. In core this doesn't cause a problem because we only we really on it to initialise $configuration but the same might not be true in contrib. Without the @trigger_error they might not know that something has changed. Well, even with this is possible but at least we're being helpful.

Also since this is a change in behaviour in a class that is an extension point we should have a CR.

tim.plunkett’s picture

Yeah, #2575081: [policy, no patch] Use E_USER_DEPRECATED in Drupal 8 minor releases wasn't done at the time. We can do this now!
Good catch.

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.

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.

tim.plunkett’s picture

Status: Needs work » Needs review
FileSize
3.22 KB
1002 bytes

Status: Needs review » Needs work

The last submitted patch, 16: 2853234-plugin-16.patch, failed testing. View results

tim.plunkett’s picture

Status: Needs work » Needs review
FileSize
5.28 KB
1.87 KB

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

Drupal 8.7.0-alpha1 will be released the week of March 11, 2019, which means new developments and disruptive changes should now be targeted against the 8.8.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

tim.plunkett’s picture

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.0-alpha1 will be released the week of October 14th, 2019, which means new developments and disruptive changes should now be targeted against the 8.9.x-dev branch. (Any changes to 8.9.x will also be committed to 9.0.x in preparation for Drupal 9’s release, but some changes like significant feature additions will be deferred to 9.1.x.). For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 8.9.x-dev » 9.1.x-dev

Drupal 8.9.0-beta1 was released on March 20, 2020. 8.9.x is the final, long-term support (LTS) minor release of Drupal 8, which means new developments and disruptive changes should now be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 9.1.x-dev » 9.2.x-dev

Drupal 9.1.0-alpha1 will be released the week of October 19, 2020, which means new developments and disruptive changes should now be targeted for the 9.2.x-dev branch. For more information see the Drupal 9 minor version schedule and the Allowed changes during the Drupal 9 release cycle.

Version: 9.2.x-dev » 9.3.x-dev

Drupal 9.2.0-alpha1 will be released the week of May 3, 2021, which means new developments and disruptive changes should now be targeted for the 9.3.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.3.x-dev » 9.4.x-dev

Drupal 9.3.0-rc1 was released on November 26, 2021, which means new developments and disruptive changes should now be targeted for the 9.4.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.4.x-dev » 9.5.x-dev

Drupal 9.4.0-alpha1 was released on May 6, 2022, which means new developments and disruptive changes should now be targeted for the 9.5.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

smustgrave’s picture

FileSize
824 bytes
5.53 KB

Ignored #27

smustgrave’s picture

Also took a shot at the change record. So removing that tag.

longwave’s picture

Status: Needs review » Needs work

Thanks for reviving this one.

+++ b/core/lib/Drupal/Core/Plugin/DefaultSingleLazyPluginCollection.php
@@ -52,7 +52,13 @@ class DefaultSingleLazyPluginCollection extends LazyPluginCollection {
+      @trigger_error(sprintf('Instantiating %s with a NULL instance ID is deprecated in Drupal 10.1.0 and support will be removed before Drupal 11.0.0.', __CLASS__), E_USER_DEPRECATED);

Deprecation messages need to match the standard format: "... is deprecated in drupal:10.1.0 and is removed from drupal:11.1.0. See https://www.drupal.org/node/3302915"

smustgrave’s picture

FileSize
3.38 KB
5.63 KB

Updated based on #30

smustgrave’s picture

Status: Needs work » Needs review
andypost’s picture

Status: Needs review » Needs work
  1. +++ b/core/lib/Drupal/Core/Plugin/DefaultSingleLazyPluginCollection.php
    @@ -52,7 +52,13 @@ class DefaultSingleLazyPluginCollection extends LazyPluginCollection {
    +      @trigger_error(sprintf('Instantiating %s with a NULL instance ID is deprecated in Drupal 10.1.0 and is removed from drupal:11.1.0. See https://www.drupal.org/node/3302915', __CLASS__), E_USER_DEPRECATED);
    

    it should be `drupal:10.1.0` and `drupal:11.0.0`

    wondered why sniffers skipped it

  2. +++ b/core/modules/block/tests/src/Kernel/BlockStorageUnitTest.php
    @@ -2,11 +2,11 @@
    +use Drupal\Component\Plugin\Exception\PluginException;
    ...
    -use Drupal\Component\Plugin\Exception\PluginException;
    

    unrelated change, please remove

smustgrave’s picture

Status: Needs work » Needs review
FileSize
15.17 KB
17.78 KB

Updated based on feedback in #33

longwave’s picture

> wondered why sniffers skipped it

Because of sprintf() call - only exact strings are checked, too many false positives with dynamic strings.

borisson_’s picture

The last change contains a lot of theme related things as well, is that on purpose? Change request looks good.

longwave’s picture

Status: Needs review » Needs work

Yeah the theme related changes look like they come from a Bartik removal patch, out of scope here. NW to undo those.

smustgrave’s picture

Status: Needs work » Needs review
FileSize
5.24 KB

Sorry about that.

andypost’s picture

+++ b/core/lib/Drupal/Core/Plugin/DefaultSingleLazyPluginCollection.php
@@ -52,7 +52,13 @@ class DefaultSingleLazyPluginCollection extends LazyPluginCollection {
+      @trigger_error(sprintf('Instantiating %s with a NULL instance ID is deprecated in drupal:10.1.0 and is removed from drupal:11.0.0. See https://www.drupal.org/node/3302915', __CLASS__), E_USER_DEPRECATED);

please replace "sprintf" to allow sniffers to catch format

joachim’s picture

+++ b/core/lib/Drupal/Core/Plugin/DefaultSingleLazyPluginCollection.php
@@ -52,7 +52,13 @@ class DefaultSingleLazyPluginCollection extends LazyPluginCollection {
+      @trigger_error(sprintf('Instantiating %s with a NULL instance ID is deprecated in drupal:10.1.0 and is removed from drupal:11.0.0. See https://www.drupal.org/node/3302915', __CLASS__), E_USER_DEPRECATED);

Do we need to do a trigger_error() here, or could we throw an exception?

IIRC, at the moment, if $instance_id is NULL it crashes.

So if we throw an exception here, we're changing people's code from one crash to another.

smustgrave’s picture

FileSize
856 bytes
5.22 KB

Updated patch based on #39

andypost’s picture

FileSize
4.25 KB
5.72 KB

++ to #40, changed wording and using exactly a tested class

andypost’s picture

andypost’s picture

IIRC, at the moment, if $instance_id is NULL it crashes.

would be great to get a real example (maybe contrib) to prove it, otherwise follow-up is #2579743: Config entities implementing EntityWithPluginCollectionInterface should ask the plugins to react when their dependencies are removed

joachim’s picture

I don't about contrib, but I saw this in a project last week where a mistake in config caused DefaultSingleLazyPluginCollectionTest to be used with a NULL.

To reproduce in a test, in DefaultSingleLazyPluginCollectionTest::setupPluginCollection(), just add:

    $this->defaultPluginCollection = new DefaultSingleLazyPluginCollection($this->pluginManager, NULL, ['id' => 'apple', 'key' => 'value']);

run the test and it fails with:

Undefined array key ""

/Users/joachim/Sites/drupal-core-composer/repos/drupal/core/tests/Drupal/Tests/Listeners/DeprecationListenerTrait.php:163
/Users/joachim/Sites/drupal-core-composer/repos/drupal/core/tests/Drupal/Tests/Core/Plugin/DefaultSingleLazyPluginCollectionTest.php:28
/Users/joachim/Sites/drupal-core-composer/vendor/phpunit/phpunit/src/Framework/MockObject/Stub/ReturnCallback.php:33
/Users/joachim/Sites/drupal-core-composer/vendor/phpunit/phpunit/src/Framework/MockObject/Matcher.php:153
/Users/joachim/Sites/drupal-core-composer/vendor/phpunit/phpunit/src/Framework/MockObject/InvocationHandler.php:122
/Users/joachim/Sites/drupal-core-composer/repos/drupal/core/lib/Drupal/Core/Plugin/DefaultSingleLazyPluginCollection.php:62
/Users/joachim/Sites/drupal-core-composer/repos/drupal/core/lib/Drupal/Component/Plugin/LazyPluginCollection.php:80
/Users/joachim/Sites/drupal-core-composer/repos/drupal/core/lib/Drupal/Core/Plugin/DefaultSingleLazyPluginCollection.php:83
/Users/joachim/Sites/drupal-core-composer/repos/drupal/core/lib/Drupal/Core/Plugin/DefaultSingleLazyPluginCollection.php:99
/Users/joachim/Sites/drupal-core-composer/repos/drupal/core/lib/Drupal/Core/Plugin/DefaultSingleLazyPluginCollection.php:55
/Users/joachim/Sites/drupal-core-composer/repos/drupal/core/tests/Drupal/Tests/Core/Plugin/DefaultSingleLazyPluginCollectionTest.php:31
/Users/joachim/Sites/drupal-core-composer/repos/drupal/core/tests/Drupal/Tests/Core/Plugin/DefaultSingleLazyPluginCollectionTest.php:41

The line of the test which makes it fail is this in the anonymous class:

    $this->configuration = $configuration + $this->defaultConfiguration();

Version: 9.5.x-dev » 10.1.x-dev

Drupal 9.5.0-beta2 and Drupal 10.0.0-beta2 were released on September 29, 2022, which means new developments and disruptive changes should now be targeted for the 10.1.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

andypost’s picture

Version: 10.1.x-dev » 10.0.x-dev

as bug

smustgrave’s picture

Status: Needs review » Reviewed & tested by the community

Change record is simple and makes sense.

Code has coverage.

Think this is good.

catch’s picture

Status: Reviewed & tested by the community » Needs work
+++ b/core/lib/Drupal/Core/Plugin/DefaultSingleLazyPluginCollection.php
@@ -52,7 +52,13 @@ class DefaultSingleLazyPluginCollection extends LazyPluginCollection {
+
+    if ($instance_id === NULL) {
+      @trigger_error('Instantiating %s with a NULL instance ID is deprecated in drupal:10.1.0 and is removed from drupal:11.0.0. See https://www.drupal.org/node/3302915', E_USER_DEPRECATED);
+    }
+    else {
+      $this->addInstanceId($instance_id, $configuration);
+    }

A bit nitpicky, but it won't be removed in Drupal 11, it's either going to be a type error if we explicitly type hint with string, or it'll throw an exception. Can we maybe say 'and must be a string in Drupal 11' instead?

Rishabh Vishwakarma’s picture

Version: 10.0.x-dev » 10.1.x-dev
Status: Needs work » Needs review
FileSize
5.68 KB
3.78 KB

Changed according to the suggestion given in #49

Rishabh Vishwakarma’s picture

Version: 10.1.x-dev » 10.0.x-dev
Rishabh Vishwakarma’s picture

Fixed PHP CBF errors from the earlier patch.

Rishabh Vishwakarma’s picture

Fixed PHP CBF errors from the earlier patch.

smustgrave’s picture

Status: Needs review » Needs work
sahil.goyal’s picture

Trying to Fix CCF errors.

andypost’s picture

Status: Needs review » Needs work

The last submitted patch, 56: 2853234-56.patch, failed testing. View results

andypost’s picture

Issue summary: View changes
Status: Needs work » Needs review
FileSize
1014 bytes
5.71 KB

Fix remaining message

smustgrave’s picture

Status: Needs review » Reviewed & tested by the community
Issue tags: +Needs Review Queue Initiative

Think I'm able to review this as the patch has gone through several changes since I last worked on it 7 months ago.

Deprecation looks good, with change record
Tests look good and fail as expected without the fix.

Think this is good.

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 58: 2853234-58.patch, failed testing. View results

Wim Leers’s picture