You are here

commerce_gc_product.module in Commerce GC 7

Provides Giftcard product type and support.

File

modules/commerce_gc_product/commerce_gc_product.module
View source
<?php

/**
 * @file
 * Provides Giftcard product type and support.
 */

/*
 * Implements hook_product_type_info().
 */
function commerce_gc_product_commerce_product_type_info() {
  $types['giftcard'] = array(
    'type' => 'giftcard',
    'name' => t('Giftcard'),
    'description' => t('This product generates a giftcard when purchased.'),
  );
  return $types;
}

/*
 * Implements hook_commerce_line_item_type_info().
 */
function commerce_gc_product_commerce_line_item_type_info() {
  $types['giftcard_purchase'] = array(
    'type' => 'giftcard_purchase',
    'name' => t('Giftcard Purchase'),
    'description' => t('Default giftcard line item type with mail and message fields.'),
    'giftcard' => TRUE,
    'add_form_submit_value' => t('Add giftcard product'),
  );
  return $types;
}

/*
 * Implements hook_commerce_line_item_type_info_alter().
 */
function commerce_gc_product_commerce_line_item_type_info_alter(&$info) {
  foreach ($info as $type => $line_item_info) {

    // Standard settings for all giftcard types.
    if (!empty($line_item_info['giftcard'])) {
      $info[$type]['product'] = TRUE;
      $callbacks = array(
        'configuration' => 'commerce_gc_product_line_item_configuration',
        'add_form' => 'commerce_gc_product_line_item_add_form',
        'add_form_submit' => 'commerce_gc_product_line_item_add_form_submit',
        'title' => 'commerce_product_line_item_title',
      );

      // Merge user settings into defaults
      if (isset($line_item_info['callbacks'])) {
        $info[$type]['callbacks'] = array_merge($line_item_info['callbacks'], $callbacks);
      }
      else {
        $info[$type]['callbacks'] = $callbacks;
      }
    }
  }
}

/**
 * Provides a list of giftcard line item types.
 *
 * @return type
 */
function commerce_gc_product_giftcard_line_item_types() {
  $return = array();
  foreach (commerce_line_item_types() as $name => $type) {
    if (!empty($type['giftcard'])) {
      $return[] = $name;
    }
  }
  return $return;
}

/*
 * Line item type callback: giftcard purchase add form
 */
function commerce_gc_product_line_item_add_form($element, &$form_state) {
  $form['sku'] = array(
    '#type' => 'textfield',
    '#title' => t('Giftcard product SKU'),
    '#description' => t('Enter the SKU of the giftcard product to add to the order.'),
    '#autocomplete_path' => 'commerce_gc_product/autocomplete/line_item_gc_product_selector',
    '#size' => 60,
    '#maxlength' => 255,
  );
  $form['line_item_fields'] = array(
    '#type' => 'container',
    '#parents' => array(
      'commerce_line_items',
      LANGUAGE_NONE,
      'actions',
    ),
  );

  // Attach fields
  $line_item_type = $element['actions']['line_item_type']['#value']['type'];
  $line_item = commerce_line_item_new($line_item_type);
  field_attach_form('commerce_line_item', $line_item, $form['line_item_fields'], $form_state);

  // Hide certain fields
  $hide = array(
    'commerce_product',
    'commerce_display_path',
    'commerce_unit_price',
    'commerce_giftcards',
  );
  foreach ($hide as $field) {
    $form['line_item_fields'][$field]['#access'] = 0;
  }

  // Store the new line item in the form so it can be accessed easily.
  $form_state['line_item'] = $line_item;
  return $form;
}

/*
 * Implements hook_menu().
 */
function commerce_gc_product_menu() {
  $items['commerce_gc_product/autocomplete/line_item_gc_product_selector'] = array(
    'page callback' => 'commerce_gc_product_autocomplete_page',
    'access arguments' => array(
      'View any commerce_product of any type',
    ),
    'type' => MENU_CALLBACK,
    'title' => 'Giftcard product autocomplete',
  );
  return $items;
}

/*
 * Page callback: giftcard product autocomplete
 */
