Vote up!
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!
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.

 * 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
$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, '=');
// 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);
// 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);
$displays as $display) {
// Update actual node
if ($display->nid == $node->nid) {
$display = $node;
// Get display actual variations product IDs
$local_pids = array_map(
$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;
Answer by: wayaslij
Posted: May 31, 2013