Problem/Motivation
IconsHooks::formMenuLinkContentFormAlter() attaches a submit handler to the menu link content form using an instance callable:
$form['actions']['submit']['#submit'][] = [$this, 'menuLinkContentFormSubmit'];
IconsHooks is a #[Hook] handler class that injects IconsManager, which in turn holds EntityTypeManagerInterface and RendererInterface. Neither IconsHooks nor IconsManager uses Drupal\Core\DependencyInjection\DependencySerializationTrait.
When the menu link form also contains a field using the media_library_widget (e.g. an image/media field added to menu_link_content), removing a media item triggers an AJAX form rebuild. During the rebuild, FormBuilder::rebuildForm() → FormCache::setCache() serializes the whole form array (including #submit) into the keyvalue.expirable.form store.
Because #submit contains [$this, …], PHP serializes the IconsHooks instance, which drags in IconsManager → Renderer → ThemeManager → Registry → DrupalKernel → ClassLoader. ClassLoader::$includeFile is a Closure, and closures cannot be serialized:
Exception: Serialization of 'Closure' is not allowed in serialize() (line 14 of core/lib/Drupal/Component/Serialization/PhpSerialize.php). Drupal\Component\Serialization\PhpSerialize::encode(Array) Drupal\Core\KeyValueStore\DatabaseStorageExpirable->doSetWithExpire(...) Drupal\Core\KeyValueStore\DatabaseStorageExpirable->setWithExpire(...) Drupal\Core\Form\FormCache->setCache(...) Drupal\Core\Form\FormBuilder->setCache(...) Drupal\Core\Form\FormBuilder->rebuildForm('menu_link_content_main_form', ...) Drupal\Core\Form\FormBuilder->processForm(...) Drupal\Core\Form\FormBuilder->buildForm(...)
The AJAX request returns HTTP 500 and the media item cannot be removed.
This is the same anti-pattern that was fixed in other contrib modules after the move to OOP #[Hook] handlers, e.g. ui_styles #3447102 and resend_register_mail #3543585, and is related to the core guidance in #3424106.
Steps to reproduce
- Install the
iconsmodule (2.3.0) on Drupal 11.3.x. - Add an entity reference field to
menu_link_content.mainthat uses themedia_library_widget(e.g. a "Visual" image field,field_media_menu_item_visual). - Create/edit a menu link and attach a media item to that field.
- On the menu link edit form, click Remove on the media item (the media_library_widget AJAX button).
- Observe an AJAX HTTP 500 with
Exception: Serialization of 'Closure' is not allowed.
The error does not occur when the icons module is disabled, or when the menu link form has no AJAX-rebuilding widget such as media_library_widget.
Issue fork icons-3610627
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