I'm trying to create a rule to update a product display node when a product it references is updated.

For a while I had trouble loading the node in the rule - it turns out that this is because the 'query callback' key for the entity property info wasn't set when looking at the product reference field. I've managed to figure out that this is because in commerce_product_reference_property_info_callback(), it unsets that key.

I've commented the unset out and now my rule does what it's meant to, but I can only assume it was there for a reason. Should I submit a patch to take it out, or is this the wrong way to fix this issue? Ta :)

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

vasike’s picture

i want the same thing. thanks for the tip but it didn't work for me.
for me it seems that are some conflicts with the Meta tags module. if i disable the metatags then it seems it works

rszrama’s picture

Hmm, are you sure it's that unset()? I just noticed a typo a few lines up ($propery instead of $property) and wonder if that wasn't the real problem.

See also: #1300170: Rules to mirror product displays when products created/updated/deleted

rupertj’s picture

I just tried it again with the unset($property['query callback']); uncommented, and the typo fixed. The rule behaves as before, and doesn't load the display node.

Why's that key being unset in that function? I'd do some investigation into the effects of the change, but I can't figure out the reasoning for unsetting the key there. All it seems to do is stop queries against product reference fields working :)

lukus’s picture

Could this issue be related: https://drupal.org/node/1269342 ?

Anonymous’s picture

I have the same problem. I'm trying to automate the updating/deletion of display nodes with rules but i'm stuck here. Anyone figured out a workaround for that?

rszrama’s picture

@genox - there's a separate issue for that with a definitive set of Rules to use. #1300170: Rules to mirror product displays when products created/updated/deleted

lukus’s picture

I'm assuming that rules is making use of EntityFieldQuery.

After reading the API page listed above I learned the following:

This class allows finding entities based on entity properties (for example, node->changed), field values, and generic entity meta data (bundle, entity type, entity id, and revision ID). It is not possible to query across multiple entity types. For example, there is no facility to find published nodes written by users created in the last hour, as this would require querying both node->status and user->created.

Perhaps this is the reason it's near impossible to get a list of related nodes?

Maybe the most sensible solution is provide each product entity with a back-reference to its associated display nodes?

In the interim - for display nodes which are created automatically by rules, this back reference could be added using a rule.

liupascal’s picture

@lukus : with EntityFieldQuery, if your node content type has a product reference field, then you can query all the node bundle that have, say, product id 1 referenced. What you cannot do however, is to query a product attributes through a product referenced relationship. EntityField query only returns entity ids.

If you want to get all the product display that references product id 1, you can do it -> the query for EntityFieldQuery will look like "get all the node of product display bundle, where the field product reference is equal to 1".
-> But you cannot use it to do "get all the node of product display bundle, where the referenced product price is 15$" as you are querying against nodes, but filtering on a product attribute.

--

For the issue with rule, I am also having trouble when trying to use the "fetch entity by property" with rules. I'm trying to load line items, and not product, but i think it might be related.

In entity.property.inc in rules, the function entity_property_query() action function calls
return $info['query callback']($entity_type, $property, $value, $limit);

but $info['query callback'] is set to FALSE by this line earlier in the code, because $properties[$property]['schema field'] doesn't exist

  $info = $properties[$property] + array('type' => 'text', 'query callback' => isset($properties[$property]['schema field']) ? 'entity_metadata_table_query' : FALSE);

and $properties is filled up with entity_get_all_property_info() which gathers information for the entity and its bundles
$properties = entity_get_all_property_info($entity_type);

Does this mean that some entities may not have correctly provided their info / callback somewhere ?

@rszrama in #2 : no typo in commerce_line_item_property_info_callback(), but not as much call back set

rupertj’s picture

@liupascal - I think you've run into what I found. Try what I suggest in #3. Go to commerce_product_reference_property_info_callback() and comment out the line that says unset($property['query callback']);

This fixes the issue for me, but I don't know what side-effects (if any) it has. I assume that line's there for a reason, but don't know what it is.

liupascal’s picture

@rupertj : just ran into a side-effect i think :-)

I commented the line

  unset($property['query callback']);

in commerce_line_item_property_info_callback(); and when i tested my rule (which requires me to create order) i had the following error : Fatal error: Call to undefined method EntityDrupalWrapper::count() in ...sites/all/modules/commerce/modules/line_item/commerce_line_item.module on line 310

