Problem/Motivation
The goal of #2844302: Move Field Layout data model and API directly into \Drupal\Core\Entity\EntityDisplayBase is to move the functionality of Field Layout directly into the EntityDisplay system and Field UI.
In order to accomplish that move, several changes must be made to existing core code, this is one of them.
DefaultSingleLazyPluginCollection is used to maintain a single plugin instance and its configuration.
The benefit is that callers don't know that it's different from DefaultLazyPluginCollection, which contains multiple plugins.
Plugin collections can be iterated over.
Consider the following code:
$collection = new DefaultSingleLazyPluginCollection($manager, 'apple', $apple_configuration);
foreach ($collection as $id => $instance) {
var_dump($id);
}
$collection->addInstanceId('banana', $banana_configuration);
foreach ($collection as $id => $instance) {
var_dump($id);
}
Expected:
apple
banana
Actual:
apple
apple
banana
Even though it is intended to only represent a single plugin, iterating over the collection will return any instance ID it ever contained.
Proposed resolution
Reset the list of instance IDs when a new one is added.
Remaining tasks
N/A
User interface changes
N/A
API changes
N/A
Data model changes
N/A
Comments
Comment #2
tim.plunkettComment #3
dawehnerIt is always nice to not bypass APIs in constructors. The only tricky bit is that this might cause BC problems. Imagine the following: A subclass having a constructor with one additional dependency. This dependency is used in the addInstanceId method. Now this new call leads to a call to NULL
Nice and good to understand test coverage.
Comment #5
tim.plunkettIn general, I agree. But I think this is a special case and it is okay. Nothing overrides this method in any contrib or custom module I've seen.
Fixing plugins that already merge their defaults correctly, but just not in the correct place.
Comment #6
tim.plunkettComment #8
tim.plunkettConflicted with #2830581: Fix ContentModeration workflow type to calculate correct dependencies and #2844594: Default workflow states and transitions
Comment #10
tim.plunkettPHP 5 is the worst. That's not a problem in 7!
https://3v4l.org/hUrTd
Interdiff against #2, just doing the bare minimum now.
Comment #11
jibranNew test made the review easier. Is it worth it to add test only patch?
Comment #12
tim.plunkettReuploading last patch and a fail version.
But that's not a new test, it was in the original patch.
Comment #14
alexpottWhat impacts will this have on contrib?
Comment #15
alexpottComment #16
tim.plunkettTL;DR, none.
Most plugins, search plugins included, blindly assume that $this->configuration/$this->getConfiguration() always contain a value.
For the change above, two things are now different:
1) Before, if you called $search_plugin->setConfiguration() and did not include a value for each key, you would start triggering "undefined index" errors. Now you will not.
2) Now there is no way to purposefully cause undefined index errors. Which I don't consider a loss of functionality. If you don't like the default values, add
'the_key_you_do_not_want' => NULLto the array before you pass to setConfiguration().Comment #17
alexpottDiscussed about the implications for contrib with @tim.plunkett in iRC. I think we need a change record to inform contrib about the need to make changes like:
If we get this early into 8.4.x then contrib has plenty of time to apply and these changes will work for 8.3.x we should be all good. According to @tim.plunkett if they don;t make the changes then the worst that will occur is some PHP notices but the site should not be broken.
Comment #18
tim.plunkettThis is actually the preferred way to do it, I opted to keep Action working with the += approach instead of switching to NestedArray to stay within scope.
Wrote https://www.drupal.org/node/2852190
Comment #19
dawehnerI'm wondering whether we should have a protected function called setConfigurationNested and allow contrib modules to use it in their setConfiguration implementation. This would then allow all contrib modules to have the new method already and then we could maybe switch over at some point.
Comment #20
tim.plunkettWe don't have a trait yet (tried to add one but failed, see #8 above), and no generic "ConfigurablePluginBase" or anything...
Also we need them to call it from their __construct too.
Comment #21
jibran#17 is answered in #18 so back to RTBC
Comment #22
alexpottCan we get a followup to investigate adding a trait for
\Drupal\Component\Plugin\ConfigurablePluginInterfaceand for all core base plugin classes to use it where possible. The differences betweenConfigurableSearchPluginBaseand others confuse me and probably others.Once the followup exists this looks ready to commit to 8.4.x.
Comment #23
alexpottCreated #2852463: Create a trait and base class to implement \Drupal\Component\Plugin\ConfigurableInterface
Comment #24
alexpottCommitted 037932d and pushed to 8.4.x. Thanks!
Comment #26
tim.plunkettslashsrm points out what seems like a gross oversight: by doing this, a plugin collection full of configurable plugins is no longer lazy.
DefaultSingleLazyPluginCollection::setConfiguration() instantiates the plugin.
I'm not honestly sure how important this is, since usually the single plugin collection isn't instantiated unless the plugin will be too. It really only exists to mimic DefaultLazyPluginCollection, so that code like ConfigEntityBase can have one way to handle plugins...
Comment #28
bojanz commentedThe fact that DefaultLazyPluginCollection is no longer lazy broke Commerce hard.
Caught and fixed (need to start testing against future branches), but it feels like the core BC process was unusually lax here.
Comment #29
amateescu commentedThis broke Entityqueue as well, it needed the same fix as Commerce: #2903149: Fatal error when updating to Drupal 8.4