You are here

uc_product_kit.module in Ubercart 5

The product kit module for Übercart.

Product kits are groups of products that are sold as a unit.

Coded by: Lyle Mantooth

File

uc_product_kit/uc_product_kit.module
View source
<?php

/**
 * @file
 * The product kit module for Übercart.
 *
 * Product kits are groups of products that are sold as a unit.
 *
 * Coded by: Lyle Mantooth
 */
define('UC_PRODUCT_KIT_UNMUTABLE_NO_LIST', -1);
define('UC_PRODUCT_KIT_UNMUTABLE_WITH_LIST', 0);
define('UC_PRODUCT_KIT_MUTABLE', 1);

/******************************************************************************
 * Drupal Hooks                                                               *
 ******************************************************************************/

/**
 * Implementation of hook_access().
 */
function uc_product_kit_access($op, $node) {
  global $user;
  switch ($op) {
    case 'create':
      return user_access('create products');
    case 'update':
    case 'delete':
      if ($user->uid == $node->uid) {
        return user_access('edit own products');
      }
      else {
        return user_access('edit products');
      }
  }
}
function uc_product_kit_enable() {
  $node_type = node_get_types('type', 'product_kit');
  if ($node_type->module == 'node') {
    $node_type->module = 'uc_product_kit';
    $node_type->custom = 0;
    node_type_save($node_type);
  }
}
function uc_product_kit_disable() {
  $node_type = node_get_types('type', 'product_kit');
  $node_type->module = 'node';
  $node_type->custom = 1;
  node_type_save($node_type);
}

/**
 * Implementation of hook_node_info().
 *
 * @return Node type information for product kits.
 */
function uc_product_kit_node_info() {
  return array(
    'product_kit' => array(
      'name' => t('Product kit'),
      'module' => 'uc_product_kit',
      'description' => t('This node represents two or more products that have been listed together. This presents a logical and convenient grouping of items to the customer.'),
      'title_label' => t('Name'),
      'body_label' => t('Description'),
    ),
  );
}

/**
 * Implementation of hook_insert().
 *
 * Add a row to {uc_products} to make a product. Extra information about the
 *   component products are stored in {uc_product_kits}.
 * @param &$node The node object being saved.
 * @see uc_product_insert
 */
function uc_product_kit_insert(&$node) {
  $obj = new stdClass();
  $obj->vid = $node->vid;
  $obj->nid = $node->nid;
  $obj->model = '';
  $obj->list_price = 0;
  $obj->cost = 0;
  $obj->sell_price = 0;
  $obj->weight = 0;
  $obj->weight_units = variable_get('uc_weight_unit', 'lb');
  $obj->ordering = $node->ordering;
  $obj->shippable = false;
  $values = array();
  $placeholders = array();
  foreach ($node->products as $product) {
    $product = node_load($product);
    $values[] = $node->vid;
    $values[] = $node->nid;
    $values[] = $product->nid;
    $values[] = $node->mutable;
    $values[] = 1;
    $values[] = $product->sell_price;
    $placeholders[] = '(%d, %d, %d, %d, %d, %f)';
    $obj->model .= $product->model . ' / ';
    $obj->list_price += $product->list_price;
    $obj->cost += $product->cost;
    $obj->sell_price += $product->sell_price;
    $obj->weight += $product->weight * uc_weight_conversion($product->weight_units, $obj->weight_units);
    if ($product->shippable) {
      $obj->shippable = true;
    }
  }
  db_query("INSERT INTO {uc_product_kits} (vid, nid, product_id, mutable, qty, discount) VALUES " . implode(',', $placeholders), $values);
  $obj->model = rtrim($obj->model, ' / ');
  db_query("INSERT INTO {uc_products} (vid, nid, model, list_price, cost, sell_price, weight, weight_units, default_qty, unique_hash, ordering, shippable) VALUES (%d, %d, '%s', %f, %f, %f, %f, '%s', %d, '%s', %d, %d)", $obj->vid, $obj->nid, $obj->model, $obj->list_price, $obj->cost, $obj->sell_price, $obj->weight, $obj->weight_units, $obj->default_qty, md5($obj->vid . $obj->nid . $obj->model . $obj->list_price . $obj->cost . $obj->sell_price . $obj->weight . $obj->weight_units . $obj->default_qty . $obj->ordering . $obj->shippable . time()), $obj->ordering, $obj->shippable);
}

