I think this bug is best explained with a use case.
Drupal commerce has line_items, which contain a reference to a product through the special commerce_product_reference field. Commerce uses rules, to add the ability to dynamic alter the price for a product, used for discounts etc, that passes along the line item with a product reference to the rule event.
I wanted to add a rule, that would need to check the value of a field on the product and based on that alter the price.
The problem I had, was that I could only access the enity defined properties for the product related to the line item, but not fields created for the product. I was able to add conditions, that the product is a certain type, or contained said field. Even doing this, I was unable to access the field in the data comparison condition.
It seems like the problem is, that the checks that's made for the main entity before adding the fields for data comparison, is not done recursively for the entities that is reference. I tried to poke around the code, but got stuck at the info function for the entity wrapper, which is seems like is what is generating the list of fields/values that can be used in the data comparison.
| Comment | File | Size | Author |
|---|---|---|---|
| #38 | rules_metadata_assertion.patch | 12.27 KB | fago |
| #37 | rules_metadata_assertion.patch | 6.35 KB | fago |
| #36 | rules_metadata_assertion.patch | 6.36 KB | fago |
Comments
Comment #1
googletorp commentedUpdate:
Upon further examination, it seems that if info is added about the field in hook_entity_property_info_alter, this works properly, but fields that are added through the UI/module, but info about them isn't added in hook_entity_property_info_alter, won't is unable to show up for related entities as described above.
Comment #2
fagoIf the referenced entity is of a known bundle type, drupal commerce should add a 'bundle' => 'foo' key to the property info of the entity reference. If the bundle is not known beforehand though, it's unavoidable that you'll have to check it yourself.
However, indeed "metadata assertions" won't work currently for nested data selections ala entity:reference. -> Changing the issue title.
For now, a possible work-a-round is to pass the referenced entity to another rule component and do the check there.
Comment #3
fagoMarked #1065496: Data selectors only don't include fields of child entities as duplicate.
Comment #4
cyberwolf commentedSubscribing.
Comment #5
realityloop commentedSubscribe +1
Comment #6
deekayen commentedSubscribe
Comment #7
lobo235 commentedSubscribing
Comment #8
mtiftSubscribing
Comment #9
minneapolisdan commentedSubscribing
Comment #10
jon betts commentedSub +!
Comment #11
keithm commentedsubscribing
Comment #12
sebnor commentedSubscribing!
Comment #13
checker commented+1
Comment #14
EndEd commentedSubscribing
Comment #15
guypaddock commentedI hate to do this, but... subscribing.
Comment #16
frank pfabigan+1
having the same problem right now ^^
Comment #17
rickmanelius commentedSubscribing. Same issue. In addition, I'm trying to add a rule where I check and order status and payment type. Each has a way of referencing each other through an ID number... but even if I load the entity by fetching by ID or value, it only returns a partial object that can't be updated.
Different issue, so ignore. But I feel it's somewhat related.
Comment #18
benhelps commentedsubscribe
Comment #19
adamwhite commentedSubscribing
Comment #20
zabelc commentedsubscribing
Comment #21
chrinor2002 commentedsubscribe
Comment #22
bc24102 commentedsubscribe
Comment #23
zolee commentedsubscribe
Comment #24
BenK commentedSubscribing
Comment #25
kbalderson commentedsubscribing
Comment #26
pitxels commentedsubscribing
Comment #27
maxchock commentedsubscribing..
Comment #28
pitxels commentedjust wondering, Is this issue expected to be solved in the near future?
Comment #29
fagoI'm aware of the issue and I'm going to take a look at it as time permits. If you need it earlier you are welcome to chime in or organizing someone else doing it for you.
Comment #30
fagoadding tag
Comment #31
Drupa1ish commentedAn workaround is to use rules actions with php evaluation. Don't forget to enable the core module PHP filter.
Here is a sample code, for the use case Adding a Taxonomy Term To Drive Discounts, see http://www.drupalcommerce.org/node/461
The rule is: event Calculating the sell price of a product, Conditions Order is a shopping cart,Parameter: Order: [line-item:order], Actions Multiply the unit price by some amount,Parameter: line-item:line-item-id
At amount , click switch to data selection
This code works only with Conditions Order is a shopping cart,Parameter: Order: [line-item:order], because before adding to cart line item object doesn't exists.
In php evaluation input the following code:
Comment #32
guy_schneerson commentedsubscribing
Comment #33
rfaysubscribe
Comment #34
rickmanelius commentedThanks for the work around @EuroDomenii. I unfortunately need to do this for a client ASAP, so I'm glad to have something. The question is, shouldn't this be considered hackish or do you think this will be the only way? considered standard/best practice?
Comment #35
claudiuenache commentedPhp evaluation is a smart feature of fago, I suppose just for this kind of situations
On the other hand, drupal commerce developers totally rely on rules for dynamic price modification ( in commerce_product_pricing.module, function commerce_product_calculate_sell_price there is no hook, only
rules_invoke_event('commerce_product_calculate_sell_price', $line_item); ). Even this looks hackish, it is clean.
The nice alternative is http://www.drupalcommerce.org/node/461, but is for a particular use case.
With php evalution is more general... You just take the data selectors that rules gives you in the context, and with entity_load you can grab whatever you want from drupal.
Comment #36
fagook, I finally managed to work on this and created a working patch. I really regret using metadata-wrappers for tracking configuration-time metadata as that just makes issues like this complicated - a simple, fat $info array would be probably much simpler to handle. Well, that's something we could refactor anytime or towards d8..
Attached patch works for me, e.g. this rule works now (given all content-types, fields and latest og are there):
To ensure this does not break, we need to cover it with tests. Let's add
* a rule using a generic entity property and asserting its entity type
* a rule asserting a field of a referenced entity
* a rule asserting the bundle, and so the fields of the referenced entity + ensure the property can be passed on as argument for parameters requiring the asserted bundle.
Patch attached. Please test.
Comment #37
fagoAs tests have shown, the patch had problems with assertions directly on variables and asserting bundles. Fixed that.
Comment #38
fagoimplemented tests + committed it.
Comment #39
rfayWoohoo! Thanks for all the great work on this!
Comment #40
rickmanelius commentedNICE!
Comment #41
carn1x commentedsubscribe!
is this fix in dev now?
EDIT: My bad, its in release :D
Comment #43
pitxels commentedI am creating a Rule for commerce so when an order is completed, the customer name is populated in a product custom field.
For what I understand, Orders Entity has a reference to Line Items Entity,
and Line Items has a reference to commerce products.
So I try to use " Entity has field" twice like this
"Commerce order" has field "Line Items"
"Commerce order" has field "Commerce product"
(I can't set "Line items" has field "Commerce product" as I would expect)
But I can not see the Products and their fields into scope.
so I want to ask, Is it possible to navigate trough referenced entities?? thanks
Comment #44
emptyvoid commentedSorry pitxels, this issue isn't the right place to post your question. I'd recommend trying either on www.drupalcommerce.org or the Drupal Commerce issue queue.
The key thing I've struggled with is properly defining the conditions to then manipulate it in the actions section. Try reading this writeup by Ryan: http://www.drupalcommerce.org/faq/rules-field-data-selection
What is missing is a list of the unique fields each entity type has to you can properly scope it.