| [ Index ] |
PHP Cross Reference of Drupal 6 (yi-drupal) |
[Summary view] [Print] [Text view]
1 <?php 2 3 /** 4 * @file 5 * These are the hooks that are invoked by the Ubercart core. 6 * 7 * Core hooks are typically called in all modules at once using 8 * module_invoke_all(). 9 */ 10 11 /** 12 * @addtogroup hooks 13 * @{ 14 */ 15 16 /** 17 * Do extra processing when an item is added to the shopping cart. 18 * 19 * Some modules need to be able to hook into the process of adding items to a 20 * cart. For example, an inventory system may need to check stock levels and 21 * prevent an out of stock item from being added to a customer's cart. This hook 22 * lets developers squeeze right in at the end of the process after the product 23 * information is all loaded and the product is about to be added to the cart. 24 * In the event that a product should not be added to the cart, you simply have 25 * to return a failure message described below. This hook may also be used simply 26 * to perform some routine action when products are added to the cart. 27 * 28 * @param $nid 29 * The node ID of the product 30 * @param $qty 31 * The quantity being added 32 * @param $data 33 * The data array, including attributes and model number adjustments 34 * @return 35 * The function can use this data to whatever purpose to see if the item can 36 * be added to the cart or not. The function should return an array containing 37 * the result array. (This is due to the nature of Drupal's module_invoke_all() 38 * function. You must return an array within an array or other module data will 39 * end up getting ignored.) At this moment, there are only three keys: 40 * - "success": TRUE or FALSE for whether the specified quantity of the item 41 * may be added to the cart or not; defaults to TRUE. 42 * - "message": the fail message to display in the event of a failure; if 43 * omitted, Ubercart will display a default fail message. 44 * - "silent": return TRUE to suppress the display of any messages; useful 45 * when a module simply needs to do some other processing during an add to 46 * cart or fail silently. 47 */ 48 function hook_add_to_cart($nid, $qty, $data) { 49 if ($qty > 1) { 50 $result[] = array( 51 'success' => FALSE, 52 'message' => t('Sorry, you can only add one of those at a time.'), 53 ); 54 } 55 return $result; 56 } 57 58 /** 59 * Add extra information to a cart item's "data" array. 60 * 61 * This is effectively the submit handler of any alterations to the Add to Cart 62 * form. It provides a standard way to store the extra information so that it 63 * can be used by hook_add_to_cart(). 64 * 65 * @param $form_values 66 * The values submitted to the Add to Cart form. 67 * @return 68 * An array of data to be merged into the item added to the cart. 69 */ 70 function hook_add_to_cart_data($form_values) { 71 $node = node_load($form_values['nid']); 72 return array('module' => 'uc_product', 'shippable' => $node->shippable); 73 } 74 75 /** 76 * Calculate tax line items for an order. 77 * 78 * @param $order 79 * An order object or an order id. 80 * @return 81 * An array of tax line item objects keyed by a module-specific id. 82 */ 83 function hook_calculate_tax($order) { 84 global $user; 85 if (is_numeric($order)) { 86 $order = uc_order_load($order); 87 $account = user_load(array('uid' => $order->uid)); 88 } 89 elseif ((int)$order->uid) { 90 $account = user_load(array('uid' => intval($order->uid))); 91 } 92 else { 93 $account = $user; 94 } 95 if (!is_object($order)) { 96 return array(); 97 } 98 if (empty($order->delivery_postal_code)) { 99 $order->delivery_postal_code = $order->billing_postal_code; 100 } 101 if (empty($order->delivery_zone)) { 102 $order->delivery_zone = $order->billing_zone; 103 } 104 if (empty($order->delivery_country)) { 105 $order->delivery_country = $order->billing_country; 106 } 107 108 $order->taxes = array(); 109 110 if (isset($order->order_status)) { 111 $state = uc_order_status_data($order->order_status, 'state'); 112 $use_same_rates = in_array($state, array('payment_received', 'completed')); 113 } 114 else { 115 $use_same_rates = FALSE; 116 } 117 118 $arguments = array( 119 'order' => array( 120 '#entity' => 'uc_order', 121 '#title' => t('Order'), 122 '#data' => $order, 123 ), 124 'tax' => array( 125 '#entity' => 'tax', 126 '#title' => t('Tax rule'), 127 // #data => each $tax in the following foreach() loop; 128 ), 129 'account' => array( 130 '#entity' => 'user', 131 '#title' => t('User'), 132 '#data' => $account, 133 ), 134 ); 135 136 $predicates = ca_load_trigger_predicates('calculate_taxes'); 137 foreach (uc_taxes_rate_load() as $tax) { 138 if ($use_same_rates) { 139 foreach ((array)$order->line_items as $old_line) { 140 if ($old_line['type'] == 'tax' && $old_line['data']['tax_id'] == $tax->id) { 141 $tax->rate = $old_line['data']['tax_rate']; 142 break; 143 } 144 } 145 } 146 147 $arguments['tax']['#data'] = $tax; 148 if (ca_evaluate_conditions($predicates['uc_taxes_'. $tax->id], $arguments)) { 149 $line_item = uc_taxes_action_apply_tax($order, $tax); 150 if ($line_item) { 151 $order->taxes[$line_item->id] = $line_item; 152 } 153 } 154 } 155 156 return $order->taxes; 157 } 158 159 /** 160 * Control the display of an item in the cart. 161 * 162 * Product type modules allow the creation of nodes that can be added to the 163 * cart. The cart determines how they are displayed through this hook. This is 164 * especially important for product kits, because it may be displayed as a single 165 * unit in the cart even though it is represented as several items. 166 * 167 * @param $item 168 * The item in the cart to display. 169 * @return 170 * A form array containing the following elements: 171 * - "nid" 172 * - #type: value 173 * - #value: The node id of the $item. 174 * - "module" 175 * - #type: value 176 * - #value: The module implementing this hook and the node represented by 177 * $item. 178 * - "remove" 179 * - #type: checkbox 180 * - #value: If selected, removes the $item from the cart. 181 * - "description" 182 * - #type: markup 183 * - #value: Themed markup (usually an unordered list) displaying extra information. 184 * - "title" 185 * - #type: markup 186 * - #value: The displayed title of the $item. 187 * - "#total" 188 * - "type": float 189 * - "value": Numeric price of $item. Notice the '#' signifying that this is 190 * not a form element but just a value stored in the form array. 191 * - "data" 192 * - #type: hidden 193 * - #value: The serialized $item->data. 194 * - "qty" 195 * - #type: textfield 196 * - #value: The quantity of $item in the cart. When "Update cart" is clicked, 197 * the customer's input is saved to the cart. 198 */ 199 function hook_cart_display($item) { 200 $node = node_load($item->nid); 201 $element = array(); 202 $element['nid'] = array('#type' => 'value', '#value' => $node->nid); 203 $element['module'] = array('#type' => 'value', '#value' => 'uc_product'); 204 $element['remove'] = array('#type' => 'checkbox'); 205 206 $element['title'] = array( 207 '#value' => node_access('view', $node) ? l($item->title, 'node/'. $node->nid) : check_plain($item->title), 208 ); 209 210 $context = array( 211 'revision' => 'altered', 212 'type' => 'cart_item', 213 'subject' => array( 214 'cart_item' => $item, 215 'node' => $node, 216 ), 217 ); 218 $price_info = array( 219 'price' => $item->price, 220 'qty' => $item->qty, 221 ); 222 223 $element['#total'] = uc_price($price_info, $context); 224 $element['data'] = array('#type' => 'hidden', '#value' => serialize($item->data)); 225 $element['qty'] = array( 226 '#type' => 'textfield', 227 '#default_value' => $item->qty, 228 '#size' => 5, 229 '#maxlength' => 6 230 ); 231 232 if ($description = uc_product_get_description($item)) { 233 $element['description'] = array('#value' => $description); 234 } 235 236 return $element; 237 } 238 239 /** 240 * Add extra data about an item in the cart. 241 * 242 * Products that are added to a customer's cart are referred as items until the 243 * sale is completed. Just think of a grocery store having a bunch of products 244 * on the shelves but putting a sign over the express lane saying "15 Items or 245 * Less." hook_cart_item() is in charge of acting on items at various times like 246 * when they are being added to a cart, saved, loaded, and checked out. 247 * 248 * Here's the rationale for this hook: Products may change on a live site during 249 * a price increase or change to attribute adjustments. If a user has previously 250 * added an item to their cart, when they go to checkout or view their cart 251 * screen we want the latest pricing and model numbers to show. So, the essential 252 * product information is stored in the cart, but when the items in a cart are 253 * loaded, modules are given a chance to adjust the data against the latest settings. 254 * 255 * @param $op 256 * The action that is occurring. Possible values: 257 * - "load" - Passed for each item when a cart is being loaded in the function 258 * uc_cart_get_contents(). This gives modules the chance to tweak information 259 * for items when the cart is being loaded prior to being view or added to 260 * an order. No return value is expected. 261 * - "can_ship" - Passed when a cart is being scanned for items that are not 262 * shippable items. Übercart will bypass cart and checkout operations 263 * specifically related to tangible products if nothing in the cart is 264 * shippable. hook_cart_item functions that check for this op are expected 265 * to return TRUE or FALSE based on whether a product is shippable or not. 266 * - "remove" - Passed when an item is removed from the cart. 267 * - "checkout" - Passed for each item when the cart is being emptied for checkout. 268 * @return 269 * No return value for load. 270 * TRUE or FALSE for can_ship. 271 */ 272 function hook_cart_item($op, &$item) { 273 switch ($op) { 274 case 'load': 275 $term = array_shift(taxonomy_node_get_terms_by_vocabulary($item->nid, variable_get('uc_manufacturer_vid', 0))); 276 $arg1->manufacturer = $term->name; 277 break; 278 } 279 } 280 281 /** 282 * Register callbacks for a cart pane. 283 * 284 * The default cart view page displays a table of the cart contents and a few 285 * simple form features to manage the cart contents. For a module to add 286 * information to this page, it must use hook_cart_pane to define extra panes 287 * that may be ordered to appear above or below the default information. 288 * 289 * @param $items 290 * The current contents of the shopping cart. 291 * @return 292 * The function is expected to return an array of pane arrays with the following 293 * keys: 294 * - "id" 295 * - type: string 296 * - value: The internal ID of the pane, using a-z, 0-9, and - or _. 297 * - "title" 298 * - type: string 299 * - value: The name of the cart pane displayed to the user. Use t(). 300 * - "enabled" 301 * - type: boolean 302 * - value: Whether the pane is enabled by default or not. (Defaults to TRUE.) 303 * - "weight" 304 * - type: integer 305 * - value: The weight of the pane to determine its display order. (Defaults 306 * to 0.) 307 * - "body" 308 * - type: string 309 * - value: The body of the pane when rendered on the cart view screen. 310 * 311 * The body gets printed to the screen if it is on the cart view page. For the 312 * settings page, the body field is ignored. You may want your function to check 313 * for a NULL argument before processing any queries or foreach() loops. 314 */ 315 function hook_cart_pane($items) { 316 $panes[] = array( 317 'id' => 'cart_form', 318 'title' => t('Default cart form'), 319 'enabled' => TRUE, 320 'weight' => 0, 321 'body' => !is_null($items) ? drupal_get_form('uc_cart_view_form', $items) : '', 322 ); 323 324 return $panes; 325 } 326 327 /** 328 * Alter cart pane definitions. 329 * 330 * @param $panes 331 * The array of pane information in the format defined in hook_cart_pane(), passed 332 * by reference. 333 * 334 * @param $items 335 * The array of item information. 336 */ 337 function hook_cart_pane_alter(&$panes, $items) { 338 foreach ($panes as &$pane) { 339 if ($pane['id'] == 'cart') { 340 $pane['body'] = drupal_get_form('my_custom_pane_form_builder', $items); 341 } 342 } 343 } 344 345 /** 346 * Register callbacks for a checkout pane. 347 * 348 * The checkout screen for Ubercart is a compilation of enabled checkout panes. 349 * A checkout pane can be used to display order information, collect data from 350 * the customer, or interact with other panes. Panes are defined in enabled modules 351 * with hook_checkout_pane() and displayed and processed through specified callback 352 * functions. Some of the settings for each pane are configurable from the checkout 353 * settings page with defaults being specified in the hooks. 354 * 355 * The default panes are defined in uc_cart.module in the function 356 * uc_cart_checkout_pane(). These include panes to display the contents of the 357 * shopping cart and to collect essential site user information, a shipping address, 358 * a payment address, and order comments. Other included modules offer panes for 359 * shipping and payment purposes as well. 360 * 361 * @return 362 * An array of checkout pane arrays using the following keys: 363 * - "id" 364 * - type: string 365 * - value: The internal ID of the checkout pane, using a-z, 0-9, and - or _. 366 * - "title" 367 * - type: string 368 * - value:The name of the pane as it appears on the checkout form. 369 * - "desc" 370 * - type: string 371 * - value: A short description of the pane for the admin pages. 372 * - "callback" 373 * - type: string 374 * - value: The name of the callback function for this pane. View 375 * @link http://www.ubercart.org/docs/developer/245/checkout this page @endlink 376 * for more documentation and examples of checkout pane callbacks. 377 * - "weight" 378 * - type: integer 379 * - value: Default weight of the pane, defining its order on the checkout form. 380 * - "enabled" 381 * - type: boolean 382 * - value: Optional. Whether or not the pane is enabled by default. Defaults 383 * to TRUE. 384 * - "process" 385 * - type: boolean 386 * - value: Optional. Whether or not this pane needs to be processed when the 387 * checkout form is submitted. Defaults to TRUE. 388 * - "collapsible" 389 * - type: boolean 390 * - value: Optional. Whether or not this pane is displayed as a collapsible 391 * fieldset. Defaults to TRUE. 392 */ 393 function hook_checkout_pane() { 394 $panes[] = array( 395 'id' => 'cart', 396 'callback' => 'uc_checkout_pane_cart', 397 'title' => t('Cart Contents'), 398 'desc' => t("Display the contents of a customer's shopping cart."), 399 'weight' => 1, 400 'process' => FALSE, 401 'collapsible' => FALSE, 402 ); 403 return $panes; 404 } 405 406 /** 407 * Alter checkout pane definitions. 408 * 409 * @param $panes 410 * Array with the panes information as defined in hook_checkout_pane(), passed 411 * by reference. 412 */ 413 function hook_checkout_pane_alter(&$panes) { 414 foreach ($panes as &$pane) { 415 if ($pane['id'] == 'cart') { 416 $pane['callback'] = 'my_custom_module_callback'; 417 } 418 } 419 } 420 421 /** 422 * Give clearance to a user to download a file. 423 * 424 * By default the uc_file module can implement 3 restrictions on downloads: by 425 * number of IP addresses downloaded from, by number of downloads, and by a set 426 * expiration date. Developers wishing to add further restrictions can do so by 427 * implementing this hook. After the 3 aforementioned restrictions are checked, 428 * the uc_file module will check for implementations of this hook. 429 * 430 * @param $user 431 * The drupal user object that has requested the download 432 * @param $file_download 433 * The file download object as defined as a row from the uc_file_users table 434 * that grants the user the download 435 * @return 436 * TRUE or FALSE depending on whether the user is to be permitted download of 437 * the requested files. When a implementation returns FALSE it should set an 438 * error message in Drupal using drupal_set_message() to inform customers of 439 * what is going on. 440 */ 441 function hook_download_authorize($user, $file_download) { 442 if (!$user->status) { 443 drupal_set_message(t("This account has been banned and can't download files anymore. "),'error'); 444 return FALSE; 445 } 446 else { 447 return TRUE; 448 } 449 } 450 451 /** 452 * Perform actions on file products. 453 * 454 * The uc_file module comes with a file manager (found at Administer » Store 455 * administration » Products » View file downloads) that provides some basic 456 * functionality: deletion of multiple files and directories, and upload of single 457 * files (those looking to upload multiple files should just directly upload them 458 * to their file download directory then visit the file manager which automatically 459 * updates new files found in its directory). Developers that need to create more 460 * advanced actions with this file manager can do so by using this hook. 461 * 462 * @param $op 463 * The operation being taken by the hook, possible ops defined below. 464 * - 'info': Called before the uc_file module builds its list of possible file 465 * actions. This op is used to define new actions that will be placed in 466 * the file action select box. 467 * - 'insert': Called after uc_file discovers a new file in the file download 468 * directory. 469 * - 'form': When any defined file action is selected and submitted to the form 470 * this function is called to render the next form. Because this is called 471 * whenever a module-defined file action is selected, the variable 472 * $args['action'] can be used to define a new form or append to an existing 473 * form. 474 * - 'upload': After a file has been uploaded, via the file manager's built in 475 * file upload function, and moved to the file download directory this op 476 * can perform any remaining operations it needs to perform on the file 477 * before its placed into the uc_files table. 478 * - 'upload_validate': This op is called to validate the uploaded file that 479 * was uploaded via the file manager's built in file upload function. At 480 * this point, the file has been uploaded to PHP's temporary directory. 481 * Files passing this upload validate function will be moved into the file 482 * downloads directory. 483 * - 'validate': This op is called to validate the file action form. 484 * - 'submit': This op is called to submit the file action form. 485 * @param $args 486 * A keyed array of values that varies depending on the op being performed, 487 * possible values defined below. 488 * - 'info': None 489 * - 'insert': 490 * - 'file_object': The file object of the newly discovered file 491 * - 'form': 492 * - 'action': The file action being performed as defined by the key in the 493 * array sent by hook_file_action($op = 'info') 494 * - 'file_ids' - The file ids (as defined in the uc_files table) of the 495 * selected files to perform the action on 496 * - 'upload': 497 * - 'file_object': The file object of the file moved into file downloads 498 * directory 499 * - 'form_id': The form_id variable of the form_submit function 500 * - 'form_values': The form_values variable of the form_submit function 501 * - 'upload_validate': 502 * - 'file_object': The file object of the file that has been uploaded into 503 * PHP's temporary upload directory 504 * - 'form_id': The form_id variable of the form_validate function 505 * - 'form_values': The form_values variable of the form_validate function 506 * - 'validate': 507 * - 'form_id': The form_id variable of the form_validate function 508 * - 'form_values': The form_values variable of the form_validate function 509 * - 'submit': 510 * - 'form_id': The form_id variable of the form_submit function 511 * - 'form_values': The form_values variable of the form_submit function 512 * @return 513 * The return value of hook depends on the op being performed, possible return 514 * values defined below. 515 * - 'info': The associative array of possible actions to perform. The keys are 516 * unique strings that defines the actions to perform. The values are the 517 * text to be displayed in the file action select box. 518 * - 'insert': None 519 * - 'form': This op should return an array of drupal form elements as defined 520 * by the drupal form API. 521 * - 'upload': None 522 * - 'upload_validate': None 523 * - 'validate': None 524 * - 'submit': None 525 */ 526 function hook_file_action($op, $args) { 527 switch ($op) { 528 case 'info': 529 return array('uc_image_watermark_add_mark' => 'Add Watermark'); 530 case 'insert': 531 //automatically adds watermarks to any new files that are uploaded to the file download directory 532 _add_watermark($args['file_object']->filepath); 533 break; 534 case 'form': 535 if ($args['action'] == 'uc_image_watermark_add_mark') { 536 $form['watermark_text'] = array( 537 '#type' => 'textfield', 538 '#title' => t('Watermark Text'), 539 ); 540 $form['submit_watermark'] = array( 541 '#type' => 'submit', 542 '#value' => t('Add Watermark'), 543 ); 544 } 545 return $form; 546 case 'upload': 547 _add_watermark($args['file_object']->filepath); 548 break; 549 case 'upload_validate': 550 //Given a file path, function checks if file is valid JPEG 551 if(!_check_image($args['file_object']->filepath)) { 552 form_set_error('upload',t('Uploaded file is not a valid JPEG')); 553 } 554 break; 555 case 'validate': 556 if ($args['form_values']['action'] == 'uc_image_watermark_add_mark') { 557 if (empty($args['form_values']['watermark_text'])) { 558 form_set_error('watermar_text',t('Must fill in text')); 559 } 560 } 561 break; 562 case 'submit': 563 if ($args['form_values']['action'] == 'uc_image_watermark_add_mark') { 564 foreach ($args['form_values']['file_ids'] as $file_id) { 565 $filename = db_result(db_query("SELECT filename FROM {uc_files} WHERE fid = %d",$file_id)); 566 //Function adds watermark to image 567 _add_watermark($filename); 568 } 569 } 570 break; 571 } 572 } 573 574 /** 575 * Make changes to a file before it is downloaded by the customer. 576 * 577 * Stores, either for customization, copy protection or other reasons, might want 578 * to send customized downloads to customers. This hook will allow this to happen. 579 * Before a file is opened to be transfered to a customer, this hook will be called 580 * to make any altercations to the file that will be used to transfer the download 581 * to the customer. This, in effect, will allow a developer to create a new, 582 * personalized, file that will get transfered to a customer. 583 * 584 * @param $file_user 585 * The file_user object (i.e. an object containing a row from the uc_file_users 586 * table) that corresponds with the user download being accessed. 587 * @param $ip 588 * The IP address from which the customer is downloading the file 589 * @param $fid 590 * The file id of the file being transfered 591 * @param $file 592 * The file path of the file to be transfered 593 * @return 594 * The path of the new file to transfer to customer. 595 */ 596 function hook_file_transfer_alter($file_user, $ip, $fid, $file) { 597 $file_data = file_get_contents($file)." [insert personalized data]"; //for large files this might be too memory intensive 598 $new_file = tempnam(file_directory_temp(),'tmp'); 599 file_put_contents($new_file,$file_data); 600 return $new_file; 601 } 602 603 /** 604 * Used to define line items that are attached to orders. 605 * 606 * A line item is a representation of charges, fees, and totals for an order. 607 * Default line items include the subtotal and total line items, the tax line 608 * item, and the shipping line item. There is also a generic line item that store 609 * admins can use to add extra fees and discounts to manually created orders. 610 * Module developers will use this hook to define new types of line items for 611 * their stores. An example use would be for a module that allows customers to 612 * use coupons and wants to represent an entered coupon as a line item. 613 * 614 * Once a line item has been defined in hook_line_item, Übercart will begin 615 * interacting with it in various parts of the code. One of the primary ways this 616 * is done is through the callback function you specify for the line item. 617 * 618 * @return 619 * Your hook should return an array of associative arrays. Each item in the 620 * array represents a single line item and should use the following keys: 621 * - "id" 622 * - type: string 623 * - value: The internal ID of the line item. 624 * - "title" 625 * - type: string 626 * - value: The title of the line item shown to the user in various interfaces. 627 * Use t(). 628 * - "callback" 629 * - type: string 630 * - value: Name of the line item's callback function, called for various 631 * operations. 632 * - "weight" 633 * - type: integer 634 * - value: Display order of the line item in lists; "lighter" items are 635 * displayed first. 636 * - "stored" 637 * - type: boolean 638 * - value: Whether or not the line item will be stored in the database. 639 * Should be TRUE for any line item that is modifiable from the order 640 * edit screen. 641 * - "add_list" 642 * - type: boolean 643 * - value: Whether or not a line item should be included in the "Add a Line 644 * Item" select box on the order edit screen. 645 * - "calculated" 646 * - type: boolean 647 * - value: Whether or not the value of this line item should be added to the 648 * order total. (Ex: would be TRUE for a shipping charge line item but 649 * FALSE for the subtotal line item since the product prices are already 650 * taken into account.) 651 * - "display_only" 652 * - type: boolean 653 * - value: Whether or not this line item is simply a display of information 654 * but not calculated anywhere. (Ex: the total line item uses display to 655 * simply show the total of the order at the bottom of the list of line 656 * items.) 657 */ 658 function hook_line_item() { 659 $items[] = array( 660 'id' => 'generic', 661 'title' => t('Empty Line'), 662 'weight' => 2, 663 'default' => FALSE, 664 'stored' => TRUE, 665 'add_list' => TRUE, 666 'calculated' => TRUE, 667 'callback' => 'uc_line_item_generic', 668 ); 669 670 return $items; 671 } 672 673 /** 674 * Alter a line item on an order when the order is loaded. 675 * 676 * @param &$item 677 * The line item array. 678 * @param $order 679 * The order object containing the line item. 680 */ 681 function hook_line_item_alter(&$item, $order) { 682 $account = user_load($order->uid); 683 ca_pull_trigger('calculate_line_item_discounts', $item, $account); 684 } 685 686 /** 687 * Alter the line item definitions declared in hook_line_item(). 688 * 689 * @param &$items 690 * The combined return value of hook_line_item(). 691 */ 692 function hook_line_item_data_alter(&$items) { 693 foreach ($items as &$item) { 694 // Tax amounts are added in to other line items, so the actual tax line 695 // items should not be added to the order total. 696 if ($item['id'] == 'tax') { 697 $item['calculated'] = FALSE; 698 } 699 // Taxes are included already, so the subtotal without taxes doesn't 700 // make sense. 701 elseif ($item['id'] == 'tax_subtotal') { 702 $item['callback'] = NULL; 703 } 704 } 705 } 706 707 708 /** 709 * Perform actions on orders. 710 * 711 * An order in Übercart represents a single transaction. Orders are created 712 * during the checkout process where they sit in the database with a status of In 713 * Checkout. When a customer completes checkout, the order's status gets updated 714 * to show that the sale has gone through. Once an order is created, and even 715 * during its creation, it may be acted on by any module to connect extra 716 * information to an order. Every time an action occurs to an order, hook_order() 717 * gets invoked to let your modules know what's happening and make stuff happen. 718 * 719 * @param $op 720 * The action being performed. 721 * @param &$arg1 722 * This is the order object. 723 * @param $arg2 724 * This is variable and is based on the value of $op: 725 * - new: Called when an order is created. $arg1 is a reference to the new 726 * order object, so modules may add to or modify the order at creation. 727 * - presave: Before an order object is saved, the hook gets invoked with this 728 * op to let other modules alter order data before it is written to the 729 * database. $order is a reference to the order object. 730 * - save: When an order object is being saved, the hook gets invoked with this 731 * op to let other modules do any necessary saving. $arg1 is a reference to 732 * the order object. 733 * - load: Called when an order is loaded after the order and product data has 734 * been loaded from the database. Passes $arg1 as the reference to the 735 * order object, so modules may add to or modify the order object when it's 736 * loaded. 737 * - submit: When a sale is being completed and the customer has clicked the 738 * Submit order button from the checkout screen, the hook is invoked with 739 * this op. This gives modules a chance to determine whether or not the 740 * order should be allowed. An example use of this is the credit module 741 * attempting to process payments when an order is submitted and returning 742 * a failure message if the payment failed. 743 * 744 * To prevent an order from passing through, you must return an array 745 * resembling the following one with the failure message: 746 * @code 747 * return array(array('pass' => FALSE, 'message' => t('We were unable to process your credit card.'))); 748 * @endcode 749 * - can_update: Called before an order's status is changed to make sure the 750 * order can be updated. $arg1 is the order object with the old order 751 * status ID ($arg1->order_status), and $arg2 is simply the new order 752 * status ID. Return FALSE to stop the update for some reason. 753 * - update: Called when an order's status is changed. $arg1 is the order 754 * object with the old order status ID ($arg1->order_status), and $arg2 is 755 * the new order status ID. 756 * - can_delete: Called before an order is deleted to verify that the order may 757 * be deleted. Returning FALSE will prevent a delete from happening. (For 758 * example, the payment module returns FALSE by default when an order has 759 * already received payments.) 760 * - delete: Called when an order is deleted and before the rest of the order 761 * information is removed from the database. Passes $arg1 as the order 762 * object to let your module clean up it's tables. 763 * - total: Called when the total for an order is being calculated after the 764 * total of the products has been added. Passes $arg1 as the order object. 765 * Expects in return a value (positive or negative) by which to modify the 766 * order total. 767 */ 768 function hook_order($op, $arg1, $arg2) { 769 switch ($op) { 770 case 'save': 771 // Do something to save payment info! 772 break; 773 } 774 } 775 776 /** 777 * Add links to local tasks for orders on the admin's list of orders. 778 * 779 * @param $order 780 * An order object. 781 * @return 782 * An array of specialized link arrays. Each link has the following keys: 783 * - "name": The title of page being linked. 784 * - "url": The link path. Do not use url(), but do use the $order's order_id. 785 * - "icon": HTML of an image. 786 * - "title": Title attribute text (mouseover tool-tip). 787 */ 788 function hook_order_actions($order) { 789 $actions = array(); 790 $module_path = base_path() . drupal_get_path('module', 'uc_shipping'); 791 if (user_access('fulfill orders')) { 792 $result = db_query("SELECT nid FROM {uc_order_products} WHERE order_id = %d AND data LIKE '%%s:9:\"shippable\";s:1:\"1\";%%'", $order->order_id); 793 if (db_num_rows($result)) { 794 $title = t('Package order !order_id products.', array('!order_id' => $order->order_id)); 795 $actions[] = array( 796 'name' => t('Package'), 797 'url' => 'admin/store/orders/'. $order->order_id .'/packages', 798 'icon' => '<img src="'. $module_path .'/images/package.gif" alt="'. $title .'" />', 799 'title' => $title, 800 ); 801 $result = db_query("SELECT package_id FROM {uc_packages} WHERE order_id = %d", $order->order_id); 802 if (db_num_rows($result)) { 803 $title = t('Ship order !order_id packages.', array('!order_id' => $order->order_id)); 804 $actions[] = array( 805 'name' => t('Ship'), 806 'url' => 'admin/store/orders/'. $order->order_id .'/shipments', 807 'icon' => '<img src="'. $module_path .'/images/ship.gif" alt="'. $title .'" />', 808 'title' => $title, 809 ); 810 } 811 } 812 } 813 return $actions; 814 } 815 816 /** 817 * Register callbacks for an order pane. 818 * 819 * This hook is used to add panes to the order viewing and administration screens. 820 * The default panes include areas to display and edit addresses, products, 821 * comments, etc. Developers should use this hook when they need to display or 822 * modify any custom data pertaining to an order. For example, a store that uses 823 * a custom checkout pane to find out a customer's desired delivery date would 824 * then create a corresponding order pane to show the data on the order screens. 825 * 826 * hook_order_pane() works by defining new order panes and providing a little bit 827 * of information about them. View the return value section below for information 828 * about what parts of an order pane are defined by the hook. 829 * 830 * The real meat of an order pane is its callback function (which is specified in 831 * the hook). The callback function handles what gets displayed on which screen 832 * and what data can be manipulated. That is all somewhat out of the scope of 833 * this API page, so you'll have to click here to read more about what a callback 834 * function should contain. 835 */ 836 function hook_order_pane() { 837 $panes[] = array( 838 'id' => 'payment', 839 'callback' => 'uc_order_pane_payment', 840 'title' => t('Payment'), 841 'desc' => t('Specify and collect payment for an order.'), 842 'class' => 'pos-left', 843 'weight' => 4, 844 'show' => array('view', 'edit', 'customer'), 845 ); 846 return $panes; 847 } 848 849 /** 850 * Alter order pane definitions. 851 * 852 * @param $panes 853 * Array with the panes information as defined in hook_order_pane(), passed 854 * by reference. 855 */ 856 function hook_order_pane_alter(&$panes) { 857 foreach ($panes as &$pane) { 858 if ($pane['id'] == 'payment') { 859 $pane['callback'] = 'my_custom_module_callback'; 860 } 861 } 862 } 863 864 /** 865 * Allows modules to alter ordered products when they're loaded with an order. 866 * 867 * @param &$product 868 * The product object as found in the $order object. 869 * @param $order 870 * The order object to which the product belongs. 871 * @return 872 * Nothing should be returned. Hook implementations should receive the 873 * $product object by reference and alter it directly. 874 */ 875 function hook_order_product_alter(&$product, $order) { 876 drupal_set_message('hook_order_product_alter(&$product, $order):'); 877 drupal_set_message('&$product: <pre>'. print_r($product, TRUE) .'</pre>'); 878 drupal_set_message('$order: <pre>'. print_r($order, TRUE) .'</pre>'); 879 } 880 881 /** 882 * Register static order states. 883 * 884 * Order states are module-defined categories for order statuses. Each state 885 * will have a default status that is used when modules need to move orders to 886 * new state, but don't know which status to use. 887 * 888 * @return 889 * An array of order state definitions. Each definition is an array with the 890 * following keys: 891 * - id: The machine-readable name of the order state. 892 * - title: The human-readable, translated name. 893 * - weight: The list position of the state. 894 * - scope: Either "specific" or "general". 895 */ 896 function hook_order_state() { 897 $states[] = array( 898 'id' => 'canceled', 899 'title' => t('Canceled'), 900 'weight' => -20, 901 'scope' => 'specific', 902 ); 903 $states[] = array( 904 'id' => 'in_checkout', 905 'title' => t('In checkout'), 906 'weight' => -10, 907 'scope' => 'specific', 908 ); 909 $states[] = array( 910 'id' => 'post_checkout', 911 'title' => t('Post checkout'), 912 'weight' => 0, 913 'scope' => 'general', 914 ); 915 $states[] = array( 916 'id' => 'completed', 917 'title' => t('Completed'), 918 'weight' => 20, 919 'scope' => 'general', 920 ); 921 922 return $states; 923 } 924 925 /** 926 * Register payment gateway callbacks. 927 * 928 * @see @link http://www.ubercart.org/docs/api/hook_payment_gateway @endlink 929 * 930 * @return 931 * Returns an array of payment gateways, which are arrays with the following keys: 932 * - "id" 933 * - type: string 934 * - value: The internal ID of the payment gateway, using a-z, 0-9, and - or 935 * _. 936 * - "title" 937 * - type: string 938 * - value: The name of the payment gateway displayed to the user. Use t(). 939 * - "description" 940 * - type: string 941 * - value: A short description of the payment gateway. 942 * - "settings" 943 * - type: string 944 * - value: The name of a function that returns an array of settings form 945 * elements for the gateway. 946 */ 947 function hook_payment_gateway() { 948 $gateways[] = array( 949 'id' => 'test_gateway', 950 'title' => t('Test Gateway'), 951 'description' => t('Process credit card payments through the Test Gateway.'), 952 'credit' => 'test_gateway_charge', 953 ); 954 return $gateways; 955 } 956 957 /** 958 * Alter payment gateways. 959 * 960 * @param $gateways 961 * Payment gateways passed by reference. 962 */ 963 function hook_payment_gateway_alter(&$gateways) { 964 // Change the title of all gateways. 965 foreach ($gateways as &$gateway) { 966 // $gateway was passed by reference. 967 $gateway['title'] = t('Altered gateway @original', array('@original' => $gateway['title'])); 968 } 969 } 970 971 /** 972 * Register callbacks for payment methods. 973 * 974 * Payment methods are different ways to collect payment. By default, Übercart 975 * comes with support for check, credit card, and generic payments. Payment 976 * methods show up at checkout or on the order administration screens, and they 977 * collect different sorts of information from the user that is used to process 978 * or track the payment. 979 * 980 * @return 981 * An array of payment methods. 982 */ 983 function hook_payment_method() { 984 $methods[] = array( 985 'id' => 'check', 986 'name' => t('Check'), 987 'title' => t('Check or Money Order'), 988 'desc' => t('Pay by mailing a check or money order.'), 989 'callback' => 'uc_payment_method_check', 990 'weight' => 1, 991 'checkout' => TRUE, 992 ); 993 return $methods; 994 } 995 996 /** 997 * Perform actions on product classes. 998 * 999 * @param $type 1000 * The node type of the product class. 1001 * @param $op 1002 * The action being performed on the product class: 1003 * - "insert": A new node type is created, or an existing node type is being 1004 * converted into a product type. 1005 * - "update": A product class has been updated. 1006 * - "delete": A product class has been deleted. Modules that have attached 1007 * additional information to the node type because it is a product type 1008 * should delete this information. 1009 */ 1010 function hook_product_class($type, $op) { 1011 switch ($op) { 1012 case 'delete': 1013 db_query("DELETE FROM {uc_class_attributes} WHERE pcid = '%s'", $type); 1014 db_query("DELETE FROM {uc_class_attribute_options} WHERE pcid = '%s'", $type); 1015 break; 1016 } 1017 } 1018 1019 /** 1020 * Return a structured array representing the given product's description. 1021 * 1022 * Modules that add data to cart items when they are selected should display it 1023 * with this hook. The return values from each implementation will be 1024 * sent through to hook_product_description_alter() implementations and then 1025 * all descriptions are rendered using drupal_render(). 1026 * 1027 * @param $product 1028 * Product. Usually one of the values of the array returned by 1029 * uc_cart_get_contents(). 1030 * @return 1031 * A structured array that can be fed into drupal_render(). 1032 */ 1033 function hook_product_description($product) { 1034 $description = array( 1035 'attributes' => array( 1036 '#product' => array( 1037 '#type' => 'value', 1038 '#value' => $product, 1039 ), 1040 '#theme' => 'uc_product_attributes', 1041 '#weight' => 1, 1042 ), 1043 ); 1044 1045 $desc =& $description['attributes']; 1046 1047 // Cart version of the product has numeric attribute => option values so we 1048 // need to retrieve the right ones 1049 $weight = 0; 1050 if (empty($product->order_id)) { 1051 foreach (_uc_cart_product_get_options($product) as $option) { 1052 if (!isset($desc[$option['aid']])) { 1053 $desc[$option['aid']]['#attribute_name'] = $option['attribute']; 1054 $desc[$option['aid']]['#options'] = array($option['name']); 1055 } 1056 else { 1057 $desc[$option['aid']]['#options'][] = $option['name']; 1058 } 1059 $desc[$option['aid']]['#weight'] = $weight++; 1060 } 1061 } 1062 else { 1063 foreach ((array)$product->data['attributes'] as $attribute => $option) { 1064 $desc[] = array( 1065 '#attribute_name' => $attribute, 1066 '#options' => $option, 1067 '#weight' => $weight++, 1068 ); 1069 } 1070 } 1071 1072 return $description; 1073 } 1074 1075 /** 1076 * Alters the given product description. 1077 * 1078 * @param $description 1079 * Description array reference. 1080 * @param $product 1081 * The product being described. 1082 */ 1083 function hook_product_description_alter(&$description, $product) { 1084 $description['attributes']['#weight'] = 2; 1085 } 1086 1087 /** 1088 * List node types which should be considered products. 1089 * 1090 * Trusts the duck philosophy of object identification: if it walks like a duck, 1091 * quacks like a duck, and has feathers like a duck, it's probably a duck. 1092 * Products are nodes with prices, SKUs, and everything else Übercart expects 1093 * them to have. 1094 * 1095 * @return 1096 * Array of node type ids. 1097 */ 1098 function hook_product_types() { 1099 return array('product_kit'); 1100 } 1101 1102 /** 1103 * Handle additional data for shipments. 1104 * 1105 * @param $op 1106 * The action being taken on the shipment. One of the following values: 1107 * - "load": The shipment and its packages are loaded from the database. 1108 * - "save": Changes to the shipment have been written. 1109 * - "delete": The shipment has been deleted and the packages are available 1110 * for reshipment. 1111 * @param &$shipment 1112 * The shipment object. 1113 * @return 1114 * Only given when $op is "load". An array of extra data to be added to the 1115 * shipment object. 1116 */ 1117 function hook_shipment($op, &$shipment) { 1118 switch ($op) { 1119 case 'save': 1120 $google_order_number = uc_google_checkout_get_google_number($shipment->order_id); 1121 if ($google_order_number && $shipment->is_new) { 1122 $xml_data = ''; 1123 foreach ($shipment->packages as $package) { 1124 if ($package->tracking_number) { 1125 $tracking_number = $package->tracking_number; 1126 } 1127 else if ($shipment->tracking_number) { 1128 $tracking_number = $shipment->tracking_number; 1129 } 1130 if ($tracking_number) { 1131 foreach ($package->products as $product) { 1132 $xml_data .= '<item-shipping-information>'; 1133 $xml_data .= '<item-id>'; 1134 $xml_data .= '<merchant-item-id>'. check_plain($product->nid .'|'. $product->model) .'</merchant-item-id>'; 1135 $xml_data .= '</item-id>'; 1136 $xml_data .= '<tracking-data-list>'; 1137 $xml_data .= '<tracking-data>'; 1138 $xml_data .= '<carrier>'. check_plain($shipment->carrier) .'</carrier>'; 1139 $xml_data .= '<tracking-number>'. check_plain($tracking_number) .'</tracking-number>'; 1140 $xml_data .= '</tracking-data>'; 1141 $xml_data .= '</tracking-data-list>'; 1142 $xml_data .= '</item-shipping-information>'; 1143 } 1144 } 1145 } 1146 if ($xml_data) { 1147 $request = '<?xml version="1.0" encoding="UTF-8"?>'. "\n"; 1148 $request .= '<ship-items xmlns="http://checkout.google.com/schema/2" google-order-number="'. $google_order_number .'">'; 1149 $request .= '<item-shipping-information-list>'; 1150 $request .= $xml_data; 1151 $request .= '</item-shipping-information-list>'; 1152 $request .= '<send-email>true</send-email>'; 1153 $request .= '</ship-items>'; 1154 $response = uc_google_checkout_send_request('request', $request); 1155 } 1156 } 1157 break; 1158 case 'delete': 1159 $google_order_number = uc_google_checkout_get_google_number($shipment->order_id); 1160 if ($google_order_number) { 1161 foreach ($shipment->packages as $package) { 1162 foreach ($package->products as $product) { 1163 $reset_ids[] = check_plain($product->nid .'|'. $product->model); 1164 } 1165 } 1166 $request = '<?xml version="1.0" encoding="UTF-8"?>' . "\n"; 1167 $request .= '<reset-items-shipping-information xmlns="http://checkout.google.com/schema/2" google-order-number="'. $google_order_number .'">'; 1168 $request .= '<item-ids>'; 1169 foreach (array_unique($reset_ids) as $item_id) { 1170 $request .= '<item-id>'; 1171 $request .= '<merchant-item-id>'. $item_id .'</merchant-item-id>'; 1172 $request .= '</item-id>'; 1173 } 1174 $request .= '</item-ids>'; 1175 $request .= '<send-email>false</send-email>'; 1176 $request .= '</reset-items-shipping-information>'; 1177 } 1178 $response = uc_google_checkout_send_request('request', $request); 1179 break; 1180 } 1181 } 1182 1183 /** 1184 * Define callbacks and service options for shipping methods. 1185 * 1186 * The shipping quote controller module, uc_quote, expects a very specific 1187 * structured array of methods from the implementations of this hook. 1188 * 1189 * The weights and enabled flags for shipping methods and types are set at the 1190 * Shipping Quote Settings page under Store Configuration. They keys of the 1191 * variables are the ids of the shipping methods. The "quote" and "ship" arrays of 1192 * the method are both optional. 1193 * 1194 * @return 1195 * An array of shipping methods which have the following keys. 1196 * - "type": The quote and shipping types are ids of the product shipping type 1197 * that these methods apply to. type may also be 'order' which indicates 1198 * that the quote applies to the entire order, regardless of the shipping 1199 * types of its products. This is used by quote methods that are base on 1200 * the location of the customer rather than their purchase. 1201 * - "callback": The function that is called by uc_quote when a shipping quote 1202 * is requested. Its arguments are the array of products and an array of 1203 * order details (the shipping address). The return value is an array 1204 * representing the rates quoted and errors returned (if any) for each 1205 * option in the accessorials array. 1206 * - "accessorials": This array represents the different options the customer 1207 * may choose for their shipment. The callback function should generate a 1208 * quote for each option in accessorials and return them via an array. 1209 * drupal_to_js() is very useful for this. 1210 * @code 1211 * return array( 1212 * '03' => array('rate' => 15.75, 'format' => uc_price(15.75, $context) 'option_label' => t('UPS Ground'), 1213 * 'error' => 'Additional handling charge automatically applied.'), 1214 * '14' => array('error' => 'Invalid package type.'), 1215 * '59' => array('rate' => 26.03, 'format' => uc_price(26.03, $context), 'option_label' => t('UPS 2nd Day Air A.M.')) 1216 * ); 1217 * @endcode 1218 * - "pkg_types": The list of package types that the shipping method can handle. 1219 * This should be an associative array that can be used as the #options of 1220 * a select form element. It is recommended that a function be written to 1221 * output this array so the method doesn't need to be found just for the 1222 * package types. 1223 */ 1224 function hook_shipping_method() { 1225 $methods = array(); 1226 1227 $enabled = variable_get('uc_quote_enabled', array('ups' => TRUE)); 1228 $weight = variable_get('uc_quote_method_weight', array('ups' => 0)); 1229 $methods['ups'] = array( 1230 'id' => 'ups', 1231 'title' => t('UPS'), 1232 'enabled' => $enabled['ups'], 1233 'weight' => $weight['ups'], 1234 'quote' => array( 1235 'type' => 'small package', 1236 'callback' => 'uc_ups_quote', 1237 'accessorials' => array( 1238 '03' => t('UPS Ground'), 1239 '11' => t('UPS Standard'), 1240 '01' => t('UPS Next Day Air'), 1241 '13' => t('UPS Next Day Air Saver'), 1242 '14' => t('UPS Next Day Early A.M.'), 1243 '02' => t('UPS 2nd Day Air'), 1244 '59' => t('UPS 2nd Day Air A.M.'), 1245 '12' => t('UPS 3-Day Select'), 1246 ), 1247 ), 1248 'ship' => array( 1249 'type' => 'small package', 1250 'callback' => 'uc_ups_fulfill_order', 1251 'pkg_types' => array( 1252 '01' => t('UPS Letter'), 1253 '02' => t('Customer Supplied Package'), 1254 '03' => t('Tube'), 1255 '04' => t('PAK'), 1256 '21' => t('UPS Express Box'), 1257 '24' => t('UPS 25KG Box'), 1258 '25' => t('UPS 10KG Box'), 1259 '30' => t('Pallet'), 1260 ), 1261 ), 1262 ); 1263 1264 return $methods; 1265 } 1266 1267 /** 1268 * Define shipping types for shipping methods. 1269 * 1270 * This hook defines a shipping type that this module is designed to handle. 1271 * These types are specified by a machine- and human-readable name called 'id', 1272 * and 'title' respectively. Shipping types may be set for individual products, 1273 * manufacturers, and for the entire store catalog. Shipping modules should be 1274 * careful to use the same shipping type ids as other similar shipping modules 1275 * (i.e., FedEx and UPS both operate on "small package" shipments). Modules that 1276 * do not fulfill orders may not need to implement this hook. 1277 * 1278 * @return 1279 * An array of shipping types keyed by a machine-readable name. 1280 */ 1281 function hook_shipping_type() { 1282 $weight = variable_get('uc_quote_type_weight', array('small_package' => 0)); 1283 1284 $types = array(); 1285 $types['small_package'] = array( 1286 'id' => 'small_package', 1287 'title' => t('Small Packages'), 1288 'weight' => $weight['small_package'], 1289 ); 1290 1291 return $types; 1292 } 1293 1294 /** 1295 * Add status messages to the "Store administration" page. 1296 * 1297 * This hook is used to add items to the store status table on the main store 1298 * administration screen. Each item gets a row in the table that consists of a 1299 * status icon, title, and description. These items should be used to give 1300 * special instructions, notifications, or indicators for components of the cart 1301 * enabled by the modules. At a glance, a store owner should be able to look here 1302 * and see if a critical component of your module is not functioning properly. 1303 * 1304 * For example, if the catalog module is installed and it cannot find the catalog 1305 * taxonomy vocabulary, it will show an error message here to alert the store 1306 * administrator. 1307 * 1308 * @return 1309 * An array of tore status items which are arrays with the following keys: 1310 * - "status": "ok", "warning", or "error" depending on the message. 1311 * - "title" The title of the status message or module that defines it. 1312 * - "desc": The description; can be any message, including links to pages and 1313 * forms that deal with the issue being reported. 1314 */ 1315 function hook_store_status() { 1316 if ($key = uc_credit_encryption_key()) { 1317 $statuses[] = array( 1318 'status' => 'ok', 1319 'title' => t('Credit card encryption'), 1320 'desc' => t('Credit card data in the database is currently being encrypted.'), 1321 ); 1322 } 1323 return $statuses; 1324 } 1325 1326 /** 1327 * Allow modules to alter the TAPIr table after the rows are populated. 1328 * 1329 * The example below adds a value for the custom 'designer' column to the table 1330 * rows. Each table row has a numeric key in $table and these keys can be 1331 * accessed using element_children() from the Form API. 1332 * 1333 * @param $table Table declaration containing header and populated rows. 1334 * @param $table_id Table ID. Also the function called to build the table 1335 * declaration. 1336 */ 1337 function hook_tapir_table_alter(&$table, $table_id) { 1338 if ($table_id == 'uc_product_table') { 1339 foreach (element_children($table) as $key) { 1340 $node = node_load($table['#parameters'][1][$key]); 1341 1342 $table[$key]['designer'] = array( 1343 '#value' => l($node->designer, 'collections/'.$node->designer_tid), 1344 '#cell_attributes' => array( 1345 'nowrap' => 'nowrap', 1346 ), 1347 ); 1348 } 1349 } 1350 } 1351 1352 /** 1353 * Allow modules to alter TAPIr table headers. 1354 * 1355 * This is most often done when a developer wants to add a sortable field to 1356 * the table. A sortable field is one where the header can be clicked to sort 1357 * the table results. This cannot be done using hook_tapir_table_alter() as 1358 * once that is called the query has already executed. 1359 * 1360 * The example below adds a 'designer' column to the catalog product table. The 1361 * example module would also have added joins to the query using 1362 * hook_db_rewrite_sql() in order for table 'td2' to be valid. The 'name' field 1363 * is displayed in the table and the header has the title 'Designer'. 1364 * 1365 * Also shown are changes made to the header titles for list_price and 1366 * price fields. 1367 * 1368 * @see hook_db_rewrite_sql() 1369 * 1370 * @param $header Reference to the array header declaration 1371 * (i.e $table['#header']). 1372 * @param $table_id Table ID. Also the function called to build the table 1373 * declaration. 1374 */ 1375 function hook_tapir_table_header_alter(&$header, $table_id) { 1376 if ($table_id == 'uc_product_table') { 1377 $header['designer'] = array( 1378 'weight' => 2, 1379 'cell' => array( 1380 'data' => t('Designer'), 1381 'field' => 'td2.name', 1382 ), 1383 ); 1384 1385 $header['list_price']['cell']['data'] = t('RRP'); 1386 $header['price']['cell']['data'] = t('Sale'); 1387 $header['add_to_cart']['cell']['data'] = ''; 1388 } 1389 } 1390 1391 /** 1392 * Take action when checkout is completed. 1393 * 1394 * @param $order 1395 * The resulting order object from the completed checkout. 1396 * @param $account 1397 * The customer that completed checkout, either the current user, or the 1398 * account created for an anonymous customer. 1399 */ 1400 function hook_uc_checkout_complete($order, $account) { 1401 // Get previous records of customer purchases. 1402 $nids = array(); 1403 $result = db_query("SELECT uid, nid, qty FROM {uc_customer_purchases} WHERE uid = %d", $account->uid); 1404 while ($record = db_fetch_object($result)) { 1405 $nids[$record->nid] = $record->qty; 1406 } 1407 1408 // Update records with new data. 1409 $record = array('uid' => $account->uid); 1410 foreach ($order->products as $product) { 1411 $record['nid'] = $product->nid; 1412 if (isset($nids[$product->nid])) { 1413 $record['qty'] = $nids[$product->nid] + $product->qty; 1414 db_write_record($record, 'uc_customer_purchases', array('uid', 'nid')); 1415 } 1416 else { 1417 $record['qty'] = $product->qty; 1418 db_write_record($record, 'uc_customer_purchases'); 1419 } 1420 } 1421 } 1422 1423 /** 1424 * Allow modules to modify forms before Drupal invokes hook_form_alter(). 1425 * 1426 * This hook will normally be used by core modules so any form modifications 1427 * they make can be further modified by contrib modules using a normal 1428 * hook_form_alter(). At this point, drupal_prepare_form() has not been called, 1429 * so none of the automatic form data (e.g.: #parameters, #build_id, etc.) has 1430 * been added yet. 1431 * 1432 * For a description of the hook parameters: 1433 * @see hook_form_alter() 1434 */ 1435 function hook_uc_form_alter(&$form, &$form_state, $form_id) { 1436 // If the node has a product list, add attributes to them 1437 if (isset($form['products']) && count(element_children($form['products']))) { 1438 foreach (element_children($form['products']) as $key) { 1439 $form['products'][$key]['attributes'] = _uc_attribute_alter_form(node_load($key)); 1440 if (is_array($form['products'][$key]['attributes'])) { 1441 $form['products'][$key]['attributes']['#tree'] = TRUE; 1442 $form['products'][$key]['#type'] = 'fieldset'; 1443 } 1444 } 1445 } 1446 // If not, add attributes to the node. 1447 else { 1448 $form['attributes'] = _uc_attribute_alter_form($node); 1449 1450 if (is_array($form['attributes'])) { 1451 $form['attributes']['#tree'] = TRUE; 1452 $form['attributes']['#weight'] = -1; 1453 } 1454 } 1455 } 1456 1457 /** 1458 * Add invoice templates to the list of suggested template files. 1459 * 1460 * Allows modules to declare new "types" of invoice templates (other than the 1461 * default 'admin' and 'customer'). 1462 * 1463 * @return 1464 * Array of template names that are available choices when mailing an 1465 * invoice. 1466 */ 1467 function hook_uc_invoice_templates() { 1468 return array('admin', 'customer'); 1469 } 1470 1471 /** 1472 * Convenience function to display large blocks of text in several places. 1473 * 1474 * There are many instances where Ubercart modules have configurable blocks of 1475 * text. These usually come with default messages, like e-mail templates for new 1476 * orders. Because of the way default values are normally set, you're then stuck 1477 * having to copy and paste a large chunk of text in at least two different 1478 * places in the module (when you're wanting to use the variable or to display 1479 * the settings form with the default value). To cut down code clutter, this hook 1480 * was introduced. It lets you put your messages in one place and use the 1481 * function uc_get_message() to retrieve the default value at any time (and from 1482 * any module). 1483 * 1484 * The function is very simple, expecting no arguments and returning a basic 1485 * associative array with keys being message IDs and their values being the 1486 * default message. When you call uc_get_message(), use the message ID you set 1487 * here to refer to the message you want. 1488 * 1489 * Note: When using t(), you must not pass it a concatenated string! So our 1490 * example has no line breaks in the message even though it is much wider than 80 1491 * characters. Using concatenation breaks translation. 1492 * 1493 * @return 1494 * An array of messages. 1495 */ 1496 function hook_uc_message() { 1497 $messages['configurable_message_example'] = t('This block of text represents a configurable message such as a set of instructions or an e-mail template. Using hook_uc_message to handle the default values for these is so easy even your grandma can do it!'); 1498 1499 return $messages; 1500 } 1501 1502 /** 1503 * Take action when a payment is entered for an order. 1504 * 1505 * @param $order 1506 * The order object. 1507 * @param $method 1508 * The name of the payment method used. 1509 * @param $amount 1510 * The value of the payment. 1511 * @param $account 1512 * The user account that entered the order. When the payment is entered 1513 * during checkout, this is probably the order's user. Otherwise, it is 1514 * likely a store administrator. 1515 * @param $data 1516 * Extra data associated with the transaction. 1517 * @param $comment 1518 * Any comments from the user about the transaction. 1519 */ 1520 function hook_uc_payment_entered($order, $method, $amount, $account, $data, $comment) { 1521 drupal_set_message(t('User @uid entered a @method payment of @amount for order @order_id.', 1522 array( 1523 '@uid' => $account->uid, 1524 '@method' => $method, 1525 '@amount' => uc_price($amount, array('location' => 'hook-payment', 'revision' => 'formatted-original')), 1526 '@order_id' => $order->order_id, 1527 )) 1528 ); 1529 } 1530 1531 /** 1532 * Use this hook to define price handlers for your module. You may define one 1533 * price alterer and one price formatter. You may also define options that are 1534 * merged into the options array in order of each price alterer's weight. 1535 */ 1536 function hook_uc_price_handler() { 1537 return array( 1538 'alter' => array( 1539 'title' => t('My price handler'), 1540 'description' => t('Handles my price alteration needs.'), 1541 'callback' => 'my_price_handler_alter', 1542 ), 1543 'format' => array( 1544 'title' => t('My price handler'), 1545 'description' => t('Handles my price formatting needs.'), 1546 'callback' => 'my_price_handler_format', 1547 ), 1548 'options' => array( 1549 'sign' => variable_get('uc_currency_sign', '*'), 1550 'sign_after' => TRUE, 1551 'prec' => 4, 1552 'dec' => ',', 1553 'thou' => '.', 1554 'label' => FALSE, 1555 'my_option_that_my_formatter_recognizes' => 1337, 1556 ) 1557 ); 1558 } 1559 1560 /** 1561 * Define default product classes. 1562 * 1563 * The results of this hook are eventually passed through hook_node_info(), 1564 * so you may include any keys that hook_node_info() uses. Defaults will 1565 * be provided where keys are not set. This hook can also be used to 1566 * override the default "product" product class name and description. 1567 */ 1568 function hook_uc_product_default_classes() { 1569 return array( 1570 'my_class' => array( 1571 'name' => t('My product class'), 1572 'description' => t('Content type description for my product class.'), 1573 ), 1574 ); 1575 } 1576 1577 /** 1578 * Notify core of any SKUs your module adds to a given node. 1579 * 1580 * NOTE: DO NOT map the array keys, as the possibility for numeric SKUs exists, and 1581 * this will conflict with the behavior of module_invoke_all(), specifically 1582 * array_merge_recursive(). 1583 * 1584 * Code lifted from uc_attribute.module. 1585 */ 1586 function hook_uc_product_models($node) { 1587 $models = array(); 1588 1589 // Get all the SKUs for all the attributes on this node. 1590 $adjustments = db_query("SELECT model FROM {uc_product_adjustments} WHERE nid = %d", $node->nid); 1591 while ($adjustment = db_fetch_object($adjustments)) { 1592 if (!in_array($adjustment->model, $models)) { 1593 $models[] = $adjustment->model; 1594 } 1595 } 1596 1597 return $models; 1598 } 1599 1600 /** 1601 * Allow modules to take action when a stock level is changed. 1602 * 1603 * @param $sku 1604 * The SKU whose stock level is being changed. 1605 * @param $stock 1606 * The stock level before the adjustment. 1607 * @param $qty 1608 * The amount by which the stock level was changed. 1609 */ 1610 function hook_uc_stock_adjusted($sku, $stock, $qty) { 1611 $params = array( 1612 'sku' => $sku, 1613 'stock' => $stock, 1614 'qty' => $qty, 1615 ); 1616 1617 drupal_mail('uc_stock_notify', 'stock-adjusted', uc_store_email_from(), language_default(), $params); 1618 } 1619 1620 /** 1621 * Used to determine whether or not UC Google Analytics should add e-commerce 1622 * tracking code to the bottom of the page. 1623 * 1624 * The Google Analytics module takes care of adding the necessary .js file from 1625 * Google for tracking general statistics. The UC Google Analytics module works 1626 * in conjunction with this code to add e-commerce specific code. However, the 1627 * e-commerce code should only be added on appropriate pages. Generally, the 1628 * correct page will be the checkout completion page at cart/checkout/complete. 1629 * However, because modules can change the checkout flow as necessary, it must 1630 * be possible for alternate pages to be used. 1631 * 1632 * This hook allows other modules to tell the UC Google Analytics module that 1633 * it should go ahead and add the e-commerce tracking code to the current page. 1634 * A module simply needs to implement this hook and return TRUE on the proper 1635 * order completion page to let UC Google Analytics know it should add the 1636 * e-commerce tracking code to the current page. 1637 * 1638 * The implementation below comes from the 2Checkout.com module which uses an 1639 * alternate checkout completion page. 1640 * 1641 * @return 1642 * TRUE if e-commerce tracking code should be added to the current page. 1643 */ 1644 function hook_ucga_display() { 1645 // Tell UC Google Analytics to display the e-commerce JS on the custom 1646 // order completion page for this module. 1647 if (arg(0) == 'cart' && arg(1) == '2checkout' && arg(2) == 'complete') { 1648 return TRUE; 1649 } 1650 } 1651 1652 /** 1653 * Allows modules to alter items before they're added to the UC Google Analytics 1654 * e-commerce tracking code. 1655 * 1656 * The UC Google Analytics module constructs function calls that work through 1657 * the Google Analytics JS API to report purchased items for e-commerce tracking 1658 * purposes. The module builds the argument list for each product on an order 1659 * and uses this hook to give other modules a chance to alter what gets reported 1660 * to Google Analytics. Additional arguments passed to implementations of this 1661 * hook are provided for context. 1662 * 1663 * @param $item 1664 * An array of arguments being passed to Google Analytics representing an item 1665 * on the order, including order_id, sku, name, category, price, and qty. 1666 * @param $product 1667 * The product object as found in the $order object. 1668 * @param $trans 1669 * The array of arguments that were passed to Google Analytics to represent 1670 * the transaction. 1671 * @param $order 1672 * The order object being reported to Google Analytics. 1673 * @return 1674 * Nothing should be returned. Hook implementations should receive the $item 1675 * array by reference and alter it directly. 1676 */ 1677 function hook_ucga_item_alter(&$item, $product, $trans, $order) { 1678 // Example implementation: always set the category to "UBERCART". 1679 $item['category'] = 'UBERCART'; 1680 } 1681 1682 /** 1683 * Allows modules to alter transaction info before it's added to the UC Google 1684 * Analytics e-commerce tracking code. 1685 * 1686 * The UC Google Analytics module constructs function calls that work through 1687 * the Google Analytics JS API to report order information for e-commerce 1688 * tracking purposes. The module builds the argument list for the transaction 1689 * and uses this hook to give other modules a chance to alter what gets reported 1690 * to Google Analytics. 1691 * 1692 * @param $trans 1693 * An array of arguments being passed to Google Analytics representing the 1694 * transaction, including order_id, store, total, tax, shipping, city, 1695 * state, and country. 1696 * @param $order 1697 * The order object being reported to Google Analytics. 1698 * @return 1699 * Nothing should be returned. Hook implementations should receive the $trans 1700 * array by reference and alter it directly. 1701 */ 1702 function hook_ucga_trans_alter(&$trans, $order) { 1703 // Example implementation: prefix all orders with "UC-". 1704 $trans['order_id'] = 'UC-'. $trans['order_id']; 1705 } 1706 1707 /** 1708 * Handle requests to update a cart item. 1709 * 1710 * @param $nid 1711 * Node id of the cart item. 1712 * @param $data 1713 * Array of extra information about the item. 1714 * @param $qty 1715 * The quantity of this item in the cart. 1716 * @param $cid 1717 * The cart id. Defaults to NULL, which indicates that the current user's cart 1718 * should be retrieved with uc_cart_get_id(). 1719 */ 1720 function hook_update_cart_item($nid, $data = array(), $qty, $cid = NULL) { 1721 if (!$nid) return NULL; 1722 $cid = !(is_null($cid) || empty($cid)) ? $cid : uc_cart_get_id(); 1723 if ($qty < 1) { 1724 uc_cart_remove_item($nid, $cid, $data); 1725 } 1726 else { 1727 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)); 1728 } 1729 1730 // Rebuild the items hash 1731 uc_cart_get_contents(NULL, 'rebuild'); 1732 if (!strpos(request_uri(), 'cart', -4)) { 1733 drupal_set_message(t('Your item(s) have been updated.')); 1734 } 1735 } 1736 1737 /** 1738 * @} End of "addtogroup hooks". 1739 */
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated: Mon Jul 9 18:01:44 2012 | Cross-referenced by PHPXref 0.7 |