Loss of stored data when multiple profiles are displayed as a form on account form

Created on 14 October 2022, about 2 years ago
Updated 26 April 2024, 7 months ago

Problem

When multiple profiles per user are allowed, and the profile form is displayed on the user account form, the first profile is displayed multiple times and any changes made overwrite the data from the first profile, causing a loss of stored data.

Steps to reproduce

- Define a Profile Type (let's call it "Pet") with text field "Name"
- Select the option to "Allow multiple profiles per user"
- Under Configuration / People / Account Settings / Manage form display, enable the display of "Pet Profiles" and set the widget to "Profile Form".
- Add two Pet profiles to a particular user, say "Rover" and "Killer".
- Edit that user. Notice that 3 profile forms are displayed, all with "Rover". Change the third one to "Frank".
- Observe that Rover is now Frank and Killer is unchanged.

Proposed resolution

I believe the root of this problem is that the form state contains an array of profiles, indexed by profile type. Thus only the data from one profile of a given type is stored.

Remaining tasks

Fix the bug.

User interface changes

None

API changes

Unknown. The internal structure of the profiles in the form state may need to change.

Data model changes

None.

I reluctantly assigned the Priority of Critical because this bug causes a loss of stored data when the form is submitted. It can be reasonably argued that the circumstances that are needed to exhibit the bug are sufficiently uncommon that a lower priority such as major is appropriate.

🐛 Bug report
Status

Fixed

Version

1.0

Component

Code

Created by

🇺🇸United States DanChadwick

Live updates comments and jobs are added and updated live.
  • API change

    Changes an existing API or subsystem. Not backportable to earlier major versions, unless absolutely required to fix a critical bug.

Sign in to follow issues

Merge Requests

Comments & Activities

Not all content is available!

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

  • 🇺🇦Ukraine tbkot

    The patch from #2 is almost working for me. The issue I'm facing after applying it is that whenever we edit user info and save changes a new empty profile is created. So I added a condition to remove empty profiles from the form state, it works only for new items.

  • 🇺🇸United States DanChadwick

    Neither #2 nor #3 apply to 1.8. In reviewing #3, I feel this is a distinct issue -- should new empty profiles be saved? This applies both to single and multiple profile entity references. I suggest @tBKoT create a new issue. First question is do you simply not save new empty profiles, or do you delete existing profiles which became empty. I would advocate the latter, but this is a change in behavior. This could be accomplished with something like:

          $empty_profile = $this->entityTypeManager->getStorage('profile')->create(['type' => $profile_type]);
          $profiles = array_filter($profiles, fn (ProfileInterface $profile) => $profile->equalToProfile($empty_profile));
    <code>
    This could be placed in <code>extractFormValues

    , but might be better in saveProfiles.

    Since patch-based testing is being discontinued, I will open an issue fork for a re-roll of #2.

  • Status changed to Needs work 9 months ago
  • Status changed to Needs review 9 months ago
  • Open in Jenkins → Open on Drupal.org →
    Core: 9.5.x + Environment: PHP 7.3 & MySQL 5.7
    last update 9 months ago
    PHPLint Failed
  • 🇺🇸United States DanChadwick

    Reroll of #2, leaving the empty profile changes of #3 to a to-be-created separate issue. Patch for convenience of composer workflow.

  • Open in Jenkins → Open on Drupal.org →
    Core: 9.5.x + Environment: PHP 7.3 & MySQL 5.7
    last update 9 months ago
    PHPLint Failed
  • Open in Jenkins → Open on Drupal.org →
    Core: 10.2.x + Environment: PHP 7.4 & MySQL 5.7
    last update 9 months ago
    Composer require failure
  • 🇺🇸United States DanChadwick

    Catch 22. Drupal 9 support ended November 1st. The latest version of Drupal 9 required PHP 7.4, which includes support for arrow functions, which I used in this patch. But I cannot start a test with PHP 7.4 without using Drupal 10, which requires a composer.json file. So either I need to remove the arrow function just to make the linting pass, or we need to make profile be Drupal 10 testing compatible.

    • jsacksick committed 8cb44eb1 on 8.x-1.x
      Issue #3315270 by DanChadwick, tBKoT: Loss of stored data when multiple...
  • Status changed to Fixed 8 months ago
  • 🇮🇱Israel jsacksick

    I committed your patch. If you're in the mood for writing a change record, that'd be great... Added the following note to the release notes for now:

    As part of #3315270, the storage of the profiles in the form state changed from an array of profiles indexed by profile type to an associative array (indexed by profile type) of arrays (indexed by delta) of profiles.

  • 🇺🇸United States DanChadwick

    Draft change record created.

  • 🇦🇹Austria drupalfan2

    After upgrading from profile 1.8 to 1.9 I get this error message:

    Error: Class "Drupal\profile\ProfileType" not found in Drupal\profile\ProfileListBuilder->getDefaultOperations() (line 120 of modules/contrib/profile/src/ProfileListBuilder.php).
    Drupal\Core\Entity\EntityListBuilder->getOperations() (Line: 212)
    Drupal\Core\Entity\EntityListBuilder->buildOperations() (Line: 194)
    Drupal\Core\Entity\EntityListBuilder->buildRow() (Line: 112)
    Drupal\profile\ProfileListBuilder->buildRow() (Line: 242)
    Drupal\Core\Entity\EntityListBuilder->render() (Line: 23)
    Drupal\Core\Entity\Controller\EntityListController->listing()
    call_user_func_array() (Line: 123)
    Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}() (Line: 627)
    Drupal\Core\Render\Renderer->executeInRenderContext() (Line: 121)
    Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->wrapControllerExecutionInRenderContext() (Line: 97)
    Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}() (Line: 181)
    Symfony\Component\HttpKernel\HttpKernel->handleRaw() (Line: 76)
    Symfony\Component\HttpKernel\HttpKernel->handle() (Line: 58)
    Drupal\Core\StackMiddleware\Session->handle() (Line: 48)
    Drupal\Core\StackMiddleware\KernelPreHandle->handle() (Line: 28)
    Drupal\Core\StackMiddleware\ContentLength->handle() (Line: 32)
    Drupal\big_pipe\StackMiddleware\ContentLength->handle() (Line: 106)
    Drupal\page_cache\StackMiddleware\PageCache->pass() (Line: 85)
    Drupal\page_cache\StackMiddleware\PageCache->handle() (Line: 48)
    Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle() (Line: 51)
    Drupal\Core\StackMiddleware\NegotiationMiddleware->handle() (Line: 36)
    Drupal\Core\StackMiddleware\AjaxPageState->handle() (Line: 51)
    Drupal\Core\StackMiddleware\StackedHttpKernel->handle() (Line: 704)
    Drupal\Core\DrupalKernel->handle() (Line: 19)

    Same problem with profile 1.10.

    I do not allow multiple profiles per user, "Allow multiple profiles per user" is off.

    And patch #16 of https://www.drupal.org/project/profile/issues/2599014 📌 Create the revision UI for profiles Needs review does not apply anymore.

    I need a solution to get profile 1.9 and 1.10 running.

  • 🇦🇹Austria drupalfan2

    #12 is solved here: https://www.drupal.org/project/profile/issues/3437825 🐛 Error: Class "Drupal\profile\ProfileType" not found Closed: cannot reproduce

  • 🇮🇱Israel jsacksick

    @DanChadwick: Where is the change record?

  • 🇺🇸United States DanChadwick

    @jsacksick: Scroll up. It should be in the right sidebar at the bottom. Unless only I see it? I think a maintainer has to publish it, maybe?
    https://www.drupal.org/node/3432547

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

Production build 0.71.5 2024