[AdminToolbarToolsSettingsForm] Fix Fatal Error: Call to undefined method Drupal\Core\Menu\MenuLinkManager::invalidateAll()

Created on 7 August 2024, 5 months ago
Updated 6 September 2024, 4 months ago

Problem/Motivation

Fix PHP Fatal error resulting in WSOD, occurring when saving AdminToolbarToolsSettingsForm:

Error: Call to undefined method Drupal\Core\Menu\MenuLinkManager::invalidateAll() in Drupal\admin_toolbar_tools\Form\AdminToolbarToolsSettingsForm->submitForm() (line 95 of /var/www/html/web/modules/contrib/admin_toolbar/admin_toolbar_tools/src/Form/AdminToolbarToolsSettingsForm.php).

Detailed stacktrace :

#0 [internal function]: Drupal\admin_toolbar_tools\Form\AdminToolbarToolsSettingsForm->submitForm(Array, Object(Drupal\Core\Form\FormState))
#1 /var/www/html/web/core/lib/Drupal/Core/Form/FormSubmitter.php(129): call_user_func_array(Array, Array)
#2 /var/www/html/web/core/lib/Drupal/Core/Form/FormSubmitter.php(67): Drupal\Core\Form\FormSubmitter->executeSubmitHandlers(Array, Object(Drupal\Core\Form\FormState))
#3 /var/www/html/web/core/lib/Drupal/Core/Form/FormBuilder.php(597): Drupal\Core\Form\FormSubmitter->doSubmitForm(Array, Object(Drupal\Core\Form\FormState))
#4 /var/www/html/web/core/lib/Drupal/Core/Form/FormBuilder.php(326): Drupal\Core\Form\FormBuilder->processForm('admin_toolbar_t...', Array, Object(Drupal\Core\Form\FormState))
#5 /var/www/html/web/core/lib/Drupal/Core/Controller/FormController.php(73): Drupal\Core\Form\FormBuilder->buildForm(Object(Drupal\admin_toolbar_tools\Form\AdminToolbarToolsSettingsForm), Object(Drupal\Core\Form\FormState))
#6 [internal function]: Drupal\Core\Controller\FormController->getContentResult(Object(Symfony\Component\HttpFoundation\Request), Object(Drupal\Core\Routing\RouteMatch))
#7 /var/www/html/web/core/lib/Drupal/Core/EventSubscriber/EarlyRenderingControllerWrapperSubscriber.php(123): call_user_func_array(Array, Array)
#8 /var/www/html/web/core/lib/Drupal/Core/Render/Renderer.php(638): Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}()
#9 /var/www/html/web/core/lib/Drupal/Core/EventSubscriber/EarlyRenderingControllerWrapperSubscriber.php(124): Drupal\Core\Render\Renderer->executeInRenderContext(Object(Drupal\Core\Render\RenderContext), Object(Closure))
#10 /var/www/html/web/core/lib/Drupal/Core/EventSubscriber/EarlyRenderingControllerWrapperSubscriber.php(97): Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->wrapControllerExecutionInRenderContext(Array, Array)
#11 /var/www/html/vendor/symfony/http-kernel/HttpKernel.php(181): Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}()
#12 /var/www/html/vendor/symfony/http-kernel/HttpKernel.php(76): Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object(Symfony\Component\HttpFoundation\Request), 1)
#13 /var/www/html/web/core/lib/Drupal/Core/StackMiddleware/Session.php(53): Symfony\Component\HttpKernel\HttpKernel->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#14 /var/www/html/web/core/lib/Drupal/Core/StackMiddleware/KernelPreHandle.php(48): Drupal\Core\StackMiddleware\Session->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#15 /var/www/html/web/core/lib/Drupal/Core/StackMiddleware/ContentLength.php(28): Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#16 /var/www/html/web/core/modules/big_pipe/src/StackMiddleware/ContentLength.php(32): Drupal\Core\StackMiddleware\ContentLength->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#17 /var/www/html/web/core/modules/page_cache/src/StackMiddleware/PageCache.php(106): Drupal\big_pipe\StackMiddleware\ContentLength->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#18 /var/www/html/web/core/modules/page_cache/src/StackMiddleware/PageCache.php(85): Drupal\page_cache\StackMiddleware\PageCache->pass(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#19 /var/www/html/web/core/lib/Drupal/Core/StackMiddleware/ReverseProxyMiddleware.php(48): Drupal\page_cache\StackMiddleware\PageCache->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#20 /var/www/html/web/core/lib/Drupal/Core/StackMiddleware/NegotiationMiddleware.php(51): Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#21 /var/www/html/web/core/lib/Drupal/Core/StackMiddleware/AjaxPageState.php(36): Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#22 /var/www/html/web/core/lib/Drupal/Core/StackMiddleware/StackedHttpKernel.php(51): Drupal\Core\StackMiddleware\AjaxPageState->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#23 /var/www/html/web/core/lib/Drupal/Core/DrupalKernel.php(741): Drupal\Core\StackMiddleware\StackedHttpKernel->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#24 /var/www/html/web/index.php(19): Drupal\Core\DrupalKernel->handle(Object(Symfony\Component\HttpFoundation\Request))
#25 {main}

