Hacktoberfest 2026: le issue che i maintainer hanno segnato per ottobre, aperte e adatte ai principianti. Sfoglia le issue Hacktoberfest

[5.x]: Block added through a draft gets an empty first revision on multi-site, so reverting deletes its nested content

Aperta
#20,151 1 commento 0 reazioni 0 assegnatari Vedi su GitHub

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
Tipo di issue
Bug
Chiarezza
Specificata chiaramente
Stato di attività
Attiva
Stack tecnologico
php
Ambito
backend, databases

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

bug repo:cms
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 field blocks (view mode "Cards", "Enable versioning for entries in this field" on, propagation "All sites"), entry type block.
  • Entry type block: title + Matrix field innerBlocks (view mode "Blocks", versioning off, propagation "All sites"), entry type child.
  • Entry type child: title + Plain Text field body.

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:

  1. Saving the live entry applies its provisional draft. NestedElementManager::duplicateNestedElements() copies the new block (owned by the draft) with duplicateElement() (NestedElementManager.php:1164), passing 'propagating' => false in $newAttributes (NestedElementManager.php:1104).
  2. Elements::duplicateElement() saves the block for the first site, then clones it for each other site and sets $siteClone->propagating = true (Elements.php:2046), but Craft::configure($siteClone, $newAttributes) (Elements.php:2072) sets it back to false.
  3. 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}".
  4. The block's nested entries are copied afterwards, in afterPropagate(). The next revision request for the block (from Entry::afterPropagate(), then from the owner's revision) is short-circuited in Revisions::createRevision() (Revisions.php:109): the block's dateUpdated equals the empty revision's dateCreated, 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
  1. On a multi-site install, set up the section and fields above.
  2. Create a page with one block ("Block A", with an inner entry with some body text) and save it. Revision 1 is complete.
  3. 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).
  4. View revision 2: "Block B" has no inner entry.
  5. 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

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di craftcms/cms

Tutte le issue di craftcms/cms

Issue simili

Altre issue su PHP

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.