Skip to content

[6.x] Fix deleted terms reappearing after clearing the Stache - #15426

Open
duncanmcclean wants to merge 5 commits into
6.xfrom
sync-term-originals
Open

duncanmcclean wants to merge 5 commits into
6.xfrom
sync-term-originals

Conversation

@duncanmcclean

@duncanmcclean duncanmcclean commented Sep 8, 2026

Copy link
Copy Markdown
Member

Deleting a taxonomy term left its slug behind in any entries referencing it, so the term reappeared as a "ghost" the next time the Stache was rebuilt.

UpdateTermReferences is what strips the slug from entries, but it bails when $term->getOriginal('slug') is empty — so the delete silently did nothing, and the leftover reference regenerated the term.

The original state was empty because TaxonomyTermsStore overrides BasicStore::getItem (to support terms which only exist in entry data), and #5502 removed the syncOriginal() that used to live in makeItemFromFile. Every other store still gets it from BasicStore.

This syncs the original state when a term is hydrated, before it's cached. The cache-hit branch backfills too, since items are cached with forever() and terms cached by an older version would otherwise never get one — but only when it's missing. Syncing unconditionally there mutates the shared cached instance, and both TaxonomyTermsStore::save() and Term::save() re-enter getItem() mid-save, which would reset the original and break renaming.

Fixes #11264
Caused by #5502
Related: #11058

duncanmcclean and others added 5 commits September 8, 2026 12:51
`TaxonomyTermsStore::getItem` overrides `BasicStore::getItem` without syncing the term's original state, so `UpdateTermReferences` saw a null original slug on deletion and left the term's references in entries.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XzL1xhLTSn6kRxAi7UTcm8
Syncing on every getItem() mutated the shared cached instance, which
clobbered pending changes mid-save: TaxonomyTermsStore::save() looks up
the old term to delete its file, and Term::save() looks the term up for
its isNew check, both of which re-entered getItem() and reset the
original. Renaming a term retrieved from the Stache stopped updating
entry references, and isDirty() was false inside TermSaving.

Sync in makeItemFromFile() instead, restoring what #5502 removed, and
once more on the term built in getItem() before it's cached.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Cache items are written with forever(), so terms cached by a version
that didn't sync their original state persist across an upgrade and
come back through the cache hit branch without one. Sync those, but
only when it's missing, so a term already in the middle of being saved
keeps the original state its pending changes are measured against.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
getItem() already syncs every term it builds, and terms cached in bulk
by paths() get their original state backfilled when they're read, so
this was only ever duplicating work.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Ghost Taxonomies / Deleted Taxonomy not always deleting associations from entry

2 participants