Drupal Commerce, automatic product display generation module.

Comparing Ubercart and Drupal Commerce I've made a conclusion that Commerce is better. At first glance, commerce is very and very complicated but it worth to be understood. I can easily explain why, my expirience with Ubercart is quite enough to understand it's illogical nature. For example you need to create multicurrency store, Commerce have nice multicurrency module (in later articles i'll explain how to use it). Ubercart on the contrary doesn't have it. More over Commerce has friendly api and  a lot of examples for developpers. For those who doesn't know it yet: main Commerce developper was the Ubercart founder.It means that he understood importance of quite new programming approach and decided to create something significantly new, so new that old project were thrown away. Thats all about commerce benefits.

Sometimes for store we don't need main commerce functionality, i mean separation between commerce product and product display.

Little about what it is. Commerce product it's a product entity (entity means another layer of abstraction). Product display it's a simple node with two fields: title and product_reference (field with commerce product id). We can easily imagine that display is just cover for multiple commerce products. This separation gives us great flexibility (greater then product attributes in Ubercart), but we should pay the complexity for this flexibility. There are a lot of partial solutions for onetoone Drupal Commerce usage: a lot of rules which automatically update, generate and even try to delete product displays while commerce product are created. Also there are rules able to create commerce product  while product display  are created. it's not quite easy to implement them, sometimes delete rule doesn't work at all, it means that we would have a lot of empty nodes or products to delete manually. 

Our solution is more simple. You just need to create custom module with code given below. In this code you need to put your product type name inside function hook_get_node_type(), and change 'hook' on your custom module name, thats all. You will enjoy commerce functionality. if this article was useful for you, please follow us in socials. If something is not clear you may ask, i will try to explain. Best wishes! Continue doing Drupal!

<?php 
/**
* this function return display type 
* choosen for commerce product display 
*/
function hook_get_node_type() {
	$node_type = 'product_display';
	return $node_type;
}
/**
* this function get reference field name
* reference to commerce product inside product display 
* fields
*/
function _hook_get_reference_field_name() {
  $node_type = hook_get_node_type();
  if ($fields = field_info_instances('node', $node_type)) {
	foreach ($fields as $name => $field) {
	  $field_info = field_read_field($name);
	  if ($field_info['type'] == 'commerce_product_reference') {
		return $name;
	  }
	}
  }
}

function hook_entity_insert($entity, $type) {
  if ($type == 'commerce_product') {
		$node_type = hook_get_node_type();
		$node = new stdClass();
		$node->type = $node_type;
		node_object_prepare($node);
		$node->language = LANGUAGE_NONE;
		$node->title = $entity->title;

	    $ref_field_name = _hook_get_reference_field_name($node_type);
	     //foreach ($entity->product_id as $id) {
		   $node->{$ref_field_name}[LANGUAGE_NONE][] = array('product_id' => $entity->product_id);
	     //}
	    node_save($node);
	  }
}
function hook_entity_update($entity, $type) {
	if ($type == 'commerce_product') {
		$node_type = hook_get_node_type();
		$field_name = _hook_get_reference_field_name($node_type);
		$query = new EntityFieldQuery;
		$query->entityCondition('entity_type', 'node', '=')
			->entityCondition('bundle', $node_type )
			->fieldCondition($field_name, 'product_id', $entity->product_id, '=');
		$result = $query->execute();
		if (isset($result['node'])) {
			$items_nids = array_keys($result['node']);
			$nodes = node_load_multiple($items_nids);
			foreach($nodes AS $node) {
				$node->language = LANGUAGE_NONE;
				$node->title = $entity->title;

				$node->{$field_name}[LANGUAGE_NONE][] = array('product_id' => $entity->product_id);
				drupal_alter('commerce_form_display_node', $node);
				node_save($node);
			}
		}
	}
}


/**
 * Implements hook_commerce_product_delete().
 *
 * Remove this product in all product reference field contents.
 */
function hook_commerce_product_delete($product) {
  // Check the data in every product reference field.
  foreach (commerce_info_fields('commerce_product_reference') as $field_name => $field) {
    // Query for any entity referencing the deleted product in this field.
    $query = new EntityFieldQuery();
    $query->fieldCondition($field_name, 'product_id', $product->product_id, '=');
    $result = $query->execute();

    // If results were returned...
    if (!empty($result)) {
      // Loop over results for each type of entity returned.
      foreach ($result as $entity_type => $data) {
        // Load the entities of the current type.
        $entities = entity_load($entity_type, array_keys($data));
		$nids = array_keys($entities);
        node_delete_multiple($nids);
      }
    }
  }
}

  
Rating: 
10 out of 10 based on 1 ratings.