/**
 * Implementation of hook_update().
 *
 * Updates information in {uc_products} as well as {uc_product_kits}. Because
 *   component products are known when the form is loaded, discount information
 *   can be input and saved.
 * @param &$node The node to be updated.
 * @see uc_product_update
 */
function uc_product_kit_update(&$node) {
  $obj = new stdClass();
  $obj->vid = $node->vid;
  $obj->nid = $node->nid;
  $obj->model = '';
  $obj->list_price = 0;
  $obj->cost = 0;
  $obj->sell_price = 0;
  $obj->weight = 0;
  $obj->weight_units = variable_get('uc_weight_unit', 'lb');
  $obj->default_qty = $node->default_qty;
  $obj->ordering = $node->ordering;
  $obj->shippable = false;
  $values = array();
  $placeholders = array();
  foreach ($node->products as $nid) {
    $values[] = $node->vid;
    $values[] = $node->nid;
    $values[] = $nid;
    $values[] = $node->mutable;
    $product = node_load($nid);
    if (is_null($node->items[$nid]['qty']) || $node->items[$nid]['qty'] === '') {
      $node->items[$nid]['qty'] = 1;
    }
    $values[] = $node->items[$nid]['qty'];
    if (is_null($node->items[$nid]['discount']) || $node->items[$nid]['discount'] === '') {
      $node->items[$nid]['discount'] = $product->sell_price;
    }
    $values[] = $node->items[$nid]['discount'];
    $values[] = $node->items[$nid]['ordering'];
    $placeholders[] = '(%d, %d, %d, %d, %d, %f, %d)';
    $product->qty = $node->items[$nid]['qty'];
    if ($node->items[$nid]['discount'] < 0) {
      $product->sell_price += $node->items[$nid]['discount'];
    }
    else {
      $product->sell_price = $node->items[$nid]['discount'];
    }
    $obj->model .= $product->model . ' / ';
    $obj->list_price += $product->list_price * $product->qty;
    $obj->cost += $product->cost * $product->qty;
    $obj->sell_price += $product->sell_price * $product->qty;
    $obj->weight += $product->weight * $product->qty * uc_weight_conversion($product->weight_units, $obj->weight_units);
    if ($product->shippable) {
      $obj->shippable = true;
    }
  }
  $obj->model = rtrim($obj->model, ' / ');
  if (!$node->revision) {
    db_query("DELETE FROM {uc_product_kits} WHERE nid = %d", $node->nid);
  }
  db_query("INSERT INTO {uc_product_kits} (vid, nid, product_id, mutable, qty, discount, ordering) VALUES " . implode(',', $placeholders), $values);
  if ($node->revision) {
    db_query("INSERT INTO {uc_products} (vid, nid, model, list_price, cost, sell_price, weight, weight_units, default_qty, unique_hash, ordering, shippable) VALUES (%d, %d, '%s', %f, %f, %f, %f, '%s', %d, '%s', %d, %d)", $obj->vid, $obj->nid, $obj->model, $obj->list_price, $obj->cost, $obj->sell_price, $obj->weight, $obj->weight_units, $obj->default_qty, md5($obj->vid . $obj->nid . $obj->model . $obj->list_price . $obj->cost . $obj->sell_price . $obj->weight . $obj->weight_units . $obj->default_qty . $obj->ordering . time()), $obj->ordering, $obj->shippable);
  }
  else {
    db_query("UPDATE {uc_products} SET model = '%s', list_price = %f, cost = %f, sell_price = %f, weight = %f, weight_units = '%s', default_qty = %d, ordering = %d, shippable = %d WHERE vid = %d", $obj->model, $obj->list_price, $obj->cost, $obj->sell_price, $obj->weight, $obj->weight_units, $obj->default_qty, $obj->ordering, $obj->shippable, $obj->vid);
    if (!db_affected_rows()) {
      db_query("INSERT INTO {uc_products} (vid, nid, model, list_price, cost, sell_price, weight, weight_units, default_qty, unique_hash, ordering, shippable) VALUES (%d, %d, '%s', %f, %f, %f, %f, '%s', %d, '%s', %d, %d)", $obj->vid, $obj->nid, $obj->model, $obj->list_price, $obj->cost, $obj->sell_price, $obj->weight, $obj->weight_units, $obj->default_qty, md5($obj->vid . $obj->nid . $obj->model . $obj->list_price . $obj->cost . $obj->sell_price . $obj->weight . $obj->weight_units . $obj->default_qty . $obj->ordering . $obj->shippable . time()), $obj->ordering, $boj->shippable);
    }
  }
}

