thierry-b
11/28/2013 - 11:39 AM

Validate that offline commerce products are not for sale online.

Validate that offline commerce products are not for sale online.

<?php
/**
 * @file offline_sale
 *
 * @description Prevents that offline products can be bought online.
 **/


/**
 * Implements hook_form_alter().
 **/
function offline_sale_form_alter(&$form, &$form_state, $form_id) {

  switch ($form_id) {
    case 'views_form_commerce_cart_form_default':
      // Add validate function to the cart form.
      $form['#validate'][] = 'offline_sale_form_commerce_cart_validate';
      break;

    case 'commerce_checkout_form_checkout':
    case 'commerce_checkout_form_shipping':
    case 'commerce_checkout_form_review':
    case 'commerce_checkout_form_complete':
      $form['buttons']['continue']['#validate'][] = 'offline_sale_checkout_form_validate';
      break;

    default:
      break;
  }

}


/**
 * Alter the add to cart form
 */
function offline_sale_form_commerce_cart_add_to_cart_form_alter(&$form, &$form_state) {
  // Are we coming from a node/x page or the attribute refresh AJAX callback?
  // Depending on the context: fetch the product display object from the URL or
  // form_state context.
  $entity = NULL;
  if (isset($form_state['triggering_element'])) {
    if (isset($form_state['context']['entity'])) {
      $entity = $form_state['context']['entity'];
      continue;
    }
    else {
      $entity = node_load($form_state['context']['entity_id']);
    }
  }
  else {
    $entity = menu_get_object();
  }

  if (isset($entity)) {
    // Check the products offline sale status
    if (isset($entity->field_offline_sale)) {
      $items_offline_sale = field_get_items('node', $entity, 'field_offline_sale');
      if (!empty($items_offline_sale)) {
        $item_offline_sale = array_shift($items_offline_sale);

        // The product is ment for offline sale only
        if((bool)$item_offline_sale['value']) {
          $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Product not available online'),
            '#weight' => 15,
            // Do not set #disabled in order not to prevent submission.
            '#attributes' => array('disabled' => 'disabled'),
            '#validate' => array('offline_sale_add_to_cart_form_offline_validate'),
          );
        }
      }
    }
  }
}


/**
 * Validation callback that prevents submission if the product is not available.
 */
function offline_sale_add_to_cart_form_offline_validate($form, &$form_state) {
  form_set_error('offline_sale', t('This product is not available for online sale.'));
}


/**
 * Form validation handler for views_form_commerce_cart_form_default().
 *
 * Checks each line item to make sure that they have not requested items that
 * are only for sale offline.
 */
function offline_sale_form_commerce_cart_validate($form, &$form_state) {
  // If a user choses to remove an item, then its valid.
  if ($form_state['triggering_element']['#value'] == t('Remove')) {
    return;
  }

  $line_items = array_keys($form_state['line_items']);
  offline_sale_checkout_validate($line_items);
}


/**
 * Form validation handler for commerce_checkout_form_X().
 */
function offline_sale_checkout_form_validate($form, &$form_state) {
  $order_line_items = field_get_items('commerce_order', $form_state['order'], 'commerce_line_items');

  $line_items = array();
  foreach ($order_line_items as $key => $line_item) {
    $line_items[] = current($line_item);
  }
  offline_sale_checkout_validate($line_items, TRUE);
}


/**
 * Offline sale validation function.
 *
 * Make sure all items in the cart are online saleable before continuing.
 */
function offline_sale_checkout_validate($line_items_ids, $redirect = FALSE) {
  $found_errors = FALSE;
  $line_items = array();

  if (!empty($line_items_ids)) {
    // Load all line item entities
    $line_items = entity_load('commerce_line_item', $line_items_ids);

    if (!empty($line_items)) {
      // Check each line item
      foreach ($line_items as $line_item) {
        $entity = NULL;

        // Get the referencing entity
        if ($line_item->data['context']['entity']['entity_type'] == 'node' && isset($line_item->data['context']['entity']['entity_id'])) {
          $entity = node_load($line_item->data['context']['entity']['entity_id']);
        }

        if (isset($entity)) {
          // Check the products offline sale status
          if (isset($entity->field_offline_sale)) {
            $items_offline_sale = field_get_items('node', $entity, 'field_offline_sale');
            if (!empty($items_offline_sale)) {
              $item_offline_sale = array_shift($items_offline_sale);

              // The prodcut is ment for offline sale only
              if((bool)$item_offline_sale['value']) {
                // There are errors found.
                $found_errors = TRUE;
                // Get the line item's commerce product entity to retrieve the title
                $line_item_entity = entity_load('commerce_product', array($line_item->commerce_product['und'][0]['product_id']));
                // Set the error message
                form_set_error('offline_sale', t('The product %line_item is not available for online sale.', array('%line_item' => $line_item_entity[$line_item->commerce_product['und'][0]['product_id']]->title)));
            }
            }
          }
        }
      }
    }
  }

  if ($found_errors && $redirect) {
    drupal_set_message(t('Please remove the products from your cart that are not for sale online.'));

    if ($redirect) {
      $cart_url = url('cart', array('absolute' => TRUE));
      drupal_goto($cart_url);
    }
  }
}