function commerce_gc_product_autocomplete_page($string = '') {
  $return = array();
  $query = new EntityFieldQuery();
  $results = $query
    ->entityCondition('entity_type', 'commerce_product')
    ->propertyCondition('sku', $string, 'CONTAINS')
    ->fieldCondition('commerce_gc_value', 'amount', 'NULL', '<>')
    ->propertyOrderBy('sku')
    ->range(0, 3)
    ->execute();
  if (!empty($results['commerce_product'])) {
    $products = commerce_product_load_multiple(array_keys($results['commerce_product']));
    foreach ($products as $product) {
      $return[$product->sku] = $product->sku;
    }
  }
  drupal_json_output($return);
}

/*
 * Line item type callback: giftcard purchase add form
 */
function commerce_gc_product_line_item_add_form_submit($line_item, $element, &$form_state, $form) {

  // Make sure the SKU is valid
  $product = commerce_gc_product_load_giftcard_by_sku($element['actions']['sku']['#value']);
  if (!$product) {
    return t('Please enter a valid giftcard product.');
  }
  $lang = LANGUAGE_NONE;
  $line_item_field_elements = $form['commerce_line_items'][$lang]['actions']['line_item_fields'];
  field_attach_form_validate('commerce_line_item', $form_state['line_item'], $line_item_field_elements, $form_state);
  if (form_get_errors()) {
    return;
  }

  // Attach submitted field values.
  field_attach_submit('commerce_line_item', $line_item, $line_item_field_elements, $form_state);

  // Populate the line item just like a regular product.
  commerce_product_line_item_populate($line_item, $product);
}

/**
 * Load a giftcard product by SKU.
 *
 * @param type $sku
 * @return type
 */
function commerce_gc_product_load_giftcard_by_sku($sku) {
  $query = new EntityFieldQuery();
  $results = $query
    ->entityCondition('entity_type', 'commerce_product')
    ->propertyCondition('sku', $sku)
    ->fieldCondition('commerce_gc_value', 'amount', 'NULL', '<>')
    ->execute();
  if (!empty($results['commerce_product'])) {
    $product_id = reset(array_keys($results['commerce_product']));
    return commerce_product_load($product_id);
  }
}

/*
 * Implements hook_form_FORM_ID_alter().
 */
function commerce_gc_product_form_commerce_order_ui_order_form_alter(&$form, &$form_state) {

  // Add custom submit handlers for processing giftcard purchases.
  $form['actions']['submit']['#submit'][] = 'commerce_gc_product_submit_order_form_giftcard_purchases';
}

/*
 * Form submit callback: submit order UI form giftcard_purchases
 */
function commerce_gc_product_submit_order_form_giftcard_purchases(&$form, &$form_state) {
  $order = $form_state['commerce_order'];
  $order_wrapper = entity_metadata_wrapper('commerce_order', $order);
  foreach ($order_wrapper->commerce_line_items as $line_item_wrapper) {
    if (commerce_gc_product_line_item_is_giftcard($line_item_wrapper) && !$line_item_wrapper->commerce_giftcards
      ->value()) {

      // If a giftcard purchase line item is found, hand it off to rules for
      // processing.
      commerce_gc_product_process_line_item_giftcards($line_item_wrapper);
    }
  }
}

/**
 * Determine whether a line item wrapper qualifies as a giftcard
 *
 * @param EntityDrupalWrapper $line_item_wrapper
 * @return boolean
 */
function commerce_gc_product_line_item_is_giftcard(EntityDrupalWrapper $line_item_wrapper) {
  $types = commerce_gc_product_giftcard_line_item_types();
  return in_array($line_item_wrapper->type
    ->value(), $types);
}

/*
 * Line item type callback: giftcard purchase configuration
 */