/**
 * Implementation of hook_delete().
 */
function uc_product_kit_delete(&$node) {
  if (module_exists('uc_cart')) {
    db_query("DELETE FROM {uc_cart_products} WHERE data LIKE '%%s:6:\"kit_id\";s:%d:\"%s\";%%'", strlen($node->nid), $node->nid);
  }
  db_query("DELETE FROM {uc_product_kits} WHERE nid = %d", $node->nid);
  db_query("DELETE FROM {uc_products} WHERE nid = %d", $node->nid);
}

/**
 * Implementation of hook_load().
 */
function uc_product_kit_load(&$node) {
  $obj = new stdClass();
  $products = array();
  $result = db_query("SELECT product_id, mutable, qty, discount, ordering FROM {uc_product_kits} WHERE vid = %d ORDER BY ordering", $node->vid);
  while ($prod = db_fetch_object($result)) {
    $obj->mutable = $prod->mutable;
    $product = node_load($prod->product_id);
    $product->qty = $prod->qty;
    $product->discount = $prod->discount;
    $product->ordering = $prod->ordering;
    $products[$prod->product_id] = $product;
  }
  uasort($products, '_uc_product_kit_sort_products');
  $obj->products = $products;
  if ($extra = uc_product_load($node)) {
    foreach ($extra as $key => $value) {
      $obj->{$key} = $value;
    }
  }
  return $obj;
}
function uc_product_kit_nodeapi(&$node, $op, $arg3 = null, $arg4 = null) {
  switch ($op) {
    case 'update':
      $result = db_query("SELECT DISTINCT nid FROM {uc_product_kits} WHERE product_id = %d", $node->nid);
      while ($nid = db_fetch_object($result)) {
        $kit = node_load($nid, NULL, TRUE);
        $redirect = drupal_execute('product_kit_node_form', array(
          'nid' => $kit->nid,
        ), $kit);
      }
      break;
  }
}

/**
 * Register an "Add to Cart" form for each product kit.
 * @see uc_product_kit_add_to_cart_form
 * @see uc_catalog_buy_it_now_form
 */
function uc_product_kit_forms($saved_args) {
  $forms = array();
  if (substr($saved_args[0], 0, 31) == 'uc_product_kit_add_to_cart_form' || substr($saved_args[0], 0, 27) == 'uc_product_add_to_cart_form' || substr($saved_args[0], 0, 26) == 'uc_catalog_buy_it_now_form') {
    $product = $saved_args[1];
    if ($product->type == 'product_kit') {
      $forms['uc_product_kit_add_to_cart_form_' . $product->nid] = array(
        'callback' => 'uc_product_kit_add_to_cart_form',
      );
      $forms['uc_product_add_to_cart_form_' . $product->nid] = array(
        'callback' => 'uc_product_kit_add_to_cart_form',
      );
      $forms['uc_catalog_buy_it_now_form_' . $product->nid] = array(
        'callback' => 'uc_product_kit_buy_it_now_form',
      );
    }
  }
  return $forms;
}

/**
 * Add product kit settings to the product settings form.
 */
function uc_product_kit_form_alter($form_id, &$form) {
  if ($form_id == 'uc_product_settings_form') {
    $form['uc_product_kit_mutable'] = array(
      '#type' => 'radios',
      '#title' => t('How are product kits handled by the cart?'),
      '#options' => array(
        UC_PRODUCT_KIT_UNMUTABLE_NO_LIST => t('As a unit. Customers may only change how many kits they are buying. Do not list component products.'),
        UC_PRODUCT_KIT_UNMUTABLE_WITH_LIST => t('As a unit. Customers may only change how many kits they are buying. List component products.'),
        UC_PRODUCT_KIT_MUTABLE => t('As individual products. Customers may add or remove kit components at will.'),
      ),
      '#default_value' => variable_get('uc_product_kit_mutable', 0),
      '#weight' => -5,
    );
  }
}

