Uninstalling a module providing display extenders causes fatal errors

Created on 15 December 2015, about 9 years ago
Updated 23 September 2023, over 1 year ago

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

<!-- See https://drupal.org/core-mentoring/novice-tasks for tips on identifying novice tasks. Delete or add "Novice" from the Novice? column in the table below as appropriate. Uncomment tasks as the issue advances. Update the Complete? column to indicate when they are done, and maybe reference the comment number where they were done. -->

User interface changes

API changes

Data model changes

🐛 Bug report
Status

Needs work

Version

11.0 🔥

Component
Views 

Last updated about 4 hours ago

Created by

🇺🇸United States Jamie Holly

Live updates comments and jobs are added and updated live.
  • Triaged core major

    There is consensus among core maintainers that this is a major issue. Only core committers should add this tag.

Sign in to follow issues

Merge Requests

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

  • 🇬🇧United Kingdom catch

    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.

  • 🇯🇵Japan tyler36 Osaka

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

  • 🇦🇺Australia acbramley

    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

  • First commit to issue fork.
  • Pipeline finished with Failed
    15 days ago
    Total: 611s
    #425653
  • Pipeline finished with Success
    15 days ago
    Total: 376s
    #425661
  • 🇩🇪Germany tobiasb Berlin

    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.

  • Pipeline finished with Success
    15 days ago
    Total: 895s
    #425696
  • Pipeline finished with Success
    15 days ago
    Total: 437s
    #425751
  • Pipeline finished with Failed
    15 days ago
    Total: 151s
    #425852
  • 🇩🇪Germany tobiasb Berlin

    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 ViewsConfigUpdater cleanup the config for uninstalled extender.

  • Pipeline finished with Failed
    15 days ago
    Total: 136s
    #425857
  • Pipeline finished with Failed
    15 days ago
    Total: 1043s
    #425859
  • Pipeline finished with Success
    15 days ago
    Total: 1197s
    #425872
  • First commit to issue fork.
  • 🇮🇳India mohit_aghera Rajkot

    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.

  • Pipeline finished with Success
    3 days ago
    Total: 1198s
    #436787
Production build 0.71.5 2024