| 1 |
<?php
|
| 2 |
// $Id$
|
| 3 |
|
| 4 |
/**
|
| 5 |
* @file
|
| 6 |
* The product kit module for Übercart.
|
| 7 |
*
|
| 8 |
* Product kits are groups of products that are sold as a unit.
|
| 9 |
*
|
| 10 |
* Coded by: Lyle Mantooth
|
| 11 |
*/
|
| 12 |
|
| 13 |
/******************************************************************************
|
| 14 |
* Drupal Hooks *
|
| 15 |
******************************************************************************/
|
| 16 |
|
| 17 |
/**
|
| 18 |
* Implementation of hook_access().
|
| 19 |
*/
|
| 20 |
function uc_product_kit_access($op, $node) {
|
| 21 |
global $user;
|
| 22 |
|
| 23 |
switch ($op) {
|
| 24 |
case 'create':
|
| 25 |
return user_access('create products');
|
| 26 |
case 'update':
|
| 27 |
case 'delete':
|
| 28 |
if ($user->uid == $node->uid) {
|
| 29 |
return user_access('edit own products');
|
| 30 |
}
|
| 31 |
else {
|
| 32 |
return user_access('edit products');
|
| 33 |
}
|
| 34 |
}
|
| 35 |
}
|
| 36 |
|
| 37 |
function uc_product_kit_enable() {
|
| 38 |
$node_type = node_get_types('type', 'product_kit');
|
| 39 |
if ($node_type->module == 'node') {
|
| 40 |
$node_type->module = 'uc_product_kit';
|
| 41 |
$node_type->custom = 0;
|
| 42 |
node_type_save($node_type);
|
| 43 |
}
|
| 44 |
}
|
| 45 |
|
| 46 |
function uc_product_kit_disable() {
|
| 47 |
$node_type = node_get_types('type', 'product_kit');
|
| 48 |
$node_type->module = 'node';
|
| 49 |
$node_type->custom = 1;
|
| 50 |
node_type_save($node_type);
|
| 51 |
}
|
| 52 |
|
| 53 |
/**
|
| 54 |
* Implementation of hook_node_info().
|
| 55 |
*
|
| 56 |
* @return Node type information for product kits.
|
| 57 |
*/
|
| 58 |
function uc_product_kit_node_info() {
|
| 59 |
return array(
|
| 60 |
'product_kit' => array(
|
| 61 |
'name' => t('Product kit'),
|
| 62 |
'module' => 'uc_product_kit',
|
| 63 |
'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.'),
|
| 64 |
'title_label' => t('Name'),
|
| 65 |
'body_label' => t('Description'),
|
| 66 |
),
|
| 67 |
);
|
| 68 |
}
|
| 69 |
|
| 70 |
/**
|
| 71 |
* Implementation of hook_insert().
|
| 72 |
*
|
| 73 |
* Add a row to {uc_products} to make a product. Extra information about the
|
| 74 |
* component products are stored in {uc_product_kits}.
|
| 75 |
* @param &$node The node object being saved.
|
| 76 |
* @see uc_product_insert
|
| 77 |
*/
|
| 78 |
function uc_product_kit_insert(&$node) {
|
| 79 |
$obj = new stdClass();
|
| 80 |
$obj->vid = $node->vid;
|
| 81 |
$obj->nid = $node->nid;
|
| 82 |
$obj->model = '';
|
| 83 |
$obj->list_price = 0;
|
| 84 |
$obj->cost = 0;
|
| 85 |
$obj->sell_price = 0;
|
| 86 |
$obj->weight = 0;
|
| 87 |
$obj->weight_units = variable_get('uc_weight_unit', 'lb');
|
| 88 |
|
| 89 |
$obj->ordering = $node->ordering;
|
| 90 |
$obj->shippable = false;
|
| 91 |
|
| 92 |
$values = array();
|
| 93 |
$placeholders = array();
|
| 94 |
foreach ($node->products as $product) {
|
| 95 |
$product = node_load($product);
|
| 96 |
|
| 97 |
$values[] = $node->vid;
|
| 98 |
$values[] = $node->nid;
|
| 99 |
$values[] = $product->nid;
|
| 100 |
$values[] = $node->mutable;
|
| 101 |
$values[] = 1;
|
| 102 |
$values[] = $product->sell_price;
|
| 103 |
$placeholders[] = '(%d, %d, %d, %d, %d, %f)';
|
| 104 |
|
| 105 |
$obj->model .= $product->model . ' / ';
|
| 106 |
$obj->list_price += $product->list_price;
|
| 107 |
$obj->cost += $product->cost;
|
| 108 |
$obj->sell_price += $product->sell_price;
|
| 109 |
$obj->weight += $product->weight * uc_weight_conversion($product->weight_units, $obj->weight_units);
|
| 110 |
if ($product->shippable) {
|
| 111 |
$obj->shippable = true;
|
| 112 |
}
|
| 113 |
}
|
| 114 |
db_query("INSERT INTO {uc_product_kits} (vid, nid, product_id, mutable, qty, discount) VALUES ". implode(',', $placeholders), $values);
|
| 115 |
$obj->model = rtrim($obj->model, ' / ');
|
| 116 |
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)",
|
| 117 |
$obj->vid, $obj->nid, $obj->model, $obj->list_price, $obj->cost, $obj->sell_price, $obj->weight, $obj->weight_units, $obj->default_qty,
|
| 118 |
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()),
|
| 119 |
$obj->ordering, $obj->shippable
|
| 120 |
);
|
| 121 |
}
|
| 122 |
|
| 123 |
/**
|
| 124 |
* Implementation of hook_update().
|
| 125 |
*
|
| 126 |
* Updates information in {uc_products} as well as {uc_product_kits}. Because
|
| 127 |
* component products are known when the form is loaded, discount information
|
| 128 |
* can be input and saved.
|
| 129 |
* @param &$node The node to be updated.
|
| 130 |
* @see uc_product_update
|
| 131 |
*/
|
| 132 |
function uc_product_kit_update(&$node) {
|
| 133 |
$obj = new stdClass();
|
| 134 |
$obj->vid = $node->vid;
|
| 135 |
$obj->nid = $node->nid;
|
| 136 |
$obj->model = '';
|
| 137 |
$obj->list_price = 0;
|
| 138 |
$obj->cost = 0;
|
| 139 |
$obj->sell_price = 0;
|
| 140 |
$obj->weight = 0;
|
| 141 |
$obj->weight_units = variable_get('uc_weight_unit', 'lb');
|
| 142 |
$obj->default_qty = $node->default_qty;
|
| 143 |
$obj->ordering = $node->ordering;
|
| 144 |
$obj->shippable = false;
|
| 145 |
|
| 146 |
$values = array();
|
| 147 |
$placeholders = array();
|
| 148 |
foreach ($node->products as $i => $product) {
|
| 149 |
$values[] = $node->vid;
|
| 150 |
$values[] = $node->nid;
|
| 151 |
$values[] = $product;
|
| 152 |
$values[] = $node->mutable;
|
| 153 |
$product = node_load($product);
|
| 154 |
if (is_null($node->items[$i]['qty']) || $node->items[$i]['qty'] === '') {
|
| 155 |
$node->items[$i]['qty'] = 1;
|
| 156 |
}
|
| 157 |
$values[] = $node->items[$i]['qty'];
|
| 158 |
if (is_null($node->items[$i]['discount']) || $node->items[$i]['discount'] === '') {
|
| 159 |
$node->items[$i]['discount'] = $product->sell_price;
|
| 160 |
}
|
| 161 |
$values[] = $node->items[$i]['discount'];
|
| 162 |
$values[] = $node->items[$i]['ordering'];
|
| 163 |
$placeholders[] = '(%d, %d, %d, %d, %d, %f, %d)';
|
| 164 |
|
| 165 |
$product->qty = $node->items[$i]['qty'];
|
| 166 |
if ($node->items[$i]['discount'] < 0) {
|
| 167 |
$product->sell_price += $node->items[$i]['discount'];
|
| 168 |
}
|
| 169 |
else {
|
| 170 |
$product->sell_price = $node->items[$i]['discount'];
|
| 171 |
}
|
| 172 |
$obj->model .= $product->model . ' / ';
|
| 173 |
$obj->list_price += $product->list_price * $product->qty;
|
| 174 |
$obj->cost += $product->cost * $product->qty;
|
| 175 |
$obj->sell_price += $product->sell_price * $product->qty;
|
| 176 |
$obj->weight += $product->weight * $product->qty * uc_weight_conversion($product->weight_units, $obj->weight_units);
|
| 177 |
if ($product->shippable) {
|
| 178 |
$obj->shippable = true;
|
| 179 |
}
|
| 180 |
}
|
| 181 |
$obj->model = rtrim($obj->model, ' / ');
|
| 182 |
if (!$node->revision) {
|
| 183 |
db_query("DELETE FROM {uc_product_kits} WHERE nid = %d", $node->nid);
|
| 184 |
}
|
| 185 |
db_query("INSERT INTO {uc_product_kits} (vid, nid, product_id, mutable, qty, discount, ordering) VALUES ". implode(',', $placeholders), $values);
|
| 186 |
if ($node->revision) {
|
| 187 |
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)",
|
| 188 |
$obj->vid, $obj->nid, $obj->model, $obj->list_price, $obj->cost, $obj->sell_price, $obj->weight, $obj->weight_units, $obj->default_qty,
|
| 189 |
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()),
|
| 190 |
$obj->ordering, $obj->shippable
|
| 191 |
);
|
| 192 |
}
|
| 193 |
else {
|
| 194 |
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",
|
| 195 |
$obj->model, $obj->list_price, $obj->cost, $obj->sell_price, $obj->weight, $obj->weight_units, $obj->default_qty, $obj->ordering, $obj->shippable, $obj->vid);
|
| 196 |
if (!db_affected_rows()) {
|
| 197 |
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)",
|
| 198 |
$obj->vid, $obj->nid, $obj->model, $obj->list_price, $obj->cost, $obj->sell_price, $obj->weight, $obj->weight_units, $obj->default_qty,
|
| 199 |
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()),
|
| 200 |
$obj->ordering, $boj->shippable
|
| 201 |
);
|
| 202 |
}
|
| 203 |
}
|
| 204 |
}
|
| 205 |
|
| 206 |
/**
|
| 207 |
* Implementation of hook_delete().
|
| 208 |
*/
|
| 209 |
function uc_product_kit_delete(&$node) {
|
| 210 |
if (module_exists('uc_cart')) {
|
| 211 |
db_query("DELETE FROM {uc_cart_products} WHERE data LIKE '%%s:6:\"kit_id\";s:%d:\"%s\";%%'", strlen($node->nid), $node->nid);
|
| 212 |
}
|
| 213 |
db_query("DELETE FROM {uc_product_kits} WHERE nid = %d", $node->nid);
|
| 214 |
db_query("DELETE FROM {uc_products} WHERE nid = %d", $node->nid);
|
| 215 |
}
|
| 216 |
|
| 217 |
/**
|
| 218 |
* Implementation of hook_load().
|
| 219 |
*/
|
| 220 |
function uc_product_kit_load(&$node) {
|
| 221 |
$obj = new stdClass();
|
| 222 |
|
| 223 |
$products = array();
|
| 224 |
$result = db_query("SELECT product_id, mutable, qty, discount, ordering FROM {uc_product_kits} WHERE vid = %d ORDER BY ordering", $node->vid);
|
| 225 |
while ($prod = db_fetch_object($result)) {
|
| 226 |
$obj->mutable = $prod->mutable;
|
| 227 |
$product = node_load($prod->product_id);
|
| 228 |
$product->qty = $prod->qty;
|
| 229 |
$product->discount = $prod->discount;
|
| 230 |
$product->ordering = $prod->ordering;
|
| 231 |
$products[$prod->product_id] = $product;
|
| 232 |
}
|
| 233 |
uasort($products, '_uc_product_kit_sort_products');
|
| 234 |
$obj->products = $products;
|
| 235 |
if ($extra = uc_product_load($node)) {
|
| 236 |
foreach ($extra as $key => $value) {
|
| 237 |
$obj->$key = $value;
|
| 238 |
}
|
| 239 |
}
|
| 240 |
|
| 241 |
return $obj;
|
| 242 |
}
|
| 243 |
|
| 244 |
function uc_product_kit_nodeapi(&$node, $op, $arg3 = null, $arg4 = null) {
|
| 245 |
switch ($op) {
|
| 246 |
case 'update':
|
| 247 |
$result = db_query("SELECT nid FROM {uc_product_kits} WHERE product_id = %d", $node->nid);
|
| 248 |
while ($nid = db_fetch_object($result)) {
|
| 249 |
$kit = node_load($nid, NULL, TRUE);
|
| 250 |
node_object_prepare($kit);
|
| 251 |
$redirect = drupal_execute('product_kit_node_form', array(), $kit);
|
| 252 |
}
|
| 253 |
break;
|
| 254 |
}
|
| 255 |
}
|
| 256 |
|
| 257 |
/**
|
| 258 |
* Register an "Add to Cart" form for each product kit.
|
| 259 |
* @see uc_product_kit_add_to_cart_form
|
| 260 |
* @see uc_catalog_buy_it_now_form
|
| 261 |
*/
|
| 262 |
function uc_product_kit_forms($saved_args) {
|
| 263 |
$forms = array();
|
| 264 |
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') {
|
| 265 |
$products = db_query("SELECT DISTINCT nid FROM {uc_product_kits} WHERE nid = %d", $saved_args[1]->nid);
|
| 266 |
|
| 267 |
while ($prodrow = db_fetch_object($products)) {
|
| 268 |
$forms['uc_product_kit_add_to_cart_form_'. $prodrow->nid] = array('callback' => 'uc_product_kit_add_to_cart_form');
|
| 269 |
$forms['uc_product_add_to_cart_form_'. $prodrow->nid] = array('callback' => 'uc_product_kit_add_to_cart_form');
|
| 270 |
$forms['uc_catalog_buy_it_now_form_'. $prodrow->nid] = array('callback' => 'uc_product_kit_buy_it_now_form');
|
| 271 |
}
|
| 272 |
}
|
| 273 |
return $forms;
|
| 274 |
}
|
| 275 |
|
| 276 |
/**
|
| 277 |
* Add product kit settings to the product settings form.
|
| 278 |
*/
|
| 279 |
function uc_product_kit_form_alter($form_id, &$form) {
|
| 280 |
if ($form_id == 'uc_product_settings_form') {
|
| 281 |
$form['uc_product_kit_mutable'] = array('#type' => 'radios',
|
| 282 |
'#title' => t('How are product kits handled by the cart?'),
|
| 283 |
'#options' => array(t('As a unit. Customers may only change how many kits they are buying.'), t('As individual products. Customers may add or remove kit components at will.')),
|
| 284 |
'#default_value' => variable_get('uc_product_kit_mutable', 0),
|
| 285 |
'#weight' => -5,
|
| 286 |
);
|
| 287 |
}
|
| 288 |
}
|
| 289 |
|
| 290 |
/**
|
| 291 |
* Implementation of hook_form().
|
| 292 |
*
|
| 293 |
* @ingroup forms
|
| 294 |
*/
|
| 295 |
function uc_product_kit_form(&$node) {
|
| 296 |
$form = array();
|
| 297 |
|
| 298 |
$form['title'] = array('#type' => 'textfield',
|
| 299 |
'#title' => t('Name'),
|
| 300 |
'#required' => TRUE,
|
| 301 |
'#weight' => -5,
|
| 302 |
'#default_value' => $node->title,
|
| 303 |
'#description' => t('Name of the product kit')
|
| 304 |
);
|
| 305 |
$form['body_filter']['body'] = array('#type' => 'textarea',
|
| 306 |
'#title' => t('Description'),
|
| 307 |
'#required' => FALSE,
|
| 308 |
'#default_value' => $node->body,
|
| 309 |
'#rows' => 20,
|
| 310 |
'#description' => t('Explain these whatchamacallits.'),
|
| 311 |
);
|
| 312 |
$form['body_filter']['format'] = filter_form($node->format);
|
| 313 |
$form['body_filter']['#weight'] = -4;
|
| 314 |
|
| 315 |
$product_types = module_invoke_all('product_types');
|
| 316 |
unset($product_types[array_search('product_kit', $product_types)]);
|
| 317 |
$result = db_query("SELECT nid, title FROM {node} WHERE type IN ('". implode("','", $product_types) ."')");
|
| 318 |
$products = array();
|
| 319 |
while ($product = db_fetch_object($result)) {
|
| 320 |
$products[$product->nid] = $product->title;
|
| 321 |
}
|
| 322 |
$form['base'] = array('#type' => 'fieldset',
|
| 323 |
'#title' => t('Product Information'),
|
| 324 |
'#collapsible' => true,
|
| 325 |
'#collapsed' => false,
|
| 326 |
'#weight' => -1,
|
| 327 |
'#attributes' => array('class' => 'product-field'),
|
| 328 |
);
|
| 329 |
$form['base']['mutable'] = array('#type' => 'radios',
|
| 330 |
'#title' => t('How is this product kit handled by the cart?'),
|
| 331 |
'#options' => array(t('As a unit. Customers may only change how many kits they are buying.'), t('As individual products. Customers may add or remove kit components at will.')),
|
| 332 |
'#default_value' => isset($node->mutable) ? $node->mutable : variable_get('uc_product_kit_mutable', 0),
|
| 333 |
);
|
| 334 |
$form['base']['products'] = array('#type' => 'select',
|
| 335 |
'#multiple' => true,
|
| 336 |
'#required' => true,
|
| 337 |
'#title' => t('Products'),
|
| 338 |
'#options' => $products,
|
| 339 |
'#default_value' => isset($node->products) ? array_keys($node->products) : array(),
|
| 340 |
);
|
| 341 |
$form['base']['items'] = array('#tree' => true);
|
| 342 |
if (isset($node->products)) {
|
| 343 |
foreach ($node->products as $i => $product) {
|
| 344 |
$form['base']['items'][$i] = array('#type' => 'fieldset',
|
| 345 |
//'#title' => $product->title,
|
| 346 |
);
|
| 347 |
$form['base']['items'][$i]['link'] = array('#type' => 'item',
|
| 348 |
'#value' => l(t('@product', array('@product' => $product->title)), 'node/'. $i),
|
| 349 |
);
|
| 350 |
$form['base']['items'][$i]['qty'] = array('#type' => 'textfield',
|
| 351 |
'#title' => t('Quantity'),
|
| 352 |
'#default_value' => $product->qty,
|
| 353 |
'#size' => 5,
|
| 354 |
);
|
| 355 |
$form['base']['items'][$i]['ordering'] = array('#type' => 'weight',
|
| 356 |
'#title' => t('Ordering'),
|
| 357 |
'#default_value' => $product->ordering,
|
| 358 |
);
|
| 359 |
$item = node_load($i);
|
| 360 |
$form['base']['items'][$i]['discount'] = array('#type' => 'textfield',
|
| 361 |
'#title' => t('Discount'),
|
| 362 |
'#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)),
|
| 363 |
'#default_value' => (is_null($product->discount) || $product->discount === '' ? $item->sell_price : $product->discount),
|
| 364 |
'#size' => 5,
|
| 365 |
);
|
| 366 |
}
|
| 367 |
}
|
| 368 |
$form['base']['default_qty'] = array('#type' => 'textfield',
|
| 369 |
'#title' => t('Default quantity to add to cart'),
|
| 370 |
'#default_value' => !is_null($node->default_qty) ? $node->default_qty : 1,
|
| 371 |
'#description' => t('Leave blank or zero to disable the quantity field in the add to cart form.'),
|
| 372 |
'#weight' => 27,
|
| 373 |
'#size' => 5,
|
| 374 |
'#maxlength' => 6,
|
| 375 |
);
|
| 376 |
$form['base']['ordering'] = array('#type' => 'weight',
|
| 377 |
'#title' => t('List order'),
|
| 378 |
'#delta' => 25,
|
| 379 |
'#default_value' => $node->ordering,
|
| 380 |
'#weight' => 30,
|
| 381 |
);
|
| 382 |
|
| 383 |
return $form;
|
| 384 |
}
|
| 385 |
|
| 386 |
/**
|
| 387 |
* Implementation of hook_view().
|
| 388 |
*/
|
| 389 |
function uc_product_kit_view($node, $teaser = 0, $page = 0) {
|
| 390 |
$node = node_prepare($node, $teaser);
|
| 391 |
|
| 392 |
$enabled = variable_get('uc_product_field_enabled', array(
|
| 393 |
'image' => 1,
|
| 394 |
'display_price' => 1,
|
| 395 |
'model' => 1,
|
| 396 |
'list_price' => 0,
|
| 397 |
'cost' => 0,
|
| 398 |
'sell_price' => 1,
|
| 399 |
'weight' => 0,
|
| 400 |
'dimensions' => 0,
|
| 401 |
'add_to_cart' => 1,
|
| 402 |
));
|
| 403 |
$weight = variable_get('uc_product_field_weight', array(
|
| 404 |
'image' => -2,
|
| 405 |
'display_price' => -1,
|
| 406 |
'model' => 0,
|
| 407 |
'list_price' => 2,
|
| 408 |
'cost' => 3,
|
| 409 |
'sell_price' => 4,
|
| 410 |
'weight' => 5,
|
| 411 |
'dimensions' => 6,
|
| 412 |
'add_to_cart' => 10,
|
| 413 |
));
|
| 414 |
|
| 415 |
//drupal_set_message('<pre>'. print_r($node->field_image_cache, true) .'</pre>');
|
| 416 |
if (isset($node->field_image_cache) && file_exists($node->field_image_cache[0]['filepath'])) {
|
| 417 |
$node->content['image'] = array('#value' => theme('uc_product_image', $node->field_image_cache),
|
| 418 |
'#access' => $enabled['image'] && module_exists('imagecache'),
|
| 419 |
'#weight' => $weight['image'],
|
| 420 |
);
|
| 421 |
}
|
| 422 |
$node->content['display_price'] = array('#value' => theme('uc_product_display_price', $node->sell_price),
|
| 423 |
'#access' => $enabled['display_price'],
|
| 424 |
'#weight' => $weight['display_price'],
|
| 425 |
);
|
| 426 |
if (!$teaser) {
|
| 427 |
$node->content['model'] = array('#value' => theme('uc_product_model', $node->model),
|
| 428 |
'#access' => $enabled['model'],
|
| 429 |
'#weight' => $weight['model'],
|
| 430 |
);
|
| 431 |
$node->content['body']['#weight'] = 1;
|
| 432 |
$node->content['list_price'] = array('#value' => theme('uc_product_price', $node->list_price, 'list_price'),
|
| 433 |
'#access' => $enabled['list_price'],
|
| 434 |
'#weight' => $weight['list_price'],
|
| 435 |
);
|
| 436 |
$node->content['cost'] = array('#value' => theme('uc_product_price', $node->cost, 'cost'),
|
| 437 |
'#access' => $enabled['cost'] && user_access('administer products'),
|
| 438 |
'#weight' => $weight['cost'],
|
| 439 |
);
|
| 440 |
}
|
| 441 |
else {
|
| 442 |
$node->content['#attributes'] = array('style' => 'display: inline');
|
| 443 |
}
|
| 444 |
|
| 445 |
$node->content['sell_price'] = array('#value' => theme('uc_product_sell_price', $node->sell_price, $teaser),
|
| 446 |
'#access' => $enabled['sell_price'],
|
| 447 |
'#weight' => $weight['sell_price'],
|
| 448 |
);
|
| 449 |
|
| 450 |
if (!$teaser) {
|
| 451 |
$node->content['weight'] = array('#value' => theme('uc_product_weight', $node->weight, $node->weight_units),
|
| 452 |
'#access' => $enabled['weight'],
|
| 453 |
'#weight' => $weight['weight'],
|
| 454 |
);
|
| 455 |
$node->content['products'] = array('#weight' => 6);
|
| 456 |
foreach ($node->products as $product) {
|
| 457 |
$node->content['products'][$product->nid]['qty'] = array('#value' => '<div class="product-qty">'. $product->qty .' x '. l($product->title, 'node/'. $product->nid) .'</div>');
|
| 458 |
$node->content['products'][$product->nid]['#weight'] = $product->ordering;
|
| 459 |
}
|
| 460 |
$node->content['add_to_cart'] = array('#value' => theme('uc_product_kit_add_to_cart', $node),
|
| 461 |
'#weight' => 10,
|
| 462 |
);
|
| 463 |
}
|
| 464 |
else if (variable_get('uc_product_add_to_cart_teaser', true)) {
|
| 465 |
$node->content['add_to_cart'] = array('#value' => theme('uc_product_kit_add_to_cart', $node),
|
| 466 |
'#weight' => 10,
|
| 467 |
);
|
| 468 |
}
|
| 469 |
//print '<pre>'. print_r($node, true) .'</pre>';
|
| 470 |
return $node;
|
| 471 |
}
|
| 472 |
|
| 473 |
/**
|
| 474 |
* Wrap the "Add to Cart" form in a <div>.
|
| 475 |
*
|
| 476 |
* @ingroup themeable
|
| 477 |
*/
|
| 478 |
function theme_uc_product_kit_add_to_cart($node) {
|
| 479 |
$output = '<div class="add_to_cart" title="'. t('Click to add to cart.') .'">';
|
| 480 |
if ($node->nid) {
|
| 481 |
$output .= drupal_get_form('uc_product_kit_add_to_cart_form_'. $node->nid, $node);
|
| 482 |
}
|
| 483 |
else {
|
| 484 |
$output .= drupal_get_form('uc_product_kit_add_to_cart_form', $node);
|
| 485 |
}
|
| 486 |
$output .= '</div>';
|
| 487 |
return $output;
|
| 488 |
}
|
| 489 |
|
| 490 |
/**
|
| 491 |
* Lets the cart know how many of which products are included in a kit.
|
| 492 |
*
|
| 493 |
* uc_attribute_form_alter() hooks into this form to add attributes to each
|
| 494 |
* element in $form['products'].
|
| 495 |
* @ingroup forms
|
| 496 |
* @see uc_product_kit_add_to_cart_form_submit
|
| 497 |
*/
|
| 498 |
function uc_product_kit_add_to_cart_form($node) {
|
| 499 |
$form = array();
|
| 500 |
$form['#base'] = 'uc_product_kit_add_to_cart_form';
|
| 501 |
$form['nid'] = array('#type' => 'value', '#value' => $node->nid, );
|
| 502 |
$form['products'] = array('#tree' => true);
|
| 503 |
foreach ($node->products as $i => $product) {
|
| 504 |
$form['products'][$i] = array(/* '#type' => 'fieldset', */'#title' => $product->title);
|
| 505 |
$form['products'][$i]['nid'] = array('#type' => 'hidden', '#value' => $product->nid);
|
| 506 |
$form['products'][$i]['qty'] = array('#type' => 'hidden', '#value' => $product->qty);
|
| 507 |
}
|
| 508 |
if ($node->default_qty > 0 && variable_get('uc_product_add_to_cart_qty', false)) {
|
| 509 |
$form['qty'] = array('#type' => 'textfield',
|
| 510 |
'#title' => t('Quantity'),
|
| 511 |
'#default_value' => $node->default_qty,
|
| 512 |
'#size' => 5,
|
| 513 |
'#maxlength' => 6,
|
| 514 |
);
|
| 515 |
}
|
| 516 |
else {
|
| 517 |
$form['qty'] = array('#type' => 'hidden', '#value' => 1);
|
| 518 |
}
|
| 519 |
$form['submit'] = array(
|
| 520 |
'#type' => 'submit',
|
| 521 |
'#value' => variable_get('uc_product_add_to_cart_text', t('Add to cart')),
|
| 522 |
'#id' => 'edit-submit-'. $node->nid,
|
| 523 |
'#attributes' => array(
|
| 524 |
'class' => 'node-add-to-cart',
|
| 525 |
),
|
| 526 |
);
|
| 527 |
return $form;
|
| 528 |
}
|
| 529 |
|
| 530 |
/**
|
| 531 |
* Submit function for uc_product_kit_add_to_cart_form().
|
| 532 |
*
|
| 533 |
* Iterates through the kit's product list and adds each to the cart in the
|
| 534 |
* correct quantities.
|
| 535 |
*/
|
| 536 |
function uc_product_kit_add_to_cart_form_submit($form_id, $form_values) {
|
| 537 |
return uc_cart_add_item($form_values['nid'], $form_values['qty'], $form_values);
|
| 538 |
}
|
| 539 |
|
| 540 |
function uc_product_kit_buy_it_now_form($node) {
|
| 541 |
$form = array();
|
| 542 |
$form['#base'] = 'uc_product_kit_buy_it_now_form';
|
| 543 |
$form['nid'] = array('#type' => 'hidden', '#value' => $node->nid);
|
| 544 |
if ($node->type == 'product_kit') {
|
| 545 |
$form['products'] = array('#tree' => true);
|
| 546 |
foreach ($node->products as $i => $product) {
|
| 547 |
$form['products'][$i] = array(/* '#type' => 'fieldset', */'#title' => $product->title);
|
| 548 |
$form['products'][$i]['nid'] = array('#type' => 'hidden', '#value' => $product->nid);
|
| 549 |
$form['products'][$i]['qty'] = array('#type' => 'hidden', '#value' => $product->qty);
|
| 550 |
}
|
| 551 |
}
|
| 552 |
$form['submit'] = array(
|
| 553 |
'#type' => 'submit',
|
| 554 |
'#value' => variable_get('uc_teaser_add_to_cart_text', t('Add to cart')),
|
| 555 |
'#id' => 'edit-submit-'. $node->nid,
|
| 556 |
'#attributes' => array(
|
| 557 |
'class' => 'list-add-to-cart',
|
| 558 |
),
|
| 559 |
);
|
| 560 |
return $form;
|
| 561 |
}
|
| 562 |
|
| 563 |
function uc_product_kit_buy_it_now_form_submit($form_id, $form_values) {
|
| 564 |
$node = node_load($form_values['nid']);
|
| 565 |
if (module_exists('uc_attribute')) {
|
| 566 |
$attributes = uc_product_get_attributes($node->nid);
|
| 567 |
if (!empty($attributes)) {
|
| 568 |
drupal_set_message(t('This product has options that need to be selected before purchase. Please select them in the form below.'), 'error');
|
| 569 |
return drupal_get_path_alias('node/'. $form_values['nid']);
|
| 570 |
}
|
| 571 |
if (is_array($node->products)) {
|
| 572 |
foreach ($node->products as $nid => $product) {
|
| 573 |
$attributes = uc_product_get_attributes($nid);
|
| 574 |
if (!empty($attributes)) {
|
| 575 |
drupal_set_message(t('This product has options that need to be selected before purchase. Please select them in the form below.'), 'error');
|
| 576 |
return drupal_get_path_alias('node/'. $form_values['nid']);
|
| 577 |
}
|
| 578 |
}
|
| 579 |
}
|
| 580 |
}
|
| 581 |
return uc_cart_add_item($form_values['nid'], 1, $form_values);
|
| 582 |
}
|
| 583 |
|
| 584 |
/******************************************************************************
|
| 585 |
* Übercart Hooks *
|
| 586 |
******************************************************************************/
|
| 587 |
|
| 588 |
function uc_product_kit_product_types() {
|
| 589 |
return array('product_kit');
|
| 590 |
}
|
| 591 |
|
| 592 |
function uc_product_kit_store_status() {
|
| 593 |
if (module_exists('imagefield')) {
|
| 594 |
$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'");
|
| 595 |
if (!db_num_rows($result)) {
|
| 596 |
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')))));
|
| 597 |
}
|
| 598 |
}
|
| 599 |
|
| 600 |
}
|
| 601 |
|
| 602 |
function uc_product_kit_add_to_cart($nid, $qty, $kit_data) {
|
| 603 |
$node = node_load($nid);
|
| 604 |
if ($node->type == 'product_kit') {
|
| 605 |
$unique = uniqid('', true);
|
| 606 |
foreach ($node->products as $product) {
|
| 607 |
$data = array('kit_id' => $node->nid, 'unique_id' => $unique, 'module' => 'uc_product_kit');
|
| 608 |
uc_cart_add_item($product->nid, $product->qty * $qty, $data + module_invoke_all('add_to_cart_data', $kit_data['products'][$product->nid]), null, true, false);
|
| 609 |
}
|
| 610 |
if ($check_redirect) {
|
| 611 |
if (isset($_GET['destination'])) {
|
| 612 |
drupal_goto();
|
| 613 |
}
|
| 614 |
|
| 615 |
$redirect = variable_get('uc_add_item_redirect', 'cart');
|
| 616 |
if ($redirect != '<none>') {
|
| 617 |
$_SESSION['last_url'] = referer_uri();
|
| 618 |
return $redirect;
|
| 619 |
}
|
| 620 |
else {
|
| 621 |
return referer_uri();
|
| 622 |
}
|
| 623 |
}
|
| 624 |
return array(array('success' => false, 'silent' => true, $message => ''));
|
| 625 |
}
|
| 626 |
}
|
| 627 |
|
| 628 |
/**
|
| 629 |
* Implementation of Übercart's hook_cart_item().
|
| 630 |
*/
|
| 631 |
function uc_product_kit_cart_item($op, &$item) {
|
| 632 |
switch ($op) {
|
| 633 |
case 'load':
|
| 634 |
if (isset($item->data['kit_id']) && ($kit = node_load($item->data['kit_id'])) && !$kit->mutable) {
|
| 635 |
$kit_discount = $kit->products[$item->nid]->discount;
|
| 636 |
if ($kit_discount !== '') {
|
| 637 |
if ($kit_discount < 0) {
|
| 638 |
$item->price += $kit_discount;
|
| 639 |
}
|
| 640 |
else {
|
| 641 |
$item->price += $kit_discount - $kit->products[$item->nid]->sell_price;
|
| 642 |
}
|
| 643 |
}
|
| 644 |
}
|
| 645 |
break;
|
| 646 |
}
|
| 647 |
}
|
| 648 |
|
| 649 |
/**
|
| 650 |
* Implementation of Übercart's hook_cart_display().
|
| 651 |
*
|
| 652 |
* Displays either the kit as a whole, or each individual product based on the
|
| 653 |
* store configuration. Each product in the cart that was added by uc_product_kit
|
| 654 |
* was also given a unique kit id in order to help prevent collisions. The side
|
| 655 |
* effect is that identical product kits are listed separately if added separately.
|
| 656 |
* The customer may still change the quantity of kits like other products.
|
| 657 |
*
|
| 658 |
* @param $item
|
| 659 |
* An item in the shopping cart.
|
| 660 |
* @return
|
| 661 |
* A form element array to be processed by uc_cart_view_form().
|
| 662 |
*/
|
| 663 |
function uc_product_kit_cart_display($item) {
|
| 664 |
static $elements = array();
|
| 665 |
static $products;
|
| 666 |
$unique_id = $item->data['unique_id'];
|
| 667 |
$kit = node_load($item->data['kit_id']);
|
| 668 |
//print '<pre>'. print_r($kit, true) .'</pre>';
|
| 669 |
if ($kit->mutable) {
|
| 670 |
return uc_product_cart_display($item);
|
| 671 |
}
|
| 672 |
else {
|
| 673 |
if (!isset($products[$unique_id])) {
|
| 674 |
// Initialize table row
|
| 675 |
$element = array();
|
| 676 |
$element['nid'] = array('#type' => 'value', '#value' => $kit->nid);
|
| 677 |
$element['module'] = array('#type' => 'value', '#value' => 'uc_product_kit');
|
| 678 |
$element['remove'] = array('#type' => 'checkbox');
|
| 679 |
$element['options'] = array('#value' => '<div class="item-list"><ul class="cart-options">'. "\n");
|
| 680 |
$element['title'] = array('#value' => l($kit->title, 'node/'. $kit->nid));
|
| 681 |
$element['#total'] = 0;
|
| 682 |
$element['qty'] = array(
|
| 683 |
'#type' => 'textfield',
|
| 684 |
'#default_value' => $item->qty / $kit->products[$item->nid]->qty,
|
| 685 |
'#size' => 3,
|
| 686 |
'#maxlength' => 3,
|
| 687 |
);
|
| 688 |
$elements[$unique_id] = $element;
|
| 689 |
}
|
| 690 |
// Add product specific information
|
| 691 |
$op_names = '';
|
| 692 |
foreach ($item->options as $option) {
|
| 693 |
$op_names .= $option['name'] .', ';
|
| 694 |
}
|
| 695 |
$op_names = substr($op_names, 0, strlen($op_names) - 2);
|
| 696 |
if ($op_names) {
|
| 697 |
$op_names = '-- '. $op_names;
|
| 698 |
}
|
| 699 |
$elements[$unique_id]['options']['#value'] .= '<li>'. $item->qty .' x '. l($item->title, 'node/'. $item->nid) ." <em>$op_names</em></li>\n";
|
| 700 |
$elements[$unique_id]['#total'] += $item->price * $item->qty;
|
| 701 |
$elements[$unique_id]['data'][$item->nid] = $item;
|
| 702 |
$products[$unique_id][] = $item->nid;
|
| 703 |
// Check if all products in this kit have been accounted for.
|
| 704 |
$done = true;
|
| 705 |
foreach ($kit->products as $product) {
|
| 706 |
if (!in_array($product->nid, $products[$unique_id])) {
|
| 707 |
$done = false;
|
| 708 |
break;
|
| 709 |
}
|
| 710 |
}
|
| 711 |
if ($done) {
|
| 712 |
$elements[$unique_id]['data'] = array('#type' => 'value', '#value' => serialize($elements[$unique_id]['data']));
|
| 713 |
$elements[$unique_id]['options']['#value'] .= "</ul></div>\n";
|
| 714 |
$element = $elements[$unique_id];
|
| 715 |
unset($products[$unique_id]);
|
| 716 |
unset($elements[$unique_id]);
|
| 717 |
return $element;
|
| 718 |
}
|
| 719 |
}
|
| 720 |
return array();
|
| 721 |
}
|
| 722 |
|
| 723 |
/**
|
| 724 |
* Implementation of Übercart's hook_update_cart_item().
|
| 725 |
*
|
| 726 |
* Handles individual products or entire kits.
|
| 727 |
*/
|
| 728 |
function uc_product_kit_update_cart_item($nid, $data = array(), $qty, $cid = null) {
|
| 729 |
if (!$nid) return NULL;
|
| 730 |
$cid = !(is_null($cid) || empty($cid)) ? $cid : uc_cart_get_id();
|
| 731 |
if ($qty < 1) {
|
| 732 |
foreach ($data as $p_nid => $product) {
|
| 733 |
uc_cart_remove_item($p_nid, $cid, $product->data);
|
| 734 |
}
|
| 735 |
}
|
| 736 |
else {
|
| 737 |
if (isset($data['kit_id'])) { // Product was listed individually
|
| 738 |
uc_product_update_cart_item($nid, $data, $qty, $cid);
|
| 739 |
}
|
| 740 |
else {
|
| 741 |
$kit = node_load($nid);
|
| 742 |
foreach ($data as $p_nid => $product) {
|
| 743 |
uc_product_update_cart_item($p_nid, $product->data, $qty * $kit->products[$p_nid]->qty, $cid);
|
| 744 |
}
|
| 745 |
}
|
| 746 |
}
|
| 747 |
}
|
| 748 |
|
| 749 |
/**
|
| 750 |
* usort() callback.
|
| 751 |
*/
|
| 752 |
function _uc_product_kit_sort_products($a, $b) {
|
| 753 |
if ($a->ordering == $b->ordering) {
|
| 754 |
return 0;
|
| 755 |
}
|
| 756 |
else {
|
| 757 |
return ($a->ordering < $b->ordering) ? -1 : 1;
|
| 758 |
}
|
| 759 |
}
|