/**
 * Implementation of hook_form().
 *
 * @ingroup forms
 */
function uc_product_kit_form(&$node) {
  $form = array();
  $form['title'] = array(
    '#type' => 'textfield',
    '#title' => t('Name'),
    '#required' => TRUE,
    '#weight' => -5,
    '#default_value' => $node->title,
    '#description' => t('Name of the product kit'),
  );
  $form['body_filter']['body'] = array(
    '#type' => 'textarea',
    '#title' => t('Description'),
    '#required' => FALSE,
    '#default_value' => $node->body,
    '#rows' => 20,
    '#description' => t('Explain these whatchamacallits.'),
  );
  $form['body_filter']['format'] = filter_form($node->format);
  $form['body_filter']['#weight'] = -4;
  $product_types = module_invoke_all('product_types');
  $products = array();
  unset($product_types[array_search('product_kit', $product_types)]);
  $result = db_query("SELECT nid, title FROM {node} WHERE type IN ('" . implode("','", $product_types) . "') ORDER BY title, nid");
  while ($product = db_fetch_object($result)) {
    $products[$product->nid] = $product->title;
  }
  $form['base'] = array(
    '#type' => 'fieldset',
    '#title' => t('Product Information'),
    '#collapsible' => true,
    '#collapsed' => false,
    '#weight' => -1,
    '#attributes' => array(
      'class' => 'product-field',
    ),
  );
  $form['base']['mutable'] = array(
    '#type' => 'radios',
    '#title' => t('How is this product kit handled by the cart?'),
    '#options' => array(
      UC_PRODUCT_KIT_UNMUTABLE_NO_LIST => t('As a unit. Customers may only change how many kits they are buying. Do not list component products.'),
      UC_PRODUCT_KIT_UNMUTABLE_WITH_LIST => t('As a unit. Customers may only change how many kits they are buying. List component products.'),
      UC_PRODUCT_KIT_MUTABLE => t('As individual products. Customers may add or remove kit components at will.'),
    ),
    '#default_value' => isset($node->mutable) ? $node->mutable : variable_get('uc_product_kit_mutable', UC_PRODUCT_KIT_UNMUTABLE_WITH_LIST),
  );
  $form['base']['products'] = array(
    '#type' => 'select',
    '#multiple' => true,
    '#required' => true,
    '#title' => t('Products'),
    '#options' => $products,
    '#default_value' => isset($node->products) ? array_keys($node->products) : array(),
  );
  $form['base']['items'] = array(
    '#tree' => true,
  );
  if (isset($node->products)) {
    foreach ($node->products as $i => $product) {
      $form['base']['items'][$i] = array(
        '#type' => 'fieldset',
      );
      $form['base']['items'][$i]['link'] = array(
        '#type' => 'item',
        '#value' => l($product->title, 'node/' . $i),
      );
      $form['base']['items'][$i]['qty'] = array(
        '#type' => 'textfield',
        '#title' => t('Quantity'),
        '#default_value' => $product->qty,
        '#size' => 5,
      );
      $form['base']['items'][$i]['ordering'] = array(
        '#type' => 'weight',
        '#title' => t('Ordering'),
        '#default_value' => isset($product->ordering) ? $product->ordering : 0,
      );
      $item = node_load($i);
      $form['base']['items'][$i]['discount'] = array(
        '#type' => 'textfield',
        '#title' => t('Discount'),
        '#description' => t('Enter a negative value to lower the item price by that amount. Enter a postive value to set the item price to that amount. This discount is applied to each %product in the kit.', array(
          '%product' => $product->title,
        )),
        '#default_value' => is_null($product->discount) || $product->discount === '' ? $item->sell_price : $product->discount,
        '#size' => 5,
      );
    }
  }
  $form['base']['default_qty'] = array(
    '#type' => 'textfield',
    '#title' => t('Default quantity to add to cart'),
    '#default_value' => !is_null($node->default_qty) ? $node->default_qty : 1,
    '#description' => t('Leave blank or zero to disable the quantity field in the add to cart form.'),
    '#weight' => 27,
    '#size' => 5,
    '#maxlength' => 6,
  );
  $form['base']['ordering'] = array(
    '#type' => 'weight',
    '#title' => t('List order'),
    '#delta' => 25,
    '#default_value' => $node->ordering,
    '#weight' => 30,
  );
  return $form;
}

