diff --git a/CHANGELOG-WIP.md b/CHANGELOG-WIP.md index b89120d813..c192e19d5d 100644 --- a/CHANGELOG-WIP.md +++ b/CHANGELOG-WIP.md @@ -1,3 +1,11 @@ # Release Notes for Craft Commerce 4.7 (WIP) -## Unreleased +### Store Management +- Product conditions can now have a “Variant Search” rule. ([#3689](https://github.com/craftcms/commerce/issues/3689)) + +### Administration + +### Development + +### Extensibility +- Added `craft\commerce\elements\conditions\products\ProductVariantSearchConditionRule`. \ No newline at end of file diff --git a/src/elements/conditions/products/ProductCondition.php b/src/elements/conditions/products/ProductCondition.php index e00df945cf..ff1a5c772d 100644 --- a/src/elements/conditions/products/ProductCondition.php +++ b/src/elements/conditions/products/ProductCondition.php @@ -25,6 +25,7 @@ protected function conditionRuleTypes(): array { return array_merge(parent::conditionRuleTypes(), [ ProductTypeConditionRule::class, + ProductVariantSearchConditionRule::class, ProductVariantSkuConditionRule::class, ProductVariantStockConditionRule::class, ProductVariantHasUnlimitedStockConditionRule::class, diff --git a/src/elements/conditions/products/ProductVariantSearchConditionRule.php b/src/elements/conditions/products/ProductVariantSearchConditionRule.php new file mode 100644 index 0000000000..cfa31155b5 --- /dev/null +++ b/src/elements/conditions/products/ProductVariantSearchConditionRule.php @@ -0,0 +1,93 @@ + + * @since 4.7.0 + */ +class ProductVariantSearchConditionRule extends BaseTextConditionRule implements ElementConditionRuleInterface +{ + /** + * @inheritdoc + */ + public function getLabel(): string + { + return Craft::t('commerce', 'Variant Search'); + } + + /** + * @inheritdoc + */ + public function getExclusiveQueryParams(): array + { + return []; + } + + /** + * @inheritdoc + */ + protected function operators(): array + { + return []; + } + + /** + * @inheritdoc + */ + protected function paramValue(): ?string + { + return trim(parent::paramValue()); // TODO: Change the autogenerated stub + } + + /** + * @param ElementQueryInterface $query + */ + public function modifyQuery(ElementQueryInterface $query): void + { + $variantQuery = Variant::find(); + $variantQuery->select(['commerce_variants.productId as id']); + $variantQuery->search($this->paramValue()); + + /** @var ProductQuery $query */ + $query->andWhere(['elements.id' => $variantQuery]); + } + + /** + * @param Product $element + * @return bool + * @throws InvalidConfigException + */ + public function matchElement(ElementInterface $element): bool + { + $variantIds = ArrayHelper::getColumn($element->getVariants(), 'id'); + if (empty($variantIds)) { + return false; + } + + // Perform a variant query search to ensure it is the same process as `modifyQuery` + $variantQuery = Variant::find(); + $variantQuery->search($this->paramValue()); + $variantQuery->id($variantIds); + + return $variantQuery->count() > 0; + } +} diff --git a/src/translations/en/commerce.php b/src/translations/en/commerce.php index 9a5f6e4491..ee64b359a3 100644 --- a/src/translations/en/commerce.php +++ b/src/translations/en/commerce.php @@ -1120,6 +1120,7 @@ 'Variant Has Unlimited Stock' => 'Variant Has Unlimited Stock', 'Variant Price' => 'Variant Price', 'Variant SKU' => 'Variant SKU', + 'Variant Search' => 'Variant Search', 'Variant Stock' => 'Variant Stock', 'Variant Title Format' => 'Variant Title Format', 'Variants' => 'Variants',