[5.x]: Block added through a draft gets an empty first revision on multi-site, so reverting deletes its nested content
I maintainer di solito rispondono entro 1 giorno
Nessuno ha ancora preso questa issue.
Valutazione
- Difficoltà
- 4/5
- Tempo stimato
- 3-5 giorni
- Idoneità per principianti
- 45/100
Direzione di ricerca
Start by tracing NestedElementManager::duplicateNestedElements() through Elements::duplicateElement() and the propagation saves described in the report. Then read Entry::beforeSave() and Revisions::createRevision() to follow when the initial revision is created and reused. Reproduce the multi-site setup and confirm the fix by checking that revision 2 retains the nested entry after reverting.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
What happened?
Description
On a multi-site install, when a new nested entry is added to a versioned Matrix field through a draft (any edit of a live entry), Craft saves that nested entry's first revision before its own nested entries are copied. The owner's revision reuses that empty revision, and so does every later owner revision until the nested entry changes. Reverting the owner to any of those revisions deletes the nested content from the canonical entry.
Reproduced on a fresh craftcms/craft project (Craft 5.11.5.1, no plugins, no modules) with:
- 2 sites in one group.
- Channel section "Pages", versioning on, propagation "All sites", enabled for both sites.
- Entry type
page: title + Matrix fieldblocks(view mode "Cards", "Enable versioning for entries in this field" on, propagation "All sites"), entry typeblock. - Entry type
block: title + Matrix fieldinnerBlocks(view mode "Blocks", versioning off, propagation "All sites"), entry typechild. - Entry type
child: title + Plain Text fieldbody.
The same steps in a section enabled for one site only don't reproduce it: the block's revision is then created after its inner entry and is complete.
What happens on save, traced with a backtrace on Revisions::EVENT_BEFORE_CREATE_REVISION:
- Saving the live entry applies its provisional draft.
NestedElementManager::duplicateNestedElements()copies the new block (owned by the draft) withduplicateElement()(NestedElementManager.php:1164), passing'propagating' => falsein$newAttributes(NestedElementManager.php:1104). Elements::duplicateElement()saves the block for the first site, then clones it for each other site and sets$siteClone->propagating = true(Elements.php:2046), butCraft::configure($siteClone, $newAttributes)(Elements.php:2072) sets it back tofalse.- So the second site's save (
Elements.php:2102) is a non-propagating save of an existing entry with no revisions.Entry::beforeSave()("Make sure the entry has at least one revision",Entry.php:2934) creates a revision from the DB, while the block exists in one site only and has no nested entries yet. The revision note is "Revision from {date}". - The block's nested entries are copied afterwards, in
afterPropagate(). The next revision request for the block (fromEntry::afterPropagate(), then from the owner's revision) is short-circuited inRevisions::createRevision()(Revisions.php:109): the block'sdateUpdatedequals the empty revision'sdateCreated, so the empty revision is returned and reused.
Element IDs on the fresh install show the order:
| ID | Element |
|---|---|
| #15 | new block "Block B" (canonical) |
| #16 | its revision, note "Revision from Oct 28, 2026, 3:11:48 PM PDT", no inner entry |
| #17 | its inner child entry "Child B" |
| #18 | owner revision 2 ("Applied “Draft 1”"), which owns #16 |
After "Revert content from this revision" on revision 2, #17 is soft-deleted and the live block #15 has no inner entry.
We also tested the fix for #19594 (commit 53cba141) on 5.11.5.1: it doesn't change this. The nested entry's owners get their dateUpdated bumped, but to the same second, and the comparison uses the in-memory block.
Workaround (verified on our own project): turning off "Enable versioning for entries in this field" on the outer Matrix field. Blocks then get no revision of their own, and the owner revision snapshots them after their nested entries exist.
Steps to reproduce
- On a multi-site install, set up the section and fields above.
- Create a page with one block ("Block A", with an inner entry with some body text) and save it. Revision 1 is complete.
- Edit the live page, add a second block ("Block B"), add its inner entry with some body text, save the block's slideout, then save the page (revision 2).
- View revision 2: "Block B" has no inner entry.
- Revert to revision 2 ("Revert content from this revision").
Expected behavior
Revision 2 contains "Block B" with its inner entry, and reverting to it keeps that content.
Actual behavior
Revision 2's copy of "Block B" has no inner entry, and reverting to it deletes the inner entry (and its body text) from the live page.
Craft CMS version
5.11.5.1 (Pro, trial)
PHP version
8.5.11
Operating system and version
Linux (Docker, Alpine 3.24.2)
Database type and version
MySQL 8.4
Image driver and version
Imagick 3.8.1 (ImageMagick 7.1.2-30)
Installed plugins and versions
None (fresh craftcms/craft project)
- Lingua principale
- PHP
- Stelle
- 3.6k
- Fork
- 710
- Merge medio
- 12h 19m
- PR unite (30g)
- 293
Preparare l'ambiente
- Nessun Dockerfile né file Docker Compose
- Nessun modello di pull request
- Leggi la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di craftcms/cms
-
[5.x]: Moving an asset with “Replace it” throws TypeError: volumeUid must be of type string, null givenForse già presa @i-just l’ha presa 1 giorno fa. Apertabug repo:cms
Difficoltà 2/5 1-3 ore Idoneità per principianti 72/100
craftcms/cms#20128 · 2 commenti · 1 assegnatario ·
I maintainer di solito rispondono entro 1 giorno
-
bug repo:cms
Difficoltà 5/5 Più di una settimana Idoneità per principianti 25/100
craftcms/cms#20150 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
-
bug repo:cms
Difficoltà 3/5 1-2 giorni Idoneità per principianti 57/100
craftcms/cms#20143 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
-
bug repo:cms
Difficoltà 3/5 1-2 giorni Idoneità per principianti 56/100
craftcms/cms#20142 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
-
bug
Difficoltà 3/5 1-2 giorni Idoneità per principianti 55/100
craftcms/cms#20141 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
Tutte le issue di craftcms/cms
Issue simili
-
ServiceMapMissingAnalyser reads @method in docblock prose as a tag and reports a phantom accessorApertaagent-ready area:static-analysis bug p3
Difficoltà 2/5 1-3 ore Idoneità per principianti 82/100
gacela-project/gacela#1050 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 68/100
grokability/massdriver-server#38 ·
I maintainer di solito rispondono entro 1 giorno
-
bug review needed
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 86/100
OpenMage/magento-lts#5816 ·
I maintainer di solito rispondono entro 2 giorni
-
priority:low type:docs
Difficoltà 2/5 1-3 ore Idoneità per principianti 84/100
crazy-goat/rabbit-stream#958 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 72/100
pterodactyl/panel#7310 ·
I maintainer di solito rispondono entro 1 giorno