/**
 * Implementation of hook_view().
 */
function uc_product_kit_view($node, $teaser = 0, $page = 0) {
  $node = node_prepare($node, $teaser);
  $enabled = variable_get('uc_product_field_enabled', array(
    'image' => 1,
    'display_price' => 1,
    'model' => 1,
    'list_price' => 0,
    'cost' => 0,
    'sell_price' => 1,
    'weight' => 0,
    'dimensions' => 0,
    'add_to_cart' => 1,
  ));
  $weight = variable_get('uc_product_field_weight', array(
    'image' => -2,
    'display_price' => -1,
    'model' => 0,
    'list_price' => 2,
    'cost' => 3,
    'sell_price' => 4,
    'weight' => 5,
    'dimensions' => 6,
    'add_to_cart' => 10,
  ));
  if (isset($node->field_image_cache) && file_exists($node->field_image_cache[0]['filepath'])) {
    $node->content['image'] = array(
      '#value' => theme('uc_product_image', $node->field_image_cache),
      '#access' => $enabled['image'] && module_exists('imagecache'),
      '#weight' => $weight['image'],
    );
  }
  $node->content['display_price'] = array(
    '#value' => theme('uc_product_display_price', $node->sell_price),
    '#access' => $enabled['display_price'],
    '#weight' => $weight['display_price'],
  );
  if (!$teaser) {
    $node->content['model'] = array(
      '#value' => theme('uc_product_model', $node->model),
      '#access' => $enabled['model'],
      '#weight' => $weight['model'],
    );
    $node->content['body']['#weight'] = 1;
    $node->content['list_price'] = array(
      '#value' => theme('uc_product_price', $node->list_price, 'list_price'),
      '#access' => $enabled['list_price'],
      '#weight' => $weight['list_price'],
    );
    $node->content['cost'] = array(
      '#value' => theme('uc_product_price', $node->cost, 'cost'),
      '#access' => $enabled['cost'] && user_access('administer products'),
      '#weight' => $weight['cost'],
    );
  }
  else {
    $node->content['#attributes'] = array(
      'style' => 'display: inline',
    );
  }
  $node->content['sell_price'] = array(
    '#value' => theme('uc_product_sell_price', $node->sell_price, $teaser),
    '#access' => $enabled['sell_price'],
    '#weight' => $weight['sell_price'],
  );
  if (!$teaser) {
    $node->content['weight'] = array(
      '#value' => theme('uc_product_weight', $node->weight, $node->weight_units),
      '#access' => $enabled['weight'],
      '#weight' => $weight['weight'],
    );
    if ($node->mutable != UC_PRODUCT_KIT_UNMUTABLE_NO_LIST) {
      $node->content['products'] = array(
        '#weight' => 6,
      );
      foreach ($node->products as $product) {
        if (node_access('view', $product)) {
          $title = l($product->title, 'node/' . $product->nid);
        }
        else {
          $title = check_plain($product->title);
        }
        $node->content['products'][$product->nid]['qty'] = array(
          '#value' => '<div class="product-qty">' . $product->qty . ' x ' . $title . '</div>',
        );
        $node->content['products'][$product->nid]['#weight'] = $product->ordering;
      }
    }
    if (module_exists('uc_cart')) {
      $node->content['add_to_cart'] = array(
        '#value' => theme('uc_product_kit_add_to_cart', $node),
        '#weight' => 10,
      );
    }
  }
  else {
    if (module_exists('uc_cart') && variable_get('uc_product_add_to_cart_teaser', true)) {
      $node->content['add_to_cart'] = array(
        '#value' => theme('uc_product_kit_add_to_cart', $node),
        '#weight' => 10,
      );
    }
  }
  return $node;
}

/**
 * Wrap the "Add to Cart" form in a <div>.
 *
 * @ingroup themeable
 */
function theme_uc_product_kit_add_to_cart($node) {
  $output = '<div class="add_to_cart" title="' . t('Click to add to cart.') . '">';
  if ($node->nid) {
    $output .= drupal_get_form('uc_product_kit_add_to_cart_form_' . $node->nid, $node);
  }
  else {
    $output .= drupal_get_form('uc_product_kit_add_to_cart_form', $node);
  }
  $output .= '</div>';
  return $output;
}

