The Formatter Table of Fields from the Reference Table Formatter module creat warnings.

Created on 5 June 2023, over 1 year ago
Updated 11 October 2023, about 1 year ago

Problem/Motivation

With Drupal 9.5.9, Reference Table Formatter 8.x-1.2, Entity Reference Revisions 8.x-1.10, Paragraphs 8.x-1.15. For peoples account a form with a set of fields.
In manage display, uri admin/config/people/accounts/display, clicking the button in the Operations column to access the format settings, for the Table of Fields formatter from the Reference Table Formatter module, of a field of Entity Reference Revisions type on entities of paragraphs type, produce a lot of warning in the log, from the function copyFormValuesToEntity() of the file core/modules/field_ui/src/Form/EntityDisplayFormBase.php,

Warning : Undefined array key "field_courriel" dans Drupal\field_ui\Form\EntityDisplayFormBase->copyFormValuesToEntity() (RootFolder/web/core/modules/field_ui/src/Form/EntityDisplayFormBase.php ligne 594)

#0 RootFolder/web/core/includes/bootstrap.inc(347): _drupal_error_handler_real()
#1 RootFolder/web/core/modules/field_ui/src/Form/EntityDisplayFormBase.php(594): _drupal_error_handler()
#2 RootFolder/web/core/lib/Drupal/Core/Entity/EntityForm.php(293): Drupal\field_ui\Form\EntityDisplayFormBase->copyFormValuesToEntity()
#3 RootFolder/web/core/lib/Drupal/Core/Entity/EntityForm.php(170): Drupal\Core\Entity\EntityForm->buildEntity()
#4 [internal function]: Drupal\Core\Entity\EntityForm->afterBuild()
#5 RootFolder/web/core/lib/Drupal/Core/Form/FormBuilder.php(1083): call_user_func_array()
#6 RootFolder/web/core/lib/Drupal/Core/Form/FormBuilder.php(1075): Drupal\Core\Form\FormBuilder->doBuildForm()
#7 RootFolder/web/core/lib/Drupal/Core/Form/FormBuilder.php(1075): Drupal\Core\Form\FormBuilder->doBuildForm()
#8 RootFolder/web/core/lib/Drupal/Core/Form/FormBuilder.php(1075): Drupal\Core\Form\FormBuilder->doBuildForm()
#9 RootFolder/web/core/lib/Drupal/Core/Form/FormBuilder.php(1075): Drupal\Core\Form\FormBuilder->doBuildForm()
#10 RootFolder/web/core/lib/Drupal/Core/Form/FormBuilder.php(1075): Drupal\Core\Form\FormBuilder->doBuildForm()
#11 RootFolder/web/core/lib/Drupal/Core/Form/FormBuilder.php(449): Drupal\Core\Form\FormBuilder->doBuildForm()
#12 RootFolder/web/core/lib/Drupal/Core/Form/FormBuilder.php(633): Drupal\Core\Form\FormBuilder->rebuildForm()
#13 RootFolder/web/core/lib/Drupal/Core/Form/FormBuilder.php(325): Drupal\Core\Form\FormBuilder->processForm()
#14 RootFolder/web/core/lib/Drupal/Core/Controller/FormController.php(73): Drupal\Core\Form\FormBuilder->buildForm()
#15 [internal function]: Drupal\Core\Controller\FormController->getContentResult()
#16 RootFolder/web/core/lib/Drupal/Core/EventSubscriber/EarlyRenderingControllerWrapperSubscriber.php(123): call_user_func_array()
#17 RootFolder/web/core/lib/Drupal/Core/Render/Renderer.php(580): Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}()
#18 RootFolder/web/core/lib/Drupal/Core/EventSubscriber/EarlyRenderingControllerWrapperSubscriber.php(124): Drupal\Core\Render\Renderer->executeInRenderContext()
#19 RootFolder/web/core/lib/Drupal/Core/EventSubscriber/EarlyRenderingControllerWrapperSubscriber.php(97): Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->wrapControllerExecutionInRenderContext()
#20 RootFolder/vendor/symfony/http-kernel/HttpKernel.php(169): Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}()
#21 RootFolder/vendor/symfony/http-kernel/HttpKernel.php(81): Symfony\Component\HttpKernel\HttpKernel->handleRaw()
#22 RootFolder/web/core/lib/Drupal/Core/StackMiddleware/Session.php(58): Symfony\Component\HttpKernel\HttpKernel->handle()
#23 RootFolder/web/core/lib/Drupal/Core/StackMiddleware/KernelPreHandle.php(48): Drupal\Core\StackMiddleware\Session->handle()
#24 RootFolder/web/core/modules/page_cache/src/StackMiddleware/PageCache.php(106): Drupal\Core\StackMiddleware\KernelPreHandle->handle()
#25 RootFolder/web/core/modules/page_cache/src/StackMiddleware/PageCache.php(85): Drupal\page_cache\StackMiddleware\PageCache->pass()
#26 RootFolder/web/core/lib/Drupal/Core/StackMiddleware/ReverseProxyMiddleware.php(48): Drupal\page_cache\StackMiddleware\PageCache->handle()
#27 RootFolder/web/core/lib/Drupal/Core/StackMiddleware/NegotiationMiddleware.php(51): Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle()
#28 RootFolder/vendor/stack/builder/src/Stack/StackedHttpKernel.php(23): Drupal\Core\StackMiddleware\NegotiationMiddleware->handle()
#29 RootFolder/web/core/lib/Drupal/Core/DrupalKernel.php(718): Stack\StackedHttpKernel->handle()
#30 RootFolder/web/index.php(19): Drupal\Core\DrupalKernel->handle()
#31 {main}
Warning : Trying to access array offset on value of type null dans Drupal\field_ui\Form\EntityDisplayFormBase->copyFormValuesToEntity() (RootFolder/web/core/modules/field_ui/src/Form/EntityDisplayFormBase.php ligne 596)