Line 310 is
if ($field['widget']['type'] == 'commerce_line_item_manager' && $wrapper->{$field_name}->count() > 0) {

I just used admin/commerce/orders/add, added a line item and saved.
You might want to clear your cache if you want to test, as i believe that entity properties are cached.

dhayles’s picture

subscribe

OnkelTem’s picture

@ liupascal

Maybe the problem is in Entity module?
In `entity.property.inc` the `query_callback` is set to FALSE if `schema field` is NULL, while the latter is used I believe only for querying fields located in entity main table and the function `entity_metadata_table_query` used for that:

function entity_property_query($entity_type, $property, $value, $limit = 30) {
  $properties = entity_get_all_property_info($entity_type);
  $info = $properties[$property] + array('type' => 'text', 'query callback' => isset($properties[$property]['schema field']) ? 'entity_metadata_table_query' : FALSE);

i.e. this function can not be used for querying fields. The trivial solution which comes to mind:

function entity_property_query($entity_type, $property, $value, $limit = 30) {
  $properties = entity_get_all_property_info($entity_type);
  $info = $properties[$property] + array('type' => 'text', 'query callback' => isset($properties[$property]['schema field']) ? 'entity_metadata_table_query' : 'entity_metadata_field_query');

This fixes the problem for me. Please check if it works for you.

UPDATE

Requesting help from Entity guys: http://drupal.org/node/1349756

UPDATE 2

For those interesting in fetching Entities by properties this might be the subject of interest too: http://drupal.org/node/1349924 since it brings similar functionality to Conditions.

UPDATE 3

I should update more frequently. I was editing 1.0-beta11, while the current release is entity 1.0-rc1 and this problem seems to be fixed there in similar way:

function entity_property_query($entity_type, $property, $value, $limit = 30) {
  $properties = entity_get_all_property_info($entity_type);
  $info = $properties[$property] + array('type' => 'text', 'queryable' => !empty($properties[$property]['schema field']));

  // We still support the deprecated query callback, so just add in EFQ-based
  // callbacks in case 'queryable' is set to TRUE and make use of the callback.
  if ($info['queryable'] && empty($info['query callback'])) {
    $info['query callback'] = !empty($info['field']) ? 'entity_metadata_field_query' : 'entity_metadata_table_query';
  }
OnkelTem’s picture

Version: 7.x-1.x-dev » 7.x-1.0
FileSize
815 bytes

After I installed latset Entity (1.0-rc1) Fetching by reference stopped working again.
But finally I hope I found the real reason.

Patch is applied.

I'm changing the version of the issue to test the patch.
There is old weird typo "propery" though which I don't fix since I believe it is fixed in dev already. So if you have already fixed that "propery" in your stable, this patch might not apply. In this case - do modification by hand - its only line to add.

OnkelTem’s picture

Status: Active » Needs review

Status: Needs review » Needs work

The last submitted patch, product_reference_entity_property_query_7.x-1.0.patch, failed testing.

OnkelTem’s picture

Version: 7.x-1.0 » 7.x-1.x-dev

Changing it back.

pcambra’s picture

Ok, let's keep this at needs work as patch in #13 is exactly the same as removing the unset();

I wonder why are we dropping the query callback everywhere for fields, probably now it needs to be there.

rfay’s picture

Status: Needs work » Needs review

Status: Needs review » Needs work

The last submitted patch, product_reference_entity_property_query_7.x-1.0.patch, failed testing.

rfay’s picture

@OnkelTem, testing it with the version = 7.x-1.0 doesn't work because back then the tests were broken.

This patch has to have a reroll as it doesn't apply to 7.x-1.x

pcambra’s picture

Status: Needs work » Needs review
FileSize
610 bytes

As fago points out in #1356006-5: Fix entity property info of product / customer profile / line item reference fields it seems to be safe to go forward removing the unset of query callback for our product reference.

pcambra’s picture

Status: Needs review » Closed (duplicate)

Actually, marking this one as duplicate of #1356006: Fix entity property info of product / customer profile / line item reference fields

There, the product reference query callback unset is removed which will fix this one

Maciej Lukianski’s picture

I would say this still does not work.
There are other discussions on this here:
http://drupal.org/node/1300170
http://drupal.org/node/1269342

The below rule should fetch product displays by the product reference field but it always receives an empty array and so, does not delete the display nodes.

{ "rules_delete_display_on_product_deletion" : {
    "LABEL" : "Delete display on product deletion",
    "PLUGIN" : "reaction rule",
    "TAGS" : [ "marketplace_products" ],
    "REQUIRES" : [ "rules", "entity" ],
    "ON" : [ "commerce_product_delete" ],
    "DO" : [
      { "entity_query" : {
          "USING" : {
            "type" : "node",
            "property" : "field_display_ref_product",
            "value" : [ "commerce-product" ]
          },
          "PROVIDE" : { "entity_fetched" : { "entity_fetched" : "Fetched entity" } }
        }
      },
      { "LOOP" : {
          "USING" : { "list" : [ "entity-fetched" ] },
          "ITEM" : { "list_item" : "Current list item" },
          "DO" : [ { "entity_delete" : { "data" : [ "list-item" ] } } ]
        }
      }
    ]
  }
}
liupascal’s picture

@MagicMcj
If you are triggering this on "commerce_product_delete", then the rule is triggered AFTER the product is deleted, hence no product display are referencing it anymore.

Maciej Lukianski’s picture

Oh, This might make sense...
but how would I go about deleting all the referencing nodes then?