/**
 * Lets the cart know how many of which products are included in a kit.
 *
 * uc_attribute_form_alter() hooks into this form to add attributes to each
 * element in $form['products'].
 * @ingroup forms
 * @see uc_product_kit_add_to_cart_form_submit
 */
function uc_product_kit_add_to_cart_form($node) {
  $form = array();
  $form['#base'] = 'uc_product_kit_add_to_cart_form';
  $form['nid'] = array(
    '#type' => 'value',
    '#value' => $node->nid,
  );
  $form['products'] = array(
    '#tree' => true,
  );
  foreach ($node->products as $i => $product) {
    $form['products'][$i] = array(
      /* '#type' => 'fieldset',  */
      '#title' => $product->title,
    );
    $form['products'][$i]['nid'] = array(
      '#type' => 'hidden',
      '#value' => $product->nid,
    );
    $form['products'][$i]['qty'] = array(
      '#type' => 'hidden',
      '#value' => $product->qty,
    );
  }
  if ($node->default_qty > 0 && variable_get('uc_product_add_to_cart_qty', false)) {
    $form['qty'] = array(
      '#type' => 'textfield',
      '#title' => t('Quantity'),
      '#default_value' => $node->default_qty,
      '#size' => 5,
      '#maxlength' => 6,
    );
  }
  else {
    $form['qty'] = array(
      '#type' => 'hidden',
      '#value' => 1,
    );
  }
  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => variable_get('uc_product_add_to_cart_text', t('Add to cart')),
    '#id' => 'edit-submit-' . $node->nid,
    '#attributes' => array(
      'class' => 'node-add-to-cart',
    ),
  );
  return $form;
}

/**
 * Submit function for uc_product_kit_add_to_cart_form().
 *
 * Iterates through the kit's product list and adds each to the cart in the
 * correct quantities.
 */
function uc_product_kit_add_to_cart_form_submit($form_id, $form_values) {
  $node = node_load($form_values['nid']);
  drupal_set_message(t('<strong>@product-title</strong> added to <a href="!url">your shopping cart</a>.', array(
    '@product-title' => $node->title,
    '!url' => url('cart'),
  )));
  return uc_cart_add_item($form_values['nid'], $form_values['qty'], $form_values);
}
function uc_product_kit_buy_it_now_form($node) {
  $form = array();
  $form['#base'] = 'uc_product_kit_buy_it_now_form';
  $form['nid'] = array(
    '#type' => 'hidden',
    '#value' => $node->nid,
  );
  if ($node->type == 'product_kit') {
    $form['products'] = array(
      '#tree' => true,
    );
    foreach ($node->products as $i => $product) {
      $form['products'][$i] = array(
        /* '#type' => 'fieldset',  */
        '#title' => $product->title,
      );
      $form['products'][$i]['nid'] = array(
        '#type' => 'hidden',
        '#value' => $product->nid,
      );
      $form['products'][$i]['qty'] = array(
        '#type' => 'hidden',
        '#value' => $product->qty,
      );
    }
  }
  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => variable_get('uc_teaser_add_to_cart_text', t('Add to cart')),
    '#id' => 'edit-submit-' . $node->nid,
    '#attributes' => array(
      'class' => 'list-add-to-cart',
    ),
  );
  return $form;
}
function uc_product_kit_buy_it_now_form_submit($form_id, $form_values) {
  $node = node_load($form_values['nid']);
  if (module_exists('uc_attribute')) {
    $attributes = uc_product_get_attributes($node->nid);
    if (!empty($attributes)) {
      drupal_set_message(t('This product has options that need to be selected before purchase. Please select them in the form below.'), 'error');
      return drupal_get_path_alias('node/' . $form_values['nid']);
    }
    if (is_array($node->products)) {
      foreach ($node->products as $nid => $product) {
        $attributes = uc_product_get_attributes($nid);
        if (!empty($attributes)) {
          drupal_set_message(t('This product has options that need to be selected before purchase. Please select them in the form below.'), 'error');
          return drupal_get_path_alias('node/' . $form_values['nid']);
        }
      }
    }
  }
  return uc_cart_add_item($form_values['nid'], 1, $form_values);
}

