Problem/Motivation

Since 2.0.4 the widget never preselects stored values. Edit forms show "- None -", and the next save wipes the value.

#3517342: Widget loads references that it never uses, causing increased memory usage made getOptions() return an empty array, assuming the options are never used. They are: OptionsSelectWidget::formElement() sets '#default_value' => $this->getSelectedOptions($items), and OptionsWidgetBase::getSelectedOptions() filters stored values against that list. Empty list, nothing matches, no default value.

Affects 2.0.4 - 2.0.7. Not 2.0.3, not 3.0.x.

Same bug as #17 in #3613802-17: Empty widget output after updating to 2.0.6 (that issue is otherwise about the D10 getBundleListCacheTags() fatal).

Steps to reproduce

  1. Entity reference field to a vocabulary, widget "Simple hierarchical select".
  2. Create node, select a term, save.
  3. Edit: widget shows "- None -".
  4. Save: value gone.

Proposed resolution

Override getSelectedOptions() to return the stored values unfiltered. The #3517342 optimisation stays intact - the option list is still never loaded.

Patch attached with a kernel test. Drupal 11.4.5 / PHP 8.3, shs 2.0.7, phpcs clean.

Remaining tasks

Implement.

User interface changes

None.

API changes

None.

Data model changes

None.

CommentFileSizeAuthor
shs_preselect_stored_values.patch6.59 KBcarlitus

Issue fork shs-3620147

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

carlitus created an issue. See original summary.

greenskin’s picture

Priority: Normal » Critical

Patch applies and looks to work.

serverjohn’s picture

I am having the same issue as described. The patch resolves the issue.

malcomio made their first commit to this issue’s fork.

malcomio’s picture

Thanks for the patch - it does seem to address the issue, from my initial tests.

Not aware of the history on #3517342: Widget loads references that it never uses, causing increased memory usage

Patches are now deprecated on drupal.org, see Creating merge requests instead.

I've taken the patch and put it into https://git.drupalcode.org/project/shs/-/merge_requests/58

philltran’s picture

Status: Needs review » Reviewed & tested by the community

@malcomio Thanks for filing MR!58

Confirming the patch worked on four Drupal 10.6.16 / PHP 8.3 sites.

I believe this issue is 2.0.7 only, not 2.0.4 - 2.0.7.

The empty `getOptions()` from #3517342 has been there since 2.0.4, but shs also carried its own `getSelectedOptions()` override returning the stored `target_id`s unfiltered. The override is present in 2.0.3, 2.0.4, 2.0.5 and 2.0.6, and absent only in 2.0.7.

This caused a silent data loss in addition to a display problem. The widget renders "- None -", and the next save writes an empty value and deletes the stored term. On our site every product save erased its category tag causing products to lose their taxonomy references.

joe huggans’s picture

The patch also worked for me Drupal 11.4.7

Thank you @philltran for confirming this issue only arose in version 2.0.7, that is very helpful for when I need to advise my client.

joco_sp’s picture

The patch worked also for me on core 11.4.7 and shs on 2.0.7

bserem’s picture

I am bumping this as it causes data-loss from the DB using 2.0.7

If you got revisions enabled you can get the data back from a revision.

The patch works

sahal_va made their first commit to this issue’s fork.

sahal_va’s picture

Status: Reviewed & tested by the community » Needs review

MR !59 is based on !58 and keeps its fix, while also preserving the behaviour from #3359851.

!58 brings #3359851 back

!58 returns the stored values unfiltered. When a referenced term has been deleted, the stale ID is preselected, and the entity reference constraint then rejects the save:

The referenced entity (taxonomy_term: X) does not exist.

The entity can no longer be saved at all, and there’s no way to clear the value through the UI — arguably worse than the empty widget. That’s exactly what #3359851 removed this override to fix.

It shows in !58’s own pipeline, which is red:

Drupal\Tests\shs\Functional\ShsTermTest 4 passed, 1 failed Fail testEditNodeWithDeletedTerm Behat\Mink\Exception\ResponseTextException: The text "... has been updated." was not found anywhere in the text of the current page.

The phpunit job is allow_failure: false, so this blocks. The manual confirmations above wouldn’t catch it, because the symptom only appears on content referencing a deleted term. On our site, 10 of 50 affected nodes are in that state.

!59 fixes it

!59 drops values whose target no longer exists, resolved with a single entity query — so no referenced entities are loaded, and the memory saving from #3517342 is preserved.

Its pipeline is green:

Drupal\Tests\shs\Kernel\OptionsShsWidgetDefaultValueTest 4 passed Drupal\Tests\shs\Functional\ShsTermTest 5 passed Pass testEditNodeWithDeletedTerm

phpunit, phpcs, and cspell pass. eslint and phpstan fail, but they fail on 2.0.x as well and are non-blocking, so they’re pre-existing.

No new test was needed — the existing testEditNodeWithDeletedTerm already covers the regression.

Verified on Drupal 11.4.8 / shs 2.0.7: valid terms preselect, stale references are dropped, mixed live/dead preserves order, and a node holding a stale reference saves and clears.

Credit to @carlitus for the diagnosis and test, and @malcomio for !58.

liam morland’s picture

Issue summary: View changes

The patch in merge request 59 fixes it for us.

kovalevm’s picture

Patch 59 didn't help me; there is no option to select the value. Only version 2.0.5 works. Please fix this in the official release!