craftcms / cms

Build bespoke content experiences with Craft.
https://craftcms.com
Other
3.21k stars 624 forks source link

Matrix fields with same handles overwrite content #9894

Closed leevigraham closed 2 years ago

leevigraham commented 2 years ago

Description

Bit of a strange one… Here's the story…

We update a site from Craft2 to Craft 3.7.13.

In a single matrix field we have matrix blocks that contain fields that have the same handle:

image

Content is saved to the matrixcontent_fieldName table correctly in the correct columns:

However when the data is retrieved from the BlockQuery and the rows are populated the data is wrong.

I've traced this down to ElelementQuery::createElement

There's actually a comment that addresses this:

// Account for results where multiple fields have the same handle, but from
// different columns e.g. two Matrix block types that each have a field with the
// same handle

On line 1887 the value is being set based on the fieldHandle (which is not unique)

First matrix field with mobileLayout field handle:

image

Second matrix field with mobileLayout field handle:

image

Third matrix field with mobileLayout field handle:

image

In the example above the context changes:

image

Once the data has been merged we end up with one value for mobileLayout

image

The query is correct:

SELECT `elements`.`id`,
       `elements`.`fieldLayoutId`,
       `elements`.`uid`,
       `elements`.`enabled`,
       `elements`.`archived`,
       `elements`.`dateCreated`,
       `elements`.`dateUpdated`,
       `elements_sites`.`id`      AS `siteSettingsId`,
       `elements_sites`.`slug`,
       `elements_sites`.`siteId`,
       `elements_sites`.`uri`,
       `elements_sites`.`enabled` AS `enabledForSite`,
       `elements`.`canonicalId`,
       `elements`.`dateLastMerged`,
       `matrixblocks`.`fieldId`,
       `matrixblocks`.`ownerId`,
       `matrixblocks`.`typeId`,
       `matrixblocks`.`sortOrder`,
       `content`.`id`             AS `contentId`,
       `content`.`field_richText_textContent`,
       `content`.`field_richText_blockStyle`,
       `content`.`field_richText_textAlignment`,
       `content`.`field_richText_maxWidth`,
       `content`.`field_pullQuote_quote`,
       `content`.`field_pullQuote_blockStyle`,
       `content`.`field_pullQuote_quoteSource`,
       `content`.`field_pullQuote_quoteSourceLink`,
       `content`.`field_pullQuote_showQuoteTitle`,
       `content`.`field_pullQuote_overrideQuoteTitle`,
       `content`.`field_imageGallery_mobileLayout`,
       `content`.`field_imageGallery_tabletPortraitLayout`,
       `content`.`field_imageGallery_tabletLandscapeLayout`,
       `content`.`field_imageGallery_desktopLayout`,
       `content`.`field_imageGallery_displayMode`,
       `content`.`field_imageGallery_imagePreviewSizing`,
       `content`.`field_imageGallery_justifyContent`,
       `content`.`field_relatedPagesFilesAndLinks_blockTitle`,
       `content`.`field_relatedPagesFilesAndLinks_blockSummary`,
       `content`.`field_relatedEntries_blockTitle`,
       `content`.`field_relatedEntries_blockSummary`,
       `content`.`field_video_responsiveClasses`,
       `content`.`field_video_playbackMode`,
       `content`.`field_childPageNavigation_layout`,
       `content`.`field_summaryGrid_imagePositioning`,
       `content`.`field_summaryGrid_displayAsCarousel`,
       `content`.`field_summaryGrid_heading`,
       `content`.`field_summaryGrid_description`,
       `content`.`field_summaryGrid_mobileLayout`,
       `content`.`field_summaryGrid_tabletPortraitLayout`,
       `content`.`field_summaryGrid_tabletLandscapeLayout`,
       `content`.`field_summaryGrid_desktopLayout`,
       `content`.`field_summaryGrid_summaryStyle`,
       `content`.`field_summaryGrid_imagePreviewSizing`,
       `content`.`field_summaryGrid_showPrompt`,
       `content`.`field_pageSection_sectionHeading`,
       `content`.`field_pageSection_sectionSummary`,
       `content`.`field_pageSection_mobileLayout`,
       `content`.`field_pageSection_tabletPortraitLayout`,
       `content`.`field_pageSection_tabletLandscapeLayout`,
       `content`.`field_pageSection_desktopLayout`,
       `content`.`field_pageSection_verticalCentering`,
       `content`.`field_pageSection_utilityClasses`,
       `content`.`field_stripPromo_prompt`,
       `content`.`field_stripPromo_callToAction`,
       `content`.`field_stripPromo_maxWidth`,
       `content`.`field_stripPromo_style`,
       `content`.`field_form_formHandle`,
       `content`.`field_form_formClasses`,
       `content`.`field_form_successMessage`,
       `content`.`field_promptAndResponse_blockTitle`,
       `content`.`field_promptAndResponse_blockSummary`,
       `content`.`field_promptAndResponse_blockStyle`,
       `content`.`field_featuredNews_stopFeaturingThisNewsItemAt`,
       `content`.`field_issuu_issuuCodeEmbed`,
       `content`.`field_iconCircles_labelSize`,
       `content`.`field_charterSigningPromo_prependedText`,
       `content`.`field_charterSigningPromo_appendedText`,
       `content`.`field_charterSigningPromo_callToAction`,
       `content`.`field_zeroSuicidesInitiatives_mapAndPostcodeSearch`,
       `content`.`field_zeroSuicidesMapSearch_textContent`
FROM (SELECT `elements`.`id`       AS `elementsId`,
             `elements_sites`.`id` AS `elementsSitesId`,
             `content`.`id`        AS `contentId`
      FROM `craft_elements` `elements`
             INNER JOIN `craft_matrixblocks` `matrixblocks` ON `matrixblocks`.`id` = `elements`.`id`
             INNER JOIN `craft_elements_sites` `elements_sites`
                        ON `elements_sites`.`elementId` = `elements`.`id`
             INNER JOIN `craft_matrixcontent_body` `content`
                        ON `content`.`elementId` = `elements`.`id`
      WHERE (`matrixblocks`.`fieldId` = '1')
        AND (`matrixblocks`.`ownerId` = 92253)
        AND (`elements`.`type` = 'craft\\elements\\MatrixBlock')
        AND (`elements`.`archived` = FALSE)
        AND ((`elements`.`enabled` = TRUE) AND (`elements_sites`.`enabled` = TRUE))
        AND (`elements`.`dateDeleted` IS NULL)
        AND (`elements`.`draftId` IS NULL)
        AND (`elements`.`revisionId` IS NULL)
      ORDER BY `matrixblocks`.`sortOrder`) `subquery`
       INNER JOIN `craft_matrixblocks` `matrixblocks`
                  ON `matrixblocks`.`id` = `subquery`.`elementsId`
       INNER JOIN `craft_elements` `elements` ON `elements`.`id` = `subquery`.`elementsId`
       INNER JOIN `craft_elements_sites` `elements_sites`
                  ON `elements_sites`.`id` = `subquery`.`elementsSitesId`
       INNER JOIN `craft_matrixcontent_body` `content` ON `content`.`id` = `subquery`.`contentId`
ORDER BY `matrixblocks`.`sortOrder`

Possibly related:

https://craftcms.com/knowledge-base/upgrading-to-craft-3-7#randomized-database-column-names https://github.com/craftcms/cms/issues/6922

leevigraham commented 2 years ago

Thanks @brandonkelly for helping me debug. Turns out there were default values in the db column definition that where populating not related row data. This data was being pulled during the query and overwriting the correct data.