Steps to reproduce

0 - Install the admin_toolbar_tools module
1 - Browse to the Admin Toolbar Tools settings at: /admin/config/user-interface/admin-toolbar-tools
under: Home > Administration > Configuration > User interface > Admin Toolbar Tools
2 - Save the form by clicking on the Save configuration button.
3 - Confirm the page crashes with WSOD error:

The website encountered an unexpected error. Try again later.

Error: Call to undefined method Drupal\Core\Menu\MenuLinkManager::invalidateAll() in Drupal\admin_toolbar_tools\Form\AdminToolbarToolsSettingsForm->submitForm() (line 97 of modules/contrib/admin_toolbar/admin_toolbar_tools/src/Form/AdminToolbarToolsSettingsForm.php).

Proposed resolution

This issue seems to have been introduced in commit:
https://git.drupalcode.org/project/admin_toolbar/-/commit/efb450aeb115f7...
and is the same as 🐛 [AdminToolbarSettingsForm] Fix Fatal Error: Call to undefined method Drupal\Core\Menu\MenuLinkManager::invalidateAll() Fixed .

It appears the values for $container->get were reversed when injecting the dependencies.

Solution: Set the injected dependencies in the correct order, for each respective property.

Additionally, add a basic automated test class to confirm the changes fix the issue.

🐛 Bug report
Status

Needs work

Version

3.0

Component

Code

Created by

🇫🇷France dydave

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Merge Requests

