You are here

function uc_product_kit_update in Ubercart 7.3

Same name and namespace in other branches
  1. 5 uc_product_kit/uc_product_kit.module \uc_product_kit_update()
  2. 6.2 uc_product_kit/uc_product_kit.module \uc_product_kit_update()

Implements 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.

Parameters

&$node: The node to be updated.

See also

uc_product_update()

File

uc_product_kit/uc_product_kit.module, line 182
The product kit module for Ubercart.

Code

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;
  if (!isset($node->kit_total) && isset($node->synchronized) && isset($node->sell_price)) {
    $override_discounts = !$node->synchronized;
    $node->kit_total = $node->sell_price;
  }
  else {
    $override_discounts = isset($node->kit_total) && is_numeric($node->kit_total);
  }
  $product_count = count($node->products);

  // Get the price of all the products without any discounts. This number is
  // used if a total kit price was specified to calculate the individual
  // product discounts.
  if ($override_discounts) {
    $base_price = 0;
    foreach ($node->products as $nid) {

      // Usually, $node is $form_state['values'] cast as an object.
      // However, there could be times where node_save() is called with an
      // actual product kit node. $node->products is an array of objects and
      // $node->items doesn't exist then.
      if (is_numeric($nid)) {
        $product = node_load($nid, NULL, TRUE);
        if (!isset($node->items[$nid]['qty']) || $node->items[$nid]['qty'] === '') {
          $node->items[$nid]['qty'] = 1;
        }
      }
      else {
        $product = $nid;
        $nid = $product->nid;
        $node->items[$nid] = (array) $product;
      }
      $base_price += $product->sell_price * $node->items[$nid]['qty'];
    }
  }
  if (empty($node->revision)) {
    db_delete('uc_product_kits')
      ->condition('vid', $node->vid)
      ->execute();
  }
  foreach ($node->products as $nid) {
    if (is_numeric($nid)) {
      $product = node_load($nid);
    }
    else {
      $product = $nid;
      $nid = $product->nid;
    }

    // When a total kit price is specified, calculate the individual product
    // discounts needed to reach it, taking into account the product quantities
    // and their relative prices. More expensive products should be given a
    // proportionally higher discount.
    if ($override_discounts) {

      // After all the algebra that went into finding this formula, it's
      // surprising how simple it is.
      $discount = ($node->kit_total - $base_price) * $product->sell_price / $base_price;
    }
    elseif (isset($node->items[$nid]['discount'])) {
      $discount = (double) $node->items[$nid]['discount'];
    }
    elseif (isset($node->products[$nid]->discount)) {
      $discount = $node->products[$nid]->discount;
    }
    else {
      $discount = 0;
    }
    if (isset($node->items)) {
      if (!isset($node->items[$nid]['qty']) || $node->items[$nid]['qty'] === '') {
        $node->items[$nid]['qty'] = 1;
      }
      $product->qty = $node->items[$nid]['qty'];
      $product->ordering = isset($node->items[$nid]['ordering']) ? $node->items[$nid]['ordering'] : 0;
    }
    else {
      $product->qty = $node->products[$nid]->qty;
      $product->ordering = $node->products[$nid]->ordering;
    }

    // Discounts are always saved, but they are only applied if the kit can't
    // be changed by the customer.
    if ($node->mutable != UC_PRODUCT_KIT_MUTABLE) {
      $product->sell_price += $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;
    }
    db_insert('uc_product_kits')
      ->fields(array(
      'vid' => $node->vid,
      'nid' => $node->nid,
      'product_id' => $nid,
      'mutable' => $node->mutable,
      'qty' => $product->qty,
      'discount' => $discount,
      'ordering' => $product->ordering,
      'synchronized' => $override_discounts ? 0 : 1,
    ))
      ->execute();
  }
  $obj->model = rtrim($obj->model, ' / ');
  if ($node->mutable == UC_PRODUCT_KIT_MUTABLE && !empty($discount)) {
    drupal_set_message(t('Product kit discounts are not applied because the customer can remove components from their cart.'));
  }
  if (!empty($node->revision)) {
    drupal_write_record('uc_products', $obj);
  }
  else {
    db_merge('uc_products')
      ->key(array(
      'vid' => $obj->vid,
    ))
      ->fields(array(
      'model' => $obj->model,
      'list_price' => $obj->list_price,
      'cost' => $obj->cost,
      'sell_price' => $obj->sell_price,
      'weight' => $obj->weight,
      'weight_units' => $obj->weight_units,
      'default_qty' => $obj->default_qty,
      'ordering' => $obj->ordering,
      'shippable' => $obj->shippable ? 1 : 0,
    ))
      ->execute();
  }

  // When a kit is updated, remove matching kits from the cart, as there is no
  // simple way to handle product addition or removal at this point.
  if (module_exists('uc_cart')) {
    db_delete('uc_cart_products')
      ->condition('data', '%' . db_like('s:6:"kit_id";s:' . strlen($node->nid) . ':"' . $node->nid . '";') . '%', 'LIKE')
      ->execute();
  }
}