MediaWidgetAlter::formAlter() (invoked via hook_form_alter()) appends a submit handler to the submit button of every form whose form object is an EntityFormInterface:

#[Hook('form_alter')]
public function formAlter(array &$form, FormStateInterface $form_state, string $form_id): void {
  $form_object = $form_state->getFormObject();
  if (!$form_object instanceof EntityFormInterface) {
    return;
  }
  $form['actions']['submit']['#submit'][] = [static::class, 'widgetFormSubmitCallback'];
}

This has two problems:

1. Too broad. It attaches to entity forms that have no synthesizable media widget at all. The handler no-ops in that case (it returns early unless polly_media_entity_to_speech is set),
so it's functionally harmless on most forms — but it still mutates the form.
2. It breaks forms that don't set their own button #submit and instead rely on the form-level handler. Once a submit button defines any #submit handlers, Drupal's
FormSubmitter::executeSubmitHandlers() uses only the button's handlers and ignores the form-level $form['#submit'] (which normally contains the form object's ::submitForm). So by adding
a handler to the button, polly_media suppresses the form's own submit handler.

My own victim was core's taxonomy term overview form (Drupal\taxonomy\Form\OverviewTerms). In Drupal 11 this form became an EntityForm (it was a FormBase in Drupal 10). It builds
its own actions and does not put a #submit on the Save button — it depends entirely on the form-level ::submitForm. After polly_media appends widgetFormSubmitCallback to that button,
OverviewTerms::submitForm() never runs. Result: reordering taxonomy terms silently does nothing — the form submits, redirects normally, no error, but term weights are never saved.

This is a Drupal 11 regression for sites running polly_media, triggered purely by OverviewTerms changing from FormBase to EntityForm.

Steps to reproduce

1. Install polly + polly_media and enable the synthesize option on at least one media reference widget.
2. Go to a vocabulary's term overview (/admin/structure/taxonomy/manage/{vid}/overview).
3. Drag to reorder terms, click Save.

Expected: weights are saved, terms keep the new order.
Actual: "The configuration options have been saved." does not appear, order reverts, taxonomy_term_field_data.weight stays unchanged. OverviewTerms::submitForm() is never called because
only the polly callback is registered as the button's submit handler.

Any custom/contrib EntityForm that builds its own actions without a button-level #submit is affected the same way.

Proposed resolution

Two complementary changes in MediaWidgetAlter:

1. Scope the attachment to forms that actually render a synthesizable media widget. fieldWidgetCompleteFormAlter() already determines this (third-party setting allow_synthesis, entity
form, fieldable entity, permission). Set a flag there:

$form_state->set('polly_media_synthesize_widget', TRUE);

1. and have formAlter() bail unless the flag is set. Because fieldWidgetCompleteFormAlter() runs while fields are built (inside the form object's buildForm()) and hook_form_alter() runs
after buildForm() returns, the flag is reliably available.
2. Attach where Drupal will actually run it, without overriding existing handlers:

if (!$form_state->get('polly_media_synthesize_widget')) {
  return;
}
$callback = [static::class, 'widgetFormSubmitCallback'];
if (isset($form['actions']['submit']) && isset($form['actions']['submit']['#submit'])) {
  // Button has its own handlers; Drupal uses only those.
  $form['actions']['submit']['#submit'][] = $callback;
}
else {    
  // No button-level handlers; the form-level handlers are used.
  $form['#submit'][] = $callback;
}

This keeps current behaviour for normal content entity edit forms (their Save button already carries ['::submitForm', '::save'], so the callback is appended there and still runs after
::save), stops polly_media from touching unrelated forms, and never suppresses a form's own submit handler.

The fix lives entirely in MediaWidgetAlter::formAlter() and ::fieldWidgetCompleteFormAlter(), which are the same methods invoked on both Drupal 10.3 (via the procedural #[LegacyHook]
bridge in polly_media.module) and Drupal 11 (via the #[Hook] attribute), so a single change covers both supported core versions.

Issue fork polly-3600850

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

hanoii created an issue. See original summary.

hanoii’s picture

Status: Active » Needs review

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

andyf’s picture

Status: Needs review » Fixed

Many thanks @hanoii! Took the opportunity to add the first tests for the polly_media module.

Now that this issue is closed, review the contribution record.

As a contributor, attribute any organization that helped you, or if you volunteered your own time.

Maintainers, credit people who helped resolve this issue.

hanoii’s picture

Awesome, if you can release a new beta, that'd be great.

andyf’s picture

Done, should be published imminently.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.