function commerce_gc_product_line_item_configuration($line_item_type) {

  // Run the product line item configuration
  commerce_product_line_item_configuration($line_item_type);
  $type = $line_item_type['type'];
  field_info_cache_clear();
  $fields = field_info_fields();
  $instances = field_info_instances();

  /*
   * Giftcard mail
   */
  if (empty($fields['commerce_gc_mail'])) {

    // Create max uses field.
    $field = array(
      'field_name' => 'commerce_gc_mail',
      'type' => 'email',
      'locked' => FALSE,
      'cardinality' => '1',
    );
    field_create_field($field);
  }
  if (empty($instances['commerce_line_item'][$type]['commerce_gc_mail'])) {
    $instance = array(
      'field_name' => 'commerce_gc_mail',
      'entity_type' => 'commerce_line_item',
      'bundle' => $type,
      'label' => t('Recipient email'),
      'commerce_cart_settings' => array(
        'field_access' => 1,
      ),
    );
    field_create_instance($instance);
  }

  /*
   * Giftcard message
   */
  if (empty($fields['commerce_gc_message'])) {

    // Create max uses field.
    $field = array(
      'field_name' => 'commerce_gc_message',
      'type' => 'text_long',
      'locked' => FALSE,
      'cardinality' => '1',
    );
    field_create_field($field);
  }
  if (empty($instances['commerce_line_item'][$type]['commerce_gc_message'])) {
    $instance = array(
      'field_name' => 'commerce_gc_message',
      'entity_type' => 'commerce_line_item',
      'bundle' => $type,
      'label' => t('Message to recipient'),
      'commerce_cart_settings' => array(
        'field_access' => 1,
      ),
    );
    field_create_instance($instance);
  }

  /*
   * Giftcard coupon reference (on giftcard purchase line item)
   */
  if (empty($fields['commerce_giftcards'])) {

    // Create giftcard reference field
    $field = array(
      'settings' => array(
        'target_type' => 'commerce_coupon',
        'handler' => 'base',
        'handler_settings' => array(
          'target_bundles' => array(
            'product_display' => 'giftcard_coupon',
          ),
        ),
      ),
      'field_name' => 'commerce_giftcards',
      'type' => 'entityreference',
      'locked' => TRUE,
      'cardinality' => FIELD_CARDINALITY_UNLIMITED,
    );
    field_create_field($field);
  }
  if (empty($instances['commerce_line_item'][$type]['commerce_giftcards'])) {
    $instance = array(
      'label' => t('Purchased giftcards'),
      'widget' => array(
        'type' => 'entityreference_autocomplete',
        'weight' => '9',
        'settings' => array(
          'match_operator' => 'CONTAINS',
          'size' => 60,
          'path' => '',
        ),
      ),
      'field_name' => 'commerce_giftcards',
      'entity_type' => 'commerce_line_item',
      'bundle' => $type,
      'default_value' => NULL,
    );
    field_create_instance($instance);
  }
}

/*
 * Implements hook_flush_caches().
 */
function commerce_gc_product_flush_caches() {
  module_load_install('commerce_gc_product');
  _commerce_gc_product_install_helper();
}

/*
 * Implements hook_commerce_checkout_pane_info().
 */
function commerce_gc_product_commerce_checkout_pane_info() {
  $panes['commerce_gc_product'] = array(
    'title' => t('Giftcard purchases'),
    'file' => 'includes/commerce_gc_product.checkout_pane.inc',
    'base' => 'commerce_gc_product_pane',
    'page' => 'checkout',
    'fieldset' => FALSE,
    'locked' => FALSE,
  );
  return $panes;
}

/*
 * Implements hook_commerce_checkout_complete().
 */
function commerce_gc_product_commerce_checkout_complete($order) {
  $order_wrapper = entity_metadata_wrapper('commerce_order', $order);
  foreach ($order_wrapper->commerce_line_items as $line_item_wrapper) {
    if (commerce_gc_product_line_item_is_giftcard($line_item_wrapper)) {

      // Run giftcard generation rules for this line item.
      commerce_gc_product_process_line_item_giftcards($line_item_wrapper);
    }
  }
}

/**
 * Run giftcard processing on a line item once for each quantity found
 *
 * @param EntityDrupalWrapper $line_item_wrapper
 */
function commerce_gc_product_process_line_item_giftcards(EntityDrupalWrapper $line_item_wrapper) {

  // Process once for each quantity of each giftcard product line item.
  $i = 0;
  while ($i < $line_item_wrapper->quantity
    ->value()) {
    $i++;
    $line_item = $line_item_wrapper
      ->value();

    // Let rules/other modules execute actions.
    rules_invoke_all('commerce_gc_product_process_giftcard_line_item', $line_item);
  }
}