PreviewFormService::alterForm not passing on generic arguments

Created on 10 February 2025, about 2 months ago

Problem/Motivation

I encountered the following error when working with Frontend Editing and Paragraphs Edit :
TypeError: Drupal\paragraphs_edit\ParagraphLineageRevisioner::shouldCreateNewRevision(): Argument #1 ($entity) must be of type Drupal\Core\Entity\EntityInterface, null given, called in /var/www/drupal/docroot/modules/contrib/paragraphs_edit/src/Form/ParagraphEditForm.php on line 65 in Drupal\paragraphs_edit\ParagraphLineageRevisioner->shouldCreateNewRevision() (line 111 of modules/contrib/paragraphs_edit/src/ParagraphLineageRevisioner.php).

Digging into shows that the called handler: \Drupal\paragraphs_edit\ParagraphFormHelperTrait::buildForm() accepts an additional argument: ?EntityInterface $root_parent = NULL
And while it is declared as optional, it isn't really down the line - but that's another issue.

Checking further reveals that the expected argument is actually properly set in the FormState but PreviewFormService::alterForm() isn't passing it on.

Steps to reproduce

Haven't figured out a quick way to reproduce.

Proposed resolution

Core's form handler properly passes the optional argument by using the arguments in the build info of the form state.
I propose to use the same approach as core in \Drupal\Core\Form\FormBuilder::retrieveForm() to call the buildForm method of the FormObject.

So instead of

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

      // Rebuild the form to apply new values.
      $form = $formObject->buildForm($form, $form_state);

we use:

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

      // Get the build info
      $build_info = $form_state->getBuildInfo();
      $args = $build_info['args'];
      // We need to pass $form_state by reference in order for forms to modify it,
      // since call_user_func_array() requires that referenced variables are
      // passed explicitly.
      $args = array_merge([$form, &$form_state], $args);

      $callback = [$form_state->getFormObject(), 'buildForm'];
      // Rebuild the form to apply new values.
      $form = call_user_func_array($callback, $args);

this seems to the trick and is in line with what core already does.

Remaining tasks

  1. Create Patch
  2. Review
  3. Commit
  4. Release

User interface changes

None

API changes

None

Data model changes

None

🐛 Bug report
Status

Active

Version

1.0

Component

Code

Created by

🇨🇭Switzerland das-peter

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

Merge Requests

Comments & Activities

Production build 0.71.5 2024