Problem/Motivation
Instance caches its normalized tree in $sourceTree, and nothing clears it when the entity is cloned or saved.
getTranslation()clones the entity, and the clone keeps the same tree object. Once the default translation has read its tree, a translation reads the default language's nodes, and its mutators save them. Reproduced: EN holds "Hello, World" and DE "Hallo, Welt". After a read on EN, DEgetNode()answers "World", and a DEsetSource()stores DE as "Hallo2, World". "Welt" is lost.- Saving changes the sources behind the tree: UI Patterns adds node IDs to props, and the synchronized field cascades a structural change to every translation. The duplicate check of
setNewPresent()then compares a stale tree with a fresh hash, and misses. Moving a node to where it already is, or setting an unchanged value, adds an undo step.
The builder UI mostly escapes both: it loads the instance per request, and InstanceTranslationSubscriber switches translation before anything reads the tree. Code calling InstanceInterface several times in a row does not, display_builder_ai for one.
Proposed resolution
Drop the cached tree in Instance::__clone(), and in postSave() for every translation. Clearing it on the saved object alone is not enough: the default translation then drops a node its translation just added. Kernel tests for the three cases.
Found while reviewing #3624396: Plan: Harden InstanceInterface, IslandInterface and DisplayBuildableInterface as public API before RC1.
Issue fork display_builder-3626658
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 #4
mogtofu33 commented