Existing Contact can have validation error when filtered by group

Created on 13 December 2021, about 3 years ago
Updated 3 December 2023, about 1 year ago

1.0 Problem/Motivation
When validating a webform submission server-side, the presence of an "Existing Contact" widget causes a WSOD.

2.0 Detailed steps to reproduce (embed screenshots)
I've attached the YAML, but it case it doesn't work:
* Create a new webform.
* Enable CiviCRM integration, add a field of type "Existing Contact".
* Configure the field to use an auto-complete widget, and filtered by a group.
* Add any field (I used number) and add validation that is done server-side (I chose "unique").
* Submit the form, filling in the number. It's the first submission, validation passes, no error.
* Make a second submission, using the same number.

At this point, the server validation will fail the submission, but will crash with a WSOD in Drupal\Core\Form\FormErrorHandler->setElementErrorsFromFormState().

3.0 Proposed resolution
The bug happens when running this line of code, which references $child['#group'].

It's very closely related to https://github.com/colemanw/webform_civicrm/pull/619 - same bug, bug more serious and in a different place.

🐛 Bug report
Status

Needs review

Version

6.0

Component

CiviCRM Data Handling

Created by

🇺🇸United States MegaphoneJon

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

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

  • 🇨🇦Canada ShaneOnABike

    Hey folks,

    This is still an issue actually. I had a heck of a time trying to figure out where the stacktrace issue was coming from. Is there any reason we can't use a different variable than group. I think it's a useful function but presently I can't use it for a client because of this issue.

    Warning: explode() expects parameter 2 to be string, array given in Drupal\Core\Form\FormErrorHandler->setElementErrorsFromFormState()

  • 🇨🇦Canada adixon

    Confirmed for a D9 + php8.1 install.

    For my example, there are a number of "existing contact" fields, some of which are filtered by group, and it appears that the ones that break are those that are not filtered by group (but maybe that's because that's as far as it gets ...).

    I also notice that the group looks like this:

    [#group] => Array
    (
    [] =>
    )

    The code is actually happy to skip the field if it's empty, but that's an array with a single empty entry, so the array itself isn't empty.

    Conclusions:
    1. It might work to just slightly fix how that #group value is being generated, and remove any empty group.
    2. In the meantime, you can just patch your drupal core with something like this:

    diff --git web/core/lib/Drupal/Core/Form/FormErrorHandler.php web/core/lib/Drupal/Core/Form/FormErrorHandler.php
    index dfb52c072e..eabda5c87e 100644
    --- web/core/lib/Drupal/Core/Form/FormErrorHandler.php
    +++ web/core/lib/Drupal/Core/Form/FormErrorHandler.php
    @@ -147,7 +147,7 @@ protected function setElementErrorsFromFormState(array &$form, FormStateInterfac
     
             // If this direct child belongs to a group populate the grouping element
             // with the children errors.
    -        if (!empty($child['#group'])) {
    +        if (!empty($child['#group']) && is_string($child['#group'])) {
               $parents = explode('][', $child['#group']);
               $group_element = NestedArray::getValue($form, $parents);
               if (isset($group_element['#children_errors'])) {
    
  • 🇨🇦Canada ShaneOnABike

    @adixon Actually in my case it really had to do with the group being set.

    We have a webform like the following

    + Existing Contact - Contact name
    + Existing Contact Household - Contact name filtered by Group

    If I set this as empty it's just fine, and when I traced it it seems like the #group is a reserved name used already thus causing this error. Maybe I'm wrong here though.

  • 🇨🇦Canada adixon

    For sure, the source of the issue is that '#group' is used for the drupal group concept, and there's validation that assumes it's a string.

    My patch might work for you, in that by the time the form gets to that level of validation, it probably doesn't need to care about #group.

    On the other hand, your experience suggests that fixing this might be trickier than I thought or hoped.

    Ultimately, the '#group' property that webform civicrm uses really needs a different key so that we're not colliding with the drupal '#group'.

    I believe there's some work being done in that direction.

  • Status changed to Needs review about 1 year ago
  • 🇮🇳India jitendrapurohit

    I've raised a PR here https://github.com/colemanw/webform_civicrm/pull/928

    Can we please test this in detail with drush updb execution on existing webforms?

    Thanks.

  • 🇬🇧United Kingdom chumkui

    Oh how I wish I had found this a few days ago... I spent hours trying to track it down and I thought it was to do with a Webform Validation Handler I had written. https://civicrm.stackexchange.com/questions/48120/custom-webform-handler....

    It makes no difference whether the filter uses Autocomplete - we pass in Contact IDs and its static at the beggining, it is purely the #group, even 'None'.

Production build 0.71.5 2024