#0 RootFolder/web/core/includes/bootstrap.inc(347): _drupal_error_handler_real()
#1 RootFolder/web/core/modules/field_ui/src/Form/EntityDisplayFormBase.php(596): _drupal_error_handler()
#2 RootFolder/web/core/lib/Drupal/Core/Entity/EntityForm.php(293): Drupal\field_ui\Form\EntityDisplayFormBase->copyFormValuesToEntity()
#3 RootFolder/web/core/lib/Drupal/Core/Entity/EntityForm.php(170): Drupal\Core\Entity\EntityForm->buildEntity()
#4 [internal function]: Drupal\Core\Entity\EntityForm->afterBuild()
#5 RootFolder/web/core/lib/Drupal/Core/Form/FormBuilder.php(1083): call_user_func_array()
#6 RootFolder/web/core/lib/Drupal/Core/Form/FormBuilder.php(1075): Drupal\Core\Form\FormBuilder->doBuildForm()
#7 RootFolder/web/core/lib/Drupal/Core/Form/FormBuilder.php(1075): Drupal\Core\Form\FormBuilder->doBuildForm()
#8 RootFolder/web/core/lib/Drupal/Core/Form/FormBuilder.php(1075): Drupal\Core\Form\FormBuilder->doBuildForm()
#9 RootFolder/web/core/lib/Drupal/Core/Form/FormBuilder.php(1075): Drupal\Core\Form\FormBuilder->doBuildForm()
#10 RootFolder/web/core/lib/Drupal/Core/Form/FormBuilder.php(1075): Drupal\Core\Form\FormBuilder->doBuildForm()
#11 RootFolder/web/core/lib/Drupal/Core/Form/FormBuilder.php(449): Drupal\Core\Form\FormBuilder->doBuildForm()
#12 RootFolder/web/core/lib/Drupal/Core/Form/FormBuilder.php(633): Drupal\Core\Form\FormBuilder->rebuildForm()
#13 RootFolder/web/core/lib/Drupal/Core/Form/FormBuilder.php(325): Drupal\Core\Form\FormBuilder->processForm()
#14 RootFolder/web/core/lib/Drupal/Core/Controller/FormController.php(73): Drupal\Core\Form\FormBuilder->buildForm()
#15 [internal function]: Drupal\Core\Controller\FormController->getContentResult()
#16 RootFolder/web/core/lib/Drupal/Core/EventSubscriber/EarlyRenderingControllerWrapperSubscriber.php(123): call_user_func_array()
#17 RootFolder/web/core/lib/Drupal/Core/Render/Renderer.php(580): Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}()
#18 RootFolder/web/core/lib/Drupal/Core/EventSubscriber/EarlyRenderingControllerWrapperSubscriber.php(124): Drupal\Core\Render\Renderer->executeInRenderContext()
#19 RootFolder/web/core/lib/Drupal/Core/EventSubscriber/EarlyRenderingControllerWrapperSubscriber.php(97): Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->wrapControllerExecutionInRenderContext()
#20 RootFolder/vendor/symfony/http-kernel/HttpKernel.php(169): Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}()
#21 RootFolder/vendor/symfony/http-kernel/HttpKernel.php(81): Symfony\Component\HttpKernel\HttpKernel->handleRaw()
#22 RootFolder/web/core/lib/Drupal/Core/StackMiddleware/Session.php(58): Symfony\Component\HttpKernel\HttpKernel->handle()
#23 RootFolder/web/core/lib/Drupal/Core/StackMiddleware/KernelPreHandle.php(48): Drupal\Core\StackMiddleware\Session->handle()
#24 RootFolder/web/core/modules/page_cache/src/StackMiddleware/PageCache.php(106): Drupal\Core\StackMiddleware\KernelPreHandle->handle()
#25 RootFolder/web/core/modules/page_cache/src/StackMiddleware/PageCache.php(85): Drupal\page_cache\StackMiddleware\PageCache->pass()
#26 RootFolder/web/core/lib/Drupal/Core/StackMiddleware/ReverseProxyMiddleware.php(48): Drupal\page_cache\StackMiddleware\PageCache->handle()
#27 RootFolder/web/core/lib/Drupal/Core/StackMiddleware/NegotiationMiddleware.php(51): Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle()
#28 RootFolder/vendor/stack/builder/src/Stack/StackedHttpKernel.php(23): Drupal\Core\StackMiddleware\NegotiationMiddleware->handle()
#29 RootFolder/web/core/lib/Drupal/Core/DrupalKernel.php(718): Stack\StackedHttpKernel->handle()
#30 RootFolder/web/index.php(19): Drupal\Core\DrupalKernel->handle()
#31 {main}

