Problem/Motivation

EntityFormDisplay::getPluginCollections() and EntityViewDisplay::getPluginCollections() enable widget/formatter plugin dependencies to be added to the dependency list of the form/view display. This is supposed to prevent a deleted field dependency from breaking the display. The issue is that plugin collection is keyed by the type of the plugin. Here is the code for the view display, the form display code is nearly identical:

        $configurations[$configuration['type']] = $configuration + [
          'field_definition' => $field_definition,
          'view_mode' => $this->originalMode,
        ];

Multiple instances of a widget/formatter plugin will all have the same type, which means that if you have more than one instance on a display then the configuration for later instances will overwrite that of earlier instances. Only the configuration of the last instance will be added to the collections array. Therefore, only the dependencies of the last instance will be registered with the display. If a missing dependency is then deleted, the form/view display page will be broken due to a missing dependency exception.

I believe the comment formatter (CommentDefaultFormatter) is an example in core that could have this issue too, as its calculateDependencies() method will add a dependency on the view mode that the formatter is set to use. So, this would probably replicate the issue:

1. Enable comment module.
2. Add a custom view mode for comment entities.
3. Set up two comment fields on a node type.
4. Configure both fields to display in a view mode of the node type, but set each one to show the Comments in a different view mode: one to use the custom one from step 2, and the other to use the default 'Full comment' view mode.
5. Export configuration, or inspect the node type's view mode, and you should find that it is dependent on only one of the comment view modes, rather than both.

That problem in step 5 there could result in configuration being incorrectly synchronised, because a dependency would be missed.

Entity browsers may be the most common other example, as media formatters depend on them.

Proposed resolution

The patch in #9 keys the plugin collection array by the field name to ensure the key is unique in a display. According to the review in #12, re-keying the array should not have an impact on other code. The calculateDependencies() method that aggregates these dependencies does not use the keys at all.

Remaining tasks

Add update hook and tests.

User interface changes

None.

API changes

None.

Data model changes

None.

CommentFileSizeAuthor
#96 2865710-nr-bot_fi_k4vv7.txt667 bytesneeds-review-queue-bot
#89 2865710-nr-bot_05qji66t.txt91 bytesneeds-review-queue-bot
#87 2865710-nr-bot_gkfu4wo4.txt4.99 KBneeds-review-queue-bot
#65 interdiff-62-65.txt904 byteshctom
#65 2865710-65.patch14.55 KBhctom
#62 interdiff-59-62.txt961 byteshctom
#62 2865710-62.patch13.58 KBhctom
#59 interdiff-55-59.txt660 byteshctom
#59 2865710-59.patch13.56 KBhctom
#55 interdiff-41-55.txt7.22 KBhctom
#55 2865710-55.patch13.51 KBhctom
#54 entity-display-dependencies-2865710-54-without-tests.patch1.56 KBAdev22
#51 entity-display-dependencies-2865710-51-without-tests.patch1.56 KBjames.williams
#41 interdiff-2865710-37-41.txt1.15 KBjames.williams
#41 entity-display-dependencies-2865710-41.patch13.77 KBjames.williams
#4 entity-display-dependencies-2865710-4.patch1.54 KBjames.williams
#5 entity-display-dependencies-d8-2-x-2865710-5.patch1.57 KBjames.williams
#6 entity-display-dependencies-tests-only-2865710-6.patch9.76 KBjames.williams
#6 entity-display-dependencies-2865710-6.patch11.31 KBjames.williams
#9 entity-display-dependencies-tests-only-2865710-9.patch11.6 KBjames.williams
#9 entity-display-dependencies-2865710-9.patch13.14 KBjames.williams
#9 interdiff-2865710-6-9.txt1.84 KBjames.williams
#13 after.png16.4 KBdcam
#25 entity-display-dependencies-2865710-25.patch13.14 KBjames.williams
#25 interdiff-2865710-9-25.txt1.97 KBjames.williams
#28 entity-display-dependencies-2865710-28.patch22.36 KBjames.williams
#28 interdiff-2865710-25-28.txt17.73 KBjames.williams
#31 interdiff-2865710-28-31.txt971 bytesjames.williams
#31 entity-display-dependencies-2865710-31.patch22.31 KBjames.williams
#35 entity-display-dependencies-2865710-35.patch14.01 KBjames.williams
#35 interdiff-2865710-25-35.txt9.07 KBjames.williams
#37 2865710-37.patch14.03 KBjofitz
#37 interdiff-35-37.txt2.1 KBjofitz

