Resetting of override value impacting programmatic updates to webform entity

Created on 9 March 2023, almost 2 years ago
Updated 1 June 2023, over 1 year ago

Problem/Motivation

It appears the webform module code is resetting the value of the override property to TRUE on webform entities being loaded on an embedded parent entity page at some points in the saving process of a parent entity when the webform reference field is configured to OPEN. I don't know if this is intentional or not, but it is causing in certain instances to break expected functional behavior as I'll outline further. I may have tracked down related commits/issues. I will link them below.

In our use case. We are attempting to execute pretty straightforward programmatic changes to the webform entity loaded on a given parent entity after the parent content entity is saved. If the webform reference field on this node is set to OPEN, when saving the entity with the content_moderation workflow configured on the parent entity the below error is thrown on the page preventing the status of the parent entity from being saved successfully.

Drupal\Core\Entity\EntityStorageException: {WEBFORM-TITLE} has overridden settings and/or properties and can not be saved. in Drupal\Core\Entity\Sql\SqlContentEntityStorage->save() (line 815 of core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php).

This is easily reproducible with having a hook_entity_presave() in a custom module attempting to perform a basic title update to the webform being loaded on the page through a $webform->set('title', 'SAMPLE') operation and $webform->save() on the webform entity.
With the webform module code setting the override value to TRUE during the save process it is causing the $webform->save() to fail with the above error.

Steps to reproduce

1) Install drupal core minimal profile
2) Enable following modules: webform, field_ui, content_moderation
3) Configure a content type machine name say `webform_sample` with adding a `Webform Reference` field with machine name field_we.
4) Configure the default workflow for content moderation enabling it for the above created content entity type.
5) Create a node instance of the above entity type and save as draft.
6) Place the sample code block below in any enabled module code on the site.

/**
 * Implements hook_entity_presave().
 */
function nyun_webform_node_presave(EntityInterface $node) {
  if ($node->bundle() === 'webform_sample') {
    $webform = $node->field_we->entity;
    $webform->set('title', 'Sample me!');
    $webform->save();
  }
}

7) After all above steps visit the `/node/{ID}/latest` route for the above created node instance and attempt to use the moderation workflow form to update the status of the parent entity from draft to published. See above error outputted to the screen.

8) Notice while changing the value of the parent entity to published from the edit form located at `node/{ID}/edit` the save process completes successfully.

Proposed resolution

I'm unsure what the proposed resolution should be here. However I did discover the following two specific code blocks as being related to causing this error. When setting the setOverride(FALSE) in these two locations as seen below, the above error is no longer reproducible following the above functional steps.
1) https://git.drupalcode.org/project/webform/-/blame/6.2.x/src/WebformSubm...

2) https://git.drupalcode.org/project/webform/-/blame/6.2.x/src/Plugin/Fiel...

I've linked to the issues that had introduced these code blocks in the related issues. I hope with the easy reproducible steps above and this information it will be helpful in addressing this bug.

πŸ› Bug report
Status

Closed: won't fix

Version

6.2

Component

Code

Created by

πŸ‡ΊπŸ‡ΈUnited States hershy.k

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

Comments & Activities

  • Issue created by @hershy.k
  • πŸ‡ΊπŸ‡ΈUnited States hershy.k
  • πŸ‡ΊπŸ‡ΈUnited States hershy.k
  • Status changed to Needs work almost 2 years ago
  • πŸ‡ΊπŸ‡ΈUnited States hershy.k
  • πŸ‡ΊπŸ‡ΈUnited States hershy.k
  • πŸ‡ΊπŸ‡ΈUnited States hershy.k
  • πŸ‡ΊπŸ‡ΈUnited States hershy.k
  • πŸ‡ΊπŸ‡ΈUnited States hershy.k
  • πŸ‡ΊπŸ‡ΈUnited States sker101 NYC

    In my opinion, the code located at line 81 of docroot/modules/contrib/webform/src/Plugin/Field/FieldFormatter/WebformEntityReferenceFormatterBase.php is likely causing custom modules to encounter issues when attempting to save the webform entity.

    if (isset($item->open) || isset($item->close) || isset($item->status)) {
      $entity->setOverride();
    }
    

    To elaborate, this code ensures that the render cache of the referenced entity can be cached by providing constant values for certain fields from the entity reference item. Additionally, setting the override to TRUE prevents the status of the main webform from being affected by the value of the entity reference item.

    Therefore, for custom modules, resetting setOverride() to FALSE should be safe during a "hook_entity_node_presave" or "hook_entity_save" hook, provided they can handle the reversion of the status value appropriately.

  • Status changed to Closed: won't fix over 1 year ago
  • πŸ‡ΊπŸ‡ΈUnited States jrockowitz Brooklyn, NY

    I am going to recommend you use \Drupal\webform\Entity\Webform::resetSettings to allow the webform to be saved programmatically.

    /**
     * Implements hook_entity_presave().
     */
    function nyun_webform_node_presave(EntityInterface $node) {
      if ($node->bundle() === 'webform_sample') {
        $webform = $node->field_we->entity;
        $webform->set('title', 'Sample me!');
        $webform->resetSettings();
        $webform->save();
      }
    }
    
  • πŸ‡ΊπŸ‡ΈUnited States hershy.k

    @jrockowitz - perhaps this should be documented somewhere in webform's cookbook for developers?

  • πŸ‡ΊπŸ‡ΈUnited States jrockowitz Brooklyn, NY

    @hershey.k It can be documented in the cookbook. The key thing to explain is you only need to call $webform->resetSettings(); if you are getting the webform entity directly from a webform field. This feels like an edge case.

Production build 0.71.5 2024