/******************************************************************************
 * Übercart Hooks                                                             *
 ******************************************************************************/
function uc_product_kit_product_types() {
  return array(
    'product_kit',
  );
}
function uc_product_kit_store_status() {
  if (module_exists('imagefield')) {
    $result = db_query("SELECT field_name FROM {node_field_instance} WHERE field_name = 'field_image_cache' AND widget_type = 'image' AND type_name = 'product_kit'");
    if (!db_num_rows($result)) {
      return array(
        array(
          'status' => 'ok',
          'title' => t('Images'),
          'desc' => t('Product kits do not have an image field. You may add the existing <em>field_image_cache</em> at the <a href="!url">Add field page</a>.', array(
            '!url' => url('admin/content/types/product-kit/add_field'),
          )),
        ),
      );
    }
  }
}
function uc_product_kit_add_to_cart($nid, $qty, $kit_data) {
  $node = node_load($nid);
  if ($node->type == 'product_kit') {
    $unique = uniqid('', true);
    foreach ($node->products as $product) {
      $data = array(
        'kit_id' => $node->nid,
        'unique_id' => $unique,
        'module' => 'uc_product_kit',
      );
      uc_cart_add_item($product->nid, $product->qty * $qty, $data + module_invoke_all('add_to_cart_data', $kit_data['products'][$product->nid]), null, false, false);
    }
    if ($check_redirect) {
      if (isset($_GET['destination'])) {
        drupal_goto();
      }
      $redirect = variable_get('uc_add_item_redirect', 'cart');
      if ($redirect != '<none>') {
        $_SESSION['last_url'] = uc_referer_uri();
        return $redirect;
      }
      else {
        return uc_referer_uri();
      }
    }
    return array(
      array(
        'success' => false,
        'silent' => true,
        'message' => '',
      ),
    );
  }
}

/**
 * Implementation of Übercart's hook_cart_item().
 */
function uc_product_kit_cart_item($op, &$item) {
  switch ($op) {
    case 'load':
      if (isset($item->data['kit_id']) && ($kit = node_load($item->data['kit_id'])) && $kit->mutable != UC_PRODUCT_KIT_MUTABLE) {
        $kit_discount = $kit->products[$item->nid]->discount;
        if ($kit_discount !== '') {
          if ($kit_discount < 0) {
            $item->price += $kit_discount;
          }
          else {
            $item->price += $kit_discount - $kit->products[$item->nid]->sell_price;
          }
        }
      }
      break;
  }
}

/**
 * Implementation of Ubercart's hook_cart_display().
 *
 * Displays either the kit as a whole, or each individual product based on the
 * store configuration. Each product in the cart that was added by uc_product_kit
 * was also given a unique kit id in order to help prevent collisions. The side
 * effect is that identical product kits are listed separately if added separately.
 * The customer may still change the quantity of kits like other products.
 *
 * @param $item
 *   An item in the shopping cart.
 * @return
 *   A form element array to be processed by uc_cart_view_form().
 */
