1
Answers
Vote up!
0
Vote down!

Adding mutil-directional product variations

I can't find a commerce module that would create multi-directional variations.

Let's say I have 3 commerce products, associated to 3 product displays.
And I want the 3 product displays to have the 3 commerce products as variations to be able to switch from one to another on the product page but still have the 3 products in my product list.

The idea is that if I add to Display A the Variation B, then Display B would automatically have the variation A added.
And when I add to display A the variation C, then Display B would also gain the variation C and display C would have variations A and B added.
And etc..

Should not be too hard to code using hook_node_update and checking for the SKU and then loading all displays form the same content type associated to that SKU.

But it might already be a module doing such a thing or similar. Any ideas?

Asked by: wayaslij
on May 30, 2013

1 Answer

Vote up!
0
Vote down!

I have created a module with the following function in it, that does what I wanted. I had no issues so far except that I could not use the entity wrapper to save the nodes as it generated a "Maximum function nesting level of '100' reached" error.

Any critic welcome.

<?php
/**
 * Implementation of hook_node_update()
 * This will automatically add the variations to all other displays
 * of the same content type.
 */

function variation_auto_node_update($node) {
 
// Make sure we don't get any cache issues
 
entity_get_controller('node')->resetCache(array($node->nid));
 
$langcode = field_language('node', $node, 'field_product_variations');
 
// Get Display variations
 
$variations = field_get_items('node', $node, 'field_product_variations');
 
  if (
$variations) {
   
// Build request to get all displays form variations
   
$query = db_select('field_data_field_product_variations', 'variations');
   
$query->fields('variations', array('entity_id'));
   
// Filter with OR by variation product Id
   
$db_or = db_or();
    foreach (
$variations as $pid) {
     
$db_or->condition('variations.field_product_variations_product_id', $pid);
    }
   
// Filter by content type with AND
   
$db_and = db_and();
   
$db_and->condition('variations.bundle', $node->type, '=');
   
$db_and->condition($db_or);
   
$query->condition($db_and);
   
// Array of displays Ids
   
$nids = array_keys($query->execute()->fetchAllAssoc('entity_id'));
   
   
// Build request to get all variations from previous displays
   
$query = db_select('field_data_field_product_variations', 'variations');
   
$query->fields('variations', array('field_product_variations_product_id'));
   
$condition = db_or();
    foreach (
$nids as $nid) {
     
$condition->condition('variations.entity_id', $nid);
    }
   
$query->condition($condition);
   
// Array of variations product Ids
   
$pids = array_keys($query->execute()->fetchAllAssoc('field_product_variations_product_id'));
   
   
// Now that we have all displays and products
   
$displays = node_load_multiple($nids);
    foreach(
$displays as $display) {
         
// Update actual node
           
if ($display->nid == $node->nid) {
             
$display = $node;
            }
           
// Get display actual variations product IDs
           
$local_pids = array_map(
                function(
$item){return array_shift($item);},
               
field_get_items('node', $display, 'field_product_variations')
            );
           
// Find missing variations and add them
           
if ($diff = array_diff($pids, $local_pids)) {
              foreach (
$diff as $pid) {
                 
$display->field_product_variations[$langcode][]['product_id'] = (string)$pid;
              }
             
node_save($display);
            }
        }
  }
}
?>
Answer by: wayaslij
Posted: May 31, 2013