Issue fork drupal-2865710

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

james.williams created an issue. See original summary.

hchonov’s picture

The whole method looks messy. Take a look at it :

public function getPluginCollections() {
  $configurations = [];
  foreach ($this->getComponents() as $field_name => $configuration) {
    if (!empty($configuration['type']) && ($field_definition = $this->getFieldDefinition($field_name))) {
      $configurations[$configuration['type']] = $configuration + [
        'field_definition' => $field_definition,
        'view_mode' => $this->originalMode,
      ];
    }
  }

  return [
    'formatters' => new EntityDisplayPluginCollection($this->pluginManager, $configurations)
  ];

What we see is that if two fields use the same plugin the later will be the only one for which configuration of the field definition will be included.

I think here we have to use as key the field name and then at the second level the plugin ID or at first level something like field_name.plugin_id, but this will not be a BC change.

james.williams’s picture

I'm glad someone else agrees :-) I need to read up on the BC policy - it seems odd that an actual bug should be allowed to stay just to preserve its existence for BC.

As for keying the array - does it even need keying by plugin ID at all? Why not just field/component name?

james.williams’s picture

Status: Active » Needs review
StatusFileSize
new1.54 KB

From the '@internal' section of https://www.drupal.org/core/d8-bc-policy :

Plugins
Particular plugin classes should not be considered part of the public API. References to plugin IDs and settings in default configuration can be relied upon however.

So maybe fixing this within the two plugin classes would be allowed without waiting for a patch version?

Anyway, more importantly, we need a patch & tests :-) I've attached a really basic attempt at a patch just to make a start on this, no tests yet.

james.williams’s picture

Status: Needs review » Needs work
StatusFileSize
new1.57 KB

For anyone that needs it (e.g. me!), here's a version that applies to 8.2.x (which was before the great short array syntax change!).

Setting status to needs work, as a test is still needed.

james.williams’s picture

Status: Needs work » Needs review
Issue tags: -Needs tests, -Needs issue summary update
StatusFileSize
new9.76 KB
new11.31 KB

Tests! One is just tests to demonstrate the current issue, one includes the fix from comment 4.

The last submitted patch, 6: entity-display-dependencies-tests-only-2865710-6.patch, failed testing.

Status: Needs review » Needs work

The last submitted patch, 6: entity-display-dependencies-2865710-6.patch, failed testing.

james.williams’s picture

Status: Needs work » Needs review
StatusFileSize
new11.6 KB
new13.14 KB
new1.84 KB

Ah... of course adding the test plugins affects the existing tests too. This version adjusts the tests to account for them.

The last submitted patch, 9: entity-display-dependencies-tests-only-2865710-9.patch, failed testing.

dcam’s picture

I ran into this issue while developing a new module, Entity Reference Facet Link. Basically, the module provides a field formatter that renders ER fields as links to a faceted search page. To do this, the entity display becomes dependent on one or more facet config entities.* If there is more than one field on an entity that uses this formatter plugin, then only the last one has its dependent facet entity added to the list of display dependencies due to this bug.

FYI, I tracked down the issue where EntityViewDisplay::getPluginCollections() was added: #2271419: Allow field types, widgets, formatters to specify config dependencies.

I'll do a review of the patch next.

*I have not committed the calculateDependencies() code yet because until now I wasn't sure if this was a problem with my implementation or a bug in core.

dcam’s picture

Status: Needs review » Reviewed & tested by the community

This all looks good to me. Great job writing these tests, @james.williams!

