Parent Directory
|
Revision Log
|
Revision Graph
Begin the Ubercart 6.x-2.x branch.
| 1 | <?php |
| 2 | // $Id$ |
| 3 | |
| 4 | /** |
| 5 | * @file |
| 6 | * The product module for Ubercart. |
| 7 | * |
| 8 | * Provides information that is common to all products, and user-defined product |
| 9 | * classes for more specification. Recommends the image and taxonomy modules. |
| 10 | * |
| 11 | * Coded by: Lyle Mantooth |
| 12 | * Product Features by: Ryan Szrama |
| 13 | */ |
| 14 | |
| 15 | /****************************************************************************** |
| 16 | * Drupal Hooks * |
| 17 | ******************************************************************************/ |
| 18 | |
| 19 | /** |
| 20 | * Implementation of hook_menu(). |
| 21 | */ |
| 22 | function uc_product_menu() { |
| 23 | $items = array(); |
| 24 | |
| 25 | $items['admin/store/products'] = array( |
| 26 | 'title' => 'Products', |
| 27 | 'description' => 'Administer products, classes, and more.', |
| 28 | 'access arguments' => array('administer products'), |
| 29 | 'page callback' => 'uc_product_administration', |
| 30 | 'type' => MENU_NORMAL_ITEM, |
| 31 | 'weight' => -2, |
| 32 | ); |
| 33 | $items['admin/store/products/view'] = array( |
| 34 | 'title' => 'View products', |
| 35 | 'description' => 'Build and view a list of product nodes.', |
| 36 | 'access arguments' => array('administer products'), |
| 37 | 'type' => MENU_NORMAL_ITEM, |
| 38 | 'weight' => -10, |
| 39 | ); |
| 40 | $items['admin/store/products/classes'] = array( |
| 41 | 'title' => 'Manage classes', |
| 42 | 'description' => 'Create and edit product node types.', |
| 43 | 'access arguments' => array('administer product classes'), |
| 44 | 'page callback' => 'uc_product_class_default', |
| 45 | 'type' => MENU_NORMAL_ITEM, |
| 46 | 'weight' => -2, |
| 47 | ); |
| 48 | $items['admin/store/settings/products'] = array( |
| 49 | 'title' => 'Product settings', |
| 50 | 'description' => 'Configure product settings.', |
| 51 | 'access arguments' => array('administer products'), |
| 52 | 'page callback' => 'uc_product_settings_overview', |
| 53 | 'type' => MENU_NORMAL_ITEM, |
| 54 | ); |
| 55 | $items['admin/store/settings/products/overview'] = array( |
| 56 | 'title' => 'Overview', |
| 57 | 'weight' => -10, |
| 58 | 'type' => MENU_DEFAULT_LOCAL_TASK, |
| 59 | ); |
| 60 | $items['admin/store/settings/products/edit'] = array( |
| 61 | 'title' => 'Edit', |
| 62 | 'access arguments' => array('administer products'), |
| 63 | 'page callback' => 'drupal_get_form', |
| 64 | 'page arguments' => array('uc_product_settings_form'), |
| 65 | 'weight' => -5, |
| 66 | 'type' => MENU_LOCAL_TASK, |
| 67 | ); |
| 68 | $items['admin/store/settings/products/edit/general'] = array( |
| 69 | 'title' => 'Product settings', |
| 70 | 'access arguments' => array('administer products'), |
| 71 | 'weight' => -10, |
| 72 | 'type' => MENU_DEFAULT_LOCAL_TASK, |
| 73 | ); |
| 74 | $items['admin/store/settings/products/edit/fields'] = array( |
| 75 | 'title' => 'Product fields', |
| 76 | 'page callback' => 'drupal_get_form', |
| 77 | 'page arguments' => array('uc_product_field_settings_form'), |
| 78 | 'access arguments' => array('administer products'), |
| 79 | 'weight' => -5, |
| 80 | 'type' => MENU_LOCAL_TASK, |
| 81 | ); |
| 82 | $items['admin/store/settings/products/edit/features'] = array( |
| 83 | 'title' => 'Product features', |
| 84 | 'page callback' => 'drupal_get_form', |
| 85 | 'page arguments' => array('uc_product_feature_settings_form'), |
| 86 | 'access arguments' => array('administer product features'), |
| 87 | 'weight' => 0, |
| 88 | 'type' => MENU_LOCAL_TASK, |
| 89 | ); |
| 90 | // Insert subitems into the edit node page for product types. |
| 91 | $items['node/%node/edit/product'] = array( |
| 92 | 'title' => 'Product', |
| 93 | 'access callback' => 'uc_product_edit_access', |
| 94 | 'access arguments' => array(1), |
| 95 | 'weight' => -10, |
| 96 | 'type' => MENU_DEFAULT_LOCAL_TASK, |
| 97 | ); |
| 98 | $features = module_invoke_all('product_feature'); |
| 99 | if (!empty($features)) { |
| 100 | $items['node/%node/edit/features'] = array( |
| 101 | 'title' => 'Features', |
| 102 | 'page callback' => 'uc_product_features', |
| 103 | 'page arguments' => array(1), |
| 104 | 'access callback' => 'uc_product_feature_access', |
| 105 | 'access arguments' => array(1), |
| 106 | 'weight' => 10, |
| 107 | 'type' => MENU_LOCAL_TASK, |
| 108 | ); |
| 109 | } |
| 110 | |
| 111 | $items['admin/store/settings/products/defaults/%'] = array( |
| 112 | 'title' => 'Imagecache default settings', |
| 113 | 'access arguments' => array('administer products'), |
| 114 | 'page callback' => 'uc_product_image_defaults', |
| 115 | 'page arguments' => array(5), |
| 116 | 'type' => MENU_CALLBACK, |
| 117 | ); |
| 118 | $items['admin/store/products/classes/%uc_product_class'] = array( |
| 119 | 'title' => 'Product class', |
| 120 | 'access arguments' => array('administer product classes'), |
| 121 | 'page callback' => 'drupal_get_form', |
| 122 | 'page arguments' => array('uc_product_class_form', 4), |
| 123 | 'type' => MENU_CALLBACK, |
| 124 | ); |
| 125 | $items['admin/store/products/classes/%uc_product_class/edit'] = array( |
| 126 | 'title' => 'Edit', |
| 127 | 'type' => MENU_DEFAULT_LOCAL_TASK, |
| 128 | 'weight' => -5, |
| 129 | ); |
| 130 | $items['admin/store/products/classes/%uc_product_class/delete'] = array( |
| 131 | 'access arguments' => array('administer product classes'), |
| 132 | 'page callback' => 'drupal_get_form', |
| 133 | 'page arguments' => array('uc_product_class_delete_confirm', 4), |
| 134 | 'type' => MENU_CALLBACK, |
| 135 | ); |
| 136 | |
| 137 | $items['products/field_image_cache/%'] = array( |
| 138 | 'access callback' => TRUE, |
| 139 | 'page callback' => '_uc_product_get_image_field_filepath', |
| 140 | 'page arguments' => array(2), |
| 141 | 'type' => MENU_CALLBACK, |
| 142 | ); |
| 143 | |
| 144 | return $items; |
| 145 | } |
| 146 | |
| 147 | /** |
| 148 | * Implementation of hook_help(). |
| 149 | */ |
| 150 | function uc_product_help($path, $arg) { |
| 151 | // Do things here later. Figure out what you need to say for each section. |
| 152 | switch ($path) { |
| 153 | case 'admin/settings/module#description': |
| 154 | $output = t('Create products for sale in an online store.'); |
| 155 | break; |
| 156 | } |
| 157 | return $output; |
| 158 | } |
| 159 | |
| 160 | /** |
| 161 | * Implementation of hook_perm(). |
| 162 | */ |
| 163 | function uc_product_perm() { |
| 164 | $perms = array('administer products', 'administer product classes', 'administer product features'); |
| 165 | foreach (node_get_types() as $type) { |
| 166 | if ($type->module == 'uc_product') { |
| 167 | $name = check_plain($type->type); |
| 168 | if ($name == 'product') { |
| 169 | $name = ''; |
| 170 | } |
| 171 | else { |
| 172 | $name .= ' '; |
| 173 | } |
| 174 | $perms[] = 'create '. $name .'products'; |
| 175 | $perms[] = 'edit own '. $name .'products'; |
| 176 | $perms[] = 'edit '. $name .'products'; |
| 177 | } |
| 178 | } |
| 179 | return $perms; |
| 180 | } |
| 181 | |
| 182 | /** |
| 183 | * Implementation of hook_access(). |
| 184 | */ |
| 185 | function uc_product_access($op, $node) { |
| 186 | global $user; |
| 187 | $type = is_string($node) ? $node : (is_array($node) ? $node['type'] : $node->type); |
| 188 | |
| 189 | if ($type == 'product') { |
| 190 | $type = ''; |
| 191 | } |
| 192 | else { |
| 193 | $type .= ' '; |
| 194 | } |
| 195 | switch ($op) { |
| 196 | case 'create': |
| 197 | return user_access('create '. $type .'products'); |
| 198 | case 'update': |
| 199 | case 'delete': |
| 200 | if (user_access('edit '. $type .'products') || (user_access('edit own '. $type .'products') && ($user->uid == $node->uid))) { |
| 201 | return TRUE; |
| 202 | } |
| 203 | } |
| 204 | } |
| 205 | |
| 206 | /** |
| 207 | * Menu access callback for 'node/%node/edit/product'. |
| 208 | */ |
| 209 | function uc_product_edit_access($node) { |
| 210 | // Re-inherit access callback for 'node/%node/edit' |
| 211 | return uc_product_is_product($node) && node_access('update', $node); |
| 212 | } |
| 213 | |
| 214 | /** |
| 215 | * Menu access callback for 'node/%node/edit/features'. |
| 216 | */ |
| 217 | function uc_product_feature_access($node) { |
| 218 | return uc_product_is_product($node) && user_access('administer product features'); |
| 219 | } |
| 220 | |
| 221 | /** |
| 222 | * Implementation of hook_init(). |
| 223 | */ |
| 224 | function uc_product_init() { |
| 225 | drupal_add_css(drupal_get_path('module', 'uc_product') .'/uc_product.css'); |
| 226 | } |
| 227 | |
| 228 | /** |
| 229 | * Implementation of hook_enable(). |
| 230 | * |
| 231 | * Set up default imagefield and imagecache settings. |
| 232 | */ |
| 233 | function uc_product_enable() { |
| 234 | $node_types = node_get_types('types'); |
| 235 | $product_classes = array('product'); |
| 236 | $result = db_query("SELECT pcid, name, description FROM {uc_product_classes}"); |
| 237 | while ($product_class = db_fetch_object($result)) { |
| 238 | $product_classes[] = $product_class->pcid; |
| 239 | } |
| 240 | foreach ($node_types as $type => $info) { |
| 241 | if ($info->module == 'node' && in_array($type, $product_classes)) { |
| 242 | $info->module = 'uc_product'; |
| 243 | $info->custom = 0; |
| 244 | node_type_save($info); |
| 245 | } |
| 246 | } |
| 247 | |
| 248 | if (module_exists('imagefield')) { |
| 249 | $result = db_query("SELECT field_name FROM {node_field} WHERE field_name = 'field_image_cache' AND type = 'image'"); |
| 250 | if (!db_num_rows($result)) { |
| 251 | 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:{}'); |
| 252 | } |
| 253 | $image_path = file_create_path(); |
| 254 | $widget_settings = array( |
| 255 | 'max_resolution' => '0', |
| 256 | 'image_path' => $image_path, |
| 257 | 'custom_alt' => 1, |
| 258 | 'custom_title' => 1, |
| 259 | 'teaser_preset' => null, |
| 260 | 'body_preset' => null, |
| 261 | ); |
| 262 | $display_settings = array( |
| 263 | 'label' => array( |
| 264 | 'format' => 'hidden', |
| 265 | ), |
| 266 | 'teaser' => array( |
| 267 | 'format' => 'hidden', |
| 268 | ), |
| 269 | 'full' => array( |
| 270 | 'format' => 'hidden', |
| 271 | ), |
| 272 | ); |
| 273 | foreach (module_invoke_all('product_types') as $type) { |
| 274 | $result = db_query("SELECT * FROM {node_field_instance} WHERE field_name = 'field_image_cache' and type_name = '%s'", $type); |
| 275 | if (!db_num_rows($result)) { |
| 276 | db_query("INSERT INTO {node_field_instance} VALUES ('field_image_cache', '%s', -2, 'Image', 'image', '%s', '%s', '')", $type, serialize($widget_settings), serialize($display_settings)); |
| 277 | } |
| 278 | switch ($GLOBALS['db_type']) { |
| 279 | case 'mysql': |
| 280 | case 'mysqli': |
| 281 | db_query("CREATE TABLE IF NOT EXISTS {content_field_image_cache} ( |
| 282 | `vid` int(10) unsigned NOT NULL default '0', |
| 283 | `delta` int(10) unsigned NOT NULL default '0', |
| 284 | `nid` int(10) unsigned NOT NULL default '0', |
| 285 | `field_image_cache_fid` int(11) NOT NULL default '0', |
| 286 | `field_image_cache_title` varchar(255) NOT NULL default '', |
| 287 | `field_image_cache_alt` varchar(255) NOT NULL default '', |
| 288 | PRIMARY KEY (`vid`,`delta`) |
| 289 | ) /*!40100 DEFAULT CHARACTER SET utf8 */;"); |
| 290 | break; |
| 291 | case 'pgsql': |
| 292 | $result = db_query("SELECT relname FROM pg_class WHERE relname = '{content_field_image_cache}'"); |
| 293 | if (!db_num_rows($result)) { |
| 294 | db_query('CREATE TABLE {content_field_image_cache} ( |
| 295 | "vid" int_unsigned NOT NULL default \'0\', |
| 296 | "delta" int_unsigned NOT NULL default \'0\', |
| 297 | "nid" int_unsigned NOT NULL default \'0\', |
| 298 | "field_image_cache_fid" integer NOT NULL default \'0\', |
| 299 | "field_image_cache_title" varchar(255) NOT NULL, |
| 300 | "field_image_cache_alt" varchar(255) NOT NULL, |
| 301 | PRIMARY KEY ("vid","delta") |
| 302 | );'); |
| 303 | } |
| 304 | break; |
| 305 | } |
| 306 | } |
| 307 | content_clear_type_cache(); |
| 308 | } |
| 309 | if (module_exists('imagecache')) { |
| 310 | $presets = array('product' => 0, 'product_list' => 0, 'uc_thumbnail' => 0); |
| 311 | $result = db_query("SELECT * FROM {imagecache_preset} WHERE presetname IN ('". implode("','", array_keys($presets)) ."')"); |
| 312 | while ($preset = db_fetch_array($result)) { |
| 313 | $presets[$preset['presetname']] = $preset['presetid']; |
| 314 | } |
| 315 | //drupal_set_message('<pre>'. print_r($presets, true) .'</pre>'); |
| 316 | foreach ($presets as $name => $id) { |
| 317 | if ($id == 0) { |
| 318 | $id = db_next_id('{imagecache_preset}_presetid'); |
| 319 | db_query("INSERT INTO {imagecache_preset} (presetid, presetname) VALUES (%d, '%s')", $id, $name); |
| 320 | } |
| 321 | } |
| 322 | $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)) ."')"); |
| 323 | $presets = array(); |
| 324 | while ($preset = db_fetch_array($result)) { |
| 325 | if (is_null($preset['actionid'])) { |
| 326 | switch ($preset['presetname']) { |
| 327 | case 'product': |
| 328 | 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";}'); |
| 329 | break; |
| 330 | case 'product_list': |
| 331 | 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";}'); |
| 332 | break; |
| 333 | case 'uc_thumbnail': |
| 334 | 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";}'); |
| 335 | break; |
| 336 | } |
| 337 | } |
| 338 | } |
| 339 | cache_clear_all('imagecache:presets', 'cache'); |
| 340 | } |
| 341 | } |
| 342 | |
| 343 | function uc_product_disable() { |
| 344 | $product_types = node_get_types('types'); |
| 345 | // node_type_rebuild() deletes disabled modules' node types. Give these |
| 346 | // node types to node.module to prevent this. Get them back during |
| 347 | // hook_enable(). |
| 348 | foreach ($product_types as $type) { |
| 349 | if ($type->module == 'uc_product') { |
| 350 | $type->module = 'node'; |
| 351 | $type->custom = 1; |
| 352 | node_type_save($type); |
| 353 | } |
| 354 | } |
| 355 | } |
| 356 | |
| 357 | function uc_product_theme() { |
| 358 | return array( |
| 359 | 'uc_product_form_prices' => array( |
| 360 | 'arguments' => array('form' => NULL), |
| 361 | ), |
| 362 | 'uc_product_form_weight' => array( |
| 363 | 'arguments' => array('form' => NULL), |
| 364 | ), |
| 365 | 'uc_product_dimensions' => array( |
| 366 | 'arguments' => array('form' => NULL), |
| 367 | ), |
| 368 | 'uc_product_field_settings_form' => array( |
| 369 | 'arguments' => array('form' => NULL), |
| 370 | ), |
| 371 | 'uc_product_model' => array( |
| 372 | 'arguments' => array('model' => ''), |
| 373 | ), |
| 374 | 'uc_product_add_to_cart' => array( |
| 375 | 'arguments' => array('node' => NULL), |
| 376 | ), |
| 377 | 'uc_product_price' => array( |
| 378 | 'arguments' => array('price' => 0, 'class' => ''), |
| 379 | ), |
| 380 | 'uc_product_sell_price' => array( |
| 381 | 'arguments' => array('price' => 0, 'teaser' => FALSE), |
| 382 | ), |
| 383 | 'uc_product_weight' => array( |
| 384 | 'arguments' => array('weight' => 0, 'unit' => NULL), |
| 385 | ), |
| 386 | 'uc_product_dimensions' => array( |
| 387 | 'arguments' => array('length' => 0, 'width' => 0, 'height' => 0, 'units' => NULL), |
| 388 | ), |
| 389 | 'uc_product_image' => array( |
| 390 | 'arguments' => array('images'), |
| 391 | ), |
| 392 | 'uc_product_display_price' => array( |
| 393 | 'arguments' => array('price' => 0), |
| 394 | ), |
| 395 | 'uc_product_feature_add_form' => array( |
| 396 | 'arguments' => array('form' => NULL), |
| 397 | ), |
| 398 | ); |
| 399 | } |
| 400 | |
| 401 | /** |
| 402 | * Implementation of hook_node_info(). |
| 403 | * |
| 404 | * Create node types for each product class and other product modules. |
| 405 | */ |
| 406 | function uc_product_node_info($reset = false) { |
| 407 | static $types = array(); |
| 408 | $title_label = t('Name'); |
| 409 | $body_label = t('Description'); |
| 410 | |
| 411 | if (empty($types) || $reset) { |
| 412 | $types = array(); |
| 413 | $types['product'] = array( |
| 414 | 'name' => t('Product'), |
| 415 | 'module' => 'uc_product', |
| 416 | 'description' => t('This node displays the representation of a product for sale on the website. It includes |
| 417 | all the unique information that can be attributed to a specific model number.'), |
| 418 | 'title_label' => $title_label, |
| 419 | 'body_label' => $body_label, |
| 420 | ); |
| 421 | |
| 422 | $result = db_query("SELECT pcid, name, description FROM {uc_product_classes}"); |
| 423 | while ($class = db_fetch_object($result)) { |
| 424 | $types[$class->pcid] = array( |
| 425 | 'name' => $class->name, |
| 426 | 'module' => 'uc_product', |
| 427 | 'description' => $class->description, |
| 428 | 'title_label' => $title_label, |
| 429 | 'body_label' => $body_label, |
| 430 | ); |
| 431 | } |
| 432 | } |
| 433 | return $types; |
| 434 | } |
| 435 | |
| 436 | /** |
| 437 | * Implementation of hook_forms(). |
| 438 | * |
| 439 | * Register an "add to cart" form for each product to prevent id collisions. |
| 440 | */ |
| 441 | function uc_product_forms($form_id, $args) { |
| 442 | $forms = array(); |
| 443 | if (substr($form_id, 0, 27) == 'uc_product_add_to_cart_form' || substr($form_id, 0, 26) == 'uc_catalog_buy_it_now_form') { |
| 444 | $products = db_query("SELECT DISTINCT nid, type FROM {node} WHERE nid = %d", $args[0]->nid); |
| 445 | |
| 446 | while ($product = db_fetch_object($products)) { |
| 447 | if (in_array($product->type, array_keys(uc_product_node_info()))) { |
| 448 | $forms['uc_product_add_to_cart_form_'. $product->nid] = array('callback' => 'uc_product_add_to_cart_form'); |
| 449 | $forms['uc_catalog_buy_it_now_form_'. $product->nid] = array('callback' => 'uc_catalog_buy_it_now_form'); |
| 450 | } |
| 451 | } |
| 452 | } |
| 453 | return $forms; |
| 454 | } |
| 455 | |
| 456 | /** |
| 457 | * Implementation of hook_form(). |
| 458 | * |
| 459 | * @ingroup forms |
| 460 | * @see theme_uc_product_form_prices |
| 461 | * @see theme_uc_product_form_weight |
| 462 | * @see theme_uc_product_dimensions |
| 463 | * @see uc_product_form_validate |
| 464 | */ |
| 465 | function uc_product_form(&$node) { |
| 466 | $location = array(); |
| 467 | $location[] = menu_get_item('admin'); |
| 468 | $location[] = menu_get_item('admin/store'); |
| 469 | $location[] = menu_get_item('admin/store/products'); |
| 470 | $location[] = menu_get_item('admin/store/settings/products'); |
| 471 | $breadcrumb = array(l('Home', '')); |
| 472 | foreach ($location as $item) { |
| 473 | $breadcrumb[] = l($item['title'], $item['path']); |
| 474 | } |
| 475 | drupal_set_breadcrumb($breadcrumb); |
| 476 | $sign_flag = variable_get('uc_sign_after_amount', FALSE); |
| 477 | $currency_sign = variable_get('uc_currency_sign', '$'); |
| 478 | |
| 479 | $form['title'] = array('#type' => 'textfield', |
| 480 | '#title' => t('Name'), |
| 481 | '#required' => TRUE, |
| 482 | '#weight' => -5, |
| 483 | '#default_value' => $node->title, |
| 484 | '#description' => t('Name of the product.') |
| 485 | ); |
| 486 | |
| 487 | $form['body_filter']['body'] = array('#type' => 'textarea', |
| 488 | '#title' => t('Description'), |
| 489 | '#required' => FALSE, |
| 490 | '#default_value' => $node->body, |
| 491 | '#rows' => 20, |
| 492 | '#description' => t('Enter the product description used for product teasers and pages.'), |
| 493 | ); |
| 494 | $form['body_filter']['format'] = filter_form($node->format); |
| 495 | $form['body_filter']['#weight'] = -4; |
| 496 | |
| 497 | $form['base'] = array('#type' => 'fieldset', |
| 498 | '#title' => t('Product information'), |
| 499 | '#collapsible' => true, |
| 500 | '#collapsed' => false, |
| 501 | '#weight' => -1, |
| 502 | '#attributes' => array('class' => 'product-field'), |
| 503 | ); |
| 504 | $form['base']['model'] = array('#type' => 'textfield', |
| 505 | '#title' => t('SKU'), |
| 506 | '#required' => TRUE, |
| 507 | '#default_value' => $node->model, |
| 508 | '#description' => t('Product SKU/model.'), |
| 509 | '#weight' => 0, |
| 510 | '#size' => 32, |
| 511 | ); |
| 512 | |
| 513 | $form['base']['prices'] = array( |
| 514 | '#weight' => 5, |
| 515 | '#theme' => 'uc_product_form_prices', |
| 516 | ); |
| 517 | |
| 518 | $form['base']['prices']['list_price'] = array( |
| 519 | '#type' => 'textfield', |
| 520 | '#title' => t('List price'), |
| 521 | '#required' => FALSE, |
| 522 | '#default_value' => $node->list_price, |
| 523 | '#description' => t('The listed MSRP.'), |
| 524 | '#weight' => 0, |
| 525 | '#size' => 20, |
| 526 | '#maxlength' => 35, |
| 527 | '#field_prefix' => $sign_flag ? '' : $currency_sign, |
| 528 | '#field_suffix' => $sign_flag ? $currency_sign : '', |
| 529 | ); |
| 530 | $form['base']['prices']['cost'] = array( |
| 531 | '#type' => 'textfield', |
| 532 | '#title' => t('Cost'), |
| 533 | '#required' => FALSE, |
| 534 | '#default_value' => $node->cost, |
| 535 | '#description' => t("Your store's cost."), |
| 536 | '#weight' => 1, |
| 537 | '#size' => 20, |
| 538 | '#maxlength' => 35, |
| 539 | '#field_prefix' => $sign_flag ? '' : $currency_sign, |
| 540 | '#field_suffix' => $sign_flag ? $currency_sign : '', |
| 541 | ); |
| 542 | $form['base']['prices']['sell_price'] = array( |
| 543 | '#type' => 'textfield', |
| 544 | '#title' => t('Sell price'), |
| 545 | '#required' => TRUE, |
| 546 | '#default_value' => $node->sell_price, |
| 547 | '#description' => t('Customer purchase price.'), |
| 548 | '#weight' => 2, |
| 549 | '#size' => 20, |
| 550 | '#maxlength' => 35, |
| 551 | '#field_prefix' => $sign_flag ? '' : $currency_sign, |
| 552 | '#field_suffix' => $sign_flag ? $currency_sign : '', |
| 553 | ); |
| 554 | |
| 555 | $form['base']['shippable'] = array( |
| 556 | '#type' => 'checkbox', |
| 557 | '#title' => t('Product and its derivatives are shippable.'), |
| 558 | '#default_value' => isset($node->shippable) ? $node->shippable : TRUE, |
| 559 | '#weight' => 10, |
| 560 | ); |
| 561 | |
| 562 | $form['base']['weight'] = array( |
| 563 | '#weight' => 15, |
| 564 | '#theme' => 'uc_product_form_weight', |
| 565 | ); |
| 566 | $form['base']['weight']['weight'] = array('#type' => 'textfield', |
| 567 | '#title' => t('Weight'), |
| 568 | '#default_value' => $node->weight, |
| 569 | '#size' => 10, |
| 570 | '#maxlength' => 15, |
| 571 | ); |
| 572 | $units = array( |
| 573 | 'lb' => t('Pounds'), |
| 574 | 'kg' => t('Kilograms'), |
| 575 | 'oz' => t('Ounces'), |
| 576 | 'g' => t('Grams'), |
| 577 | ); |
| 578 | $form['base']['weight']['weight_units'] = array('#type' => 'select', |
| 579 | '#title' => t('Unit of measurement'), |
| 580 | '#default_value' => $node->weight_units ? $node->weight_units : variable_get('uc_weight_unit', 'lb'), |
| 581 | '#options' => $units, |
| 582 | ); |
| 583 | $form['base']['dimensions'] = array('#type' => 'fieldset', |
| 584 | '#title' => t('Dimensions'), |
| 585 | '#description' => t('Physical dimensions of the packaged product.'), |
| 586 | '#weight' => 20, |
| 587 | '#theme' => 'uc_product_dimensions_form', |
| 588 | ); |
| 589 | $form['base']['dimensions']['length_units'] = array('#type' => 'select', |
| 590 | '#title' => t('Units of measurement'), |
| 591 | '#options' => array( |
| 592 | 'in' => t('Inches'), |
| 593 | 'ft' => t('Feet'), |
| 594 | 'cm' => t('Centimeters'), |
| 595 | 'mm' => t('Millimeters'), |
| 596 | ), |
| 597 | '#default_value' => $node->length_units ? $node->length_units : variable_get('uc_length_unit', 'in'), |
| 598 | ); |
| 599 | $form['base']['dimensions']['length'] = array('#type' => 'textfield', |
| 600 | '#title' => t('Length'), |
| 601 | '#default_value' => $node->length, |
| 602 | '#size' => 10, |
| 603 | ); |
| 604 | $form['base']['dimensions']['width'] = array('#type' => 'textfield', |
| 605 | '#title' => t('Width'), |
| 606 | '#default_value' => $node->width, |
| 607 | '#size' => 10, |
| 608 | ); |
| 609 | $form['base']['dimensions']['height'] = array('#type' => 'textfield', |
| 610 | '#title' => t('Height'), |
| 611 | '#default_value' => $node->height, |
| 612 | '#size' => 10, |
| 613 | ); |
| 614 | $form['base']['pkg_qty'] = array('#type' => 'textfield', |
| 615 | '#title' => t('Package quantity'), |
| 616 | '#default_value' => $node->pkg_qty ? $node->pkg_qty : 1, |
| 617 | '#description' => t('For a package containing only this product, how many are in it?'), |
| 618 | '#weight' => 25, |
| 619 | ); |
| 620 | $form['base']['default_qty'] = array('#type' => 'textfield', |
| 621 | '#title' => t('Default quantity to add to cart'), |
| 622 | '#default_value' => !is_null($node->default_qty) ? $node->default_qty : 1, |
| 623 | '#description' => t('Leave blank or zero to disable the quantity field in the add to cart form.'), |
| 624 | '#weight' => 27, |
| 625 | '#size' => 5, |
| 626 | '#maxlength' => 6, |
| 627 | ); |
| 628 | $form['base']['ordering'] = array('#type' => 'weight', |
| 629 | '#title' => t('List position'), |
| 630 | '#description' => t("Specify a value to set this product's position in product lists.<br />Products in the same position will be sorted alphabetically."), |
| 631 | '#delta' => 25, |
| 632 | '#default_value' => isset($node->ordering) ? $node->ordering : 0, |
| 633 | '#weight' => 30, |
| 634 | ); |
| 635 | |
| 636 | return $form; |
| 637 | } |
| 638 | |
| 639 | /** |
| 640 | * @ingroup themeable |
| 641 | */ |
| 642 | function theme_uc_product_form_prices($form) { |
| 643 | return "<table><tr><td>\n". drupal_render($form['list_price']) |
| 644 | .'</td><td>'. drupal_render($form['cost']) |
| 645 | .'</td><td>'. drupal_render($form['sell_price']) |
| 646 | ."</td></tr></table>\n"; |
| 647 | } |
| 648 | |
| 649 | /** |
| 650 | * @ingroup themeable |
| 651 | */ |
| 652 | function theme_uc_product_form_weight($form) { |
| 653 | return '<table><tr><td>'. drupal_render($form['weight']) .'</td><td>' |
| 654 | . drupal_render($form['weight_units']) .'</td></tr></table>'; |
| 655 | } |
| 656 | |
| 657 | /** |
| 658 | * Put length, width, and height fields on the same line. |
| 659 | * |
| 660 | * @ingroup themeable |
| 661 | */ |
| 662 | function theme_uc_product_dimensions_form($form) { |
| 663 | $output = ''; |
| 664 | $row = array(); |
| 665 | foreach (element_children($form) as $dimension) { |
| 666 | $row[] = drupal_render($form[$dimension]); |
| 667 | } |
| 668 | $output .= theme('table', array(), array($row)); |
| 669 | return $output; |
| 670 | } |
| 671 | |
| 672 | function uc_product_validate($node) { |
| 673 | $pattern = '/^\d*(\.\d*)?$/'; |
| 674 | $price_error = t('Price must be in a valid number format. No commas and only one decimal point.'); |
| 675 | if (!empty($node->list_price) && !is_numeric($node->list_price) && !preg_match($pattern, $node->list_price)) { |
| 676 | form_set_error('list_price', $price_error); |
| 677 | } |
| 678 | if (!empty($node->cost) && !is_numeric($node->cost) && !preg_match($pattern, $node->cost)) { |
| 679 | form_set_error('cost', $price_error); |
| 680 | } |
| 681 | if (!is_numeric($node->sell_price) && !preg_match($pattern, $node->sell_price)) { |
| 682 | form_set_error('sell_price', $price_error); |
| 683 | } |
| 684 | if (!empty($node->weight) && !is_numeric($node->weight)) { |
| 685 | form_set_error('weight', t('Weight must be in a valid number format. No commas and only one decimal point.')); |
| 686 | } |
| 687 | if ($node->default_qty) { |
| 688 | if (!is_numeric($node->default_qty)) { |
| 689 | form_set_error('default_qty', t('Quantities should be numeric.')); |
| 690 | } |
| 691 | else if ($node->default_qty < 0) { |
| 692 | form_set_error('default_qty', t("Adding negative items to the cart doesn't make sense, so don't make it easy.")); |
| 693 | } |
| 694 | } |
| 695 | } |
| 696 | |
| 697 | /** |
| 698 | * Implementation of hook_insert(). |
| 699 | */ |
| 700 | function uc_product_insert($node) { |
| 701 | if (!isset($node->unique_hash)) { |
| 702 | $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()); |
| 703 | } |
| 704 | 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)", |
| 705 | $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 |
| 706 | ); |
| 707 | } |
| 708 | |
| 709 | /** |
| 710 | * Implementation of hook_update(). |
| 711 | */ |
| 712 | function uc_product_update($node) { |
| 713 | if ($node->revision) { |
| 714 | 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)", |
| 715 | $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 |
| 716 | ); |
| 717 | } |
| 718 | else { |
| 719 | //drupal_set_message('<pre>'. print_r($node, true) .'</pre>');drupal_set_message('<pre>'. print_r($node, true) .'</pre>'); |
| 720 | 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", |
| 721 | $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); |
| 722 | } |
| 723 | } |
| 724 | |
| 725 | /** |
| 726 | * Implementation of hook_load(). |
| 727 | */ |
| 728 | function uc_product_load(&$node) { |
| 729 | 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)); |
| 730 | } |
| 731 | |
| 732 | /** |
| 733 | * Implementation of hook_delete(). |
| 734 | */ |
| 735 | function uc_product_delete(&$node) { |
| 736 | db_query("DELETE from {uc_products} WHERE nid = %d", $node->nid); |
| 737 | } |
| 738 | |
| 739 | /** |
| 740 | * Implementation of hook_view(). |
| 741 | */ |
| 742 | function uc_product_view($node, $teaser = 0, $page = 0) { |
| 743 | $node = node_prepare($node, $teaser); |
| 744 | |
| 745 | $enabled = variable_get('uc_product_field_enabled', array( |
| 746 | 'image' => 1, |
| 747 | 'display_price' => 1, |
| 748 | 'model' => 1, |
| 749 | 'list_price' => 0, |
| 750 | 'cost' => 0, |
| 751 | 'sell_price' => 1, |
| 752 | 'weight' => 0, |
| 753 | 'dimensions' => 0, |
| 754 | 'add_to_cart' => 1, |
| 755 | )); |
| 756 | $weight = variable_get('uc_product_field_weight', array( |
| 757 | 'image' => -2, |
| 758 | 'display_price' => -1, |
| 759 | 'model' => 0, |
| 760 | 'list_price' => 2, |
| 761 | 'cost' => 3, |
| 762 | 'sell_price' => 4, |
| 763 | 'weight' => 5, |
| 764 | 'dimensions' => 6, |
| 765 | 'add_to_cart' => 10, |
| 766 | )); |
| 767 | |
| 768 | //drupal_set_message('<pre>'. print_r($node->field_image_cache, true) .'</pre>'); |
| 769 | if (isset($node->field_image_cache) && file_exists($node->field_image_cache[0]['filepath'])) { |
| 770 | $node->content['image'] = array('#value' => theme('uc_product_image', $node->field_image_cache), |
| 771 | '#access' => $enabled['image'] && module_exists('imagecache'), |
| 772 | '#weight' => $weight['image'], |
| 773 | ); |
| 774 | } |
| 775 | $node->content['display_price'] = array('#value' => theme('uc_product_display_price', $node->sell_price), |
| 776 | '#access' => $enabled['display_price'], |
| 777 | '#weight' => $weight['display_price'], |
| 778 | ); |
| 779 | if (!$teaser) { |
| 780 | $node->content['model'] = array('#value' => theme('uc_product_model', $node->model), |
| 781 | '#access' => $enabled['model'], |
| 782 | '#weight' => $weight['model'], |
| 783 | ); |
| 784 | $node->content['body']['#weight'] = 1; |
| 785 | $node->content['list_price'] = array('#value' => theme('uc_product_price', $node->list_price, 'list_price'), |
| 786 | '#access' => $enabled['list_price'], |
| 787 | '#weight' => $weight['list_price'], |
| 788 | ); |
| 789 | $node->content['cost'] = array('#value' => theme('uc_product_price', $node->cost, 'cost'), |
| 790 | '#access' => $enabled['cost'] && user_access('administer products'), |
| 791 | '#weight' => $weight['cost'], |
| 792 | ); |
| 793 | } |
| 794 | else { |
| 795 | $node->content['#attributes'] = array('style' => 'display: inline'); |
| 796 | } |
| 797 | |
| 798 | $node->content['sell_price'] = array('#value' => theme('uc_product_sell_price', $node->sell_price, $teaser), |
| 799 | '#access' => $enabled['sell_price'], |
| 800 | '#weight' => $weight['sell_price'], |
| 801 | ); |
| 802 | |
| 803 | if (!$teaser) { |
| 804 | $node->content['weight'] = array('#value' => theme('uc_product_weight', $node->weight, $node->weight_units), |
| 805 | '#access' => $enabled['weight'], |
| 806 | '#weight' => $weight['weight'], |
| 807 | ); |
| 808 | $node->content['dimensions'] = array('#value' => theme('uc_product_dimensions', $node->length, $node->width, $node->height, $node->length_units), |
| 809 | '#access' => $enabled['dimensions'], |
| 810 | '#weight' => $weight['dimensions'], |
| 811 | ); |
| 812 | if (module_exists('uc_cart')) { |
| 813 | $node->content['add_to_cart'] = array('#value' => theme('uc_product_add_to_cart', $node), |
| 814 | '#access' => $enabled['add_to_cart'], |
| 815 | '#weight' => $weight['add_to_cart'], |
| 816 | ); |
| 817 | } |
| 818 | } |
| 819 | else if (module_exists('uc_cart') && variable_get('uc_product_add_to_cart_teaser', true)) { |
| 820 | $node->content['add_to_cart'] = array('#value' => theme('uc_product_add_to_cart', $node), |
| 821 | '#access' => $enabled['add_to_cart'], |
| 822 | '#weight' => $weight['add_to_cart'], |
| 823 | ); |
| 824 | } |
| 825 | //drupal_set_message('<pre>'. print_r($breadcrumb, true) .'</pre>'); |
| 826 | return $node; |
| 827 | } |
| 828 | |
| 829 | function uc_product_form_alter(&$form, &$form_state, $form_id) { |
| 830 | if ($form_id == 'search_form' && arg(0) == 'admin' && arg(1) == 'store' && arg(2) == 'products' && user_access('use advanced search')) { |
| 831 | // Keyword boxes: |
| 832 | $form['advanced'] = array( |
| 833 | '#type' => 'fieldset', |
| 834 | '#title' => t('Advanced search'), |
| 835 | '#collapsible' => TRUE, |
| 836 | '#collapsed' => TRUE, |
| 837 | '#attributes' => array('class' => 'search-advanced'), |
| 838 | ); |
| 839 | $form['advanced']['keywords'] = array( |
| 840 | '#prefix' => '<div class="criterion">', |
| 841 | '#suffix' => '</div>', |
| 842 | ); |
| 843 | $form['advanced']['keywords']['or'] = array( |
| 844 | '#type' => 'textfield', |
| 845 | '#title' => t('Containing any of the words'), |
| 846 | '#size' => 30, |
| 847 | '#maxlength' => 255, |
| 848 | ); |
| 849 | $form['advanced']['keywords']['phrase'] = array( |
| 850 | '#type' => 'textfield', |
| 851 | '#title' => t('Containing the phrase'), |
| 852 | '#size' => 30, |
| 853 | '#maxlength' => 255, |
| 854 | ); |
| 855 | $form['advanced']['keywords']['negative'] = array( |
| 856 | '#type' => 'textfield', |
| 857 | '#title' => t('Containing none of the words'), |
| 858 | '#size' => 30, |
| 859 | '#maxlength' => 255, |
| 860 | ); |
| 861 | |
| 862 | // Taxonomy box: |
| 863 | if ($taxonomy = module_invoke('taxonomy', 'form_all', 1)) { |
| 864 | $form['advanced']['category'] = array( |
| 865 | '#type' => 'select', |
| 866 | '#title' => t('Only in the category(s)'), |
| 867 | '#prefix' => '<div class="criterion">', |
| 868 | '#size' => 10, |
| 869 | '#suffix' => '</div>', |
| 870 | '#options' => $taxonomy, |
| 871 | '#multiple' => TRUE, |
| 872 | ); |
| 873 | } |
| 874 | |
| 875 | // Node types: |
| 876 | $types = array(); |
| 877 | $product_types = module_invoke_all('product_types'); |
| 878 | $node_types = module_invoke_all('node_info'); |
| 879 | foreach ($product_types as $id) { |
| 880 | $types[$id] = $node_types[$id]['name']; |
| 881 | } |
| 882 | $form['advanced']['type'] = array( |
| 883 | '#type' => 'checkboxes', |
| 884 | '#title' => t('Only of the type(s)'), |
| 885 | '#prefix' => '<div class="criterion">', |
| 886 | '#suffix' => '</div>', |
| 887 | '#options' => $types, |
| 888 | ); |
| 889 | $form['advanced']['submit'] = array( |
| 890 | '#type' => 'submit', |
| 891 | '#value' => t('Advanced search'), |
| 892 | '#prefix' => '<div class="action clear-block">', |
| 893 | '#suffix' => '</div>', |
| 894 | ); |
| 895 | |
| 896 | $form['#validate'][] = 'node_search_validate'; |
| 897 | } |
| 898 | } |
| 899 | |
| 900 | /****************************************************************************** |
| 901 | * TAPIr Hooks * |
| 902 | ******************************************************************************/ |
| 903 | |
| 904 | /** |
| 905 | * Define up the product list table. |
| 906 | * |
| 907 | * @see uc_product_table |
| 908 | */ |
| 909 | function uc_product_table_settings() { |
| 910 | $tables = array(); |
| 911 | |
| 912 | $tables[] = array( |
| 913 | 'id' => 'uc_product_table', |
| 914 | 'description' => t('Lists a group of products in an abbreviated format.'), |
| 915 | 'path' => 'admin/store/settings/tables', |
| 916 | 'access' => 'administer store', |
| 917 | 'preview' => FALSE, |
| 918 | ); |
| 919 | |
| 920 | return $tables; |
| 921 | } |
| 922 | |
| 923 | function uc_product_table_header() { |
| 924 | $columns = array(); |
| 925 | |
| 926 | if (module_exists('imagecache')) { |
| 927 | $columns[] = array( |
| 928 | 'id' => 'image', |
| 929 | 'weight' => -5, |
| 930 | 'cell' => array('data' => t('Image')), |
| 931 | ); |
| 932 | } |
| 933 | $columns[] = array( |
| 934 | 'id' => 'name', |
| 935 | 'weight' => 0, |
| 936 | 'cell' => array('data' => t('Name'), 'field' => 'n.title'), |
| 937 | ); |
| 938 | $columns[] = array( |
| 939 | 'id' => 'list_price', |
| 940 | 'weight' => 3, |
| 941 | 'cell' => array('data' => t('List price'), 'field' => 'p.list_price'), |
| 942 | ); |
| 943 | $columns[] = array( |
| 944 | 'id' => 'price', |
| 945 | 'weight' => 5, |
| 946 | 'cell' => array('data' => t('Price'), 'field' => 'p.sell_price'), |
| 947 | ); |
| 948 | if (module_exists('uc_cart') && (arg(0) != 'admin' || $_GET['q'] == 'admin/store/settings/tables/uc_product_table')) { |
| 949 | $columns[] = array( |
| 950 | 'id' => 'add_to_cart', |
| 951 | 'weight' => 10, |
| 952 | 'cell' => array('data' => t('Add to cart'), 'nowrap' => 'nowrap'), |
| 953 | ); |
| 954 | } |
| 955 | |
| 956 | return $columns; |
| 957 | } |
| 958 | |
| 959 | /** |
| 960 | * Display product fields in a TAPIr table. |
| 961 | * |
| 962 | * Display image, name, price, and add to cart form. |
| 963 | */ |
| 964 | function uc_product_table($form_state, $args = array()) { |
| 965 | $table = array(); |
| 966 | |
| 967 | $table['columns'] = uc_product_table_header(); |
| 968 | |
| 969 | foreach ($args['nids'] as $nid) { |
| 970 | $data = array(); |
| 971 | $node = node_load($nid); |
| 972 | if ($node->type != 'image') { |
| 973 | if (module_exists('imagecache') && isset($node->field_image_cache) && file_exists($node->field_image_cache[0]['filepath'])) { |
| 974 | $data['image'] = array('cell' => 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('html' => TRUE))); |
| 975 | } |
| 976 | else { |
| 977 | $data['image'] = array('cell' => t('n/a')); |
| 978 | } |
| 979 | $data['name'] = array('value' => $node->title, 'cell' => array('data' => l($node->title, 'node/'. $node->nid), 'width' => '100%')); |
| 980 | $data['list_price'] = array('value' => $node->list_price, 'cell' => array('data' => theme('uc_product_price', $node->list_price, 'list_price'), 'nowrap' => 'nowrap')); |
| 981 | $data['price'] = array('value' => $node->sell_price, 'cell' => array('data' => theme('uc_product_sell_price', $node->sell_price, true), 'nowrap' => 'nowrap')); |
| 982 | if (module_exists('uc_cart') && arg(0) != 'admin') { |
| 983 | $data['add_to_cart'] = array('cell' => drupal_get_form('uc_catalog_buy_it_now_form_'. $node->nid, $node)); |
| 984 | } |
| 985 | $table['rows'][] = $data; |
| 986 | } |
| 987 | } |
| 988 | |
| 989 | $form['table'] = array( |
| 990 | '#value' => $table, |
| 991 | '#theme' => 'tapir_table', |
| 992 | '#attributes' => array( |
| 993 | 'class' => 'category-products', |
| 994 | ), |
| 995 | ); |
| 996 | |
| 997 | return $form; |
| 998 | } |
| 999 | |
| 1000 | /** |
| 1001 | * @ingroup forms |
| 1002 | * @see uc_product_forms |
| 1003 | * @see uc_catalog_buy_it_now_form_submit |
| 1004 | */ |
| 1005 | function uc_catalog_buy_it_now_form($form_state, $node) { |
| 1006 | $form = array(); |
| 1007 | $form['#validate'][] = 'uc_catalog_buy_it_now_form_validate'; |
| 1008 | $form['#submit'][] = 'uc_catalog_buy_it_now_form_submit'; |
| 1009 | $form['nid'] = array('#type' => 'hidden', '#value' => $node->nid); |
| 1010 | $form['submit'] = array( |
| 1011 | '#type' => 'submit', |
| 1012 | '#value' => variable_get('uc_teaser_add_to_cart_text', t('Add to cart')), |
| 1013 | '#id' => 'edit-submit-'. $node->nid, |
| 1014 | '#attributes' => array( |
| 1015 | 'class' => 'list-add-to-cart', |
| 1016 | ), |
| 1017 | ); |
| 1018 | return $form; |
| 1019 | } |
| 1020 | |
| 1021 | function uc_catalog_buy_it_now_form_validate($form, &$form_state) { |
| 1022 | $node = node_load($form_state['values']['nid']); |
| 1023 | if (module_exists('uc_attribute')) { |
| 1024 | $attributes = uc_product_get_attributes($node->nid); |
| 1025 | if (!empty($attributes)) { |
| 1026 | drupal_set_message(t('This product has options that need to be selected before purchase. Please select them in the form below.'), 'error'); |
| 1027 | drupal_goto('node/'. $form_state['values']['nid']); |
| 1028 | } |
| 1029 | if (is_array($node->products)) { |
| 1030 | foreach ($node->products as $nid => $product) { |
| 1031 | $attributes = uc_product_get_attributes($nid); |
| 1032 | if (!empty($attributes)) { |
| 1033 | drupal_set_message(t('This product has options that need to be selected before purchase. Please select them in the form below.'), 'error'); |
| 1034 | drupal_goto('node/'. $form_state['values']['nid']); |
| 1035 | } |
| 1036 | } |
| 1037 | } |