Problem/Motivation

If you define a Display Extender plugin in a module and enable it, then uninstall that module, you are unable to load any pages. You get a "Drupal\Component\Plugin\Exception\PluginNotFoundException" error.

The same thing will occur if a module defines an input filter and then that module is uninstalled. If you go to a page with processed text using a format that filter was enabled in, then it will error out with a plugin not found exception.

While we can check uninstall requirements on a per-module basis, having core do this would make much more sense and prevent the dreaded WSOD as more modules get tried and uninstalled.

Proposed resolution

Simplest fix would be in DisplayPluginBase.php:165:

if ($plugin = $manager->createInstance($extender)) {

Change to:

if ($manager->hasDefinition($extender) && $plugin = $manager->createInstance($extender)) {

The other, more involved but possible better option would be to define a default fallback plugin for display extenders, and possibly any other Views plugins that can be defined and cause this problem.

What may be the best solution is to include these plugins, along with any others in the uninstall validator. Perhaps a new method in DefaultPluginManager (or even a trait for plugin managers to include) that allows each plugin manager to perform a check if it can be safely removed or not.

eg for the views handler:

 public function uninstallRequirements($module_name) {

  foreach ($definitions as $definition) {
      if ($definition['provider'] == $module_name && $config->get('views.settings.display_extenders' . $definition['id'])) {
          //Throw an exception or return an explanation of why this module can not be uninstalled.
     }
  }
}

For Filters it would have to loop through each formatter config entity and check if that filter is enabled.

Recommended workaround

Until this bug is fixed, any module implementing display extenders should implement hook_uninstall() to require removing dependencies on it from existing views.

Remaining tasks

Contributor tasks needed
Task Novice task? Contributor instructions Complete?
Add automated tests Instructions
Add steps to reproduce the issue Instructions

User interface changes

API changes

Data model changes

Issue fork drupal-2635728

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

Jamie Holly created an issue. See original summary.

cilefen’s picture

Are things ok if you disable the display extender thingy (is disabling something they can do?)?

I ask because the module creating the Display Extender or Views could implement the ModuleUninstallValidator which would prevent the module providing the extender from being uninstalled and explain why.

Jamie Holly’s picture

Title: Disabling A Module With An Enabled Views Extender Breaks Site » Disabling A Module With Certain Plugins Enabled Breaks Site
Issue summary: View changes

Disabling it in the Views advanced settings does allow it to uninstall without issue.

The Uninstall validator is a good idea, but that should most likely be handled in core.

I also noticed the same thing happens on input filters that a module defines (hence the title change). If a module defines an input filter and that module is then disabled without removing the filter from any formats that use it, then any formats using that filter will error out when you try to display them.

I think a better approach would be to figure out any plugins that can cause this unexpected behavior and add a check in for the uninstall validator. This is something that will pretty much be a requirement of any modules defining Views extenders, Input filters and possibly many more plugins, so leaving it up to core to decide is the best approach IMHO.

dawehner’s picture

Oh yeah I think \Drupal\views\Plugin\views\display\DisplayPluginBase::calculateDependencies needs to have some logic around display extenders as well.

Ideally the display extender for itself then would figure out whether it changes the behaviour of a particular view and in that case add itself as module dependency.

catch’s picture

Title: Disabling A Module With Certain Plugins Enabled Breaks Site » Uninstalling a module providing display extenders causes fatal errors
Priority: Major » Critical
Issue tags: +missing config dependencies, +D8 upgrade path
frob’s picture

Should there be an added 'Disabled' mode that disables all plugins that are provided by a module?

dawehner’s picture

Status: Active » Needs review
StatusFileSize
new2.53 KB

Here is an example.

geertvd’s picture

StatusFileSize
new848 bytes
new2.72 KB

Added tests exposing the problem

cilefen’s picture

+++ b/core/modules/views/src/Tests/Plugin/DisplayExtenderTest.php
@@ -49,6 +49,17 @@ public function testDisplayExtenders() {
+    ], $view->getDependencies());
+    ¶
+    \Drupal::service('module_installer')->uninstall(array('views_test_data'));

There is some unwanted white space here, which can be fixed in the next patch.

The last submitted patch, 8: 2635728-8-test.patch, failed testing.

Status: Needs review » Needs work

The last submitted patch, 8: 2635728-8-complete.patch, failed testing.

alexpott’s picture

I don't think this is the right solution... I think that we need a views_modules_uninstalled hook implementation that checks if the module being uninstalled provides a display extender and remove it from views.settings::display_extenders and also clean up any views which have configuration for that display extender.

eelkeblok’s picture

Isn't this fundamentally a question of how we want this handled from the user's perspective? It seems rather "harsh" to essentially break a user's configuration (i.e. remove everything that prevents the module from uninstalling cleanly; [IUUC, this is what catch is suggesting]). Shouldn't this be something the user more consciously decides to do? When you disable a module that is a dependency for other modules, that doesn't disable the dependent modules, it simply prevents the module from being disabled. It is up to the user to change their system in such a way that it is possible to cleanly disable/uninstall the module in a way that is well understood and planned for. I think that rational should ideally be extended to other dependency issues (such as Views Display Extender plugins or input filters).

cilefen’s picture

So, what I wrote in #2?

eelkeblok’s picture

Well, yes, although I think it's important to first agree on the intended outcome (user must take action to be able to cleanly disable a module, vs. automatically trying to do that cleaning).

alexpott’s picture

With #2 it would never be possible to uninstall a module that provided a display extender because afaik display extenders don't actually have to be configured in a view - they might just act using the views.settings::display_extenders setting.

catch’s picture

Do we tell people what happens on the uninstall form for this? If so that counts as giving people a choice for me.

frob’s picture

Is there also an issue when configuration is imported and the module/plugin isn't enabled?

alexpott’s picture

Issue summary: View changes
StatusFileSize
new46.98 KB

I've got a question about the comment #2 which claims we have similar problems with input filter plugins. Drupal\filter\FilterUninstallValidator should prevent this from happening. If we can confirm the input filters are an issue I think we should open an new issue about input filters specifically. I've tried to reproduce this by doing this:

  1. Add $settings['extension_discovery_scan_tests'] = TRUE; to settings.php
  2. Installed the filter_test_plugin module
  3. Added the sparkles plugin to the basic html filter format
  4. Visited the module uninstalled page and saw:

With regards to display extenders I think we should implement a ModuleUninstallValidatorInterface that prevents modules that provide display extenders that are in used from being uninstalled.

hass’s picture

dawehner’s picture

StatusFileSize
new2.3 KB

Just a general idea: Allow display extenders to define whether they apply to a display. When they do, we could add it to a list of them on the display and leverage that on runtime and for config dependencies. Here is a rough start of some patch to support it.

jibran’s picture

Status: Needs work » Needs review

Status: Needs review » Needs work

The last submitted patch, 21: 2635728-21.patch, failed testing.

sidharrell’s picture

Issue summary: View changes

Updated issue summary

sidharrell’s picture

Issue summary: View changes

Updated issue summary.
Working on steps to reproduce.

sidharrell’s picture

Issue summary: View changes

removing novice task tag from issue summary

lokapujya’s picture

What module provides a display extender?

The test module: views_test_data has one.

alexpott’s picture

Priority: Critical » Major

Discused with @effulgentsia, @xjm and @cottser. This was made critical in #5 due to the claims of an issue with filter plugins in #3. I investigated the claims in #19 and since then no one has replied proving the claims of #3. Therefore I'm downgrading to major since view's display extenders are strange plugins and there is an acceptable work around of just implementing hook_uninstall() in the couple of modules that use them.

If someone does find a critical issue relating to filter plugins please file a new issue.

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.

jibran’s picture

Status: Needs work » Needs review
StatusFileSize
new2.3 KB

Here is the reroll.

Status: Needs review » Needs work

The last submitted patch, 30: uninstalling_a_module-2635728-30.patch, failed testing.

The last submitted patch, 30: uninstalling_a_module-2635728-30.patch, failed testing.

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

Drupal 8.1.9 was released on September 7 and is the final bugfix release for the Drupal 8.1.x series. Drupal 8.1.x will not receive any further development aside from security fixes. Drupal 8.2.0-rc1 is now available and sites should prepare to upgrade to 8.2.0.

Bug reports should be targeted against the 8.2.x-dev branch from now on, and new development or disruptive changes should 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.

cilefen’s picture

@alexpott: I just noticed in #19 you referred to #2 but what you meant was #3. But you referenced #3 in subsequent comments, so it pays to keep reading...

xjm’s picture

Issue summary: View changes
Issue tags: +Triaged core major

@dawehner, @tim.plunkett, @alexpott, @cilefen, and I discussed this issue awhile back and agreed that it is a major bug. The bug causes fatal errors in the user interface and data integrity/uninstallability problems for a fully supported API. As explained in #28, it's not critical because display extenders are, in general, a limited/special usecase.

We recommend that any module that provides a display extender implement hook_uninstall() to require removing any dependencies on it in the meanwhile.

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

Drupal 8.2.6 was released on February 1, 2017 and is the final full bugfix release for the Drupal 8.2.x series. Drupal 8.2.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.3.0 on April 5, 2017. (Drupal 8.3.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.3.x-dev branch from now on, and new development or disruptive changes should 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.

johnpitcairn’s picture

Regarding filter plugins - we have a module that added a filter plugin to try to solve a specific problem. We solved that in another way, and would now like to remove the filter from the module without uninstalling the module. We have disabled all instances of the filter in all text formats, but removing the filter plugin from the module results in broken output wherever a text format is used:

Drupal\Component\Plugin\Exception\PluginNotFoundException: The "product_link_ajax_filter" plugin does not exist. in Drupal\Core\Plugin\DefaultPluginManager->doGetDefinition() (line 52 of core/lib/Drupal/Component/Plugin/Discovery/DiscoveryTrait.php).

Happy to open a new issue about this, but really I'd just like to know what we should do in this situation to allow us to remove the unused filter plugin from the module.

dawehner’s picture

@John Pitcairn
Please open its own issue for that. Its a bit unrelated to this one, to be honest. Thank you

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

Drupal 8.3.6 was released on August 2, 2017 and is the final full bugfix release for the Drupal 8.3.x series. Drupal 8.3.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.4.0 on October 4, 2017. (Drupal 8.4.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.4.x-dev branch from now on, and new development or disruptive changes should 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.

alan d.’s picture

It would be nice if ViewsPluginManager implemented FallbackPluginManagerInterface as suggested in the proposed resolution too.

A much nicer developer experience being able to rename plugins on the fly without reinstalling modules ;)

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

Drupal 8.4.4 was released on January 3, 2018 and is the final full bugfix release for the Drupal 8.4.x series. Drupal 8.4.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.5.0 on March 7, 2018. (Drupal 8.5.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.5.x-dev branch from now on, and new development or disruptive changes should 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.5.x-dev » 8.6.x-dev

Drupal 8.5.6 was released on August 1, 2018 and is the final bugfix release for the Drupal 8.5.x series. Drupal 8.5.x will not receive any further development aside from security fixes. Sites should prepare to update to 8.6.0 on September 5, 2018. (Drupal 8.6.0-rc1 is available for testing.)

Bug reports should be targeted against the 8.6.x-dev branch from now on, and new development or disruptive changes should 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.

socialnicheguru’s picture

can this be re-rolled for Drupal.8.6.13.

I was using socrata_views which added socrata_views_extender.
It uses hook_uninstall

However uninstalling the module does not solve the issue.

cilefen’s picture

Version: 8.6.x-dev » 8.7.x-dev
Status: Needs work » Needs review
Issue tags: -views, -missing config dependencies, -D8 upgrade path
StatusFileSize
new2.24 KB
socialnicheguru’s picture

I am on 8.6.13 and the patch does not apply:

git apply 2635728-44.patch
warning: core/modules/views/src/Plugin/views/display/DisplayPluginBase.php has type 100755, expected 100644
error: patch failed: core/modules/views/src/Plugin/views/display/DisplayPluginBase.php:565
error: core/modules/views/src/Plugin/views/display/DisplayPluginBase.php: patch does not apply

patch -p1 < 2635728-44.patch
patching file core/modules/views/config/schema/views.data_types.schema.yml
patching file core/modules/views/src/Plugin/views/display/DisplayPluginBase.php
Hunk #1 succeeded at 464 (offset 1 line).
Hunk #2 FAILED at 566.
1 out of 2 hunks FAILED -- saving rejects to file core/modules/views/src/Plugin/views/display/DisplayPluginBase.php.rej
patching file core/modules/views/src/Plugin/views/display_extender/DisplayExtenderPluginBase.php

Status: Needs review » Needs work

The last submitted patch, 44: 2635728-44.patch, failed testing. View results

cilefen’s picture

I disagree:

$ git checkout 8.6.13
HEAD is now at 89e23ccafb Drupal 8.6.13

$ curl https://www.drupal.org/files/issues/2019-04-09/2635728-44.patch | git apply
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  2291  100  2291    0     0  30268      0 --:--:-- --:--:-- --:--:-- 30546
drupal8x ((8.6.13) *)$ git status
HEAD detached at 8.6.13
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

	modified:   core/modules/views/config/schema/views.data_types.schema.yml
	modified:   core/modules/views/src/Plugin/views/display/DisplayPluginBase.php
	modified:   core/modules/views/src/Plugin/views/display_extender/DisplayExtenderPluginBase.php

no changes added to commit (use "git add" and/or "git commit -a")

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

Drupal 8.7.9 was released on November 6 and is the final full bugfix release for the Drupal 8.7.x series. Drupal 8.7.x will not receive any further development aside from security fixes. Sites should prepare to update to 8.8.0 on December 4, 2019. (Drupal 8.8.0-beta1 is available for testing.)

Bug reports should be targeted against the 8.8.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.9.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.

ghost of drupal past’s picture

We just hit this problem, if you need to fix your site, here's a quick script, run it with drush scr:


/** @var \Drupal\Core\Config\FileStorage $s */
$s = \Drupal::service('config.storage.sync');
foreach ($s->listAll('views.view.') as $name) {
  $c = $s->read($name);
  foreach (array_keys($c['display']) as $display) {
    unset($c['display'][$display]['display_options']['display_extenders']['simple_sitemap_display_extender']);
  }
  $s->write($name, $c);
}

I manually edited views.settings.yml and then ran drush cim. I will the read the issue later and see whether I can help but wanted to put this out there just in case someone needs help.

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

Drupal 8.8.7 was released on June 3, 2020 and is the final full bugfix release for the Drupal 8.8.x series. Drupal 8.8.x will not receive any further development aside from security fixes. Sites should prepare to update to Drupal 8.9.0 or Drupal 9.0.0 for ongoing support.

Bug reports should be targeted against the 8.9.x-dev branch from now on, and new development or disruptive changes should 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: 8.9.x-dev » 9.2.x-dev

Drupal 8 is end-of-life as of November 17, 2021. There will not be further changes made to Drupal 8. Bugfixes are now made to the 9.3.x and higher branches only. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

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

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

Drupal 9.3.15 was released on June 1st, 2022 and is the final full bugfix release for the Drupal 9.3.x series. Drupal 9.3.x will not receive any further development aside from security fixes. Drupal 9 bug reports should be targeted for the 9.4.x-dev branch from now on, and new development or disruptive changes should 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

Running #44 for the 9.4.x to see if any test failures happen. Confirmed the patch does apply cleanly.

Is there a good way to help test this one?

smustgrave’s picture

Think this still needs work. After applying the patch and trying to do a drush cim I get

Invalid data type in config views.data_types.schema, found in file core/modules/views/config/schem
a/views.data_types.schema.yml: Duplicate key "display_extenders" detected at line 261.

smustgrave’s picture

StatusFileSize
new439 bytes
new1.63 KB

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

Drupal 9.4.9 was released on December 7, 2022 and is the final full bugfix release for the Drupal 9.4.x series. Drupal 9.4.x will not receive any further development aside from security fixes. Drupal 9 bug reports should be targeted for the 9.5.x-dev branch from now on, and new development or disruptive changes should 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.

catch’s picture

Version: 9.5.x-dev » 11.x-dev
Priority: Major » Critical

There are several hundred sites that need to uninstall the views_ajax_get module in 10.1. It doesn't implement the hook_uninstall() workaround. Bumping to critical since this leaves sites hosed.

tyler36’s picture

This bug prevents Gutenberg module from being uninstalled when using webprofiler module. See #3261040

acbramley’s picture

Triaged as part of BSI. This definitely still seems valid but we need:
1. A reroll onto an MR.
2. Tests
3. An update to the IS as it still mentions filter plugins which seem to not be an issue as per #28

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

tobiasb’s picture

Issue tags: -Needs reroll

I do not understand, whether is missing todo or not. just with the patch views does not add the dependency via \Drupal\views\Plugin\views\display\DisplayPluginBase::calculateDependencies. It does also not call \Drupal\views\Plugin\views\display_extender\DisplayExtenderPluginBase::applies.

There is a plugin_type display_extender in \Drupal\views\Plugin\views\display\DisplayPluginBase::getAllPlugins, but always NULL, when used in \Drupal\views\Plugin\views\display\DisplayPluginBase::calculateDependencies.

I believe we need something like #2426607: Calculates and adds dependencies of views display extender, which use \Drupal\views\Plugin\views\display_extender\DisplayExtenderPluginBase::applies.

tobiasb’s picture

Ok, as mention in #2426607: Calculates and adds dependencies of views display extender a dependency is not a option because this would delete the view.

Therefore -> views_modules_uninstalled clean-up the config and we will verify that the plugin does exits before we use it.

The clean up in the view display itself is done by the next save of the display.

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

mohit_aghera’s picture

I evaluated two solutions for the issue.

  1. Modify/cleanup the views in hook_modules_uninstalled hook
  2. Implement a new module uninstall validator for the display handler plugins Comment #19

Modify/cleanup the views in hook_modules_uninstalled hook
- I feel this might not work in this case.
Reason is, that we can't fetch the list of all the display handler plugins provided by the module being uninstalled.
In the uninstall() function, this hook is the last one to get called https://git.drupalcode.org/project/drupal/-/blob/11.x/core/lib/Drupal/Co...

Since plugin ID or anything won't be available here, we can't identify which display handler plugins we want to unset from views config.

I evaluated another option to check the plugin by doing namespace-based lookup, however, that seemed a bit hacky to me.

Considering that, it might not be straightforward to update all the views and unset the display handler plugins.
We can certainly disable the plugin in views > Advanced config settings.

Implement a new module uninstall validator for the display handler plugins Comment #19
This worked fine and prevented module being uninstalled.
I added on validator plugin along with kernel test to validate the exception.
This seems to be working fine.

I feel at this point we should go ahead with the approach where we display a warning rather than silently updating the views config.

Once we have the consensus around the solution, I can update the issue summary with the necessary details.

mohit_aghera’s picture

Status: Needs work » Needs review
smustgrave’s picture

Status: Needs review » Needs work
Issue tags: -Needs issue summary update

Left some comments on the MR.

xjm credited effulgentsia.

xjm credited star-szr.

xjm’s picture

Attributing according to triage list in #28

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.