Currently on commerce/modules/product/src/Plugin/Commerce/Condition/OrderProductCategory.php the evaluate() function intersect the array of categories from the coupon settings (that is correct) with all the referenced entities related to each purchased product using the method getReferencedIds().
The problem is that function get all reference fields and this may cause wrong results. In my case I've a reference field to the product category taxonomy, which is good, but't I've also a reference field to another entity type which may contains an ID like the ones configured on the condition. And this is exactly what has happened on a site I'm working on.
This is the code of getReferencedIds():
protected function getReferencedIds(ProductInterface $product) {
$ids = [];
foreach ($this->getEntityReferenceFieldMap() as $field_name => $field_info) {
if ($product->hasField($field_name)) {
$field = $product->get($field_name);
if (!$field->isEmpty()) {
foreach ($field->getValue() as $index => $field_item) {
$ids[] = $field_item['target_id'];
}
}
}
}
return $ids;
}
Solution: the condition should check the UUID instead of ID.
| Comment | File | Size | Author |
|---|---|---|---|
| #17 | order_product_catego-3037376-17.patch | 3.79 KB | mglaman |
| #17 | interdiff-3037376-15-17.txt | 1.46 KB | mglaman |
| #15 | order_product_catego-3037376-15.patch | 2.33 KB | mglaman |
| #15 | interdiff-3037376-10-15.txt | 2.24 KB | mglaman |
| #10 | 3037376-10.patch | 968 bytes | flocondetoile |
Comments
Comment #2
rhovlandThis is an issue with the product module and affects anything that uses the condition plugin (promotion, shipping, etc).
This also affects the Order product item category condition plugin
Comment #3
rhovlandIt looks like the getReferenceIds() function is only used by the Order Product Category & Order Product Item Category condition plugins so I'm inclined to think the getReferenceIds() function should be refactored to only retrieve taxonomy ids. Either that or it should compare UUIDs.
Can a maintainer chime in on how best to address this bug?
Comment #4
andyg5000I agree this is a bug. At first I thought the method name needed to be updated to signify that it's only for terms, but then I realized it's part of there ProductCategoryTrait. Based on that we should update the API/docblock definition and limit the related field API calls to term reference fields.
Comment #5
flocondetoileI encounter same bug. But this time, it was the ID of a product (which is too an entity reference field 'product_id') which was the same ID of a product variation category, in a custom condition plugin for variation category
The fix was to update the getEntityReferenceFieldMap() method (applied on variation entities
Comment #6
flocondetoileLet's the bot test this. I wonder about performance implications (because of the call of FieldDefinitions() for the bundle inside the loop) about this patch, and if there is not a lighter way ?
Comment #8
flocondetoileOups.
commerce_product_variationinstead ofcommerce_productComment #10
flocondetoileAnother approach simplier.
Comment #12
finex commentedLast patch looks a good method :-)
Comment #13
flocondetoileYes. But I don't understand why the $field_definition is NULL in the tests. It shoudn't.
Comment #14
mglamanI think we can all agree folks use Terms for categorization, and if someone uses any other kind of entity, well.. they can open a feature request. So we need to make sure the trait only returns entity references to taxonomy terms, per #10. So that looks good, but test failure is a mystery. Probably a test setup WTF.
EDIT: It is a Unit test which failed. So definitely a problem with our mocks.
Comment #15
mglamanThis fixes the test. I'm slightly concerned we don't test the bug in question – verify it only works on taxonmy_term entity references.
EDIT: I forgot the other unit test.
Comment #17
mglamanFixes the other unit test
Comment #18
mglamanAlso, for any concern about being specific to taxonomy terms, see
Comment #19
mglamanThis looks good to me!
Comment #21
mglaman🥳 Thanks, everyone! Committed.
Comment #22
finex commentedThank you all :-)