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

  1. Install the icons module (2.3.0) on Drupal 11.3.x.
  2. Add an entity reference field to menu_link_content.main that uses the media_library_widget (e.g. a "Visual" image field, field_media_menu_item_visual).
  3. Create/edit a menu link and attach a media item to that field.
  4. On the menu link edit form, click Remove on the media item (the media_library_widget AJAX button).
  5. 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

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

aras.drupal created an issue.

aras.drupal changed the visibility of the branch 3610627-static-submit-callback to active.

  • aras.drupal committed d974a44a on 2.0.x
    Issue #3610627: Fix 'Serialization of Closure' on menu link form with...