Skip to content

[5.7] Added ContainsPurchasablesConditionRule#4243

Merged
lukeholder merged 14 commits into
5.7from
feature/has-purchasables-condition-rule
May 20, 2026
Merged

[5.7] Added ContainsPurchasablesConditionRule#4243
lukeholder merged 14 commits into
5.7from
feature/has-purchasables-condition-rule

Conversation

@lukeholder
Copy link
Copy Markdown
Member

@lukeholder lukeholder commented Mar 9, 2026

Description

Adds a new Contains Purchasables order condition rule with three match modes:

  • Any – order contains at least one of the selected purchasables
  • All – order contains all of the selected purchasables (may contain others)
  • Only – order contains exactly the selected purchasables and nothing else
CleanShot 2026-03-09 at 13 52 28@2x

hasPurchasables vs containsPurchasables

The existing hasPurchasables query param is unchanged. It accepts a single purchasable or a flat array of purchasables/IDs and always uses "any" matching — i.e. the order must contain at least one of them.

Order::find()->hasPurchasables([$variantA, $variantB])->all();
// returns orders that contain variantA OR variantB

The new containsPurchasables param accepts an array shape with a purchasables key (mixed IDs and/or objects) and a match key (ContainsPurchasablesMatch enum). All three modes are handled with correct SQL:

Mode SQL Meaning
any Single EXISTS with IN (...) Order contains at least one of the purchasables
all One EXISTS per ID, AND-joined Order contains every one of the purchasables (may contain others)
only AND-joined EXISTS per ID + NOT EXISTS for any others Order contains exactly these purchasables and nothing else
use craft\commerce\enums\ContainsPurchasablesMatch;

// any
Order::find()->containsPurchasables(['purchasables' => [1, 2, 3], 'match' => ContainsPurchasablesMatch::Any])->all();

// all
Order::find()->containsPurchasables(['purchasables' => [1, 2, 3], 'match' => ContainsPurchasablesMatch::All])->all();

// only
Order::find()->containsPurchasables(['purchasables' => [1, 2, 3], 'match' => ContainsPurchasablesMatch::Only])->all();

Twig examples

{# Orders containing at least one of the given purchasables #}
{% set orders = craft.orders()
  .containsPurchasables({ purchasables: [1, 2, 3], match: 'any' })
  .all() %}

{# Orders containing all of the given purchasables (may contain others) #}
{% set orders = craft.orders()
  .containsPurchasables({ purchasables: [1, 2, 3], match: 'all' })
  .all() %}

{# Orders containing exactly the given purchasables and nothing else #}
{% set orders = craft.orders()
  .containsPurchasables({ purchasables: [1, 2, 3], match: 'only' })
  .all() %}

New classes and methods

  • Added craft\commerce\elements\conditions\orders\ContainsPurchasablesConditionRule.

  • Added craft\commerce\enums\ContainsPurchasablesMatch.

  • Added craft\commerce\elements\db\OrderQuery::$containsPurchasables.

  • Added craft\commerce\elements\db\OrderQuery::containsPurchasables().

  • Added craft\commerce\elements\Order::hasPurchasables().

  • Needs translations

Fixes #4242

@lukeholder lukeholder marked this pull request as ready for review March 25, 2026 12:49
@lukeholder lukeholder requested a review from a team as a code owner March 25, 2026 12:49
@lukeholder lukeholder changed the base branch from 5.x to 5.7 March 25, 2026 12:49
@lukeholder lukeholder marked this pull request as draft March 25, 2026 12:50
@lukeholder lukeholder changed the title Added HasPurchasablesConditionRule [5.7] Added HasPurchasablesConditionRule Mar 25, 2026
@lukeholder lukeholder mentioned this pull request Mar 25, 2026
7 tasks
- Correct @SInCE from 4.2.0 to 5.7.0
- Remove double space in namespace declaration
- Fix @inerhitdoc typo to @inheritdoc
- Add CHANGELOG-WIP.md entry for HasPurchasablesConditionRule
For 'all', use one EXISTS subquery per purchasable ID (AND-joined) so the
DB-level filter is accurate, not just a broad pre-filter.
For 'any', the existing IN condition is correct.
For 'exact', keep the IN pre-filter and let matchElement handle the rest.
…sablesConditionRule

- Add OrderQuery::$containsPurchasables property and containsPurchasables() method
  supporting 'any', 'all', and 'only' match modes with correct SQL for each
- Rename HasPurchasablesConditionRule to ContainsPurchasablesConditionRule and
  update its label to 'Contains Purchasables'
- modifyQuery now delegates entirely to containsPurchasables() so all three match
  modes are correctly handled at the DB level
@lukeholder lukeholder changed the title [5.7] Added HasPurchasablesConditionRule [5.7] Added ContainsPurchasablesConditionRule May 20, 2026
@lukeholder lukeholder marked this pull request as ready for review May 20, 2026 01:10
@lukeholder lukeholder requested review from nfourtythree and removed request for nfourtythree May 20, 2026 01:11
@lukeholder lukeholder merged commit 18e7698 into 5.7 May 20, 2026
10 checks passed
@lukeholder lukeholder deleted the feature/has-purchasables-condition-rule branch May 20, 2026 07:57
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]: Shipping Method Conditions only allow selecting one Purchasable/Product Variant rule value

1 participant