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
- Entity reference field to a vocabulary, widget "Simple hierarchical select".
- Create node, select a term, save.
- Edit: widget shows "- None -".
- 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.
| Comment | File | Size | Author |
|---|---|---|---|
| shs_preselect_stored_values.patch | 6.59 KB | carlitus |
Issue fork shs-3620147
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
Comment #2
greenskin commentedPatch applies and looks to work.
Comment #3
serverjohn commentedI am having the same issue as described. The patch resolves the issue.
Comment #6
malcomio commentedThanks 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
Comment #7
philltran commented@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.
Comment #8
joe huggansThe 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.
Comment #9
joco_sp commentedThe patch worked also for me on core 11.4.7 and shs on 2.0.7
Comment #10
bserem commentedI 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
Comment #13
sahal_va commentedMR !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 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:
The
phpunitjob isallow_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:
phpunit,phpcs, andcspellpass.eslintandphpstanfail, but they fail on2.0.xas well and are non-blocking, so they’re pre-existing.No new test was needed — the existing
testEditNodeWithDeletedTermalready 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.
Comment #14
liam morlandThe patch in merge request 59 fixes it for us.
Comment #15
kovalevm commentedPatch 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!