Skip to content

[5.x] Fix applying default variant to provisional drafts - #4363

Open
lukeholder wants to merge 3 commits into
5.xfrom
bugfix/5.x-4361-default-variant-provisional-draft
Open

lukeholder wants to merge 3 commits into
5.xfrom
bugfix/5.x-4361-default-variant-provisional-draft

Conversation

@lukeholder

Copy link
Copy Markdown
Member

Summary

Fixes #4361 — when a variant's default status was changed via Set default variant while the product had an open provisional draft, the change didn't stick after the draft was applied, and the underlying commerce_variants.isDefault column could end up with two variants flagged true for the same product.

This PR also deprecates the use of isDefault in the database on a variant. VariantQuery now derives commerce_products.defaultVariantId always.

@lukeholder
lukeholder marked this pull request as ready for review September 15, 2026 02:49
@lukeholder
lukeholder requested a review from a team as a code owner September 15, 2026 02:49
@lukeholder lukeholder changed the title Fix applying default variant to provisional drafts [5.x] Fix applying default variant to provisional drafts Sep 15, 2026
@lukeholder
lukeholder requested a lite review from Copilot September 16, 2026 11:49

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Cleanup can leave stale legacy flags, and provisional-draft application lacks regression coverage.

Get a fresh assessment by requesting another Copilot review.

Pull request overview

Fixes provisional-draft default variant persistence and makes defaultVariantId authoritative.

Changes:

  • Resolves draft variant IDs and synchronizes legacy flags.
  • Derives isDefault queries from product data.
  • Adds tests, compatibility documentation, and changelog updates.
File summaries
File Summary and final review notes
tests/unit/elements/variant/VariantQueryTest.php Tests query/display consistency. Nit (1 vote): add provisional-draft application coverage.
src/elements/Variant.php Documents retained legacy flag compatibility.
src/elements/Product.php Resolves defaults and repairs flags. Moderate (2 votes): clear stale flags when no valid default exists. Nit (2 votes): add integration coverage for provisional-draft application and canonical-row repair.
src/elements/db/VariantQuery.php Derives default filtering from defaultVariantId.
src/elements/actions/SetDefaultVariant.php Documents compatibility writes.
CHANGELOG.md Records the fix.
Review details

Suppressed comments (1)

tests/unit/elements/variant/VariantQueryTest.php:577

  • This test only exercises the query/display result after manually flipping commerce_variants.isDefault; it does not cover the reported provisional-draft apply path that this PR changes in Product::getDefaultVariant() and Product::afterSave(). Add a regression test that creates a provisional draft, changes the default, applies it, and asserts the resulting defaultVariantId, variant order, and single raw isDefault flag, so the main fix is actually protected.
    public function testIsDefaultDerivesFromDefaultVariantId(): void
  • Files reviewed: 6/6 changed files
  • Comments generated: 2
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/elements/Product.php
Comment on lines +1712 to +1713
if ($this->getIsCanonical() && $defaultVariant?->id) {
// Make sure exactly one canonical variant is flagged as the default. This is normally kept in
Comment thread src/elements/Product.php
Comment on lines +1712 to +1716
if ($this->getIsCanonical() && $defaultVariant?->id) {
// Make sure exactly one canonical variant is flagged as the default. This is normally kept in
// sync by `SetDefaultVariant`/`Variant::afterSave()`, but that update is deferred while a
// variant's default status is changed from within a provisional draft (so as to not affect the
// canonical product before the draft is applied), and can otherwise be missed when the draft
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.

[5.x]: Default variant set from a provisional draft does not stick; two variants end up flagged isDefault

2 participants