I don't think there's any issue with changing the array keys for a couple of reasons. First, the parent issue shows that the getPluginCollections() methods were added specifically to allow plugins to declare their dependencies to these entities. So updating them to fix a bug with that functionality shouldn't be an issue. Second, ConfigEntityBase::calculateDependencies() is the method that calls getPluginCollections() to incorporate those plugins' dependencies. It ignores the collection keys entirely.

  1. +++ b/core/modules/field_ui/tests/src/Kernel/EntityDisplayTest.php
    @@ -270,6 +270,67 @@ public function testFieldComponent() {
    +        'dependent_module' => 'aggregrator',
    +      ],
    +    ]);
    +
    +    $dependencies = $display->calculateDependencies()->getDependencies();
    +    $this->assertArraySubset(['action', 'aggregrator'], $dependencies['module']);
    

    Minor nitpicks - "aggregator" is misspelled on lines 326 and 331.

  2. +++ b/core/modules/field_ui/tests/src/Kernel/EntityFormDisplayTest.php
    @@ -116,6 +116,67 @@ public function testFieldComponent() {
    +        'dependent_module' => 'aggregrator',
    +      ],
    +    ]);
    +
    +    $dependencies = $form_display->calculateDependencies()->getDependencies();
    +    $this->assertArraySubset(['action', 'aggregrator'], $dependencies['module']);
    

    It's misspelled twice here too.

I'm not going to hold up the issue by setting it back to NW or by rolling a new patch myself just for that though. This is something that could easily be fixed on commit. The tests only check for those array values to be the same. There's no reason to try and load those dependencies, which means those strings could have any value.

#9 gets an RTBC from me.

dcam’s picture

StatusFileSize
new16.4 KB

Oh. Yeah. For the record I tested to see if this definitely fixes the issue I was having with ERFL. It does. After applying the patch all of the facet dependencies get added.

james.williams’s picture

Thanks dcam! I'm glad someone else out there has delved deep down far enough into the world of plugins, config and dependencies to run into this too :-)

Non, Je Ne Regrette Rien....

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 9: entity-display-dependencies-2865710-9.patch, failed testing. View results

dcam’s picture

Status: Needs work » Reviewed & tested by the community

Unrelated failure.

dcam’s picture

Issue summary: View changes

Applied the issue summary template and rewrote the problem section so that it will be easier to get this some attention.

dcam’s picture

Issue summary: View changes

Formatted the code section correctly. Sorry for the noise.

dcam’s picture

Priority: Normal » Major

This qualifies as a major bug because it can result in a PHP error through the user interface. If a missing dependency is deleted then the form/view display will WSOD. The only workarounds to restore functionality that I know of are to re-add a plugin instance of the dependency with the same machine name or manually edit the configuration.

james.williams’s picture

Issue summary: View changes

Just added entity browsers as an example to the IS. I'm not sure how they're being implemented on core, but if they use dependencies similarly to the contrib implementation, this will become more common very soon.

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.

larowlan’s picture

Status: Reviewed & tested by the community » Needs work

Test fail looks related to me - its to do with field config dependencies being in incorrect order

james.williams’s picture

Status: Needs work » Needs review

The test fail looks like it was just a result of an unrelated issue that was solved in #2894499: Rename 'Editorial workflow' to 'Editorial'. Queued for retesting.

james.williams’s picture

Status: Needs review » Needs work

Oh, sorry, I missed this one https://www.drupal.org/pift-ci-job/750198 . So many other unrelated failures!

james.williams’s picture

Status: Needs work » Needs review
StatusFileSize
new13.14 KB
new1.97 KB

Looks like the test failed because multiple things had the same weight, which came out ordered differently in different environments / versions of PHP. No need for that though, so I've given the test formatter & widget a unique weight so that the ordering can be reliably tested.

I trust this updated patch will resolve that :-)

dcam’s picture

Status: Needs review » Reviewed & tested by the community

Looks like the test failed because multiple things had the same weight, which came out ordered differently in different environments / versions of PHP.

This seems likely. I did some digging and the plugin manager uses uasort() on the weight column. The sort order when two elements have the same value is undefined. Assuming the 8.4.x patch comes back green #25 gets an RTBC from me.

larowlan’s picture

