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.

Comments

googletorp’s picture

Component: Rules Core » Rules Engine

Update:

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.

fago’s picture

Title: Can't use data comparison on fields of referenced entities. » Fix metadata-assertions for referenced entities.

If 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.

fago’s picture

cyberwolf’s picture

Subscribing.

realityloop’s picture

Subscribe +1

deekayen’s picture

Subscribe

lobo235’s picture

Subscribing

mtift’s picture

Subscribing

minneapolisdan’s picture

Subscribing

jon betts’s picture

Sub +!

keithm’s picture

subscribing

sebnor’s picture

Subscribing!

checker’s picture

+1

EndEd’s picture

Subscribing

guypaddock’s picture

I hate to do this, but... subscribing.

frank pfabigan’s picture

+1
having the same problem right now ^^

rickmanelius’s picture

Subscribing. 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.

benhelps’s picture

subscribe

adamwhite’s picture

Subscribing

zabelc’s picture

subscribing

chrinor2002’s picture

subscribe

bc24102’s picture

subscribe

zolee’s picture

subscribe

BenK’s picture

Subscribing

kbalderson’s picture

subscribing

pitxels’s picture

subscribing

maxchock’s picture

subscribing..

pitxels’s picture

just wondering, Is this issue expected to be solved in the near future?

fago’s picture

I'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.

fago’s picture

adding tag

Drupa1ish’s picture

An 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:

$van_line_item_id['0'] = $value; #$value from rules with data selector line-item:line-item-id
	$van_line_item_ent=entity_load('commerce_line_item',$van_line_item_id);
	
	$van_product_id[0]=$van_line_item_ent[$value]->commerce_product['und'][0]['product_id'];
	$van_product_ent=entity_load('commerce_product', $van_product_id);
		
	$van_product_price=$van_product_ent[$van_product_id[0]]->commerce_price['und'][0]['amount'];
	
	
	 $van_tags = $van_product_ent[$van_product_id[0]]->field_tag_subdomenii['und'];   
     foreach ($van_tags as $van_tag  ) { 
     	$van_tag_objects[] =  taxonomy_term_load($van_tag['tid']);
     }
     #....
     #Return whatever values depending on the taxonomy found...
guy_schneerson’s picture

subscribing

rfay’s picture

subscribe

rickmanelius’s picture

Thanks 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?

claudiuenache’s picture

Php 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.

fago’s picture

Status: Active » Needs review
StatusFileSize
new6.36 KB

ok, 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):

{ "rules_og_rules_test" : {
    "LABEL" : "og rules test",
    "PLUGIN" : "reaction rule",
    "REQUIRES" : [ "rules", "og" ],
    "ON" : [ "og_membership_insert", "og_membership_update" ],
    "IF" : [
      { "entity_is_of_type" : { "entity" : [ "og-membership:entity" ], "type" : "node" } },
      { "entity_has_field" : { "entity" : [ "og-membership:entity" ], "field" : "field_tags" } }
    ],
    "DO" : [
      { "drupal_message" : { "message" : [ "og-membership:entity:title" ] } },
      { "LOOP" : {
          "USING" : { "list" : [ "og-membership:entity:field-tags" ] },
          "ITEM" : { "tag" : "Current tag" },
          "DO" : [ { "drupal_message" : { "message" : [ "tag:name" ] } } ]
        }
      }
    ]
  }
}

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.

fago’s picture

StatusFileSize
new6.35 KB

As tests have shown, the patch had problems with assertions directly on variables and asserting bundles. Fixed that.

fago’s picture

Status: Needs review » Fixed
StatusFileSize
new12.27 KB

implemented tests + committed it.

rfay’s picture

Woohoo! Thanks for all the great work on this!

rickmanelius’s picture

NICE!

carn1x’s picture

subscribe!

is this fix in dev now?

EDIT: My bad, its in release :D

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.

pitxels’s picture

I 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

emptyvoid’s picture

Sorry 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.