'products',
'title' => t('Products'),
'description' => t('List all published product nodes.'),
'access' => user_access('access content'),
'callback' => 'uc_product_default',
'type' => MENU_SUGGESTED_ITEM,
);
$items[] = array(
'path' => 'admin/store/products',
'title' => t('Products'),
'description' => t('Administer products, classes, and more.'),
'access' => user_access('administer products'),
'callback' => 'uc_product_administration',
'type' => MENU_NORMAL_ITEM,
'weight' => -2,
);
$items[] = array(
'path' => 'admin/store/products/view',
'title' => t('View products'),
'description' => t('Build and view a list of product nodes.'),
'access' => user_access('administer products'),
'type' => MENU_NORMAL_ITEM,
'weight' => -10,
);
$items[] = array(
'path' => 'admin/store/products/classes',
'title' => t('Manage classes'),
'description' => t('Create and edit product node types.'),
'access' => user_access('administer product classes'),
'callback' => 'uc_product_class_default',
'type' => MENU_NORMAL_ITEM,
'weight' => -2,
);
$items[] = array(
'path' => 'admin/store/settings/products',
'title' => t('Product settings'),
'description' => t('Configure product settings.'),
'access' => user_access('administer products'),
'callback' => 'uc_product_settings_overview',
'type' => MENU_NORMAL_ITEM,
);
$items[] = array(
'path' => 'admin/store/settings/products/overview',
'title' => t('Overview'),
'weight' => -10,
'type' => MENU_DEFAULT_LOCAL_TASK,
);
$items[] = array(
'path' => 'admin/store/settings/products/edit',
'title' => t('Edit'),
'access' => user_access('administer products'),
'callback' => 'drupal_get_form',
'callback arguments' => array('uc_product_settings_form'),
'weight' => -5,
'type' => MENU_LOCAL_TASK,
);
$items[] = array(
'path' => 'admin/store/settings/products/edit/general',
'title' => t('Product settings'),
'access' => user_access('administer products'),
'weight' => -10,
'type' => MENU_DEFAULT_LOCAL_TASK,
);
$items[] = array(
'path' => 'admin/store/settings/products/edit/fields',
'title' => t('Product fields'),
'callback' => 'drupal_get_form',
'callback arguments' => array('uc_product_field_settings_form'),
'access' => user_access('administer products'),
'weight' => -5,
'type' => MENU_LOCAL_TASK,
);
$items[] = array(
'path' => 'admin/store/settings/products/edit/features',
'title' => t('Product features'),
'callback' => 'drupal_get_form',
'callback arguments' => array('uc_product_feature_settings_form'),
'access' => user_access('administer product features'),
'weight' => 0,
'type' => MENU_LOCAL_TASK,
);
}
else {
// Insert subitems into the edit node page for product types.
if (arg(0) == 'node' && is_numeric(arg(1)) && arg(2) == 'edit') {
$node = node_load(arg(1));
if ($node->nid && in_array($node->type, module_invoke_all('product_types'))) {
$items[] = array('path' => 'node/'. arg(1) .'/edit/product',
'title' => t('Product'),
'weight' => -10,
'type' => MENU_DEFAULT_LOCAL_TASK,
);
$features = module_invoke_all('product_feature');
if (!empty($features)) {
$items[] = array('path' => 'node/'. arg(1) .'/edit/features',
'title' => t('Features'),
'callback' => 'uc_product_features',
'callback arguments' => array($node),
'access' => user_access('administer product features'),
'weight' => 10,
'type' => MENU_LOCAL_TASK,
);
}
}
}
$items[] = array('path' => 'admin/store/settings/products/defaults/'. arg(5),
'title' => t('Imagecache default settings'),
'access' => user_access('administer products'),
'callback' => 'uc_product_image_defaults',
'callback arguments' => array(arg(5)),
'type' => MENU_CALLBACK,
);
$items[] = array(
'path' => 'admin/store/products/classes/'. arg(4),
'title' => t('Product class'),
'access' => user_access('administer product classes'),
'callback' => 'drupal_get_form',
'callback arguments' => array('uc_product_class_form', arg(4)),
'type' => MENU_CALLBACK,
);
$items[] = array(
'path' => 'admin/store/products/classes/'. arg(4) .'/edit',
'title' => t('Edit'),
'type' => MENU_DEFAULT_LOCAL_TASK,
'weight' => -5,
);
$items[] = array('path' => 'admin/store/products/classes/'. arg(4) .'/delete',
'access' => user_access('administer product classes'),
'callback' => 'drupal_get_form',
'callback arguments' => array('uc_product_class_delete_confirm', arg(4)),
'type' => MENU_CALLBACK,
);
$items[] = array('path' => 'products/field_image_cache/'. arg(2),
'access' => true,
'callback' => '_uc_product_get_image_field_filepath',
'callback arguments' => array(arg(2)),
'type' => MENU_CALLBACK,
);
drupal_add_css(drupal_get_path('module', 'uc_product') .'/uc_product.css');
}
return $items;
}
/**
* Implementation of hook_help().
*/
function uc_product_help($section = '') {
// Do things here later. Figure out what you need to say for each section.
switch ($section) {
case 'admin/settings/module#description':
$output = t('Create products for sale in an online store.');
break;
}
return $output;
}
/**
* Implementation of hook_perm().
*/
function uc_product_perm() {
$perms = array('administer products', 'administer product classes', 'administer product features');
foreach (node_get_types() as $type) {
if ($type->module == 'uc_product') {
$name = check_plain($type->type);
if ($name == 'product') {
$name = '';
}
else {
$name .= ' ';
}
$perms[] = 'create '. $name .'products';
$perms[] = 'edit own '. $name .'products';
$perms[] = 'edit '. $name .'products';
}
}
return $perms;
}
/**
* Implementation of hook_access().
*/
function uc_product_access($op, $node) {
global $user;
$type = is_string($node) ? $node : (is_array($node) ? $node['type'] : $node->type);
if ($type == 'product') {
$type = '';
}
else {
$type .= ' ';
}
switch ($op) {
case 'create':
return user_access('create '. $type .'products');
case 'update':
case 'delete':
if (user_access('edit '. $type .'products') || (user_access('edit own '. $type .'products') && ($user->uid == $node->uid))) {
return TRUE;
}
}
}
/**
* Implementation of hook_enable().
*
* Set up default imagefield and imagecache settings.
*/
function uc_product_enable() {
$node_types = node_get_types('types');
$product_classes = array('product');
$result = db_query("SELECT pcid, name, description FROM {uc_product_classes}");
while ($product_class = db_fetch_object($result)) {
$product_classes[] = $product_class->pcid;
}
foreach ($node_types as $type => $info) {
if ($info->module == 'node' && in_array($type, $product_classes)) {
$info->module = 'uc_product';
$info->custom = 0;
node_type_save($info);
}
}
if (module_exists('imagefield')) {
$result = db_query("SELECT field_name FROM {node_field} WHERE field_name = 'field_image_cache' AND type = 'image'");
if (!db_num_rows($result)) {
db_query("INSERT INTO {node_field} (field_name, type, global_settings, required, multiple, db_storage) VALUES ('field_image_cache', 'image', '%s', 0, 1, 0)", 'a:0:{}');
}
$image_path = file_create_path();
$widget_settings = array(
'max_resolution' => '0',
'image_path' => $image_path,
'custom_alt' => 1,
'custom_title' => 1,
'teaser_preset' => null,
'body_preset' => null,
);
$display_settings = array(
'label' => array(
'format' => 'hidden',
),
'teaser' => array(
'format' => 'hidden',
),
'full' => array(
'format' => 'hidden',
),
);
foreach (module_invoke_all('product_types') as $type) {
$result = db_query("SELECT * FROM {node_field_instance} WHERE field_name = 'field_image_cache' and type_name = '%s'", $type);
if (!db_num_rows($result)) {
db_query("INSERT INTO {node_field_instance} VALUES ('field_image_cache', '%s', -2, 'Image', 'image', '%s', '%s', '')", $type, serialize($widget_settings), serialize($display_settings));
}
switch ($GLOBALS['db_type']) {
case 'mysql':
case 'mysqli':
db_query("CREATE TABLE IF NOT EXISTS {content_field_image_cache} (
`vid` int(10) unsigned NOT NULL default '0',
`delta` int(10) unsigned NOT NULL default '0',
`nid` int(10) unsigned NOT NULL default '0',
`field_image_cache_fid` int(11) NOT NULL default '0',
`field_image_cache_title` varchar(255) NOT NULL default '',
`field_image_cache_alt` varchar(255) NOT NULL default '',
PRIMARY KEY (`vid`,`delta`)
) /*!40100 DEFAULT CHARACTER SET utf8 */;");
break;
case 'pgsql':
$result = db_query("SELECT relname FROM pg_class WHERE relname = '{content_field_image_cache}'");
if (!db_num_rows($result)) {
db_query('CREATE TABLE {content_field_image_cache} (
"vid" int_unsigned NOT NULL default \'0\',
"delta" int_unsigned NOT NULL default \'0\',
"nid" int_unsigned NOT NULL default \'0\',
"field_image_cache_fid" integer NOT NULL default \'0\',
"field_image_cache_title" varchar(255) NOT NULL,
"field_image_cache_alt" varchar(255) NOT NULL,
PRIMARY KEY ("vid","delta")
);');
}
break;
}
}
content_clear_type_cache();
}
if (module_exists('imagecache')) {
$presets = array('product' => 0, 'product_list' => 0, 'uc_thumbnail' => 0);
$result = db_query("SELECT * FROM {imagecache_preset} WHERE presetname IN ('". implode("','", array_keys($presets)) ."')");
while ($preset = db_fetch_array($result)) {
$presets[$preset['presetname']] = $preset['presetid'];
}
//drupal_set_message('
'. print_r($presets, true) .'
');
foreach ($presets as $name => $id) {
if ($id == 0) {
$id = db_next_id('{imagecache_preset}_presetid');
db_query("INSERT INTO {imagecache_preset} (presetid, presetname) VALUES (%d, '%s')", $id, $name);
}
}
$result = db_query("SELECT ia.actionid, ip.presetid, ip.presetname FROM {imagecache_preset} AS ip LEFT JOIN {imagecache_action} AS ia ON ip.presetid = ia.presetid WHERE ip.presetname IN ('". implode("','", array_keys($presets)) ."')");
$presets = array();
while ($preset = db_fetch_array($result)) {
if (is_null($preset['actionid'])) {
switch ($preset['presetname']) {
case 'product':
db_query("INSERT INTO {imagecache_action} (actionid, presetid, weight, data) VALUES (%d, %d, 0, '%s')", db_next_id('{imagecache_action}_actionid'), $preset['presetid'], 'a:4:{s:8:"function";s:5:"scale";s:3:"fit";s:6:"inside";s:5:"width";s:3:"100";s:6:"height";s:3:"100";}');
break;
case 'product_list':
db_query("INSERT INTO {imagecache_action} (actionid, presetid, weight, data) VALUES (%d, %d, 0, '%s')", db_next_id('{imagecache_action}_actionid'), $preset['presetid'], 'a:4:{s:8:"function";s:5:"scale";s:3:"fit";s:6:"inside";s:5:"width";s:3:"100";s:6:"height";s:3:"100";}');
break;
case 'uc_thumbnail':
db_query("INSERT INTO {imagecache_action} (actionid, presetid, weight, data) VALUES (%d, %d, 0, '%s')", db_next_id('{imagecache_action}_actionid'), $preset['presetid'], 'a:4:{s:8:"function";s:5:"scale";s:3:"fit";s:6:"inside";s:5:"width";s:2:"35";s:6:"height";s:2:"35";}');
break;
}
}
}
cache_clear_all('imagecache:presets', 'cache');
}
}
function uc_product_disable() {
$product_types = node_get_types('types');
// node_type_rebuild() deletes disabled modules' node types. Give these
// node types to node.module to prevent this. Get them back during
// hook_enable().
foreach ($product_types as $type) {
if ($type->module == 'uc_product') {
$type->module = 'node';
$type->custom = 1;
node_type_save($type);
}
}
}
/**
* Implementation of hook_node_info().
*
* Create node types for each product class and other product modules.
*/
function uc_product_node_info($reset = false) {
static $types = array();
$title_label = t('Name');
$body_label = t('Description');
if (empty($types) || $reset) {
$types = array();
$types['product'] = array(
'name' => t('Product'),
'module' => 'uc_product',
'description' => t('This node displays the representation of a product for sale on the website. It includes all the unique information that can be attributed to a specific model number.'),
'title_label' => $title_label,
'body_label' => $body_label,
);
$result = db_query("SELECT pcid, name, description FROM {uc_product_classes}");
while ($class = db_fetch_object($result)) {
$types[$class->pcid] = array(
'name' => $class->name,
'module' => 'uc_product',
'description' => $class->description,
'title_label' => $title_label,
'body_label' => $body_label,
);
}
}
return $types;
}
/**
* Implementation of hook_forms().
*
* Register an "add to cart" form for each product to prevent id collisions.
*/
function uc_product_forms($saved_args) {
$forms = array();
if (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 (in_array($product->type, array_keys(uc_product_node_info()))) {
$forms['uc_product_add_to_cart_form_'. $product->nid] = array('callback' => 'uc_product_add_to_cart_form');
$forms['uc_catalog_buy_it_now_form_'. $product->nid] = array('callback' => 'uc_catalog_buy_it_now_form');
}
}
return $forms;
}
/**
* Implementation of hook_form().
*
* @ingroup forms
* @see theme_uc_product_form_prices
* @see theme_uc_product_form_weight
* @see theme_uc_product_dimensions
* @see uc_product_form_validate
*/
function uc_product_form(&$node) {
$type = node_get_types('type', $node);
$location = array();
$location[] = menu_get_item(null, 'admin');
$location[] = menu_get_item(null, 'admin/store');
$location[] = menu_get_item(null, 'admin/store/products');
$location[] = menu_get_item(null, 'admin/store/settings/products');
$breadcrumb = array();
foreach ($location as $item) {
$breadcrumb[] = l($item['title'], $item['path']);
}
drupal_set_breadcrumb($breadcrumb);
$sign_flag = variable_get('uc_sign_after_amount', FALSE);
$currency_sign = variable_get('uc_currency_sign', '$');
$form['title'] = array('#type' => 'textfield',
'#title' => $type->title_label,
'#required' => TRUE,
'#weight' => -5,
'#default_value' => $node->title,
'#description' => t('Name of the product.')
);
if ($type->has_body) {
$form['body_filter']['body'] = array('#type' => 'textarea',
'#title' => $type->body_label,
'#required' => FALSE,
'#default_value' => $node->body,
'#rows' => 20,
'#description' => t('Enter the product description used for product teasers and pages.'),
);
$form['body_filter']['format'] = filter_form($node->format);
$form['body_filter']['#weight'] = -4;
}
$form['base'] = array('#type' => 'fieldset',
'#title' => t('Product information'),
'#collapsible' => true,
'#collapsed' => false,
'#weight' => -1,
'#attributes' => array('class' => 'product-field'),
);
$form['base']['model'] = array('#type' => 'textfield',
'#title' => t('SKU'),
'#required' => TRUE,
'#default_value' => $node->model,
'#description' => t('Product SKU/model.'),
'#weight' => 0,
'#size' => 32,
);
$form['base']['prices'] = array(
'#weight' => 5,
'#theme' => 'uc_product_form_prices',
);
$form['base']['prices']['list_price'] = array(
'#type' => 'textfield',
'#title' => t('List price'),
'#required' => FALSE,
'#default_value' => $node->list_price,
'#description' => t('The listed MSRP.'),
'#weight' => 0,
'#size' => 20,
'#maxlength' => 35,
'#field_prefix' => $sign_flag ? '' : $currency_sign,
'#field_suffix' => $sign_flag ? $currency_sign : '',
);
$form['base']['prices']['cost'] = array(
'#type' => 'textfield',
'#title' => t('Cost'),
'#required' => FALSE,
'#default_value' => $node->cost,
'#description' => t("Your store's cost."),
'#weight' => 1,
'#size' => 20,
'#maxlength' => 35,
'#field_prefix' => $sign_flag ? '' : $currency_sign,
'#field_suffix' => $sign_flag ? $currency_sign : '',
);
$form['base']['prices']['sell_price'] = array(
'#type' => 'textfield',
'#title' => t('Sell price'),
'#required' => TRUE,
'#default_value' => $node->sell_price,
'#description' => t('Customer purchase price.'),
'#weight' => 2,
'#size' => 20,
'#maxlength' => 35,
'#field_prefix' => $sign_flag ? '' : $currency_sign,
'#field_suffix' => $sign_flag ? $currency_sign : '',
);
$form['base']['shippable'] = array(
'#type' => 'checkbox',
'#title' => t('Product and its derivatives are shippable.'),
'#default_value' => isset($node->shippable) ? $node->shippable : TRUE,
'#weight' => 10,
);
$form['base']['weight'] = array(
'#weight' => 15,
'#theme' => 'uc_product_form_weight',
);
$form['base']['weight']['weight'] = array('#type' => 'textfield',
'#title' => t('Weight'),
'#default_value' => $node->weight,
'#size' => 10,
'#maxlength' => 15,
);
$units = array(
'lb' => t('Pounds'),
'kg' => t('Kilograms'),
'oz' => t('Ounces'),
'g' => t('Grams'),
);
$form['base']['weight']['weight_units'] = array('#type' => 'select',
'#title' => t('Unit of measurement'),
'#default_value' => $node->weight_units ? $node->weight_units : variable_get('uc_weight_unit', 'lb'),
'#options' => $units,
);
$form['base']['dimensions'] = array('#type' => 'fieldset',
'#title' => t('Dimensions'),
'#description' => t('Physical dimensions of the packaged product.'),
'#weight' => 20,
'#theme' => 'uc_product_dimensions_form',
);
$form['base']['dimensions']['length_units'] = array('#type' => 'select',
'#title' => t('Units of measurement'),
'#options' => array(
'in' => t('Inches'),
'ft' => t('Feet'),
'cm' => t('Centimeters'),
'mm' => t('Millimeters'),
),
'#default_value' => $node->length_units ? $node->length_units : variable_get('uc_length_unit', 'in'),
);
$form['base']['dimensions']['length'] = array('#type' => 'textfield',
'#title' => t('Length'),
'#default_value' => $node->length,
'#size' => 10,
);
$form['base']['dimensions']['width'] = array('#type' => 'textfield',
'#title' => t('Width'),
'#default_value' => $node->width,
'#size' => 10,
);
$form['base']['dimensions']['height'] = array('#type' => 'textfield',
'#title' => t('Height'),
'#default_value' => $node->height,
'#size' => 10,
);
$form['base']['pkg_qty'] = array('#type' => 'textfield',
'#title' => t('Package quantity'),
'#default_value' => $node->pkg_qty ? $node->pkg_qty : 1,
'#description' => t('For a package containing only this product, how many are in it?'),
'#weight' => 25,
);
$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 position'),
'#description' => t("Specify a value to set this product's position in product lists.
Products in the same position will be sorted alphabetically."),
'#delta' => 25,
'#default_value' => $node->ordering,
'#weight' => 30,
);
return $form;
}
/**
* @ingroup themeable
*/
function theme_uc_product_form_prices($prices) {
return ''. "\n". drupal_render($prices['list_price'])
.' | '. drupal_render($prices['cost'])
.' | '. drupal_render($prices['sell_price'])
." |
\n";
}
/**
* @ingroup themeable
*/
function theme_uc_product_form_weight($form) {
return '' . drupal_render($form['weight']) .' | '
. drupal_render($form['weight_units']) .' |
';
}
/**
* Put length, width, and height fields on the same line.
*
* @ingroup themeable
*/
function theme_uc_product_dimensions_form($form) {
$output = '';
$row = array();
foreach (element_children($form) as $dimension) {
$row[] = drupal_render($form[$dimension]);
}
$output .= theme('table', array(), array($row));
return $output;
}
function uc_product_validate($node) {
$pattern = '/^\d*(\.\d*)?$/';
$price_error = t('Price must be in a valid number format. No commas and only one decimal point.');
if (!empty($node->list_price) && !is_numeric($node->list_price) && !preg_match($pattern, $node->list_price)) {
form_set_error('list_price', $price_error);
}
if (!empty($node->cost) && !is_numeric($node->cost) && !preg_match($pattern, $node->cost)) {
form_set_error('cost', $price_error);
}
if (!is_numeric($node->sell_price) && !preg_match($pattern, $node->sell_price)) {
form_set_error('sell_price', $price_error);
}
if (!empty($node->weight) && !is_numeric($node->weight)) {
form_set_error('weight', t('Weight must be in a valid number format. No commas and only one decimal point.'));
}
if ($node->default_qty) {
if (!is_numeric($node->default_qty)) {
form_set_error('default_qty', t('Quantities should be numeric.'));
}
else if ($node->default_qty < 0) {
form_set_error('default_qty', t("Adding negative items to the cart doesn't make sense, so don't make it easy."));
}
}
}
/**
* Implementation of hook_insert().
*/
function uc_product_insert($node) {
if (!isset($node->unique_hash)) {
$node->unique_hash = md5($node->vid . $node->nid . $node->model . $node->list_price . $node->cost . $node->sell_price . $node->weight . $node->weight_units . $node->length . $node->width . $node->height . $node->length_units . $node->pkg_qty . $node->default_qty . $node->shippable . time());
}
db_query("INSERT INTO {uc_products} (vid, nid, model, list_price, cost, sell_price, weight, weight_units, length, width, height, length_units, pkg_qty, default_qty, unique_hash, ordering, shippable) VALUES (%d, %d, '%s', %f, %f, %f, %f, '%s', %f, %f, %f, '%s', %d, %d, '%s', %d, %d)",
$node->vid, $node->nid, $node->model, $node->list_price, $node->cost, $node->sell_price, $node->weight, $node->weight_units, $node->length, $node->width, $node->height, $node->length_units, $node->pkg_qty, $node->default_qty, $node->unique_hash, $node->ordering, $node->shippable
);
}
/**
* Implementation of hook_update().
*/
function uc_product_update($node) {
if ($node->revision) {
db_query("INSERT INTO {uc_products} (vid, nid, model, list_price, cost, sell_price, weight, weight_units, length, width, height, length_units, pkg_qty, default_qty, unique_hash, ordering, shippable) VALUES (%d, %d, '%s', %f, %f, %f, %f, '%s', %f, %f, %f, '%s', %d, %d, '%s', %d, %d)",
$node->vid, $node->nid, $node->model, $node->list_price, $node->cost, $node->sell_price, $node->weight, $node->weight_units, $node->length, $node->width, $node->height, $node->length_units, $node->pkg_qty, $node->default_qty, $node->unique_hash, $node->ordering, $node->shippable
);
}
else {
//drupal_set_message(''. print_r($node, true) .'
');drupal_set_message(''. print_r($node, true) .'
');
db_query("UPDATE {uc_products} SET model = '%s', list_price = %f, cost = %f, sell_price = %f, weight = %f, weight_units = '%s', length = %f, width = %f, height = %f, length_units = '%s', pkg_qty = %d, default_qty = %d, ordering = %d, shippable = %d WHERE vid = %d",
$node->model, $node->list_price, $node->cost, $node->sell_price, $node->weight, $node->weight_units, $node->length, $node->width, $node->height, $node->length_units, $node->pkg_qty, $node->default_qty, $node->ordering, $node->shippable, $node->vid);
}
}
/**
* Implementation of hook_load().
*/
function uc_product_load(&$node) {
return db_fetch_object(db_query('SELECT model, list_price, cost, sell_price, weight, weight_units, length, width, height, length_units, pkg_qty, default_qty, unique_hash, ordering, shippable FROM {uc_products} WHERE vid = %d', $node->vid));
}
/**
* Implementation of hook_delete().
*/
function uc_product_delete(&$node) {
db_query("DELETE from {uc_products} WHERE nid = %d", $node->nid);
}
/**
* Implementation of hook_view().
*/
function uc_product_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,
));
//drupal_set_message(''. print_r($node->field_image_cache, true) .'
');
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, $teaser, $page),
'#access' => $enabled['image'] && module_exists('imagecache'),
'#weight' => $weight['image'],
);
}
$node->content['display_price'] = array('#value' => theme('uc_product_display_price', $node->sell_price, $teaser, $page),
'#access' => $enabled['display_price'],
'#weight' => $weight['display_price'],
);
if (!$teaser) {
$node->content['model'] = array('#value' => theme('uc_product_model', $node->model, $teaser, $page),
'#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', $teaser, $page),
'#access' => $enabled['list_price'],
'#weight' => $weight['list_price'],
);
$node->content['cost'] = array('#value' => theme('uc_product_price', $node->cost, 'cost', $teaser, $page),
'#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, $page),
'#access' => $enabled['sell_price'],
'#weight' => $weight['sell_price'],
);
if (!$teaser) {
$node->content['weight'] = array('#value' => theme('uc_product_weight', $node->weight, $node->weight_units, $teaser, $page),
'#access' => $enabled['weight'],
'#weight' => $weight['weight'],
);
$node->content['dimensions'] = array('#value' => theme('uc_product_dimensions', $node->length, $node->width, $node->height, $node->length_units, $teaser, $page),
'#access' => $enabled['dimensions'],
'#weight' => $weight['dimensions'],
);
if (module_exists('uc_cart')) {
$node->content['add_to_cart'] = array('#value' => theme('uc_product_add_to_cart', $node, $teaser, $page),
'#access' => $enabled['add_to_cart'],
'#weight' => $weight['add_to_cart'],
);
}
}
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_add_to_cart', $node, $teaser, $page),
'#access' => $enabled['add_to_cart'],
'#weight' => $weight['add_to_cart'],
);
}
//drupal_set_message(''. print_r($breadcrumb, true) .'
');
return $node;
}
function uc_product_form_alter($form_id, &$form) {
if ($form_id == 'search_form' && arg(0) == 'admin' && arg(1) == 'store' && arg(2) == 'products' && user_access('use advanced search')) {
// Keyword boxes:
$form['advanced'] = array(
'#type' => 'fieldset',
'#title' => t('Advanced search'),
'#collapsible' => TRUE,
'#collapsed' => TRUE,
'#attributes' => array('class' => 'search-advanced'),
);
$form['advanced']['keywords'] = array(
'#prefix' => '',
'#suffix' => '
',
);
$form['advanced']['keywords']['or'] = array(
'#type' => 'textfield',
'#title' => t('Containing any of the words'),
'#size' => 30,
'#maxlength' => 255,
);
$form['advanced']['keywords']['phrase'] = array(
'#type' => 'textfield',
'#title' => t('Containing the phrase'),
'#size' => 30,
'#maxlength' => 255,
);
$form['advanced']['keywords']['negative'] = array(
'#type' => 'textfield',
'#title' => t('Containing none of the words'),
'#size' => 30,
'#maxlength' => 255,
);
// Taxonomy box:
if ($taxonomy = module_invoke('taxonomy', 'form_all', 1)) {
$form['advanced']['category'] = array(
'#type' => 'select',
'#title' => t('Only in the category(s)'),
'#prefix' => '',
'#size' => 10,
'#suffix' => '
',
'#options' => $taxonomy,
'#multiple' => TRUE,
);
}
// Node types:
$types = array();
$product_types = module_invoke_all('product_types');
$node_types = module_invoke_all('node_info');
foreach ($product_types as $id) {
$types[$id] = $node_types[$id]['name'];
}
$form['advanced']['type'] = array(
'#type' => 'checkboxes',
'#title' => t('Only of the type(s)'),
'#prefix' => '',
'#suffix' => '
',
'#options' => $types,
);
$form['advanced']['submit'] = array(
'#type' => 'submit',
'#value' => t('Advanced search'),
'#prefix' => '',
'#suffix' => '
',
);
$form['#validate']['node_search_validate'] = array();
}
}
/* function uc_product_search($op, $keys = null) {
switch ($op) {
case 'name':
return t('Products');
}
} */
/******************************************************************************
* TAPIr Hooks *
******************************************************************************/
/**
* Define up the product list table.
*
* @see uc_product_table
*/
function uc_product_table_settings() {
$tables = array();
$tables[] = array(
'id' => 'uc_product_table',
'description' => t('Lists a group of products in an abbreviated format.'),
'path' => 'admin/store/settings/tables',
'access' => 'administer store',
'preview' => FALSE,
);
return $tables;
}
/**
* Display product fields in a TAPIr table.
*
* Display image, name, price, and add to cart form.
*/
function uc_product_table($op, $args = array()) {
switch ($op) {
case 'fields':
$fields = array();
$fields[] = array('name' => 'image', 'title' => t('Image'), 'weight' => -5, 'enabled' => module_exists('imagecache'));
$fields[] = array('name' => 'name', 'title' => t('Name'), 'weight' => 0, 'enabled' => true, 'attributes' => array('field' => 'n.title'));
$fields[] = array('name' => 'list_price', 'title' => t('List price'), 'weight' => 3, 'enabled' => false, 'attributes' => array('field' => 'p.list_price'));
$fields[] = array('name' => 'price', 'title' => t('Price'), 'weight' => 5, 'enabled' => true, 'attributes' => array('field' => 'p.sell_price'));
if (module_exists('uc_cart') && (arg(0) != 'admin' || $_GET['q'] == 'admin/store/settings/tables/uc_product_table')) {
$fields[] = array(
'name' => 'add_to_cart',
'title' => t('Add to cart'),
'weight' => 10,
'enabled' => false,
'attributes' => array('nowrap' => 'nowrap'),
);
}
return $fields;
case 'data':
$data = array();
foreach ($args['nids'] as $nid) {
$node = node_load($nid);
if ($node->type != 'image') {
if (module_exists('imagecache') && isset($node->field_image_cache) && file_exists($node->field_image_cache[0]['filepath'])) {
$data['image'][] = l(theme('imagecache', 'product_list', $node->field_image_cache[0]['filepath'], $node->field_image_cache[0]['alt'], $node->field_image_cache[0]['title']), 'node/'. $node->nid, array(), null, null, false, true);
}
else {
$data['image'][] = t('n/a');
}
$data['name'][] = array('data' => l($node->title, 'node/'. $node->nid), 'width' => '100%');
$data['list_price'][] = array('data' => theme('uc_product_price', $node->list_price, 'list_price'), 'nowrap' => 'nowrap');
$data['price'][] = array('data' => theme('uc_product_sell_price', $node->sell_price, true), 'nowrap' => 'nowrap');
if (module_exists('uc_cart') && arg(0) != 'admin') {
$data['add_to_cart'][] = drupal_get_form('uc_catalog_buy_it_now_form_'. $node->nid, $node);
}
}
}
return $data;
case 'attributes':
return $args['attributes'];
}
}
/**
* @ingroup forms
* @see uc_product_forms
* @see uc_catalog_buy_it_now_form_submit
*/
function uc_catalog_buy_it_now_form($node) {
$form = array();
$form['#base'] = 'uc_catalog_buy_it_now_form';
$form['nid'] = array('#type' => 'hidden', '#value' => $node->nid);
$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_catalog_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, module_invoke_all('add_to_cart_data', $form_values));
}
/******************************************************************************
* Token Hooks *
******************************************************************************/
/**
* Provide product token values.
*/
function uc_product_token_values($type, $object = NULL, $options = array()) {
if ($type == 'node' && uc_product_is_product($object)) {
$tokens = array();
$tokens['model'] = $object->model;
$tokens['list_price'] = $object->list_price;
$tokens['cost'] = $object->cost;
$tokens['sell_price'] = $object->sell_price;
$tokens['weight_units'] = $object->weight_units;
$tokens['weight-raw'] = $object->weight;
$tokens['weight'] = uc_weight_format($object->weight, $object->weight_units);
$tokens['length_units'] = $object->length_units;
$tokens['length-raw'] = $object->length;
$tokens['length'] = uc_length_format($object->length, $object->length_units);
$tokens['width-raw'] = $object->width;
$tokens['width'] = uc_length_format($object->width, $object->length_units);
$tokens['height-raw'] = $object->height;
$tokens['height'] = uc_length_format($object->height, $object->length_units);
return $tokens;
}
}
function uc_product_token_list($type = 'all') {
if ($type == 'node' || $type == 'product' || $type == 'ubercart' || $type == 'all') {
$tokens = array();
$tokens['product']['model'] = t("The product's model number.");
$tokens['product']['list_price'] = t("The product's list price.");
$tokens['product']['cost'] = t("The product's cost.");
$tokens['product']['sell_price'] = t("The product's sell price.");
$tokens['product']['weight_units'] = t("The unit of measurement for the product's weight.");
$tokens['product']['weight-raw'] = t("The numerical value of the product's weight.");
$tokens['product']['weight'] = t("The product's formatted weight.");
$tokens['product']['length_units'] = t("The unit of measurement for the product's length, width, and height.");
$tokens['product']['length-raw'] = t("The numerical value of the product's length.");
$tokens['product']['length'] = t("The product's formatted length.");
$tokens['product']['width-raw'] = t("The numerical value of the product's width.");
$tokens['product']['width'] = t("The product's formatted width.");
$tokens['product']['height-raw'] = t("The numerical value of the product's height.");
$tokens['product']['height'] = t("The product's formatted height.");
return $tokens;
}
}
/******************************************************************************
* Views Hooks *
******************************************************************************/
/**
* Implementation of hook_views_tables()
*
* @see uc_views_handler_price
* @see uc_views_handler_weight
* @see uc_product_views_handler_add_to_cart_link
* @see uc_product_views_handler_filter_product
*/
function uc_product_views_tables() {
$tables['uc_products'] = array(
'name' => 'uc_products',
'join' => array(
'left' => array(
'table' => 'node',
'field' => 'vid'
),
'right' => array(
'field' => 'vid'
),
),
'fields' => array(
'model' => array(
'name' => t('Product: SKU'),
'help' => t('Model number'),
'handler' => 'views_handler_field_nodelink',
'option' => array(
'#type' => 'select',
'#options' => array(
'link' => 'As link',
'nolink' => 'Without link'
),
),
'sortable' => TRUE,
),
'list_price' => array(
'name' => t('Product: List price'),
'help' => t("Manufacturer's suggested price"),
'handler' => 'uc_views_handler_price',
'sortable' => TRUE,
),
'cost' => array(
'name' => t('Product: Cost'),
'help' => t('Amount to buy the unit'),
'handler' => 'uc_views_handler_price',
'sortable' => TRUE,
),
'sell_price' => array(
'name' => t('Product: Sell price'),
'help' => t('Amount to sell the unit'),
'handler' => 'uc_views_handler_price',
'sortable' => TRUE,
),
'weight' => array(
'name' => t('Product: Weight'),
'help' => t('Physical weight'),
'handler' => 'uc_views_handler_weight',
'sortable' => TRUE,
),
'addtocartlink' => array(
'name' => t('Product: Add to cart link'),
'help' => t("Form to put the product in the customer's cart."),
'sortable' => FALSE,
'notafield' => TRUE,
'handler' => 'uc_product_views_handler_add_to_cart_link',
),
'buyitnowbutton' => array(
'name' => t('Product: Buy it now button'),
'help' => t('A button to add a product to the cart without quantity or attribute fields.'),
'sortable' => FALSE,
'notafield' => TRUE,
'handler' => 'uc_product_views_handler_buy_it_now_button',
),
),
'sorts' => array(
'model' => array(
'name' => t('Product: SKU'),
),
'list_price' => array(
'name' => t('Product: List price'),
),
'cost' => array(
'name' => t('Product: Cost'),
),
'sell_price' => array(
'name' => t('Product: Sell price'),
),
'weight' => array(
'name' => t('Product: Weight'),
),
'ordering' => array(
'name' => t('Product: List Order'),
),
),
'filters' => array(
'is_product' => array(
'name' => t('Product: Is a product'),
'operator' => array('=' => 'Equals'),
'list' => 'views_handler_operator_yesno',
'list-type' => 'select',
'handler' => 'uc_product_views_handler_filter_product',
'help' => t('Filter the node based on whether or not it is derived from content type Product.'),
),
'model' => array(
'name' => t('Product: SKU'),
'operator' => 'views_handler_operator_like',
'handler' => 'views_handler_filter_like',
'help' => t('This filter allows nodes to be filtered by their model number.'),
),
'list_price' => array(
'name' => t('Product: List Price'),
'operator' => array('=' => 'Equals', '<' => 'Less Than', '>' => 'Greater Than'),
'handler' => 'views_handler_filter_numeric',
'help' => t('Filter the node based on whether or not it matches list price criteria.'),
),
'cost' => array(
'name' => t('Product: Cost'),
'operator' => array('=' => 'Equals', '<' => 'Less Than', '>' => 'Greater Than'),
'handler' => 'views_handler_filter_numeric',
'help' => t('Filter the node based on whether or not it matches cost criteria.'),
),
'sell_price' => array(
'name' => t('Product: Sell Price'),
'operator' => array('=' => 'Equals', '<' => 'Less Than', '>' => 'Greater Than'),
'handler' => 'views_handler_filter_numeric',
'help' => t('Filter the node based on whether or not it matches sell price criteria.'),
),
'weight' => array(
'name' => t('Product: Weight'),
'operator' => array('=' => 'Equals', '<' => 'Less Than', '>' => 'Greater Than'),
'handler' => 'views_handler_filter_numeric',
'help' => t('Filter the node based on whether or not it matches weight criteria.'),
),
),
);
return $tables;
}
/**
* Conditionally add editablefields support.
*/
function uc_product_views_tables_alter(&$tables) {
if (module_exists('editablefields')) {
if (is_array($tables['uc_products']['fields']['model']['option'])) {
$tables['uc_products']['fields']['model']['option']['#options']['editable'] = t('Editable');
}
else {
$tables['uc_products']['fields']['model']['option'] = array(
'#type' => 'select',
'#options' => array(
'display' => t('Display'),
'editable' => t('Editable'),
),
);
}
$tables['uc_products']['fields']['model']['form_parents'] = 'base][model';
if (is_array($tables['uc_products']['fields']['list_price']['option'])) {
$tables['uc_products']['fields']['list_price']['option']['#options']['editable'] = t('Editable');
}
else {
$tables['uc_products']['fields']['list_price']['option'] = array(
'#type' => 'select',
'#options' => array(
'display' => t('Display'),
'editable' => t('Editable'),
),
);
}
$tables['uc_products']['fields']['list_price']['form_parents'] = 'base][prices][list_price';
if (is_array($tables['uc_products']['fields']['cost']['option'])) {
$tables['uc_products']['fields']['cost']['option']['#options']['editable'] = t('Editable');
}
else {
$tables['uc_products']['fields']['cost']['option'] = array(
'#type' => 'select',
'#options' => array(
'display' => t('Display'),
'editable' => t('Editable'),
),
);
}
$tables['uc_products']['fields']['cost']['form_parents'] = 'base][prices][cost';
if (is_array($tables['uc_products']['fields']['sell_price']['option'])) {
$tables['uc_products']['fields']['sell_price']['option']['#options']['editable'] = t('Editable');
}
else {
$tables['uc_products']['fields']['sell_price']['option'] = array(
'#type' => 'select',
'#options' => array(
'display' => t('Display'),
'editable' => t('Editable'),
),
);
}
$tables['uc_products']['fields']['sell_price']['form_parents'] = 'base][prices][sell_price';
if (is_array($tables['uc_products']['fields']['weight']['option'])) {
$tables['uc_products']['fields']['weight']['option']['#options']['editable'] = t('Editable');
}
else {
$tables['uc_products']['fields']['weight']['option'] = array(
'#type' => 'select',
'#options' => array(
'display' => t('Display'),
'editable' => t('Editable'),
),
);
}
$tables['uc_products']['fields']['weight']['form_parents'] = 'base][weight';
}
}
/**
* Return a formatted price value to display in the View.
*/
function uc_views_handler_price($fieldinfo, $fielddata, $value, $data) {
return uc_currency_format($value);
}
/**
* Return a formatted weight value to display in the View.
*/
function uc_views_handler_weight($fieldinfo, $fielddata, $value, $data) {
return uc_weight_format($value);
}
/**
* Return a formatted add to cart form to display in the View.
*/
function uc_product_views_handler_add_to_cart_link($fieldinfo, $fielddata, $value, $data) {
$types = module_invoke_all('node_info');
$product = node_load($data->nid);
$module = $types[$product->type]['module'];
if (theme_get_function($module .'_add_to_cart')) {
return theme($module .'_add_to_cart', $product);
}
else {
return theme('uc_product_add_to_cart', $product);
}
}
/**
* Return a formatted buy it now button to display in the View.
*/
function uc_product_views_handler_buy_it_now_button($fieldinfo, $fielddata, $value, $data) {
$product = node_load($data->nid);
return drupal_get_form('uc_catalog_buy_it_now_form_'. $data->nid, $product);
}
/**
* Filter out nodes that are not products.
*/
function uc_product_views_handler_filter_product($op, $filter, $filterinfo, &$query) {
$types = module_invoke_all('product_types');
switch ($op) {
case 'handler':
switch ($filter['value'][0]) {
case '0':
$query->add_where("node.type NOT IN ('" . implode("','", $types) . "')");
break;
case '1':
$query->add_where("node.type IN ('" . implode("','", $types) . "')");
break;
}
break;
}
}
/**
* Provide a default products view.
*/
function uc_product_views_default_views() {
$view = new stdClass();
$view->name = 'products';
$view->description = 'products';
$view->access = array();
$view->view_args_php = '';
$view->page = TRUE;
$view->page_title = 'Products';
$view->page_header = '';
$view->page_header_format = '1';
$view->page_footer = '';
$view->page_footer_format = '1';
$view->page_empty = '';
$view->page_empty_format = '1';
$view->page_type = 'table';
$view->url = 'products';
$view->use_pager = TRUE;
$view->nodes_per_page = '10';
$view->menu = TRUE;
$view->menu_title = '';
$view->menu_tab = FALSE;
$view->menu_tab_weight = '0';
$view->menu_tab_default = FALSE;
$view->menu_tab_default_parent = NULL;
$view->menu_tab_default_parent_type = 'tab';
$view->menu_parent_tab_weight = '0';
$view->menu_parent_title = '';
$view->sort = array(
array(
'tablename' => 'uc_products',
'field' => 'ordering',
'sortorder' => 'ASC',
'options' => '',
),
array(
'tablename' => 'node',
'field' => 'title',
'sortorder' => 'ASC',
'options' => '',
),
);
$view->argument = array();
$view->field = array(
array(
'tablename' => 'node_data_field_image_cache',
'field' => 'field_image_cache_fid',
'label' => 'Image(s)',
'handler' => 'content_views_field_handler_group',
'options' => 'product_list_linked',
),
array(
'tablename' => 'node',
'field' => 'title',
'label' => 'Description',
'handler' => 'views_handler_field_nodelink',
'sortable' => '1',
'options' => 'link',
),
array(
'tablename' => 'uc_products',
'field' => 'sell_price',
'label' => 'Price',
'sortable' => '1',
),
);
$view->filter = array(
array(
'tablename' => 'node',
'field' => 'status',
'operator' => '=',
'options' => '',
'value' => '1',
),
array(
'tablename' => 'uc_products',
'field' => 'is_product',
'operator' => '=',
'options' => '',
'value' => '1',
),
);
$view->exposed_filter = array();
$view->requires = array('node_data_field_image_cache', 'node', 'uc_products');
$views[$view->name] = $view;
return $views;
}
/******************************************************************************
* Übercart Hooks *
******************************************************************************/
function uc_product_product_types() {
return array_keys(uc_product_node_info());
}
/**
* Display the status of the product image handlers.
*
* @see uc_product_image_defaults
*/
function uc_product_store_status() {
if (!module_exists('imagefield') || !module_exists('imagecache')) {
$description = t('To automatically configure core image support, enable the Content, CCK Image field, and Imagecache modules. This action is not required.', array('!url' => url('admin/build/modules')));
}
else {
$result = db_query("SELECT field_name, type FROM {node_field} WHERE field_name = 'field_image_cache' AND type = 'image'");
$field_check = (bool) db_num_rows($result);
$result = db_query("SELECT field_name, type_name FROM {node_field_instance} WHERE field_name = 'field_image_cache' AND type_name = 'product'");
$product_field_check = (bool) db_num_rows($result);
$presets = array('product', 'product_list', 'uc_thumbnail');
if (module_exists('uc_catalog')) {
$presets[] = 'uc_category';
}
if (module_exists('uc_cart')) {
$presets[] = 'cart';
}
if (module_exists('uc_manufacturer')) {
$presets[] = 'manufacturer';
}
$result = db_query("SELECT presetid, presetname FROM {imagecache_preset} WHERE presetname IN ('". implode("','", $presets) ."')");
$preset_check = (db_num_rows($result) == count($presets));
$actions = array();
$good_presets = array();
while ($preset_id = db_fetch_array($result)) {
$good_presets[] = $preset_id['presetname'];
$actions[$preset_id['presetid']] = db_result(db_query("SELECT actionid FROM {imagecache_action} WHERE presetid = %d", $preset_id['presetid']));
}
$missing_presets = array_diff($presets, $good_presets);
$action_check = (count(array_filter($actions)) == count($presets));
if ($field_check && $product_field_check && $preset_check && $action_check) {
$description = t('Product image support has been automatically configured by Ubercart.');
}
else {
$checks = ($field_check << 3) + ($product_field_check << 2) + ($preset_check << 1) + $action_check;
$description = t('Click here to automatically configure the following items for core image support:', array('!url' => url('admin/store/settings/products/defaults/'. $checks)));
if (!$field_check) {
$items[] = t('The Image field has not been created for CCK.');
}
if (!$product_field_check) {
$items[] = t("The Image field has not been attached to Product nodes.");
}
if (!$preset_check) {
$items[] = t('The expected Imagecache presets ("!presets") have not been created.', array('!presets' => implode('", "', $missing_presets)));
}
if (!$action_check) {
$items[] = t('The Imagecache presets do not contain actions to perform on images. Images may be displayed in their original formats.');
}
$description .= theme('item_list', $items) . t('(This action is not required and should not be taken if you do not need images or have implemented your own image support.)');
}
}
return array(array('status' => 'ok', 'title' => t('Images'), 'desc' => $description));
}
/**
* Implementation of Übercart hook_cart_display().
*/
function uc_product_cart_display($item) {
$node = node_load($item->nid);
$element = array();
$element['nid'] = array('#type' => 'value', '#value' => $node->nid);
$element['module'] = array('#type' => 'value', '#value' => 'uc_product');
$element['remove'] = array('#type' => 'checkbox');
$element['options'] = '';
if (module_exists('uc_attribute') && is_array($item->options)) {
foreach ($item->options as $option) {
$op_names[] = t('@attribute: @option', array('@attribute' => $option['attribute'], '@option' => $option['name']));
}
$element['options'] = array('#value' => theme('item_list', $op_names, NULL, 'ul', array('class' => 'cart-options')));
}
$element['title'] = array(
'#value' => node_access('view', $node) ? l($item->title, 'node/'. $node->nid) : check_plain($item->title),
);
$element['#total'] = $item->price * $item->qty;
$element['data'] = array('#type' => 'hidden', '#value' => serialize($item->data));
$element['qty'] = array(
'#type' => 'textfield',
'#default_value' => $item->qty,
'#size' => 5,
'#maxlength' => 6
);
return $element;
}
/**
* Update information about a specific item in current cart.
*/
function uc_product_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) {
uc_cart_remove_item($nid, $cid, $data);
}
else {
db_query("UPDATE {uc_cart_products} SET qty = %d, changed = %d WHERE nid = %d AND cart_id = '%s' AND data = '%s'", $qty, time(), $nid, $cid, serialize($data));
cache_clear_all();
}
// Rebuild the items hash
uc_cart_get_contents(NULL, 'rebuild');
}
/**
* Implementation of hook_add_to_cart_data().
*/
function uc_product_add_to_cart_data($form_values) {
$node = node_load($form_values['nid']);
return array('shippable' => $node->shippable);
}
function uc_product_product_class($pcid, $op) {
switch ($op) {
case 'insert':
db_query("UPDATE {node_type} SET module = 'uc_product', custom = 0 WHERE type = '%s'", $pcid);
$result = db_query("SELECT n.vid, n.nid, p.unique_hash FROM {node} AS n LEFT JOIN {uc_products} AS p ON n.vid = p.vid WHERE n.type = '%s'", $pcid);
while ($node = db_fetch_object($result)) {
if (!$node->unique_hash) {
$node->weight_units = variable_get('uc_weight_unit', 'lb');
$node->length_units = variable_get('uc_length_unit', 'in');
$node->pkg_qty = 1;
$node->default_qty = 1;
$node->shippable = 1;
uc_product_insert($node);
}
}
break;
}
}
/******************************************************************************
* Menu Callbacks *
******************************************************************************/
// Displays a sortable, paged table list of products on the site.
function uc_product_default() {
$table_nids = array();
// Redirect to /products if we have excess URL arguments.
if (arg(1) != '') {
drupal_goto('products');
}
// Get the header info from TAPIr.
$header = tapir_get_header('uc_product_table', array());
// Generate our ORDER BY clause if the table has been sorted.
$order = substr(tablesort_sql($header), 10);
// Otherwise supply a default as a TAPIr workaround.
if (empty($order)) {
$order = 'p.ordering, n.title';
}
// Fetch the product info from the database for display.
$result = pager_query(db_rewrite_sql("SELECT n.nid FROM {node} AS n RIGHT JOIN {uc_products} AS p ON n.vid = p.vid WHERE n.status = 1 ORDER BY ". $order), variable_get('uc_product_nodes_per_page', 10), 0, NULL);
while ($node = db_fetch_object($result)) {
$table_nids[] = $node->nid;
}
$args = array('nids' => $table_nids);
// Generate the output from TAPIr with a pager.
return tapir_get_table('uc_product_table', $args) . theme('pager');
}
/**
* Set up imagefield and imagecache for products.
*
* @param $checks A bitmap describing the state of the image modules. Four
* checks are made to fill this bitmap: an imagefield exists, an imagefield
* is attached to product, the imagecache presets exist, and each preset has
* at least one action.
* @see uc_product_store_status
*/
function uc_product_image_defaults($checks) {
$field_check = $checks & 8;
$product_field_check = $checks & 4;
$preset_check = $checks & 2;
$action_check = $checks & 1;
$presets = array('product', 'product_list', 'uc_thumbnail');
if (module_exists('uc_catalog')) {
$presets[] = 'uc_category';
}
if (module_exists('uc_cart')) {
$presets[] = 'cart';
}
if (module_exists('uc_manufacturer')) {
$presets[] = 'manufacturer';
}
$presets = drupal_map_assoc($presets);
if (!$field_check) {
db_query("INSERT INTO {node_field} (field_name, type, global_settings, required, multiple, db_storage) VALUES ('field_image_cache', 'image', '%s', 0, 1, 0)", 'a:0:{}');
content_clear_type_cache();
}
if (!$product_field_check) {
$widget_settings = array(
'max_resolution' => '0',
'image_path' => '',
'custom_alt' => 1,
'custom_title' => 1,
'teaser_preset' => null,
'body_preset' => null,
);
$display_settings = array(
'label' => array(
'format' => 'hidden',
),
'teaser' => array(
'format' => 'hidden',
),
'full' => array(
'format' => 'hidden',
),
);
foreach (module_invoke_all('product_types') as $type) {
db_query("INSERT INTO {node_field_instance} VALUES ('field_image_cache', '%s', -2, 'Image', 'image', '%s', '%s', '')", $type, serialize($widget_settings), serialize($display_settings));
}
switch ($GLOBALS['db_type']) {
case 'mysql':
case 'mysqli':
db_query("CREATE TABLE IF NOT EXISTS {content_field_image_cache} (
`vid` int(10) unsigned NOT NULL default '0',
`delta` int(10) unsigned NOT NULL default '0',
`nid` int(10) unsigned NOT NULL default '0',
`field_image_cache_fid` int(11) NOT NULL default '0',
`field_image_cache_title` varchar(255) NOT NULL default '',
`field_image_cache_alt` varchar(255) NOT NULL default '',
PRIMARY KEY (`vid`,`delta`)
) /*!40100 DEFAULT CHARACTER SET utf8 */;");
break;
case 'pgsql':
db_query("CREATE TABLE {content_field_image_cache} (
vid int_unsigned NOT NULL default '0',
delta int_unsigned NOT NULL default '0',
nid int_unsigned NOT NULL default '0',
field_image_cache_fid integer NOT NULL default '0',
field_image_cache_title varchar(255) NOT NULL default '',
field_image_cache_alt varchar(255) NOT NULL,
PRIMARY KEY (vid,delta)
);");
break;
}
content_clear_type_cache();
}
if (!$preset_check) {
$result = db_query("SELECT * FROM {imagecache_preset} WHERE presetname IN ('". implode("','", $presets) ."')");
$preset_keys = array();
foreach ($presets as $preset) {
$preset_keys[$preset] = 0;
}
$presets = $preset_keys;
while ($preset = db_fetch_array($result)) {
$presets[$preset['presetname']] = $preset['presetid'];
}
//drupal_set_message(''. print_r($presets, true) .'
');
foreach ($presets as $name => $id) {
if ($id == 0) {
$id = db_next_id('{imagecache_preset}_presetid');
db_query("INSERT INTO {imagecache_preset} (presetid, presetname) VALUES (%d, '%s')", $id, $name);
}
}
}
if (!$action_check) {
$result = db_query("SELECT ia.actionid, ip.presetid, ip.presetname FROM {imagecache_preset} AS ip LEFT JOIN {imagecache_action} AS ia ON ip.presetid = ia.presetid WHERE ip.presetname IN ('". implode("','", array_keys($presets)) ."')");
$presets = array();
while ($preset = db_fetch_array($result)) {
if (is_null($preset['actionid'])) {
switch ($preset['presetname']) {
case 'product':
db_query("INSERT INTO {imagecache_action} (actionid, presetid, weight, data) VALUES (%d, %d, 0, '%s')", db_next_id('{imagecache_action}_actionid'), $preset['presetid'], 'a:4:{s:8:"function";s:5:"scale";s:3:"fit";s:6:"inside";s:5:"width";s:3:"100";s:6:"height";s:3:"100";}');
break;
case 'product_list':
db_query("INSERT INTO {imagecache_action} (actionid, presetid, weight, data) VALUES (%d, %d, 0, '%s')", db_next_id('{imagecache_action}_actionid'), $preset['presetid'], 'a:4:{s:8:"function";s:5:"scale";s:3:"fit";s:6:"inside";s:5:"width";s:3:"100";s:6:"height";s:3:"100";}');
break;
case 'uc_thumbnail':
db_query("INSERT INTO {imagecache_action} (actionid, presetid, weight, data) VALUES (%d, %d, 0, '%s')", db_next_id('{imagecache_action}_actionid'), $preset['presetid'], 'a:4:{s:8:"function";s:5:"scale";s:3:"fit";s:6:"inside";s:5:"width";s:2:"35";s:6:"height";s:2:"35";}');
break;
case 'uc_category':
db_query("INSERT INTO {imagecache_action} (actionid, presetid, weight, data) VALUES (%d, %d, 0, '%s')", db_next_id('{imagecache_action}_actionid'), $preset['presetid'], 'a:4:{s:8:"function";s:5:"scale";s:3:"fit";s:6:"inside";s:5:"width";s:2:"96";s:6:"height";s:2:"96";}');
break;
case 'cart':
db_query("INSERT INTO {imagecache_action} (actionid, presetid, weight, data) VALUES (%d, %d, 0, '%s')", db_next_id('{imagecache_action}_actionid'), $preset['presetid'], 'a:4:{s:8:"function";s:5:"scale";s:3:"fit";s:6:"inside";s:5:"width";s:2:"50";s:6:"height";s:2:"50";}');
break;
case 'manufacturer':
db_query("INSERT INTO {imagecache_action} (actionid, presetid, weight, data) VALUES (%d, %d, 0, '%s')", db_next_id('{imagecache_action}_actionid'), $preset['presetid'], 'a:4:{s:8:"function";s:5:"scale";s:3:"fit";s:6:"inside";s:5:"width";s:2:"80";s:6:"height";s:2:"80";}');
break;
}
}
}
}
cache_clear_all('imagecache:presets', 'cache');
drupal_goto('admin/store');
}
/**
* List the subcategories of product administration.
*/
function uc_product_administration() {
uc_add_js(drupal_get_path('module', 'uc_product') .'/uc_product.js', 'module');
// Parse the URL for nodes in the list.
$nids = array();
foreach (func_get_args() as $nid) {
if (intval($nid) > 0) {
$nids[] = intval($nid);
}
}
// Load all the vocabularies assigned to any product node type.
$options = array();
$types = module_invoke_all('product_types');
$result = db_query("SELECT v.vid, v.name FROM {vocabulary} AS v LEFT JOIN {vocabulary_node_types} AS vnt ON v.vid = vnt.vid WHERE vnt.type IN ('". implode("','", $types) ."')");
while ($vocab = db_fetch_array($result)) {
$options[$vocab['vid']] = $vocab['name'];
}
// Set the default vid, defaulting to the catalog if it's enabled.
$default_vid = variable_get('uc_catalog_vid', 0);
// If at least one vocabularies were found, display a uBrowser selector.
if (count($options) > 0) {
if (!in_array($default_vid, array_keys($options))) {
$default_vid = array_shift(array_keys($options));
}
$output = ''. t('Use the uBrowser to select as many products as you like and move them to the product container. When you are finished adding products, click the List button to reload the page showing the selected products. This effect is not cumulative and will not add products onto an existing list.') .'
';
// Set the product filter for the uBrowser.
$product_filter = implode(',', $types);
// If more than one vocabularies were found, display a select box.
if (count($options) > 1) {
$form['vocabs'] = array(
'#type' => 'select',
'#id' => 'ubrowser-vocab-select',
'#title' => t('Display vocabulary'),
'#default_value' => $default_vid,
'#options' => $options,
'#attributes' => array('onchange' => 'switch_vocabulary(this.value);'),
);
$form['product_filter'] = array(
'#type' => 'hidden',
'#value' => $product_filter,
);
drupal_prepare_form('vocab-switcher', $form);
$output .= drupal_render($form);
}
$settings = array(
'div' => '#products-selector',
'class' => 'product-ubrowser',
'vid' => $default_vid,
'filter' => $product_filter,
'search' => 'true',
'nids' => 'true',
'nodesg' => t('product'),
'nodepl' => t('products'),
'multi' => 'true',
'select' => 'buffer_products("'. file_create_url('') .'")',
);
$output .= ubrowser($settings, 'products-selector')
. drupal_get_form('uc_product_buffer_form', $nids);
}
// If no nodes have been selected, display products 50 per page.
if (!count($nids)) {
$header = tapir_get_header('uc_product_table', array());
$order = substr(tablesort_sql($header), 10);
if (empty($order)) {
$order = 'p.ordering, n.title';
}
$nids = array();
$result = pager_query("SELECT n.nid FROM {node} AS n INNER JOIN {uc_products} AS p ON n.vid = p.vid ORDER BY ". $order, 50, 0, NULL);
while ($product = db_fetch_object($result)) {
$nids[] = $product->nid;
}
}
// Setup the arguments to pass to the table builder function.
$args = array(
'nids' => $nids,
'attributes' => array('class' => 'product-list')
);
// Display the product table and pager if necessary.
$output .= tapir_get_table('uc_product_table', $args) . theme('pager');
return $output;
}
/**
* Store a list of nodes for further processing.
*
* @ingroup forms
* @see uc_product_buffer_form_submit
*/
function uc_product_buffer_form($nids) {
foreach ($nids as $nid) {
$node = node_load($nid);
$buffer .= theme('imagecache', 'uc_thumbnail', $node->field_image_cache[0]['filepath'], $node->field_image_cache[0]['alt'], $node->field_image_cache[0]['title']);
}
$form['#attributes'] = array('class' => 'product-buffer');
$form['title'] = array(
'#value' => ''. t('Selected products:') .'',
);
$form['thumbnails'] = array(
'#value' => ''. t('Use the uBrowser above to select products.') .'
',
);
$form['products'] = array(
'#type' => 'hidden',
);
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Create list'),
);
$form['reset'] = array(
'#type' => 'submit',
'#value' => t('Reset list'),
);
return $form;
}
function uc_product_buffer_form_submit($form_id, $form_values) {
$item = menu_get_item(menu_get_active_item());
switch ($form_values['op']) {
case t('Reset list'):
return $item['path'];
default:
return $item['path'] . $form_values['products'];
}
}
/**
* Display overview of product settings.
*
* @see uc_product_settings_form
* @see uc_product_field_settings_form
*/
function uc_product_settings_overview() {
$items[] = t('Teaser and catalog pages = %text', array('%text' => variable_get('uc_teaser_add_to_cart_text', t('Add to cart'))));
$items[] = t('Product view pages = %text', array('%text' => variable_get('uc_product_add_to_cart_text', t('Add to cart'))));
$buttons = t('Add to Cart submit button text:')
. theme('item_list', $items);
$sections[] = array(
'edit' => 'admin/store/settings/products/edit',
'title' => t('Product settings'),
'items' => array(
t('Showing !number products per page.', array('!number' => variable_get('uc_product_nodes_per_page', 10))),
t('The Add to Cart form is !status in product teasers.', array('!status' => variable_get('uc_product_add_to_cart_teaser', TRUE) ? t('enabled') : t('disabled'))),
t('The Quantity field in the Add to Cart form is !status.', array('!status' => variable_get('uc_product_add_to_cart_qty', FALSE) ? t('enabled') : t('disabled'))),
$buttons,
),
);
$options = array(
'model' => t('Model'),
'image' => t('Image'),
'display_price' => t('Display price'),
'list_price' => t('List price'),
'cost' => t("Cost (seen only by 'administer products' permission)"),
'sell_price' => t('Sell price'),
'weight' => t('Weight'),
'dimensions' => t('Dimensions'),
'add_to_cart' => variable_get('uc_product_add_to_cart_text', t('Add to cart')),
);
$enabled = variable_get('uc_product_field_enabled', array(
'model' => 'model',
'image' => 'image',
'display_price' => 'display_price',
'sell_price' => 'sell_price',
'add_to_cart' => 'add_to_cart',
));
$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,
));
$fields = array();
foreach ($options as $field => $label) {
if ($enabled[$field]) {
$fields[$field] = array('enabled' => $enabled[$field],
'weight' => $weight[$field],
'data' => $label,
);
}
}
uasort($fields, 'uc_weight_sort');
$sections[] = array(
'edit' => 'admin/store/settings/products/edit/fields',
'title' => t('Product fields'),
'items' => array(
t('Displayed product fields: !list', array('!list' => theme('item_list', $fields))),
),
);
foreach (module_invoke_all('product_feature') as $feature) {
$features[] = $feature['title'];
}
if (!empty($features)) {
$items = array(
t('The following features are enabled: !list', array('!list' => theme('item_list', $features))),
);
}
else {
$items = array(
t('No product features enabled.'),
);
}
$sections[] = array(
'edit' => 'admin/store/settings/products/edit/features',
'title' => t('Product features'),
'items' => $items,
);
$output = theme('uc_settings_overview', $sections);
return $output;
}
/**
* Form to change product settings.
*
* @ingroup forms
* @see uc_product_settings_overview
*/
function uc_product_settings_form() {
$form['uc_product_nodes_per_page'] = array(
'#type' => 'select',
'#title' => t('Products per page'),
'#description' => t('The number of products per page in a list.'),
'#default_value' => variable_get('uc_product_nodes_per_page', 10),
'#options' => drupal_map_assoc(uc_range(10, 100, 10)),
);
$form['uc_product_add_to_cart_qty'] = array(
'#type' => 'checkbox',
'#title' => t('Display an optional quantity field in the Add to Cart form.'),
'#default_value' => variable_get('uc_product_add_to_cart_qty', FALSE),
);
$form['uc_product_add_to_cart_teaser'] = array(
'#type' => 'checkbox',
'#title' => t('Enable Add to cart forms in product node teasers.'),
'#default_value' => variable_get('uc_product_add_to_cart_teaser', TRUE),
);
$form['uc_add_to_cart_text'] = array(
'#type' => 'fieldset',
'#title' => t('Add to cart button text'),
'#description' => t('Use the textboxes to adjust the text of the submit button for Add to Cart forms in various places on the site.'),
'#collapsed' => FALSE,
'#collapsible' => FALSE,
);
$form['uc_add_to_cart_text']['uc_teaser_add_to_cart_text'] = array(
'#type' => 'textfield',
'#title' => t('Teaser forms'),
'#description' => t('For the form displayed on teasers and catalog pages.'),
'#default_value' => variable_get('uc_teaser_add_to_cart_text', t('Add to cart')),
);
$form['uc_add_to_cart_text']['uc_product_add_to_cart_text'] = array(
'#type' => 'textfield',
'#title' => t('Product view'),
'#description' => t('For the form displayed on the product view page.'),
'#default_value' => variable_get('uc_product_add_to_cart_text', t('Add to cart')),
);
return system_settings_form($form);
}
/**
* Allows store administrators to control what product information is relavent to their store.
*
* @ingroup forms
* @see uc_product_settings_overview
* @see theme_uc_product_field_settings_form
* @see uc_product_field_settings_form_submit
*/
function uc_product_field_settings_form() {
$form = array();
$options = array(
'model',
'image',
'display_price',
'list_price',
'cost',
'sell_price',
'weight',
'dimensions',
'add_to_cart',
);
$enabled = variable_get('uc_product_field_enabled', array(
'model' => 'model',
'image' => 'image',
'display_price' => 'display_price',
'sell_price' => 'sell_price',
'add_to_cart' => 'add_to_cart',
));
$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,
));
$fields = array();
foreach ($options as $field) {
$fields[$field] = array('enabled' => $enabled[$field], 'weight' => $weight[$field]);
}
uasort($fields, 'uc_weight_sort');
$form['fields'] = array('#tree' => true);
foreach ($fields as $label => $field) {
$form['fields'][$label]['enabled'] = array('#type' => 'checkbox',
'#default_value' => $field['enabled'],
);
$form['fields'][$label]['weight'] = array('#type' => 'weight',
'#delta' => 10,
'#default_value' => $field['weight'],
);
}
$form['buttons']['submit'] = array('#type' => 'submit', '#value' => t('Save configuration') );
$form['buttons']['reset'] = array('#type' => 'submit', '#value' => t('Reset to defaults') );
return $form;
}
/**
* Display the product field settings form.
*
* @ingroup themeable
* @see uc_product_field_settings_form
*/
function theme_uc_product_field_settings_form($form) {
$options = array(
'model' => t('Model'),
'image' => t('Image'),
'display_price' => t('Display price'),
'list_price' => t('List price'),
'cost' => t("Cost (seen only by 'administer products' permission)"),
'sell_price' => t('Sell price'),
'weight' => t('Weight'),
'dimensions' => t('Dimensions'),
'add_to_cart' => variable_get('uc_product_add_to_cart_text', t('Add to cart')),
);
$header = array(t('Enable'), t('Product field'), t('Weight'));
$rows = array();
foreach (element_children($form['fields']) as $field) {
$row = array();
$row[] = drupal_render($form['fields'][$field]['enabled']);
$row[] = $options[$field];
$row[] = drupal_render($form['fields'][$field]['weight']);
$rows[] = $row;
}
$output .= theme('table', $header, $rows);
$output .= drupal_render($form);
return $output;
}
/**
* Submit handler for uc_product_settings_form.
*/
function uc_product_field_settings_form_submit($form_id, $form_values) {
if ($form_values['op'] == t('Reset to defaults')) {
variable_del('uc_product_field_enabled');
variable_del('uc_product_field_weight');
drupal_set_message(t('The configuration options have been reset to their default values.'));
}
else {
$enabled = array();
$weight = array();
foreach ($form_values['fields'] as $id => $field) {
$enabled[$id] = $field['enabled'];
$weight[$id] = $field['weight'];
}
variable_set('uc_product_field_enabled', $enabled);
variable_set('uc_product_field_weight', $weight);
drupal_set_message(t('The configuration options have been saved.'));
}
}
/**
* Display a list of product classes.
*/
function uc_product_class_default() {
$result = db_query("SELECT * FROM {uc_product_classes}");
$header = array(t('Class ID'), t('Name'), t('Description'), t('Operations'));
$rows = array();
while ($class = db_fetch_object($result)) {
$ops = array(
l(t('edit'), 'admin/store/products/classes/'. $class->pcid .'/edit'),
l(t('delete'), 'admin/store/products/classes/'. $class->pcid .'/delete'),
);
$rows[] = array(
$class->pcid,
$class->name,
$class->description,
implode(' ', $ops),
);
}
if (count($rows) == 0) {
$rows[] = array(array('data' => t('No product classes have been defined yet.'), 'colspan' => '5'));
}
$output = theme('table', $header, $rows);
$output .= ''. t('Add a class') .'
';
$output .= drupal_get_form('uc_product_class_form');
return $output;
}
/**
* Form builder for product classes.
*
* @ingroup forms
* @see uc_product_class_form_submit
*/
function uc_product_class_form($pcid = null) {
if ($pcid) {
$class = uc_product_class_load($pcid);
drupal_set_title(check_plain($class->name));
$form['pcid'] = array('#type' => 'hidden', '#value' => $pcid);
}
else {
$form['pcid'] = array('#type' => 'textfield',
'#title' => t('Class ID'),
'#required' => true,
'#max_length' => 32,
'#description' => t('The machine-readable name of this content type. This text will be used for constructing the URL of the create content page for this content type. This name may consist only of lowercase letters, numbers, and underscores. Dashes are not allowed. Underscores will be converted into dashes when constructing the URL of the create content page. This name must be unique to this content type.'),
);
}
$form['name'] = array(
'#type' => 'textfield',
'#title' => t('Class name'),
'#default_value' => $class->name,
'#required' => true,
);
$form['description'] = array(
'#type' => 'textarea',
'#title' => t('Description'),
'#description' => t('This text describes the content type created for this product class to administrators.'),
'#default_value' => $class->description,
);
$form['op'] = array(
'#type' => 'submit',
'#value' => t('Submit'),
);
return $form;
}
/**
* Submit handler for uc_product_class_form.
*/
function uc_product_class_form_submit($form_id, $form_values) {
if (uc_product_class_load($form_values['pcid'])) {
$is_new = false;
$pcid = $form_values['pcid'];
db_query("UPDATE {uc_product_classes} SET name = '%s', description = '%s' WHERE pcid = '%s'", $form_values['name'], $form_values['description'], $pcid);
uc_product_node_info(true);
module_invoke_all('product_class', $pcid, 'update');
}
else {
$is_new = true;
// Convert whitespace to underscores, and remove other non-alphanumeric characters.
$pcid = preg_replace(array('/\s+/', '/\W/'), array('_', ''), strtolower($form_values['pcid']));
// Search for class ids of the form $pcid_# where # is any character.
$similar = db_num_rows(db_query("SELECT pcid FROM {uc_product_classes} WHERE pcid LIKE '%s\\__' OR pcid LIKE '%s' UNION SELECT type FROM {node_type} WHERE type = '%s' AND custom = 0", $pcid, $pcid, $pcid));
if ($similar) {
$pcid = $pcid .'_'. $similar;
}
db_query("INSERT INTO {uc_product_classes} (pcid, name, description) VALUES ('%s', '%s', '%s')", $pcid, $form_values['name'], $form_values['description']);
uc_product_node_info(true);
variable_set('node_options_'. $pcid, variable_get('node_options_product', array('status', 'promote')));
if (module_exists('comment')) {
variable_set('comment_'. $pcid, variable_get('comment_product', COMMENT_NODE_READ_WRITE));
}
module_invoke_all('product_class', $pcid, 'insert');
}
node_types_rebuild();
menu_rebuild();
if ($is_new && module_exists('imagefield')) {
$info = content_types($pcid);
if (!isset($info['fields']['field_image_cache'])) {
$result = db_query("SELECT field_name FROM {node_field} WHERE field_name = 'field_image_cache' AND type = 'image'");
if (db_num_rows($result)) {
drupal_execute('_content_admin_field_add_existing', array('type_name' => $pcid, 'field_name' => 'field_image_cache'), $pcid);
}
}
}
return 'admin/store/products/classes';
}
/**
* Confirm the deletion of a product class.
*
* @see uc_product_class_delete_confirm_submit
*/
function uc_product_class_delete_confirm($class_id) {
$result = db_query("SELECT COUNT(*) AS number FROM {node} WHERE type = '%s'", $class_id);
$products = db_fetch_object($result);
$form['pcid'] = array('#type' => 'value', '#value' => $class_id);
$form['#redirect'] = 'admin/store/products/classes';
$output = confirm_form($form, t('Be very sure you want to delete the %type product class. It will become a standard node type.', array('%type' => $class_id)), 'admin/store/products/classes',
format_plural($products->number, 'There is @count node of this type.', 'There are @count nodes of this type.'),
t('Continue'), t('Cancel'));
return $output;
}
/**
* Submit handler for uc_product_class_delete_confirm.
*/
function uc_product_class_delete_confirm_submit($form_id, $form_values) {
if ($form_values['confirm']) {
$type = node_get_types('type', $form_values['pcid']);
$type->module = 'node';
$type->custom = 1;
node_type_save($type);
db_query("DELETE FROM {uc_product_classes} WHERE pcid = '%s'", $form_values['pcid']);
module_invoke_all('product_class', $form_values['pcid'], 'delete');
uc_product_node_info(true);
node_types_rebuild();
menu_rebuild();
drupal_set_message(t('Product class %type deleted.', array('%type' => $form_values['pcid'])));
}
}
/******************************************************************************
* Module Functions *
******************************************************************************/
/**
* Determing if the given node is a product.
*
* @param $node If an object or array, it's "type" member is considered. If a
* a string, it's value is considered. If an integer, node_load() is called.
* @return boolean
*/
function uc_product_is_product($node) {
if (is_int($node)) {
$node = node_load($node);
}
if (is_object($node)) {
$type = $node->type;
}
elseif (is_array($node)) {
$type = $node['type'];
}
elseif (is_string($node)) {
$type = $node;
}
if (!$type) {
return false;
}
$types = module_invoke_all('product_types');
return in_array($type, $types);
}
/**
* Format a product's model number.
*
* @ingroup themeable
*/
function theme_uc_product_model($model, $teaser = 0, $page = 0) {
$output = '';
$output .= t('SKU: @sku', array('@sku' => $model));
$output .= '
';
return $output;
}
/**
* Wrap the "Add to Cart" form in a .
*
* @ingroup themeable
*/
function theme_uc_product_add_to_cart($node, $teaser = 0, $page = 0) {
$output = '
';
if ($node->nid) {
$output .= drupal_get_form('uc_product_add_to_cart_form_'. $node->nid, $node);
}
else {
$output .= drupal_get_form('uc_product_add_to_cart_form', $node);
}
$output .= '
';
return $output;
}
/**
* Form to add the $node product to the cart.
*
* @ingroup forms
* @param $node A product node.
* @see uc_product_forms
* @see uc_product_add_to_cart_form_validate
* @see uc_product_add_to_cart_form_submit
*/
function uc_product_add_to_cart_form($node) {
$form = array();
$form['#base'] = 'uc_product_add_to_cart_form';
$form['nid'] = array('#type' => 'value', '#value' => $node->nid);
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;
}
/**
* Allow only positive, numeric quantities.
*/
function uc_product_add_to_cart_form_validate($form_id, $form_values) {
if (!is_numeric($form_values['qty']) || intval($form_values['qty']) <= 0) {
form_set_error('qty', t('You have entered an invalid quantity.'));
}
}
/**
* Submit handler for uc_product_add_to_cart_form.
*/
function uc_product_add_to_cart_form_submit($form_id, $form_values) {
return uc_cart_add_item($form_values['nid'], $form_values['qty'], module_invoke_all('add_to_cart_data', $form_values));
}
/**
* Format a product's price.
*
* @param $price
* The amount to print.
* @param $class
* Determines the label and the CSS class of the
.
* @ingroup themeable
*/
function theme_uc_product_price($price, $class, $teaser = 0, $page = 0) {
$output = '
';
switch ($class) {
case 'list_price':
$output .= t('List Price: !price', array('!price' => uc_currency_format($price)));
break;
case 'cost':
$output .= t('Cost: !price', array('!price' => uc_currency_format($price)));
break;
case 'sell_price':
default:
$output .= t('Price: !price', array('!price' => uc_currency_format($price)));
break;
}
$output .= '
';
return $output;
}
/**
* Format the selling price based on the view mode.
*
* @param $price
* The price amount.
* @param $teaser
* Passed from uc_product_view().
* @ingroup themeable
*/
function theme_uc_product_sell_price($price, $teaser = 0, $page = 0) {
if ($teaser) {
$output = '
';
$output .= uc_currency_format($price);
$output .= '
';
}
else {
$output = '
';
$output .= t('Price: !price', array('!price' => uc_currency_format($price)));
$output .= '
';
}
return $output;
}
/**
* Format a product's weight.
*
* @ingroup themeable
*/
function theme_uc_product_weight($weight, $unit = null, $teaser = 0, $page = 0) {
$output = '
';
$output .= t('Weight: !weight', array('!weight' => uc_weight_format($weight, $unit)));
$output .= '
';
return $output;
}
/**
* Format a product's length, width, and height.
*
* @ingroup themeable
*/
function theme_uc_product_dimensions($length, $width, $height, $units = null, $teaser = 0, $page = 0) {
$output = '
';
$output .= t('Dimensions: !length × !width × !height', array('!length' => uc_length_format($length, $units), '!width' => uc_length_format($width, $units), '!height' => uc_length_format($height, $units)));
$output .= '
';
return $output;
}
/**
* Format a product's images with imagecache and Thickbox.
*
* @ingroup themeable
*/
function theme_uc_product_image($images, $teaser = 0, $page = 0) {
static $rel_count = 0;
$thickbox_enabled = module_exists('thickbox');
$first = array_shift($images);
$output = '
';
$rel_count++;
return $output;
}
/**
* @ingroup themeable
*/
function theme_uc_product_display_price($price, $teaser = 0, $page = 0) {
$output = '
';
$output .= uc_currency_format($price);
$output .= '
';
return $output;
}
/**
* Get the cost of a product node.
*
* @param $node_id
* nid of the selected node
* @return
* float - cost
*/
function uc_product_get_cost($node_id) {
$product = node_load($node_id);
return $product->cost;
}
/**
* Get the selling price of a product node.
*
* @param $node_id
* nid of the selected node
* @return
* float - sell price
*/
/* function uc_product_get_price($node_id) {
$product = node_load($node_id);
return $product->sell_price;
} */
/**
* Returns an HTML img tag based on a node's attached image.
*
* @param $node_id
* The node's id.
* @param $format
* By default, 'uc_thumbnail', with possible values of '_original', 'thumbnail', and 'preview'.
* @return
* An HTML img. When $format is 'uc_thumbnail', the image is a link to the node.
* When $format is 'preview', the image is a link to the image file.
*/
function uc_product_get_picture($node_id, $format = 'product') {
$img = '';
$product = node_load($node_id);
if (!module_exists('imagecache')) {
return '';
}
$path = $product->field_image_cache[0]['filepath'];
if (file_exists($path)) {
$img = theme('imagecache', $format, $path, $product->field_image_cache[0]['alt'], $product->field_image_cache[0]['title']);
if ($format == 'product') {
$img = '
'. $img .'';
}
else {
$img = l($img, 'node/'. $product->nid, array(), null, null, false, true);
}
}
return $img;
}
/**
* Load a product class.
*/
function uc_product_class_load($class_id) {
static $classes = array();
if (empty($classes[$class_id])) {
$result = db_query("SELECT * FROM {uc_product_classes} WHERE pcid = '%s'", $class_id);
$class = db_fetch_object($result);
$classes[$class_id] = $class;
}
return $classes[$class_id];
}
/**
* AJAX callback helper for product images.
*/
function _uc_product_get_image_field_filepath($nid) {
$result = db_result(db_query_range("SELECT filepath FROM {files} WHERE nid = %d ORDER BY fid", $nid, 0, 1));
if ($result) {
print $result;
}
else {
print 'false';
}
exit();
}
/**
* Display the settings form for all product features.
*
* @ingroup forms
*/
function uc_product_feature_settings_form() {
$titles = array();
$features = module_invoke_all('product_feature');
foreach ($features as $feature) {
$titles[] = $feature['title'];
}
if (empty($titles)) {
$titles[] = '
'. t('No product features found.') .'';
}
$form['features_list'] = array(
'#value' => '
'. t('The following product features are enabled')
.':
'. implode(', ', $titles) .'
',
);
foreach ($features as $feature) {
if (function_exists($feature['settings'])) {
$form[$feature['id']] = array(
'#type' => 'fieldset',
'#title' => t('!feature settings', array('!feature' => $feature['title'])),
'#collapsible' => TRUE,
'#collapsed' => TRUE,
);
$form[$feature['id']] = array_merge($form[$feature['id']], $feature['settings']());
}
}
return system_settings_form($form);
}
/**
* Displays the project features tab on a product node edit form.
*/
function uc_product_features($node) {
drupal_set_title(check_plain($node->title));
if (arg(4)) {
// First check to see if we're trying to remove a feature.
if (intval(arg(5)) > 0 && arg(6) == 'delete') {
$result = db_query("SELECT * FROM {uc_product_features} WHERE pfid = %d AND fid = '%s'", intval(arg(5)), arg(4));
if ($feature = db_fetch_array($result)) {
// If the user confirmed the delete, process it!
if ($_POST['pf_delete']) {
// Call the delete function for this product feature if it exists.
$func = uc_product_feature_data($feature['fid'], 'delete');
if (function_exists($func)) {
$func($feature);
}
// Remove the product feature data from the database.
db_query("DELETE FROM {uc_product_features} WHERE pfid = %d", intval(arg(5)));
drupal_set_message(t('The product feature has been deleted.'));
drupal_goto('node/'. arg(1) .'/edit/features');
}
// Show the confirmation form for deleting this feature.
$question = $node->title;
$description = t('Are you sure you wish to delete this %feature?', array('%feature' => uc_product_feature_data($feature['fid'], 'title')))
.'
'. t('Description') .':
'. $feature['description'] .'
';
return drupal_get_form('confirm_form', NULL, $question, 'node/'. arg(1) .'/edit/features', $description, t('Delete'), t('Cancel'), 'pf_delete');
}
else {
drupal_set_message(t("That product feature doesn't exist."), 'error');
drupal_goto('node/'. arg(1) .'/edit/features');
}
}
// Handle adding or editing product features.
$func = uc_product_feature_data(arg(4), 'callback');
if (function_exists($func)) {
if (arg(5) == 'add') {
$output = drupal_get_form($func, $node, array());
}
elseif (intval(arg(5)) > 0) {
$result = db_query("SELECT * FROM {uc_product_features} WHERE pfid = %d AND fid = '%s'", intval(arg(5)), arg(4));
if ($feature = db_fetch_array($result)) {
$output = drupal_get_form($func, $node, $feature);
}
}
}
else {
drupal_set_message(t('Error: Attempted to add a non-existent product feature type.'), 'error');
drupal_goto('node/'. $node->nid .'/edit/features');
}
if (empty($output)) {
drupal_set_message(t('Error: No form data was returned for that operation.'), 'error');
drupal_goto('node/'. $node->nid .'/edit/features');
}
return $output;
}
$header = array(t('Type'), t('Description'), t('Operations'));
$result = db_query("SELECT * FROM {uc_product_features} WHERE nid = %d ORDER BY pfid ASC", $node->nid);
while ($feature = db_fetch_object($result)) {
$operations = array(
l(t('edit'), 'node/'. $node->nid .'/edit/features/'. $feature->fid .'/'. $feature->pfid),
l(t('delete'), 'node/'. $node->nid .'/edit/features/'. $feature->fid .'/'. $feature->pfid .'/delete'),
);
$rows[] = array(
'data' => array(
array('data' => uc_product_feature_data($feature->fid, 'title'), 'nowrap' => 'nowrap'),
array('data' => $feature->description, 'width' => '100%'),
array('data' => implode(' ', $operations), 'nowrap' => 'nowrap'),
),
'valign' => 'top',
);
}
if (empty($rows)) {
$rows[] = array(
array('data' => t('No features found for this product.'), 'colspan' => 3),
);
}
$output = theme('table', $header, $rows)
. drupal_get_form('uc_product_feature_add_form');
return $output;
}
/**
* Add the form for adding a product feature to the features tab.
*
* @ingroup forms
* @see theme_uc_product_feature_add_form
*/
function uc_product_feature_add_form() {
foreach (module_invoke_all('product_feature') as $feature) {
$options[$feature['id']] = $feature['title'];
}
ksort($options);
$form['feature'] = array(
'#type' => 'select',
'#title' => t('Add a new feature'),
'#options' => $options,
);
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Add'),
);
return $form;
}
/**
* @ingroup themeable
*/
function theme_uc_product_feature_add_form($form) {
$output = '
'. drupal_render($form) .' |
';
return $output;
}
/**
* Submit handler for uc_product_feature_add_form_submit.
*/
function uc_product_feature_add_form_submit($form_id, $form_values) {
return 'node/'. arg(1) .'/edit/features/'. $form_values['feature'] .'/add';
}
/**
* Return a bit of data from a product feature array based on the feature ID
* and array key.
*
* @param $fid
* The string ID of the product feature you want to get data from.
* @param $key
* The key in the product feature array you want: title, callback, delete,
* settings
* @return
* The value of the key you specify.
*/
function uc_product_feature_data($fid, $key) {
static $features;
if (empty($features)) {
foreach (module_invoke_all('product_feature') as $feature) {
$features[$feature['id']] = $feature;
}
}
return $features[$fid][$key];
}
/**
* Returns a form array with some default hidden values and submit button.
*
* @param $form
* The form array you wish to add the elements to.
* @return
* The form array with elements added for the nid, pfid, submit button, and
* cancel link.
* @ingroup forms
*/
function uc_product_feature_form($form) {
if (!isset($form['nid'])) {
$form['nid'] = array(
'#type' => 'hidden',
'#value' => intval(arg(1)),
);
}
if (!isset($form['pfid'])) {
$form['pfid'] = array(
'#type' => 'hidden',
'#value' => intval(arg(5)),
);
}
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Save feature'),
);
$form['cancel'] = array(
'#value' => l(t('Cancel'), 'node/'. intval(arg(1)) .'/edit/features'),
);
return $form;
}
/**
* Save a product feature to a product node.
*
* @param $data
* An array consisting of the following keys:
* - pfid: the numeric ID of the product feature when editing an existing one
* - nid: the numeric ID of the product node
* - fid: the string ID of the feature type
* - description: the string description of the feature for the overview table
*/
function uc_product_feature_save($data) {
if (empty($data['nid']) && arg(0) == 'node' && intval(arg(1)) > 0) {
$data['nid'] = intval(arg(1));
}
if (empty($data['pfid'])) {
if (arg(0) == 'node' && arg(3) == 'features' && intval(arg(5)) > 0) {
$data['pfid'] = intval(arg(5));
}
else {
$data['pfid'] = db_next_id('{uc_product_features}_pfid');
}
}
// First attempt to update an existing row.
db_query("UPDATE {uc_product_features} SET description = '%s' WHERE pfid = %d", $data['description'], intval($data['pfid']));
// Otherwise insert this feature as a new row.
if (db_affected_rows() == 0) {
db_query("INSERT INTO {uc_product_features} VALUES (%d, %d, '%s', '%s')",
$data['pfid'], $data['nid'], $data['fid'], $data['description']);
drupal_set_message(t('The product feature has been added.'));
}
else {
drupal_set_message(t('The product feature has been updated.'));
}
return 'node/'. $data['nid'] .'/edit/features';
}