function uc_product_kit_cart_display($item) {
  static $elements = array();
  static $products;
  $unique_id = $item->data['unique_id'];
  $kit = node_load($item->data['kit_id']);

  //print '<pre>'. print_r($kit, true) .'</pre>';
  if ($kit->mutable == UC_PRODUCT_KIT_MUTABLE) {
    return uc_product_cart_display($item);
  }
  else {
    if (!isset($products[$unique_id])) {

      // Initialize table row
      $element = array();
      $element['nid'] = array(
        '#type' => 'value',
        '#value' => $kit->nid,
      );
      $element['module'] = array(
        '#type' => 'value',
        '#value' => 'uc_product_kit',
      );
      $element['remove'] = array(
        '#type' => 'checkbox',
      );
      if ($kit->mutable == UC_PRODUCT_KIT_UNMUTABLE_WITH_LIST) {
        $element['options'] = array(
          '#value' => '<div class="item-list"><ul class="cart-options">' . "\n",
        );
      }
      $element['title'] = array(
        '#value' => l($kit->title, 'node/' . $kit->nid),
      );
      $element['#total'] = 0;
      $element['qty'] = array(
        '#type' => 'textfield',
        '#default_value' => $item->qty / $kit->products[$item->nid]->qty,
        '#size' => 5,
        '#maxlength' => 6,
      );
      $elements[$unique_id] = $element;
    }

    // Add product specific information
    $op_names = '';
    foreach ($item->options as $option) {
      $op_names .= $option['name'] . ', ';
    }
    $op_names = substr($op_names, 0, strlen($op_names) - 2);
    if ($op_names) {
      $op_names = '-- ' . $op_names;
    }
    if (node_access('view', node_load($item->nid))) {
      $title = l($item->title, 'node/' . $item->nid);
    }
    else {
      $title = $item->title;
    }
    if ($kit->mutable == UC_PRODUCT_KIT_UNMUTABLE_WITH_LIST) {
      $elements[$unique_id]['options']['#value'] .= '<li>' . $item->qty . ' x ' . $title . " <em>{$op_names}</em></li>\n";
    }
    $elements[$unique_id]['#total'] += $item->price * $item->qty;
    $elements[$unique_id]['data'][$item->nid] = $item;
    $products[$unique_id][] = $item->nid;

    // Check if all products in this kit have been accounted for.
    $done = true;
    foreach ($kit->products as $product) {
      if (!in_array($product->nid, $products[$unique_id])) {
        $done = false;
        break;
      }
    }
    if ($done) {
      $elements[$unique_id]['data'] = array(
        '#type' => 'value',
        '#value' => serialize($elements[$unique_id]['data']),
      );
      $elements[$unique_id]['options']['#value'] .= "</ul></div>\n";
      $element = $elements[$unique_id];
      unset($products[$unique_id]);
      unset($elements[$unique_id]);
      return $element;
    }
  }
  return array();
}

/**
 * Implementation of Übercart's hook_update_cart_item().
 *
 * Handles individual products or entire kits.
 */
function uc_product_kit_update_cart_item($nid, $data = array(), $qty, $cid = null) {
  if (!$nid) {
    return NULL;
  }
  $cid = !(is_null($cid) || empty($cid)) ? $cid : uc_cart_get_id();
  if ($qty < 1) {
    foreach ($data as $p_nid => $product) {
      uc_cart_remove_item($p_nid, $cid, $product->data);
    }
  }
  else {
    if (isset($data['kit_id'])) {

      // Product was listed individually
      uc_product_update_cart_item($nid, $data, $qty, $cid);
    }
    else {
      $kit = node_load($nid);
      foreach ($data as $p_nid => $product) {
        uc_product_update_cart_item($p_nid, $product->data, $qty * $kit->products[$p_nid]->qty, $cid);
      }
    }
  }
}

/**
 * usort() callback.
 */
function _uc_product_kit_sort_products($a, $b) {
  if ($a->ordering == $b->ordering) {
    return 0;
  }
  else {
    return $a->ordering < $b->ordering ? -1 : 1;
  }
}

Functions

Namesort descending Description
theme_uc_product_kit_add_to_cart Wrap the "Add to Cart" form in a <div>.
uc_product_kit_access Implementation of hook_access().
uc_product_kit_add_to_cart
uc_product_kit_add_to_cart_form Lets the cart know how many of which products are included in a kit.
uc_product_kit_add_to_cart_form_submit Submit function for uc_product_kit_add_to_cart_form().
uc_product_kit_buy_it_now_form
uc_product_kit_buy_it_now_form_submit
uc_product_kit_cart_display Implementation of Ubercart's hook_cart_display().
uc_product_kit_cart_item Implementation of Übercart's hook_cart_item().
uc_product_kit_delete Implementation of hook_delete().
uc_product_kit_disable
uc_product_kit_enable
uc_product_kit_form Implementation of hook_form().
uc_product_kit_forms Register an "Add to Cart" form for each product kit.
uc_product_kit_form_alter Add product kit settings to the product settings form.
uc_product_kit_insert Implementation of hook_insert().
uc_product_kit_load Implementation of hook_load().
uc_product_kit_nodeapi
uc_product_kit_node_info Implementation of hook_node_info().
uc_product_kit_product_types
uc_product_kit_store_status
uc_product_kit_update Implementation of hook_update().
uc_product_kit_update_cart_item Implementation of Übercart's hook_update_cart_item().
uc_product_kit_view Implementation of hook_view().
_uc_product_kit_sort_products usort() callback.

Constants