Status: Reviewed & tested by the community » Needs review
  1. +++ b/core/modules/field_ui/tests/src/Kernel/EntityDisplayTest.php
    @@ -270,6 +270,67 @@ public function testFieldComponent() {
    +    $first_field_name = 'test_field';
    +    // Create a field storage and a field.
    +    $first_field_storage = FieldStorageConfig::create([
    +      'field_name' => $first_field_name,
    +      'entity_type' => 'entity_test',
    +      'type' => 'test_field'
    +    ]);
    +    $first_field_storage->save();
    +    $first_field = FieldConfig::create([
    +      'field_storage' => $first_field_storage,
    +      'bundle' => 'entity_test',
    +    ]);
    +    $first_field->save();
    +
    +    $second_field_name = 'test_field_2';
    +    // Create a field storage and a field.
    +    $second_field_storage = FieldStorageConfig::create([
    +      'field_name' => $second_field_name,
    +      'entity_type' => 'entity_test',
    +      'type' => 'test_field'
    +    ]);
    +    $second_field_storage->save();
    +    $second_field = FieldConfig::create([
    +      'field_storage' => $second_field_storage,
    +      'bundle' => 'entity_test',
    +    ]);
    +    $second_field->save();
    
    +++ b/core/modules/field_ui/tests/src/Kernel/EntityFormDisplayTest.php
    @@ -116,6 +116,67 @@ public function testFieldComponent() {
    +    $first_field_name = 'test_field';
    +    // Create a field storage and a field.
    +    $first_field_storage = FieldStorageConfig::create([
    +      'field_name' => $first_field_name,
    +      'entity_type' => 'entity_test',
    +      'type' => 'test_field'
    +    ]);
    +    $first_field_storage->save();
    +    $first_field = FieldConfig::create([
    +      'field_storage' => $first_field_storage,
    +      'bundle' => 'entity_test',
    +    ]);
    +    $first_field->save();
    +
    +    $second_field_name = 'test_field_2';
    +    // Create a field storage and a field.
    +    $second_field_storage = FieldStorageConfig::create([
    +      'field_name' => $second_field_name,
    +      'entity_type' => 'entity_test',
    +      'type' => 'test_field'
    +    ]);
    +    $second_field_storage->save();
    +    $second_field = FieldConfig::create([
    +      'field_storage' => $second_field_storage,
    +      'bundle' => 'entity_test',
    +    ]);
    +    $second_field->save();
    

    Some duplication here that could be in a protected method called from both tests.

  2. +++ b/core/modules/field_ui/tests/src/Kernel/EntityDisplayTest.php
    @@ -270,6 +270,67 @@ public function testFieldComponent() {
    +    // Check that providing no options results in default values being used.
    +    $display->setComponent($first_field_name, [
    +      'type' => 'field_test_dynamic_dependencies',
    +      'weight' => 0,
    +      'settings' => [
    +        // An arbitrary module that should not already be a dependency.
    +        'dependent_module' => 'action',
    +      ],
    +    ]);
    +
    +    $display->setComponent($second_field_name, [
    +      'type' => 'field_test_dynamic_dependencies',
    +      'weight' => 0,
    +      'settings' => [
    +        // Another arbitrary module that should not already be a dependency.
    +        'dependent_module' => 'aggregrator',
    +      ],
    +    ]);
    +
    +    $dependencies = $display->calculateDependencies()->getDependencies();
    +    $this->assertArraySubset(['action', 'aggregrator'], $dependencies['module']);
    
    +++ b/core/modules/field_ui/tests/src/Kernel/EntityFormDisplayTest.php
    @@ -116,6 +116,67 @@ public function testFieldComponent() {
    +    // Check that providing no options results in default values being used.
    +    $form_display->setComponent($first_field_name, [
    +      'type' => 'test_field_widget_dynamic_dependencies',
    +      'weight' => 0,
    +      'settings' => [
    +        // An arbitrary module that should not already be a dependency.
    +        'dependent_module' => 'action',
    +      ],
    +    ]);
    +
    +    $form_display->setComponent($second_field_name, [
    +      'type' => 'test_field_widget_dynamic_dependencies',
    +      'weight' => 0,
    +      'settings' => [
    +        // Another arbitrary module that should not already be a dependency.
    +        'dependent_module' => 'aggregrator',
    +      ],
    +    ]);
    +
    +    $dependencies = $form_display->calculateDependencies()->getDependencies();
    +    $this->assertArraySubset(['action', 'aggregrator'], $dependencies['module']);
    

    same here

james.williams’s picture

StatusFileSize
new22.36 KB
new17.73 KB

I'm not sure if I've gone overboard here.

  • I've created a base class for the two test classes, which now contains a createField() method to cover the first part you identified as duplicated code.
  • I've added the abstract getDefaultTestDisplay() method to the base class, which is one of only two bits that need to be different between the two test classes.
  • I've added a base helper for the refactored testMultipleFieldComponentDependencies() method, called multipleFieldComponentDependenciesHelper(). The formatter/widget ID is the second thing that needs to differ between the two test classes.
  • Then I've also replaced any parts elsewhere within the two classes that could use the two new createField() and getDefaultTestDisplay() base methods, as the classes were littered with code doing those things. If my code containing duplicate code was worth refactoring to use helper methods, I figured that should be cleared up throughout.

Maybe I've gone too far now, I don't know, sorry?!

Status: Needs review » Needs work

The last submitted patch, 28: entity-display-dependencies-2865710-28.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

tacituseu’s picture

PHP Fatal error:  Uncaught Error: Cannot instantiate abstract class Drupal\Tests\field_ui\Kernel\EntityDisplayTestBase in /var/www/html/core/scripts/run-tests.sh:786
Stack trace:
#0 /var/www/html/core/scripts/run-tests.sh(67): simpletest_script_run_one_test('838', 'Drupal\\Tests\\fi...')
#1 {main}
  thrown in /var/www/html/core/scripts/run-tests.sh on line 786
james.williams’s picture

Status: Needs work » Needs review
StatusFileSize
new971 bytes
new22.31 KB

Wow, that was obscure. The @group tag on my abstract class had told the tests script to use it. (Which hadn't been a problem when running just the class(es) locally, because that picked them specifically.) Sorry!

I've fixed the code style warning too whilst at it.

dcam’s picture

I'm not sure if I've gone overboard here.

Personally, I would say "yes." I know you were asked to do this, but in fulfilling the request you ended up touching other code that is unrelated to this issue. That can be kind of bad. Now this patch might cause a dozen others to need to be rerolled. Maybe we don't care and duplicate code elimination is more important. I feel like I can't make that call. It would be nice if @larowlan would review it. I'm going to tag it for subsystem maintainer review and hope that gets it some attention from someone who can make the determination as to whether or not this should go forward.

+++ b/core/modules/field/tests/modules/field_test/src/Plugin/Field/FieldWidget/TestFieldWidgetDynamicDependencies.php
@@ -0,0 +1,81 @@
+ * Plugin implementation of the 'test_field_widget' widget.

Nitpick that may be able to be fixed on commit: the machine name of the plugin wasn't updated here.

Also, "aggregator" was still misspelled in the dependency test helper method, not that it has any effect at all.

james.williams’s picture

Personally, I would say "yes." I know you were asked to do this, but in fulfilling the request you ended up touching other code that is unrelated to this issue. That can be kind of bad. Now this patch might cause a dozen others to need to be rerolled.

Yup, I thought that might be the case :-)

@larowlan (or someone else) : What would be the most appropriate way to avoid this duplicate code? "a protected method called from both tests." could be in a base class (like I'd done, but gone beyond in getting other code to use), a helper class/etc somewhere else

There's so much existing code that could be shared between the Display & Form mode tests, as well as within them. My original approach was to just continue with that, and maybe then a follow-up ticket could be opened to change to a proper base class or other way of clearing up all of that.

larowlan’s picture

a helper trait is probably best if they're different test classes

james.williams’s picture

StatusFileSize
new14.01 KB
new9.07 KB

/me jumps hoop :-)

OK, here we go again then. This scraps what I did for patches 28 & 31, to now use a common trait instead of an abstract base class and to only touch the parts of code touched by the patch in the first place. A follow-up could always be introduced to clear up the other very similar duplicated code between EntityDisplayTest and EntityFormDisplayTest, to use this trait more, and probably to add all sorts of other common things to it.

I've provided the interdiff between this and comment 25, which was the version reviewed when larowlan asked for the duplicate code to be addressed.

There's a still a little duplication between each of the two testMultipleFieldComponentDependencies() methods, but I can't really see a particularly better way around that, because the fields have to be created before the display mode entity is created (the latter of which is the bit that has to be different between the two classes). (The fields are cached in EntityDisplayBase::fieldDefinitions at the point of creating the display, and there's no way to reset that.)

dcam’s picture

Status: Needs review » Reviewed & tested by the community

This seems ok to me. I don't think it's such a big deal to have the little bit of duplicated code in there, since it's mostly setting up the field names. In the future we might need to add another field to one, but not the other for some reason. Maybe. If that ever happened, then it would be a good idea to let the tests define their own field set.

Anyway, I'm more comfortable RTBCing this since it doesn't touch other code like the last patch did. I only have the same minor nitpicks that I've had before, which I hope can be fixed on commit:

  1. +++ b/core/modules/field/tests/modules/field_test/src/Plugin/Field/FieldWidget/TestFieldWidgetDynamicDependencies.php
    @@ -0,0 +1,81 @@
    + * Plugin implementation of the 'test_field_widget' widget.
    

    This machine name wasn't updated.

  2. +++ b/core/modules/field_ui/tests/src/Kernel/EntityDisplayTest.php
    @@ -270,6 +273,27 @@ public function testFieldComponent() {
    +      'test_field_2' => 'aggregrator',
    
    +++ b/core/modules/field_ui/tests/src/Kernel/EntityFormDisplayTest.php
    @@ -116,6 +119,26 @@ public function testFieldComponent() {
    +      'test_field_2' => 'aggregrator',
    

    Misspelling that is totally irrelevant to the functionality of the patch.

jofitz’s picture

Status: Reviewed & tested by the community » Needs review
StatusFileSize
new14.03 KB
new2.1 KB

Fixed the nit-picks in #36.

jofitz’s picture

Status: Needs review » Reviewed & tested by the community

The changes are so minor that we can safely set this back to RTBC.

james.williams’s picture

Thanks dcam for your reviews, and Jo for catching those bits I kept missing! I hope this is now ready to be committed.

larowlan’s picture

Status: Reviewed & tested by the community » Needs review
  1. +++ b/core/modules/field_ui/src/Tests/EntityDisplayTestTrait.php
    @@ -0,0 +1,76 @@
    +  public function addDefaultTestFields($field_names, $type = 'test_field') {
    

    I think this should be protected?

  2. +++ b/core/modules/field_ui/src/Tests/EntityDisplayTestTrait.php
    @@ -0,0 +1,76 @@
    +      $created[$field_name] = [
    +        $field_storage,
    +        $field,
    +      ];
    

    This always feels like a code smell - perhaps this should be two separate methods?

  3. +++ b/core/modules/field_ui/src/Tests/EntityDisplayTestTrait.php
    @@ -0,0 +1,76 @@
    +    return $created;
    
    +++ b/core/modules/field_ui/tests/src/Kernel/EntityDisplayTest.php
    @@ -270,6 +273,27 @@ public function testFieldComponent() {
    +    $this->addDefaultTestFields(array_keys($dependent_fields));
    

    Actually - doesn't look like we're using the return? So probably can just drop the return? If someone needs it in the future, then we cross that bridge then?

What happens with existing config here?
Do we need an update hook to ensure that all config dependencies are updated accordingly?
I'll ping some folks for the subsystem maintainer review.

james.williams’s picture

Thanks @larowlan. As far as I'm aware, there is no existing config to update. The only formatters & widgets that core provides that declare dependencies dynamically, unless I'm mistaken, are for comments & images. I've checked, and there are no cases of them being used more than once within an entity display, so the dependencies in any existing config are currently correct as far as my understanding & the scope of this bug go.

Here's an updated patch with the changes from your review.

james.williams’s picture

Oh by the way, sorry, I was thinking of initial config provided by core (e.g. in /config/install directories). Existing configuration would indeed be missing any extra dependencies until it is re-saved. In the case where this bug has allowed an entity display to be installed, when the dependency is missing, how should Drupal behave?

It's not appropriate to just delete the entity display. Setting the individual component to be hidden/disabled in the display is another option. Some widgets/formatters (including all of core's) might cope to an extent without the missing dependencies (e.g. a missing image style or comment view mode), other might cause fatal errors. But it's worth noting that any such fatal errors would already be happening in that scenario. This is 'just' about hardening the config to declare the dependencies.

If those are the only options, the decision about what to do is probably this:

(A) Retain existing behaviour of formatters & widgets that are missing dependencies - i.e. images show, but without using a preset, comments use the default view mode, or a less-robust contrib formatter/widget continues to cause a fatal error.

vs

(B) Remove formatters & widgets that are missing dependencies - i.e. images & comments in that situation would no longer show, but at least any existing fatal errors from less-robust contrib modules get resolved.

My vote goes to (A)! I could be biased because that also means no update hook work is needed ;-)

What does anyone else following this think?

jofitz’s picture

I would be against option B (therefore in favour of option A, I guess, in the absence of an option C). Option B could make things (mysteriously) disappear while option A doesn't change the situation (so at least it doesn't make matters worse!).

dcam’s picture

Heh, I was writing a response to #41 and agreeing with @larowlan while these other comments were being posted.

I think that we do need an update function. Any existing configuration needs to be repaired. It would be really simple because all that needs to happen is re-saving the display entities, which will cause them to recalculate their dependencies. Something like this would probably work:

function field_update_80xx() {
  foreach (\Drupal::entityTypeManager()->getStorage('entity_form_display')->loadMultiple() as $form) {
    $form->save();
  }
  foreach (\Drupal::entityTypeManager()->getStorage('entity_view_display')->loadMultiple() as $view) {
    $view->save();
  }
}
dcam’s picture

Of course, it might not be as simple as that since it's likely that update tests will need to be written.

james.nugent7’s picture

Status: Needs review » Needs work

I tested this with @charlotte.b and we confirmed that the patch fixed the issue.

I followed the steps and was able to reproduce the missing dependency, after applying the patch the dependencies were correct.

I have marked this to needs work as it looks like more work is needed to update existing config.

james.williams’s picture

I wouldn't mind writing the update hook, but I've never done so with automated tests specifically for the update before. Can anyone point me to some documentation/guidance about how to do so please?

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.

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.

james.williams’s picture

Here's a patch that excludes the tests, which still applies. The full patch still needs a re-roll, as tests have changed.

heatherwoz’s picture

Issue summary: View changes

The latest comments suggest this needs an update hook and related tests, so it looks like more than a simple reroll. I will update the issue summary.

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.

Adev22’s picture

Status: Needs work » Needs review
Issue tags: -Needs reroll
StatusFileSize
new1.56 KB

rerolled the patch on #51 and the patch cleanly

hctom’s picture

StatusFileSize
new13.51 KB
new7.22 KB

I also stumbled about this issue while trying to implement a widget third-party setting and to get things forward, I gave it a try and rerolled the patch including the necessary test rewrites. I hope I didn't miss something.

hctom’s picture

Don't ask me what happened with the interdiff, but I can't get correct output for it - I guess it is because of the changed test file locations.

When this patch is reviewed successfully it can be used as a base for adding the update hook and the update test coverage.

hctom’s picture

Let's better hide the unreadable interdiff ;)

Status: Needs review » Needs work

The last submitted patch, 55: 2865710-55.patch, failed testing. View results

hctom’s picture

StatusFileSize
new13.56 KB
new660 bytes

Here is an updated patch with updated order on expected select options. Let's see what happens...

hctom’s picture

Status: Needs work » Needs review

Trigger testbot.

Status: Needs review » Needs work

The last submitted patch, 59: 2865710-59.patch, failed testing. View results

hctom’s picture

StatusFileSize
new13.58 KB
new961 bytes

Okay, there were some more order fixes required.

hctom’s picture

So this looks much better and therefore the reroll should be completed. Remaining tasks are still the update hook to resave all displays to recalculate dependencies correctly and tests for this update operation.

Contrary to the text in the "Remaining tasks" of issue description, I think this problem also interferes with correct dependency calculation for third-party settings. In my case, I have a third party setting for a specific widget type that is just a checkbox. If checked, the third-party setting is added to the widget settings, but if not checked, the third-party setting gets removed from the widget settings in order to have no obsolete dependencies for a feature that is not enabled (implemented via hook_entity_presave() to clean up the third-party settings array where needed).
Without this patch this also results in incorrect dependencies if you use the corresponding widget twice in a form display - when the first widget sets the third-party setting and a latter one doesn't, the required dependency is not added, because the latter one does not register it anymore due to no related third-party setting.

james.williams’s picture

Issue summary: View changes

Thanks hctom for that work on re-rolling!

Agreed, I think it's fair to remove that bit from the issue description. This has become a greater issue over time, as more interesting formatters & widgets have been developed. I haven't kept up to speed with the progress of media widgets & entity browsers in core, but it's entirely possible that this is now an issue with core ones (other than the existing example for comments), I'm not sure.

hctom’s picture

StatusFileSize
new14.55 KB
new904 bytes

To get things moving, here is an updated patch that includes the update hook to resave all entity view/form displays with recalculated dependencies. I'll investigate how to get test coverage for this, but if anybody is more familiar with tests like these, feel free to jump in ;)

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.

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.

acbramley’s picture

Issue tags: +Needs tests, +Needs reroll

Haven't read the full issue comments but the summary reads well.

Needs tests for the update hook and almost certainly needs a reroll.

acbramley’s picture

Issue tags: +Bug Smash Initiative

Forgot the most important tag :P

This was triaged as part of the daily BSI triage targets.

Bhanu951 made their first commit to this issue’s fork.

bhanu951’s picture

Status: Needs work » Needs review
Issue tags: -Needs reroll

Re-Rolled patch 2865710-65.patch for 10.1.x branch.

smustgrave’s picture

Status: Needs review » Needs work

Left MR comments

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

Drupal core is moving towards using a “main” branch. As an interim step, a new 11.x branch has been opened, as Drupal.org infrastructure cannot currently fully support a branch named main. New developments and disruptive changes should now be targeted for the 11.x branch, which currently accepts only minor-version allowed changes. For more information, see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

dcam’s picture

I messed up that MR while trying to update it for 11.x. I'll sort it out tomorrow.

dcam changed the visibility of the branch 11.x to hidden.

dcam changed the visibility of the branch 2865710-dependencies-from-only to hidden.

dcam’s picture

This is going to fail tests because I excluded all the entity_test lines from the fixture that I created. But I'm out of time to work on this right now and need to save the work. My plan is to move the test plugins out of the field_test module so that we don't have to depend on that anymore, reducing the amount of garbage that has to be in the fixture.

dcam’s picture

Status: Needs work » Needs review
Issue tags: -Needs tests

My plan is to move the test plugins out of the field_test module so that we don't have to depend on that anymore...

After evaluating how much work that would take I ended up putting all of the entity_test module stuff in the fixture. It's a pain, but it worked without having to refactor code to work without it.

larowlan’s picture

Just one minor comment on the MR, I think its ok, but would be good for a second opinion

needs-review-queue-bot’s picture

Status: Needs review » Needs work
StatusFileSize
new4.99 KB

The Needs Review Queue Bot tested this issue. It fails the Drupal core commit checks. Therefore, this issue status is now "Needs work".

This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.

Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.

dcam’s picture

Status: Needs work » Needs review
needs-review-queue-bot’s picture

Status: Needs review » Needs work
StatusFileSize
new91 bytes

The Needs Review Queue Bot tested this issue. It no longer applies to Drupal core. Therefore, this issue status is now "Needs work".

This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.

Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.

dcam’s picture

Status: Needs work » Needs review

I had to do a major reconfiguration of the tests. The test plugins were originally put into a module that had a dependency on entity_test. It seems like entity_test has been updated recently, which caused the fixture to be out of date. That would be a perpetual problem. We can't have that. So I moved the plugins to an isolated test module without a dependency.

dcam’s picture

Version: 11.x-dev » main

Drupal core is now using the main branch as the primary development branch. New developments and disruptive changes should now be targeted to the main branch.

Read more in the announcement.

dcam’s picture

The original reason I requested subsystem maintainer review over eight years ago is no longer relevant. There were extensive modifications being made to existing test classes. Those modifications were removed from the patches/MR. I've removed the tag.

dcam’s picture

Status: Needs review » Postponed

Postponing on #3577684: uninstall-contact.php doesn't delete entity displays which prevents these update tests from working.

dcam’s picture

Status: Postponed » Needs review

This just got unblocked.

needs-review-queue-bot’s picture

Status: Needs review » Needs work
StatusFileSize
new667 bytes

The Needs Review Queue Bot tested this issue. It fails the Drupal core commit checks. Therefore, this issue status is now "Needs work".

This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.

Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.

acbramley’s picture

Status: Needs work » Needs review