What happened?
Description
If a Structure section is converted to a Channel and then back again to a Structure, and this change (i.e. the section's structureId now pointing to a new structure) is later applied via project config in an environment where the section is still related to its original structure, Craft will neglect to (soft-)delete that original structure in the structures table.
I came across this when some entry queries started to return duplicate entries for a particular section (let's call this section sectionA). Specifically, any query that queried for entries in multiple sections like
{% set entries = craft.entries.section(['sectionA', 'sectionB']).all() %}
The culprit turned out to be the fact that entries in sectionA created prior to the section having its structureId changed via project config as per the above described scenario, now had multiple rows in the structureelements table that were related to multiple, non-soft-deleted rows in the structures table. Manually adding a value to the original structure's dateDeleted column in the structures table fixed the issue, confirming it as the cause for the duplicate entries being returned.
(BTW: Before figuring this out I tried running craft utils/repair/section-structure on the affected section; that did nothing in this case, but that's probably expected?).
Steps to reproduce
I'm able to reliably reproduce the issue with a clean Craft 5 install by following these steps:
- Create a Structure section (
sectionA), and another section (sectionB; type doesn't matter)
- Create an entry in both sections
- Export a database dump
- Convert the
sectionA Structure section to a Channel – then back to a Structure
- Import the database dump (the Structure section will now be back to it's original
structureId)
- Run
craft project-config/apply
- Execute a query like
craft.entries.section(['sectionA', 'sectionB']).all() and confirm that the entry from sectionA is returned twice
- Add a value to the original structure's
dateDeleted column in the structures table
- Re-run the query and confirm that the entry is no longer returned as a duplicate
Expected behavior
If an existing section becomes related to a new structure in the structures table, Craft should make sure that any existing structures for that section are (soft)deleted.
Actual behavior
Existing structures aren't soft-deleted if the section's structureId is updated via project config.
Craft CMS version
5.5.10
PHP version
8.3.14
Operating system and version
macOS; DDEV v1.24.1
Database type and version
MySQL 8.0.36
Image driver and version
No response
Installed plugins and versions
None
What happened?
Description
If a Structure section is converted to a Channel and then back again to a Structure, and this change (i.e. the section's
structureIdnow pointing to a new structure) is later applied via project config in an environment where the section is still related to its original structure, Craft will neglect to (soft-)delete that original structure in thestructurestable.I came across this when some entry queries started to return duplicate entries for a particular section (let's call this section
sectionA). Specifically, any query that queried for entries in multiple sections like{% set entries = craft.entries.section(['sectionA', 'sectionB']).all() %}The culprit turned out to be the fact that entries in
sectionAcreated prior to the section having itsstructureIdchanged via project config as per the above described scenario, now had multiple rows in thestructureelementstable that were related to multiple, non-soft-deleted rows in thestructurestable. Manually adding a value to the original structure'sdateDeletedcolumn in thestructurestable fixed the issue, confirming it as the cause for the duplicate entries being returned.(BTW: Before figuring this out I tried running
craft utils/repair/section-structureon the affected section; that did nothing in this case, but that's probably expected?).Steps to reproduce
I'm able to reliably reproduce the issue with a clean Craft 5 install by following these steps:
sectionA), and another section (sectionB; type doesn't matter)sectionAStructure section to a Channel – then back to a StructurestructureId)craft project-config/applycraft.entries.section(['sectionA', 'sectionB']).all()and confirm that the entry fromsectionAis returned twicedateDeletedcolumn in thestructurestableExpected behavior
If an existing section becomes related to a new structure in the
structurestable, Craft should make sure that any existing structures for that section are (soft)deleted.Actual behavior
Existing structures aren't soft-deleted if the section's
structureIdis updated via project config.Craft CMS version
5.5.10
PHP version
8.3.14
Operating system and version
macOS; DDEV v1.24.1
Database type and version
MySQL 8.0.36
Image driver and version
No response
Installed plugins and versions
None