Comments & Activities

  • Issue created by @dydave
  • Pipeline finished with Success
    5 months ago
    Total: 346s
    #247259
  • Pipeline finished with Success
    5 months ago
    Total: 400s
    #247270
  • Status changed to Needs review 5 months ago
  • 🇫🇷France dydave

    Quick follow-up on this issue:

    Fixed fatal error 'Call to undefined method Drupal\Core\Menu\MenuLinkManager::invalidateAll()' and added basic automated tests for the 'AdminToolbarToolsSettingsForm':
    Submit the form and confirm it doesn't crash with error.

    ✅ The merge request seems to be passing all tests, thus moving issue to Needs review.

    Please note: much more work is needed to improve the tests for the AdminToolbarToolsSettingsForm, in particular:
    While trying to write tests for max_bundle_number it appeared issue 🐛 Max Bundles not being honored Fixed is still not completely fixed:
    Tested with Media bundles: Setting the max_bundle_number to 2, for example, on a standard fresh D10 install (which should install several Media bundles by default: Audio, Document, Image, etc...), doesn't have any effect on the links under Content > Add media
    ==> All bundles are still displayed in the menu (under Content).

    However, this setting seems to work with menu items under Structure.

    I'm not sure if this is by design, but it is a bit misleading, as we would potentially expect bundles would be limited everywhere links for entity bundles are added, as the field says:

    Maximum number of bundle sub-menus to display
    Loading a large number of items can cause performance issues.

     
    In any case, this should most likely be addressed in a separate ticket, so for the time being, the tests minimally cover the error reported in this issue summary.
     

    We would greatly appreciate if a maintainer or someone with write permission could take a look at ticket's merge request MR!96 and let us know if there would be any more work needed.

    Feel free to let us know if you have any questions or concerns on any of the changes in the merge request or any aspect of this ticket in general, we would surely be glad to help.
    Thanks in advance for your feedback and reviews.

  • Similar problem here:
    - A batch upgrade from D10.2.7 to 10.3.2 brought the WSOD. A selective upgrade on 10.3.1 with PHP 8.3.9 made possible to pinpoint 'admin_toolbar' as the primary culprit, in combination with the 'admin_toolbar_tools'.
    Upgrading 'admin_toolbar_tools' (3.4.2 => 3.5.0) first while keeping 'admin_toolbar' at 3.4.2 went well. Then upgrading 'admin_toolbar' (3.4.2 => 3.5.0) as well yielded the trace below:

    TypeError: method_exists(): Argument #1 ($object_or_class) must be of type object|string, null given in method_exists() (line 68 of modules/contrib/admin_toolbar/admin_toolbar_tools/src/Plugin/Menu/MenuLinkEntity.php).

    Drupal\admin_toolbar_tools\Plugin\Menu\MenuLinkEntity->getDescription() (Line: 124)
    Drupal\Core\Menu\MenuLinkBase->getUrlObject() (Line: 215)
    Drupal\Core\Menu\DefaultMenuLinkTreeManipulators->menuLinkCheckAccess() (Line: 107)
    Drupal\Core\Menu\DefaultMenuLinkTreeManipulators->checkAccess() (Line: 111)
    Drupal\Core\Menu\DefaultMenuLinkTreeManipulators->checkAccess() (Line: 111)
    Drupal\Core\Menu\DefaultMenuLinkTreeManipulators->checkAccess()
    call_user_func() (Line: 153)
    Drupal\Core\Menu\MenuLinkTree->transform() (Line: 124)
    Drupal\toolbar\Controller\ToolbarController::preRenderGetRenderedSubtrees()
    call_user_func_array() (Line: 113)
    Drupal\Core\Render\Renderer->doTrustedCallback() (Line: 870)
    Drupal\Core\Render\Renderer->doCallback() (Line: 432)
    Drupal\Core\Render\Renderer->doRender() (Line: 248)
    Drupal\Core\Render\Renderer->render() (Line: 283)
    {closure}() (Line: 638)
    Drupal\Core\Render\Renderer->executeInRenderContext() (Line: 282)
    toolbar_get_rendered_subtrees() (Line: 295)
    _toolbar_get_subtrees_hash() (Line: 168)
    toolbar_toolbar()
    call_user_func_array() (Line: 416)
    Drupal\Core\Extension\ModuleHandler->Drupal\Core\Extension\{closure}() (Line: 395)
    Drupal\Core\Extension\ModuleHandler->invokeAllWith() (Line: 415)
    Drupal\Core\Extension\ModuleHandler->invokeAll() (Line: 78)
    Drupal\toolbar\Element\Toolbar::preRenderToolbar()
    call_user_func_array() (Line: 113)
    Drupal\Core\Render\Renderer->doTrustedCallback() (Line: 870)
    Drupal\Core\Render\Renderer->doCallback() (Line: 432)
    Drupal\Core\Render\Renderer->doRender() (Line: 504)
    Drupal\Core\Render\Renderer->doRender() (Line: 248)
    Drupal\Core\Render\Renderer->render() (Line: 475)
    Drupal\Core\Template\TwigExtension->escapeFilter() (Line: 83)
    __TwigTemplate_d68a68533d331dfee346749b4e3826a0->doDisplay() (Line: 360)
    Twig\Template->yield() (Line: 335)
    Twig\Template->render() (Line: 38)
    Twig\TemplateWrapper->render() (Line: 33)
    twig_render_template() (Line: 348)
    Drupal\Core\Theme\ThemeManager->render() (Line: 491)
    Drupal\Core\Render\Renderer->doRender() (Line: 248)
    Drupal\Core\Render\Renderer->render() (Line: 158)
    Drupal\Core\Render\MainContent\HtmlRenderer->Drupal\Core\Render\MainContent\{closure}() (Line: 638)
    Drupal\Core\Render\Renderer->executeInRenderContext() (Line: 153)
    Drupal\Core\Render\MainContent\HtmlRenderer->renderResponse() (Line: 90)
    Drupal\Core\EventSubscriber\MainContentViewSubscriber->onViewRenderArray()
    call_user_func() (Line: 111)
    Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher->dispatch() (Line: 186)
    Symfony\Component\HttpKernel\HttpKernel->handleRaw() (Line: 76)
    Symfony\Component\HttpKernel\HttpKernel->handle() (Line: 53)
    Drupal\Core\StackMiddleware\Session->handle() (Line: 48)
    Drupal\Core\StackMiddleware\KernelPreHandle->handle() (Line: 28)
    Drupal\Core\StackMiddleware\ContentLength->handle() (Line: 32)
    Drupal\big_pipe\StackMiddleware\ContentLength->handle() (Line: 106)
    Drupal\page_cache\StackMiddleware\PageCache->pass() (Line: 85)
    Drupal\page_cache\StackMiddleware\PageCache->handle() (Line: 50)
    Drupal\ban\BanMiddleware->handle() (Line: 263)
    Drupal\shield\ShieldMiddleware->bypass() (Line: 219)
    Drupal\shield\ShieldMiddleware->handle() (Line: 48)
    Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle() (Line: 51)
    Drupal\Core\StackMiddleware\NegotiationMiddleware->handle() (Line: 36)s
    Drupal\Core\StackMiddleware\AjaxPageState->handle() (Line: 51)
    Drupal\Core\StackMiddleware\StackedHttpKernel->handle() (Line: 741)
    Drupal\Core\DrupalKernel->handle() (Line: 19)

  • 🇫🇷France dydave

    @dgwolf ==> Wrong issue :

    Could you please take a look at : 🐛 TypeError: method_exists(): Argument #1 ($object_or_class) must be of type object|string, null given Needs review ?

    Thanks in advance !

  • Status changed to Needs work 4 months ago
  • 🇨🇦Canada Liam Morland Ontario, CA 🇨🇦

    @dydave The merge request only adds a test. It does not appear to do anything that would fix the error with ::invalidateAll().

  • Pipeline finished with Failed
    3 months ago
    Total: 532s
    #295766
  • Pipeline finished with Failed
    3 months ago
    Total: 564s
    #295772
Production build 0.71.5 2024