...
For one click, in our case, 97 warnings happen. Two series exist, and the total number is N = n0xm0 + n1x2m1 with (n0,m0;n1,m1) = (17,5;2,3) where ni are number of fields and mi number of lines with a warning. The first one is for fields, the second for extra. The corresponding lines are 594, 596, 611, 612, 613 for the first series and 624, 629, 630 for the second series. The function with line numbers,

584   protected function copyFormValuesToEntity(EntityInterface $entity, array $form, FormStateInterface $form_state) {
585     $form_values = $form_state->getValues();
586
587     if ($this->entity instanceof EntityWithPluginCollectionInterface) {
588       // Do not manually update values represented by plugin collections.
589       $form_values = array_diff_key($form_values, $this->entity->getPluginCollections());
590     }
591
592     // Collect data for 'regular' fields.
593     foreach ($form['#fields'] as $field_name) {
594       $values = $form_values['fields'][$field_name];
595
596       if ($values['region'] == 'hidden') {
597         $entity->removeComponent($field_name);
598       }
599       else {
600         $options = $entity->getComponent($field_name);
601
602         // Update field settings only if the submit handler told us to.
603         if ($form_state->get('plugin_settings_update') === $field_name) {
604           // Only store settings actually used by the selected plugin.
605           $default_settings = $this->pluginManager->getDefaultSettings($options['type']);
606           $options['settings'] = isset($values['settings_edit_form']['settings']) ? array_intersect_key($values['settings_edit_form']['settings'], $default_setting>
607           $options['third_party_settings'] = $values['settings_edit_form']['third_party_settings'] ?? [];
608           $form_state->set('plugin_settings_update', NULL);
609         }
610
611         $options['type'] = $values['type'];
612         $options['weight'] = $values['weight'];
613         $options['region'] = $values['region'];
614         // Only formatters have configurable label visibility.
615         if (isset($values['label'])) {
616           $options['label'] = $values['label'];
617         }
618         $entity->setComponent($field_name, $options);
619       }
620     }
621
622     // Collect data for 'extra' fields.
623     foreach ($form['#extra'] as $name) {
624       if ($form_values['fields'][$name]['region'] == 'hidden') {
625         $entity->removeComponent($name);
626       }
627       else {
628         $entity->setComponent($name, [
629           'weight' => $form_values['fields'][$name]['weight'],
630           'region' => $form_values['fields'][$name]['region'],
631         ]);
632       }
633     }
634   }

These problems occur in the same way with Drupal 10.1.0-beta1, Reference Table Formatter 2.0.0-alpha2, Entity Reference Revisions 8.x-1.10, Paragraphs 8.x-1.15.
The isset function could be a solution, but may be not a good solution. A deeper problem may exist.
We observe that all the fields producing an error are after the reference field (i.e. the field with the formatter) for the alphabetical order. And fields before produce no error. Moreover when the reference field appends a process is loaded which leads to the function where the warning are produced. Warnings seem append since some data are missing. And the data are missing since the process is loaded before all the fields have been processed.
Therefore a solution may be to disable the intermediary process for the reference field.
Investigations show that the parameter which controls the intermediary process is #after_build, with the line,
if (isset($element['#after_build']) && !isset($element['#after_build_done'])) {
in core/lib/Drupal/Core/Form/FormBuilder.php line 1081 in function doBuildForm(). And the presence of this key in the element/form comes from,
'settings' => $settings_form,
in modules/field_ui/src/Form/EntityDisplayFormBase.php line 398 in function buildFieldRow(), with the line 386,
$settings_form = $plugin->settingsForm($form, $form_state);
This settingsForm() function is the one of Reference Table Formatter module, file reference_table_formatter/src/FormatterBase.php line 82.

Steps to reproduce

Proposed resolution

A solution may be to neutralize the key #after_build from the function settingsForm() of the Reference Table Formatter module in the file reference_table_formatter/src/FormatterBase.php. With,

    if (isset($form['#after_build'])) {
      $form['#after_build'] = NULL;
    }

since then isset($element['#after_build']) is FALSE.
For module Reference Table Formatter 2.0.0-alpha2, the function settingsForm() is in another file,
reference_table_formatter/src/Plugin/Field/FieldFormatter/EntityReferenceTableFormatter.php.

Remaining tasks

User interface changes

API changes

Data model changes

Release notes snippet

🐛 Bug report
Status

Needs review

Version

1.2

Component

Code

Created by

🇫🇷France Chris64 France

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

Comments & Activities

Production build 0.71.5 2024