Parent Directory
|
Revision Log
|
Revision Graph
#605816: Warning when PayPal settings are incompatible with coupons.
| 1 | <?php |
| 2 | |
| 3 | // $Id: uc_coupon.module,v 1.40 2009/09/17 19:17:28 longwave Exp $ |
| 4 | |
| 5 | /** |
| 6 | * @file |
| 7 | * Provides discount coupons for Ubercart. |
| 8 | * |
| 9 | * Original code by Blake Lucchesi (www.boldsource.com) |
| 10 | * Maintained by David Long (dave@longwaveconsulting.com) |
| 11 | * |
| 12 | * Send any suggestions and feedback to the above address. |
| 13 | */ |
| 14 | |
| 15 | /** |
| 16 | * Implementation of hook_menu(). |
| 17 | */ |
| 18 | function uc_coupon_menu() { |
| 19 | $items = array(); |
| 20 | |
| 21 | $items['admin/store/customers/coupon'] = array( |
| 22 | 'title' => 'Coupons', |
| 23 | 'description' => 'Manage store discount coupons.', |
| 24 | 'page callback' => 'uc_coupon_display', |
| 25 | 'page arguments' => array('active'), |
| 26 | 'access arguments' => array('view store coupons'), |
| 27 | 'type' => MENU_NORMAL_ITEM, |
| 28 | ); |
| 29 | $items['admin/store/customers/coupon/list'] = array( |
| 30 | 'title' => 'Active coupons', |
| 31 | 'description' => 'View active coupons.', |
| 32 | 'page callback' => 'uc_coupon_display', |
| 33 | 'page arguments' => array('active'), |
| 34 | 'access arguments' => array('view store coupons'), |
| 35 | 'type' => MENU_DEFAULT_LOCAL_TASK, |
| 36 | ); |
| 37 | $items['admin/store/customers/coupon/inactive'] = array( |
| 38 | 'title' => 'Inactive coupons', |
| 39 | 'description' => 'View inactive coupons.', |
| 40 | 'page callback' => 'uc_coupon_display', |
| 41 | 'page arguments' => array('inactive'), |
| 42 | 'access arguments' => array('view store coupons'), |
| 43 | 'type' => MENU_LOCAL_TASK, |
| 44 | ); |
| 45 | $items['admin/store/customers/coupon/add'] = array( |
| 46 | 'title' => 'Add new coupon', |
| 47 | 'description' => 'Add a new coupon.', |
| 48 | 'page callback' => 'drupal_get_form', |
| 49 | 'page arguments' => array('uc_coupon_add_form', 'add'), |
| 50 | 'access arguments' => array('manage store coupons'), |
| 51 | 'type' => MENU_LOCAL_TASK, |
| 52 | 'weight' => 10, |
| 53 | ); |
| 54 | $items['admin/store/reports/coupon'] = array( |
| 55 | 'title' => 'Coupon usage reports', |
| 56 | 'description' => 'View coupon usage reports.', |
| 57 | 'page callback' => 'uc_coupon_reports', |
| 58 | 'access arguments' => array('view reports'), |
| 59 | 'type' => MENU_NORMAL_ITEM, |
| 60 | ); |
| 61 | $items['admin/store/customers/coupon/%uc_coupon/edit'] = array( |
| 62 | 'title' => 'Edit coupon', |
| 63 | 'description' => 'Edit an existing coupon.', |
| 64 | 'page callback' => 'drupal_get_form', |
| 65 | 'page arguments' => array('uc_coupon_add_form', 'edit', 4), |
| 66 | 'access arguments' => array('manage store coupons'), |
| 67 | 'type' => MENU_CALLBACK, |
| 68 | ); |
| 69 | $items['admin/store/customers/coupon/%uc_coupon/delete'] = array( |
| 70 | 'title' => 'Delete coupon', |
| 71 | 'description' => 'Delete a coupon.', |
| 72 | 'page callback' => 'drupal_get_form', |
| 73 | 'page arguments' => array('uc_coupon_delete_confirm', 4), |
| 74 | 'access arguments' => array('manage store coupons'), |
| 75 | 'type' => MENU_CALLBACK, |
| 76 | ); |
| 77 | $items['admin/store/customers/coupon/%uc_coupon/codes'] = array( |
| 78 | 'title' => 'Download bulk coupon codes', |
| 79 | 'description' => 'Download the list of bulk coupon codes as a CSV file.', |
| 80 | 'page callback' => 'uc_coupon_codes_csv', |
| 81 | 'page arguments' => array(4), |
| 82 | 'access arguments' => array('manage store coupons'), |
| 83 | 'type' => MENU_CALLBACK, |
| 84 | ); |
| 85 | |
| 86 | $items['cart/checkout/coupon'] = array( |
| 87 | 'title' => 'Apply coupon', |
| 88 | 'page callback' => 'uc_coupon_checkout_apply', |
| 89 | 'access arguments' => array('access content'), |
| 90 | 'type' => MENU_CALLBACK, |
| 91 | ); |
| 92 | |
| 93 | $items['uc_coupon/autocomplete/node'] = array( |
| 94 | 'title' => 'Node autocomplete', |
| 95 | 'page callback' => 'uc_coupon_autocomplete_node', |
| 96 | 'access arguments' => array('manage store coupons'), |
| 97 | 'type' => MENU_CALLBACK, |
| 98 | ); |
| 99 | $items['uc_coupon/autocomplete/term'] = array( |
| 100 | 'title' => 'Term autocomplete', |
| 101 | 'page callback' => 'uc_coupon_autocomplete_term', |
| 102 | 'access arguments' => array('manage store coupons'), |
| 103 | 'type' => MENU_CALLBACK, |
| 104 | ); |
| 105 | $items['uc_coupon/autocomplete/user'] = array( |
| 106 | 'title' => 'User autocomplete', |
| 107 | 'page callback' => 'uc_coupon_autocomplete_user', |
| 108 | 'access arguments' => array('manage store coupons'), |
| 109 | 'type' => MENU_CALLBACK, |
| 110 | ); |
| 111 | $items['uc_coupon/autocomplete/role'] = array( |
| 112 | 'title' => 'Role autocomplete', |
| 113 | 'page callback' => 'uc_coupon_autocomplete_role', |
| 114 | 'access arguments' => array('manage store coupons'), |
| 115 | 'type' => MENU_CALLBACK, |
| 116 | ); |
| 117 | |
| 118 | return $items; |
| 119 | } |
| 120 | |
| 121 | /** |
| 122 | * Implementation of hook_perm(). |
| 123 | */ |
| 124 | function uc_coupon_perm() { |
| 125 | return array('view store coupons', 'manage store coupons', 'coupon wholesale pricing'); |
| 126 | } |
| 127 | |
| 128 | |
| 129 | /** |
| 130 | * Display a brief over view of system coupons |
| 131 | * |
| 132 | * @param $view_type |
| 133 | * pass in an argument to filter out active/inactive coupons |
| 134 | */ |
| 135 | function uc_coupon_display($view_type = 'active') { |
| 136 | _uc_coupon_paypal_check(); |
| 137 | |
| 138 | $header[] = array('data' => t('Name'), 'field' => 'name'); |
| 139 | $header[] = array('data' => t('Code'), 'field' => 'code', 'sort' => 'asc'); |
| 140 | $header[] = array('data' => t('Value'), 'field' => 'value'); |
| 141 | $header[] = array('data' => t('Valid from'), 'field' => 'valid_from'); |
| 142 | $header[] = array('data' => t('Valid until'), 'field' => 'valid_until'); |
| 143 | $header[] = array('data' => t('Actions')); |
| 144 | |
| 145 | $result = pager_query('SELECT cid, name, value, code, type, valid_from, valid_until, bulk FROM {uc_coupons} WHERE status = %d'. tablesort_sql($header), 20, 0, NULL, $view_type == 'inactive' ? 0 : 1); |
| 146 | $rows = array(); |
| 147 | while ($row = db_fetch_object($result)) { |
| 148 | if ($row->type == 'percentage') { |
| 149 | $value = $row->value .'%'; |
| 150 | } |
| 151 | else { |
| 152 | $value = uc_currency_format($row->value); |
| 153 | } |
| 154 | |
| 155 | $code = $row->code; |
| 156 | $actions = l(t('edit'), "admin/store/customers/coupon/$row->cid/edit"); |
| 157 | if ($row->bulk) { |
| 158 | $code .= '* '. t('(bulk)'); |
| 159 | $actions .= ' '. l(t('codes'), "admin/store/customers/coupon/$row->cid/codes"); |
| 160 | } |
| 161 | $actions .= ' '. l(t('delete'), "admin/store/customers/coupon/$row->cid/delete"); |
| 162 | |
| 163 | $valid_from = format_date($row->valid_from, 'custom', variable_get('uc_date_format_default', 'm/d/Y')); |
| 164 | $valid_until = format_date($row->valid_until, 'custom', variable_get('uc_date_format_default', 'm/d/Y')); |
| 165 | $rows[] = array($row->name, $code, $value, $valid_from, $valid_until, $actions); |
| 166 | } |
| 167 | |
| 168 | if (count($rows)) { |
| 169 | $output = theme('table', $header, $rows, array('width' => '100%')); |
| 170 | $output .= theme('pager', NULL, 20); |
| 171 | } |
| 172 | else { |
| 173 | $output = '<p>'. t('There are currently no !type coupons in the system.', array('!type' => $view_type)) .'</p>'; |
| 174 | } |
| 175 | |
| 176 | return $output; |
| 177 | } |
| 178 | |
| 179 | |
| 180 | |
| 181 | /** |
| 182 | * Form builder for product attributes. |
| 183 | * |
| 184 | * @param $action string |
| 185 | * Form action, edit or add. 'edit' loads default values. |
| 186 | * |
| 187 | * @param $coupon object |
| 188 | * Coupon, used to load defaults when $action = 'edit' |
| 189 | */ |
| 190 | function uc_coupon_add_form($form_state, $action, $coupon = NULL) { |
| 191 | _uc_coupon_paypal_check(); |
| 192 | |
| 193 | if ($action == 'edit') { |
| 194 | $value = $coupon; |
| 195 | $used = db_result(db_query("SELECT COUNT(*) FROM {uc_coupons_orders} WHERE cid = %d", $value->cid)); |
| 196 | $form['#uc_coupon_cid'] = $value->cid; |
| 197 | $form['#uc_coupon'] = $value; |
| 198 | $form['#uc_coupon_used'] = $used; |
| 199 | } |
| 200 | else { |
| 201 | $value->valid_from = time(); |
| 202 | $value->valid_until = time(); |
| 203 | $value->minimum_order = 0; |
| 204 | $value->max_uses = 0; |
| 205 | $used = 0; |
| 206 | } |
| 207 | |
| 208 | $value->valid_from = array('year' => format_date($value->valid_from, 'custom', 'Y'), 'month' => format_date($value->valid_from, 'custom', 'n'), 'day' => format_date($value->valid_from, 'custom', 'j')); |
| 209 | $value->valid_until = array('year' => format_date($value->valid_until, 'custom', 'Y'), 'month' => format_date($value->valid_until, 'custom', 'n'), 'day' => format_date($value->valid_until, 'custom', 'j')); |
| 210 | |
| 211 | $form['name'] = array( |
| 212 | '#type' => 'textfield', |
| 213 | '#title' => t('Coupon name'), |
| 214 | '#default_value' => $value->name, |
| 215 | '#required' => TRUE, |
| 216 | ); |
| 217 | |
| 218 | $form['code'] = array( |
| 219 | '#type' => 'textfield', |
| 220 | '#title' => t('Coupon code'), |
| 221 | '#description' => t('Coupon codes cannot be changed once they have been used in an order.'), |
| 222 | '#default_value' => $value->code, |
| 223 | '#size' => 25, |
| 224 | '#required' => !$used, |
| 225 | '#maxlength' => 14, |
| 226 | '#disabled' => $used, |
| 227 | ); |
| 228 | |
| 229 | $form['bulk'] = array( |
| 230 | '#type' => 'fieldset', |
| 231 | '#title' => t('Bulk coupon codes'), |
| 232 | '#description' => t('The coupon code entered above will be used to prefix each generated code.'), |
| 233 | '#collapsible' => TRUE, |
| 234 | '#collapsed' => !$value->bulk, |
| 235 | ); |
| 236 | |
| 237 | if (!$used) { |
| 238 | $form['bulk']['bulk_generate'] = array( |
| 239 | '#type' => 'checkbox', |
| 240 | '#title' => t('Enable bulk generation of coupon codes.'), |
| 241 | '#default_value' => $value->bulk, |
| 242 | '#disabled' => $used, |
| 243 | ); |
| 244 | } |
| 245 | else { |
| 246 | $form['bulk']['bulk_generate'] = array( |
| 247 | '#type' => 'value', |
| 248 | '#default_value' => $value->bulk, |
| 249 | ); |
| 250 | } |
| 251 | |
| 252 | $form['bulk']['bulk_number'] = array( |
| 253 | '#type' => 'textfield', |
| 254 | '#title' => t('Number of codes to generate'), |
| 255 | '#default_value' => $value->data['bulk_number'], |
| 256 | '#size' => 10, |
| 257 | '#maxlength' => 10, |
| 258 | '#disabled' => $used, |
| 259 | ); |
| 260 | |
| 261 | $form['bulk']['bulk_length'] = array( |
| 262 | '#type' => 'select', |
| 263 | '#title' => t('Code length'), |
| 264 | '#description' => t('The number of characters selected here will be appended to the coupon code entered above..'), |
| 265 | '#default_value' => $value->data['bulk_length'], |
| 266 | '#options' => drupal_map_assoc(range(8, 30)), |
| 267 | '#disabled' => $used, |
| 268 | ); |
| 269 | |
| 270 | $form['valid_from'] = array( |
| 271 | '#type' => 'date', |
| 272 | '#title' => t('Start date'), |
| 273 | '#default_value' => $value->valid_from, |
| 274 | '#required' => TRUE, |
| 275 | '#after_build' => array('_uc_coupon_date_range'), |
| 276 | ); |
| 277 | |
| 278 | $form['valid_until'] = array( |
| 279 | '#type' => 'date', |
| 280 | '#title' => t('Expiry date'), |
| 281 | '#default_value' => $value->valid_until, |
| 282 | '#required' => TRUE, |
| 283 | '#after_build' => array('_uc_coupon_date_range'), |
| 284 | ); |
| 285 | |
| 286 | $form['status'] = array( |
| 287 | '#type' => 'checkbox', |
| 288 | '#title' => t('Active'), |
| 289 | '#description' => t('Check to enable the coupon, uncheck to disable the coupon.'), |
| 290 | '#default_value' => $value->status, |
| 291 | ); |
| 292 | |
| 293 | $form['type'] = array( |
| 294 | '#type' => 'select', |
| 295 | '#title' => t('Discount type'), |
| 296 | '#default_value' => $value->type, |
| 297 | '#options' => array( |
| 298 | 'percentage' => 'Percentage', |
| 299 | 'price' => 'Price' |
| 300 | ), |
| 301 | ); |
| 302 | |
| 303 | $form['value'] = array( |
| 304 | '#type' => 'textfield', |
| 305 | '#title' => t('Discount value'), |
| 306 | '#default_value' => $value->value, |
| 307 | '#size' => 10, |
| 308 | '#description' => t('Enter values without symbols, for 15%, enter "15" and choose Percentage as the discount type.'), |
| 309 | '#required' => TRUE, |
| 310 | ); |
| 311 | |
| 312 | $form['minimum_order'] = array( |
| 313 | '#type' => 'textfield', |
| 314 | '#title' => t('Minimum order total'), |
| 315 | '#default_value' => $value->minimum_order, |
| 316 | '#size' => 10, |
| 317 | '#description' => t('A minimum order total that applies to the coupon, or 0 for no minimum order limit.'), |
| 318 | '#required' => TRUE, |
| 319 | '#field_prefix' => variable_get('uc_sign_after_amount', FALSE) ? '' : variable_get('uc_currency_sign', '$'), |
| 320 | '#field_suffix' => variable_get('uc_sign_after_amount', FALSE) ? variable_get('uc_currency_sign', '$') : '', |
| 321 | ); |
| 322 | |
| 323 | $form['max_uses'] = array( |
| 324 | '#type' => 'textfield', |
| 325 | '#title' => t('Maximum number of redemptions (per code)'), |
| 326 | '#default_value' => $value->max_uses, |
| 327 | '#description' => t('Enter the maximum number of times each code for this coupon can be used, or 0 for unlimited.'), |
| 328 | '#size' => 5, |
| 329 | '#required' => TRUE, |
| 330 | ); |
| 331 | |
| 332 | $form['max_uses_per_user'] = array( |
| 333 | '#type' => 'textfield', |
| 334 | '#title' => t('Maximum number of redemptions (per user)'), |
| 335 | '#default_value' => isset($value->data['max_uses_per_user']) ? $value->data['max_uses_per_user'] : 0, |
| 336 | '#description' => t('Enter the maximum number of times this coupon can be used by a single user, or 0 for unlimited.'), |
| 337 | '#size' => 5, |
| 338 | '#required' => TRUE, |
| 339 | ); |
| 340 | |
| 341 | $form['max_applicable_products'] = array( |
| 342 | '#type' => 'textfield', |
| 343 | '#title' => t('Maximum number of applicable products'), |
| 344 | '#description' => t('For coupons that are limited in application by product class, product node, SKU, or taxonomy term, specify the maximum number of applicable products to which the discount should be applied. Enter 0 to apply the discount to every product.'), |
| 345 | '#default_value' => isset($value->data['max_applicable_products']) ? $value->data['max_applicable_products'] : 0, |
| 346 | '#size' => 5, |
| 347 | '#required' => TRUE, |
| 348 | ); |
| 349 | |
| 350 | $form['max_applicable_products_value'] = array( |
| 351 | '#type' => 'radios', |
| 352 | '#title' => t('Apply against which products'), |
| 353 | '#description' => t('For coupons that have a limited number of applicable products, specify to which products the discount should be applied.'), |
| 354 | '#options' => array( |
| 355 | 'cheapest' => t('The cheapest product(s)'), |
| 356 | 'expensive' => t('The most expensive product(s)'), |
| 357 | ), |
| 358 | '#default_value' => isset($value->data['max_applicable_products_value']) ? $value->data['max_applicable_products_value'] : 'cheapest', |
| 359 | '#required' => TRUE, |
| 360 | ); |
| 361 | |
| 362 | $options = array('' => '(none)'); |
| 363 | foreach (module_invoke_all('product_types') as $type) { |
| 364 | $options[$type] = $type; |
| 365 | } |
| 366 | |
| 367 | $form['product_types'] = array( |
| 368 | '#type' => 'select', |
| 369 | '#title' => t('Product classes'), |
| 370 | '#description' => t('Selecting one or more product classes will restrict this coupon to matching products only. Discounts will then apply to each matching product.'), |
| 371 | '#options' => $options, |
| 372 | '#default_value' => $value->data['product_types'], |
| 373 | '#multiple' => TRUE, |
| 374 | ); |
| 375 | |
| 376 | $form['products'] = array( |
| 377 | '#type' => 'fieldset', |
| 378 | '#title' => t('Applicable products'), |
| 379 | '#description' => t('Enter one or more products below to restrict this coupon to a set of products, regardless of any product attributes. Discounts will apply to each matching product.'), |
| 380 | '#tree' => TRUE, |
| 381 | '#collapsible' => TRUE, |
| 382 | '#collapsed' => !isset($value->data['products']), |
| 383 | ); |
| 384 | |
| 385 | $form['products']['negate_products'] = array( |
| 386 | '#type' => 'radios', |
| 387 | '#default_value' => isset($value->data['negate_products']) ? 1 : 0, |
| 388 | '#options' => array( |
| 389 | 0 => t('Apply coupon to products listed below.'), |
| 390 | 1 => t('Apply coupon to all products except those listed below.'), |
| 391 | ), |
| 392 | '#tree' => FALSE, |
| 393 | ); |
| 394 | |
| 395 | if (isset($value->data['products'])) { |
| 396 | foreach ($value->data['products'] as $nid) { |
| 397 | $title = db_result(db_query('SELECT title FROM {node} WHERE nid = %d', $nid)); |
| 398 | $form['products'][] = array( |
| 399 | '#type' => 'textfield', |
| 400 | '#default_value' => $title .' [nid:'. $nid .']', |
| 401 | '#autocomplete_path' => 'uc_coupon/autocomplete/node', |
| 402 | ); |
| 403 | } |
| 404 | } |
| 405 | |
| 406 | for ($i = 0; $i < 3; $i++) { |
| 407 | $form['products'][] = array( |
| 408 | '#type' => 'textfield', |
| 409 | '#autocomplete_path' => 'uc_coupon/autocomplete/node', |
| 410 | ); |
| 411 | } |
| 412 | |
| 413 | $form['skus'] = array( |
| 414 | '#type' => 'fieldset', |
| 415 | '#title' => t('Applicable SKUs'), |
| 416 | '#description' => t('Enter one or more SKUs below to restrict this coupon to a set of SKUs, allowing coupons to apply to specific products or attribute options. Discounts will apply to matching SKU.'), |
| 417 | '#tree' => TRUE, |
| 418 | '#collapsible' => TRUE, |
| 419 | '#collapsed' => !isset($value->data['skus']), |
| 420 | ); |
| 421 | |
| 422 | if (isset($value->data['skus'])) { |
| 423 | foreach ($value->data['skus'] as $sku) { |
| 424 | $form['skus'][] = array( |
| 425 | '#type' => 'textfield', |
| 426 | '#default_value' => $sku, |
| 427 | ); |
| 428 | } |
| 429 | } |
| 430 | |
| 431 | for ($i = 0; $i < 3; $i++) { |
| 432 | $form['skus'][] = array( |
| 433 | '#type' => 'textfield', |
| 434 | ); |
| 435 | } |
| 436 | |
| 437 | $form['terms'] = array( |
| 438 | '#type' => 'fieldset', |
| 439 | '#title' => t('Applicable taxonomy terms'), |
| 440 | '#description' => t('Enter one or more taxonomy terms (categories) below to restrict this coupon to a set of products. Discounts will apply to all matching products with these terms.'), |
| 441 | '#tree' => TRUE, |
| 442 | '#collapsible' => TRUE, |
| 443 | '#collapsed' => !isset($value->data['terms']), |
| 444 | ); |
| 445 | |
| 446 | $form['terms']['negate_terms'] = array( |
| 447 | '#type' => 'radios', |
| 448 | '#default_value' => isset($value->data['negate_terms']) ? 1 : 0, |
| 449 | '#options' => array( |
| 450 | 0 => t('Apply coupon to products with terms listed below.'), |
| 451 | 1 => t('Apply coupon to all products except those with terms listed below.'), |
| 452 | ), |
| 453 | '#tree' => FALSE, |
| 454 | ); |
| 455 | |
| 456 | if (isset($value->data['terms'])) { |
| 457 | foreach ($value->data['terms'] as $tid) { |
| 458 | $name = db_result(db_query('SELECT name FROM {term_data} WHERE tid = %d', $tid)); |
| 459 | $form['terms'][] = array( |
| 460 | '#type' => 'textfield', |
| 461 | '#default_value' => $name .' [tid:'. $tid .']', |
| 462 | '#autocomplete_path' => 'uc_coupon/autocomplete/term', |
| 463 | ); |
| 464 | } |
| 465 | } |
| 466 | |
| 467 | for ($i = 0; $i < 3; $i++) { |
| 468 | $form['terms'][] = array( |
| 469 | '#type' => 'textfield', |
| 470 | '#autocomplete_path' => 'uc_coupon/autocomplete/term', |
| 471 | ); |
| 472 | } |
| 473 | |
| 474 | $form['users'] = array( |
| 475 | '#type' => 'fieldset', |
| 476 | '#title' => t('User restrictions'), |
| 477 | '#description' => t('Enter one or more user names and/or "anonymous users" below to make this coupon valid only for those users.'), |
| 478 | '#tree' => TRUE, |
| 479 | '#collapsible' => TRUE, |
| 480 | '#collapsed' => !isset($value->data['users']), |
| 481 | ); |
| 482 | |
| 483 | if (isset($value->data['users'])) { |
| 484 | foreach ($value->data['users'] as $uid) { |
| 485 | $username = $uid ? db_result(db_query('SELECT name FROM {users} WHERE uid = %d', $uid)) : t('anonymous users'); |
| 486 | $form['users'][] = array( |
| 487 | '#type' => 'textfield', |
| 488 | '#default_value' => $username .' [uid:'. $uid .']', |
| 489 | '#autocomplete_path' => 'uc_coupon/autocomplete/user', |
| 490 | ); |
| 491 | } |
| 492 | } |
| 493 | |
| 494 | for ($i = 0; $i < 3; $i++) { |
| 495 | $form['users'][] = array( |
| 496 | '#type' => 'textfield', |
| 497 | '#autocomplete_path' => 'uc_coupon/autocomplete/user', |
| 498 | ); |
| 499 | } |
| 500 | |
| 501 | $form['roles'] = array( |
| 502 | '#type' => 'fieldset', |
| 503 | '#title' => t('Role restrictions'), |
| 504 | '#description' => t('Enter one or more role names below to make this coupon valid only for users with those roles.'), |
| 505 | '#tree' => TRUE, |
| 506 | '#collapsible' => TRUE, |
| 507 | '#collapsed' => !isset($value->data['roles']), |
| 508 | ); |
| 509 | |
| 510 | if (isset($value->data['roles'])) { |
| 511 | foreach ($value->data['roles'] as $role) { |
| 512 | $form['roles'][] = array( |
| 513 | '#type' => 'textfield', |
| 514 | '#default_value' => $role, |
| 515 | '#autocomplete_path' => 'uc_coupon/autocomplete/role', |
| 516 | ); |
| 517 | } |
| 518 | } |
| 519 | |
| 520 | for ($i = 0; $i < 3; $i++) { |
| 521 | $form['roles'][] = array( |
| 522 | '#type' => 'textfield', |
| 523 | '#autocomplete_path' => 'uc_coupon/autocomplete/role', |
| 524 | ); |
| 525 | } |
| 526 | |
| 527 | $form['wholesale'] = array( |
| 528 | '#type' => 'radios', |
| 529 | '#title' => 'Wholesale permissions', |
| 530 | '#description' => t('Select the groups who are able to use this coupon. This option is deprecated, it is recommended that you leave this option as "Both wholesale and retail" use the role selection above instead.'), |
| 531 | '#default_value' => isset($value->data['wholesale']) ? $value->data['wholesale'] : 1, |
| 532 | '#options' => array( |
| 533 | '1' => 'Both wholesale and retail', |
| 534 | '2' => 'Wholesale buyers only', |
| 535 | '3' => 'Retail buyers only' |
| 536 | ), |
| 537 | '#required' => TRUE, |
| 538 | ); |
| 539 | |
| 540 | $form['submit'] = array('#type' => 'submit', '#value' => t('Submit')); |
| 541 | |
| 542 | return $form; |
| 543 | } |
| 544 | |
| 545 | function _uc_coupon_date_range($form_element) { |
| 546 | $form_element['year']['#options'] = drupal_map_assoc(range(2008, 2020)); |
| 547 | return $form_element; |
| 548 | } |
| 549 | |
| 550 | function uc_coupon_autocomplete_node($string) { |
| 551 | $matches = array(); |
| 552 | $product_types = module_invoke_all('product_types'); |
| 553 | |
| 554 | $result = db_query_range("SELECT nid, title FROM {node} WHERE type IN ('". implode("','", $product_types) ."') AND title LIKE '%%%s%'", $string, 0, 10); |
| 555 | while ($row = db_fetch_object($result)) { |
| 556 | $title = check_plain($row->title); |
| 557 | $matches[$title .' [nid:'. $row->nid .']'] = $title; |
| 558 | } |
| 559 | print drupal_to_js($matches); |
| 560 | exit; |
| 561 | } |
| 562 | |
| 563 | function uc_coupon_autocomplete_term($string) { |
| 564 | $matches = array(); |
| 565 | $result = db_query_range("SELECT tid, name FROM {term_data} WHERE name LIKE '%%%s%'", $string, 0, 10); |
| 566 | while ($row = db_fetch_object($result)) { |
| 567 | $matches[$row->name .' [tid:'. $row->tid .']'] = $row->name; |
| 568 | } |
| 569 | print drupal_to_js($matches); |
| 570 | exit; |
| 571 | } |
| 572 | |
| 573 | function uc_coupon_autocomplete_user($string) { |
| 574 | $matches = array(); |
| 575 | $anonymous = t('anonymous users'); |
| 576 | if (strpos($anonymous, $string) !== FALSE) { |
| 577 | $matches[$anonymous .' [uid:0]'] = $anonymous; |
| 578 | } |
| 579 | |
| 580 | $result = db_query_range("SELECT uid, name FROM {users} WHERE name LIKE '%%%s%'", $string, 0, 10); |
| 581 | while ($row = db_fetch_object($result)) { |
| 582 | $matches[$row->name .' [uid:'. $row->uid .']'] = $row->name; |
| 583 | } |
| 584 | print drupal_to_js($matches); |
| 585 | exit; |
| 586 | } |
| 587 | |
| 588 | function uc_coupon_autocomplete_role($string) { |
| 589 | $matches = array(); |
| 590 | $result = db_query_range("SELECT name FROM {role} WHERE name LIKE '%%%s%'", $string, 0, 10); |
| 591 | while ($row = db_fetch_object($result)) { |
| 592 | $matches[$row->name] = $row->name; |
| 593 | } |
| 594 | print drupal_to_js($matches); |
| 595 | exit; |
| 596 | } |
| 597 | |
| 598 | /** |
| 599 | * Coupon form validate handler. |
| 600 | */ |
| 601 | function uc_coupon_add_form_validate($form, &$form_state) { |
| 602 | // check to ensure a unique coupon code |
| 603 | $name = db_result(db_query("SELECT name FROM {uc_coupons} WHERE code = '%s' AND cid <> %d", strtoupper($form_state['values']['code']), $form['#uc_coupon_cid'])); |
| 604 | if ($name) { |
| 605 | form_set_error('code', t('Coupon code already used by %name.', array('%name' => $name))); |
| 606 | } |
| 607 | |
| 608 | foreach ($form_state['values']['products'] as $key => $product) { |
| 609 | if ($product && !preg_match('/\[nid:(\d+)\]$/', $product)) { |
| 610 | form_set_error('products]['. $key, t('Products must include the node ID.')); |
| 611 | } |
| 612 | } |
| 613 | |
| 614 | foreach ($form_state['values']['users'] as $key => $user) { |
| 615 | if ($user && !preg_match('/\[uid:(\d+)\]$/', $user)) { |
| 616 | form_set_error('users]['. $key, t('User names must include the user ID.')); |
| 617 | } |
| 618 | } |
| 619 | |
| 620 | if (!$form['#uc_coupon_used'] && $form_state['values']['bulk_generate'] && intval($form_state['values']['bulk_number']) <= 0) { |
| 621 | form_set_error('bulk_number', t('You must specify the number of codes to generate.')); |
| 622 | } |
| 623 | |
| 624 | $valid_from = mktime(0, 0, 0, $form_state['values']['valid_from']['month'], $form_state['values']['valid_from']['day'], $form_state['values']['valid_from']['year']); |
| 625 | $valid_until = mktime(0, 0, 0, $form_state['values']['valid_until']['month'], $form_state['values']['valid_until']['day'], $form_state['values']['valid_until']['year']); |
| 626 | if ($valid_from > $valid_until) { |
| 627 | form_set_error('valid_from', t('The coupon start date must be before the expiration date.')); |
| 628 | } |
| 629 | |
| 630 | if ($form_state['values']['max_applicable_products']) { |
| 631 | $restrictions = array_filter($form_state['values']['product_types'] + $form_state['values']['products'] + $form_state['values']['skus'] + $form_state['values']['terms']); |
| 632 | if (empty($restrictions)) { |
| 633 | form_set_error('max_applicable_products', t('To use the maximum number of applicable products feature, you must restrict the coupon by product class, product node, SKU, or taxonomy term.')); |
| 634 | } |
| 635 | } |
| 636 | } |
| 637 | |
| 638 | /** |
| 639 | * Coupon form submit handler. |
| 640 | */ |
| 641 | function uc_coupon_add_form_submit($form, &$form_state) { |
| 642 | // If the coupon was previously used, reset disabled textfields to their original values. |
| 643 | if ($form['#uc_coupon_used']) { |
| 644 | $form_state['values']['code'] = $form['#uc_coupon']->code; |
| 645 | $form_state['values']['bulk_number'] = $form['#uc_coupon']->data['bulk_number']; |
| 646 | } |
| 647 | |
| 648 | $code = strtoupper($form_state['values']['code']); |
| 649 | $valid_from = mktime(0, 0, 0, $form_state['values']['valid_from']['month'], $form_state['values']['valid_from']['day'], $form_state['values']['valid_from']['year']); |
| 650 | $valid_until = mktime(0, 0, 0, $form_state['values']['valid_until']['month'], $form_state['values']['valid_until']['day'], $form_state['values']['valid_until']['year']); |
| 651 | $data = array(); |
| 652 | |
| 653 | if ($form_state['values']['bulk_generate']) { |
| 654 | $data['bulk_number'] = $form_state['values']['bulk_number']; |
| 655 | $data['bulk_length'] = $form_state['values']['bulk_length']; |
| 656 | } |
| 657 | |
| 658 | if ($form_state['values']['max_uses_per_user']) { |
| 659 | $data['max_uses_per_user'] = $form_state['values']['max_uses_per_user']; |
| 660 | } |
| 661 | |
| 662 | if ($form_state['values']['max_applicable_products']) { |
| 663 | $data['max_applicable_products'] = $form_state['values']['max_applicable_products']; |
| 664 | } |
| 665 | |
| 666 | if ($form_state['values']['max_applicable_products_value']) { |
| 667 | $data['max_applicable_products_value'] = $form_state['values']['max_applicable_products_value']; |
| 668 | } |
| 669 | |
| 670 | if ($form_state['values']['negate_products']) { |
| 671 | $data['negate_products'] = TRUE; |
| 672 | } |
| 673 | |
| 674 | if ($form_state['values']['negate_terms']) { |
| 675 | $data['negate_terms'] = TRUE; |
| 676 | } |
| 677 | |
| 678 | foreach ($form_state['values']['product_types'] as $type) { |
| 679 | if ($type) { |
| 680 | $data['product_types'][] = $type; |
| 681 | } |
| 682 | } |
| 683 | |
| 684 | foreach ($form_state['values']['products'] as $key => $product) { |
| 685 | if ($product && preg_match('/\[nid:(\d+)\]$/', $product, $matches)) { |
| 686 | $data['products'][] = $matches[1]; |
| 687 | } |
| 688 | } |
| 689 | |
| 690 | foreach ($form_state['values']['skus'] as $sku) { |
| 691 | if ($sku) { |
| 692 | $data['skus'][] = $sku; |
| 693 | } |
| 694 | } |
| 695 | |
| 696 | foreach ($form_state['values']['terms'] as $key => $term) { |
| 697 | if ($term && preg_match('/\[tid:(\d+)\]$/', $term, $matches)) { |
| 698 | $data['terms'][] = $matches[1]; |
| 699 | } |
| 700 | } |
| 701 | |
| 702 | foreach ($form_state['values']['users'] as $key => $user) { |
| 703 | if ($user && preg_match('/\[uid:(\d+)\]$/', $user, $matches)) { |
| 704 | $data['users'][] = $matches[1]; |
| 705 | } |
| 706 | } |
| 707 | |
| 708 | foreach ($form_state['values']['roles'] as $role) { |
| 709 | if ($role) { |
| 710 | $data['roles'][] = $role; |
| 711 | } |
| 712 | } |
| 713 | |
| 714 | $data['wholesale'] = $form_state['values']['wholesale']; |
| 715 | |
| 716 | if (!isset($form['#uc_coupon_cid'])) { |
| 717 | // Only set bulk coupon seed once. |
| 718 | db_query("INSERT INTO {uc_coupons} (name, code, value, type, status, valid_from, valid_until, max_uses, minimum_order, data, bulk, bulk_seed) VALUES ('%s', '%s', %f, '%s', %d, %d, %d, %d, %f, '%s', %d, '%s')", $form_state['values']['name'], $code, $form_state['values']['value'], $form_state['values']['type'], $form_state['values']['status'], $valid_from, $valid_until, $form_state['values']['max_uses'], $form_state['values']['minimum_order'], serialize($data), $form_state['values']['bulk_generate'], md5(uniqid())); |
| 719 | drupal_set_message(t('Coupon %name has been created.', array('%name' => $form_state['values']['name']))); |
| 720 | } |
| 721 | else { |
| 722 | db_query("UPDATE {uc_coupons} SET name = '%s', code = '%s', value = %f, type = '%s', status = %d, valid_from = %d, valid_until = %d, max_uses = %d, minimum_order = %f, data = '%s', bulk = %d WHERE cid = %d", $form_state['values']['name'], $code, $form_state['values']['value'], $form_state['values']['type'], $form_state['values']['status'], $valid_from, $valid_until, $form_state['values']['max_uses'], $form_state['values']['minimum_order'], serialize($data), $form_state['values']['bulk_generate'], $form['#uc_coupon_cid']); |
| 723 | drupal_set_message(t('Coupon %name has been updated.', array('%name' => $form_state['values']['name']))); |
| 724 | } |
| 725 | |
| 726 | $form_state['redirect'] = 'admin/store/customers/coupon'. ($form_state['values']['status'] ? '' : '/inactive'); |
| 727 | } |
| 728 | |
| 729 | |
| 730 | /** |
| 731 | * Load a coupon into the form for editing |
| 732 | * |
| 733 | * @param $cid |
| 734 | * Unique coupon ID. |
| 735 | * |
| 736 | * @return $coupon |
| 737 | * Returns a coupon object. |
| 738 | */ |
| 739 | function uc_coupon_load($cid) { |
| 740 | $coupon = db_fetch_object(db_query("SELECT * FROM {uc_coupons} WHERE cid = %d", $cid)); |
| 741 | if ($coupon->data) { |
| 742 | $coupon->data = unserialize($coupon->data); |
| 743 | } |
| 744 | return $coupon; |
| 745 | } |
| 746 | |
| 747 | /** |
| 748 | * Delete coupon confirm form |
| 749 | * |
| 750 | * @param $cid int |
| 751 | * Coupon ID. |
| 752 | * |
| 753 | * @return $confirm |
| 754 | * Return a drupal confirm form. |
| 755 | */ |
| 756 | function uc_coupon_delete_confirm(&$form_state, $coupon) { |
| 757 | $form['#uc_coupon_cid'] = $coupon->cid; |
| 758 | return confirm_form($form, t('Are you sure you want to delete coupon %name with code %code?', array('%name' => $coupon->name, '%code' => $coupon->code)), 'admin/store/customers/coupon', t('This action cannot be undone. Deleting this coupon will remove all records of past uses as well.'), t('Delete')); |
| 759 | } |
| 760 | |
| 761 | function uc_coupon_delete_confirm_submit($form, &$form_state) { |
| 762 | $coupon = uc_coupon_load($form['#uc_coupon_cid']); |
| 763 | |
| 764 | db_query("DELETE FROM {uc_coupons} WHERE cid = %d", $form['#uc_coupon_cid']); |
| 765 | db_query("DELETE FROM {uc_coupons_orders} WHERE cid = %d", $form['#uc_coupon_cid']); |
| 766 | |
| 767 | drupal_set_message(t('Coupon %name has been deleted.', array('%name' => $coupon->name))); |
| 768 | $form_state['redirect'] = 'admin/store/customers/coupon'. ($coupon->status ? '' : '/inactive'); |
| 769 | } |
| 770 | |
| 771 | /** |
| 772 | * Generate a list of bulk coupon codes. |
| 773 | */ |
| 774 | function uc_coupon_codes_csv($coupon = NULL) { |
| 775 | if (!$coupon->bulk) { |
| 776 | drupal_not_found(); |
| 777 | return; |
| 778 | } |
| 779 | |
| 780 | header('Content-Type: application/octet-stream'); |
| 781 | header('Content-Disposition: attachment; filename="'. $coupon->code .'.csv";'); |
| 782 | |
| 783 | for ($id = 0; $id < $coupon->data['bulk_number']; $id++) { |
| 784 | echo uc_coupon_get_bulk_code($coupon, $id) ."\n"; |
| 785 | } |
| 786 | exit; |
| 787 | } |
| 788 | |
| 789 | /** |
| 790 | * Generate a single bulk coupon code. |
| 791 | */ |
| 792 | function uc_coupon_get_bulk_code($coupon, $id) { |
| 793 | $id = str_pad(dechex($id), strlen(dechex($coupon->data['bulk_number'])), '0', STR_PAD_LEFT); |
| 794 | $length = strlen($coupon->code) + $coupon->data['bulk_length']; |
| 795 | return strtoupper(substr($coupon->code . $id . md5($coupon->bulk_seed . $id), 0, $length)); |
| 796 | } |
| 797 | |
| 798 | /** |
| 799 | * Load a coupon (single or bulk) from the supplied code. |
| 800 | */ |
| 801 | function uc_coupon_find($code) { |
| 802 | // Look for matching single coupon first. |
| 803 | $coupon = db_fetch_object(db_query("SELECT * FROM {uc_coupons} WHERE code = '%s' AND status = 1 AND bulk = 0 AND valid_from < %d AND valid_until > %d", $code, time(), time())); |
| 804 | if ($coupon !== FALSE) { |
| 805 | if ($coupon->data) { |
| 806 | $coupon->data = unserialize($coupon->data); |
| 807 | } |
| 808 | return $coupon; |
| 809 | } |
| 810 | |
| 811 | // Look through bulk coupons. |
| 812 | $result = db_query("SELECT * FROM {uc_coupons} WHERE status = 1 AND bulk = 1 AND valid_from < %d AND valid_until > %d", time(), time()); |
| 813 | while ($coupon = db_fetch_object($result)) { |
| 814 | // Check coupon prefix. |
| 815 | $prefix_length = strlen($coupon->code); |
| 816 | if (substr($code, 0, $prefix_length) != $coupon->code) { |
| 817 | continue; |
| 818 | } |
| 819 | |
| 820 | if ($coupon->data) { |
| 821 | $coupon->data = unserialize($coupon->data); |
| 822 | } |
| 823 | |
| 824 | // Check coupon sequence ID. |
| 825 | $id = substr($code, $prefix_length, strlen(dechex($coupon->data['bulk_number']))); |
| 826 | if (!preg_match("/^[0-9A-F]+$/", $id)) { |
| 827 | continue; |
| 828 | } |
| 829 | $id = hexdec($id); |
| 830 | if ($id < 0 || $id > $coupon->data['bulk_number']) { |
| 831 | continue; |
| 832 | } |
| 833 | |
| 834 | // Check complete coupon code. |
| 835 | if ($code == uc_coupon_get_bulk_code($coupon, $id)) { |
| 836 | return $coupon; |
| 837 | } |
| 838 | } |
| 839 | |
| 840 | return FALSE; |
| 841 | } |
| 842 | |
| 843 | /** |
| 844 | * Validate a coupon and calculate the coupon amount against the current cart contents. |
| 845 | * |
| 846 | * @param $code |
| 847 | * The coupon code entered at the checkout screen |
| 848 | * |
| 849 | * @return |
| 850 | * Returns a coupon result object with details about the validation |
| 851 | */ |
| 852 | function uc_coupon_validate($code) { |
| 853 | global $user; |
| 854 | |
| 855 | $result->valid = FALSE; |
| 856 | |
| 857 | $code = strtoupper($code); |
| 858 | $coupon = uc_coupon_find($code); |
| 859 | |
| 860 | if (!$coupon) { |
| 861 | $result->message = t('This coupon code is invalid or has expired.'); |
| 862 | return $result; |
| 863 | } |
| 864 | |
| 865 | if (isset($coupon->data['products']) || isset($coupon->data['skus']) || isset($coupon->data['terms']) || isset($coupon->data['product_types'])) { |
| 866 | $prices = array(); |
| 867 | |
| 868 | // Product coupons apply to the subtotal and quantity of matching products. |
| 869 | foreach (uc_cart_get_contents() as $item) { |
| 870 | $cart_total += $item->price * $item->qty; |
| 871 | |
| 872 | $terms = array(); |
| 873 | $query = db_query("SELECT tid FROM {term_node} WHERE vid = %d", $item->vid); |
| 874 | while ($tid = db_result($query)) { |
| 875 | $terms[] = $tid; |
| 876 | } |
| 877 | |
| 878 | if (isset($coupon->data['products']) && (isset($coupon->data['negate_products']) xor in_array($item->nid, $coupon->data['products']))) { |
| 879 | $prices = array_pad($prices, count($prices) + $item->qty, $item->price); |
| 880 | } |
| 881 | else if (isset($coupon->data['skus']) && in_array($item->model, $coupon->data['skus'])) { |
| 882 | $prices = array_pad($prices, count($prices) + $item->qty, $item->price); |
| 883 | } |
| 884 | else if (isset($coupon->data['terms']) && (isset($coupon->data['negate_terms']) xor count(array_intersect($terms, $coupon->data['terms'])))) { |
| 885 | $prices = array_pad($prices, count($prices) + $item->qty, $item->price); |
| 886 | } |
| 887 | else if (isset($coupon->data['product_types'])) { |
| 888 | $type = db_result(db_query("SELECT type FROM {node} WHERE nid = %d", $item->nid)); |
| 889 | if (in_array($type, $coupon->data['product_types'])) { |
| 890 | $prices = array_pad($prices, count($prices) + $item->qty, $item->price); |
| 891 | } |
| 892 | } |
| 893 | } |
| 894 | |
| 895 | // If a maximum number of applicable products has been specified... |
| 896 | if (isset($coupon->data['max_applicable_products']) && ($num = $coupon->data['max_applicable_products']) > 0) { |
| 897 | // Sort the array of applicable product prices. |
| 898 | sort($prices); |
| 899 | |
| 900 | // Slice the appropriate number of prices off the array. |
| 901 | if ($coupon->data['max_applicable_products_value'] == 'cheapest') { |
| 902 | $applicable_prices = array_slice($prices, 0, $num); |
| 903 | } |
| 904 | else { |
| 905 | $applicable_prices = array_slice($prices, -$num); |
| 906 | } |
| 907 | |
| 908 | // Set the applicable total and quantity based on our new prices. |
| 909 | $applicable_total = 0; |
| 910 | foreach ($applicable_prices as $price) { |
| 911 | $applicable_total += $price; |
| 912 | } |
| 913 | $applicable_qty = $num; |
| 914 | } |
| 915 | else { |
| 916 | // Otherwise include all the prices in the applicable totals. |
| 917 | $applicable_total = 0; |
| 918 | foreach ($prices as $price) { |
| 919 | $applicable_total += $price; |
| 920 | } |
| 921 | $applicable_qty = count($prices); |
| 922 | } |
| 923 | } |
| 924 | else { |
| 925 | // Standard coupons apply once to the whole cart. |
| 926 | foreach (uc_cart_get_contents() as $item) { |
| 927 | $cart_total += $item->price * $item->qty; |
| 928 | } |
| 929 | $applicable_total = $cart_total; |
| 930 | $applicable_qty = 1; |
| 931 | } |
| 932 | |
| 933 | if ($applicable_total == 0) { |
| 934 | $result->message = t('You do not have applicable products in your cart.'); |
| 935 | return $result; |
| 936 | } |
| 937 | |
| 938 | // CHECK MAX USES |
| 939 | if ($coupon->max_uses > 0) { |
| 940 | $used = db_result(db_query("SELECT COUNT(*) FROM {uc_coupons_orders} AS uco LEFT JOIN {uc_orders} AS uo ON uco.oid = uo.order_id LEFT JOIN {uc_order_statuses} AS uos ON uo.order_status = uos.order_status_id WHERE uos.weight > 0 AND uco.cid = %d AND uco.code = '%s'", $coupon->cid, $code)); |
| 941 | if ($used >= $coupon->max_uses) { |
| 942 | $result->message = t('This coupon has reached the maximum redemption limit.'); |
| 943 | return $result; |
| 944 | } |
| 945 | } |
| 946 | |
| 947 | // CHECK MAX USES PER USER |
| 948 | if (isset($coupon->data['max_uses_per_user'])) { |
| 949 | $used = db_result(db_query("SELECT COUNT(*) FROM {uc_coupons_orders} AS uco LEFT JOIN {uc_orders} AS uo ON uco.oid = uo.order_id LEFT JOIN {uc_order_statuses} AS uos ON uo.order_status = uos.order_status_id WHERE uos.weight > 0 AND uco.cid = %d AND uo.uid = %d", $coupon->cid, $user->uid)); |
| 950 | if ($used >= $coupon->data['max_uses_per_user']) { |
| 951 | $result->message = t('This coupon has reached the maximum redemption limit.'); |
| 952 | return $result; |
| 953 | } |
| 954 | } |
| 955 | |
| 956 | // CHECK MINIMUM PURCHASE VALUE |
| 957 | if ($coupon->minimum_order > 0 && $coupon->minimum_order > $cart_total) { |
| 958 | $result->message = t('You have not reached the minimum order total for this coupon.'); |
| 959 | return $result; |
| 960 | } |
| 961 | |
| 962 | // CHECK USER ID |
| 963 | if (isset($coupon->data['users'])) { |
| 964 | if (!in_array("$user->uid", $coupon->data['users'], TRUE)) { |
| 965 | $result->message = t('Your user ID is not allowed to use this coupon.'); |
| 966 | return $result; |
| 967 | } |
| 968 | } |
| 969 | |
| 970 | // CHECK ROLES |
| 971 | if (isset($coupon->data['roles'])) { |
| 972 | $role_found = FALSE; |
| 973 | foreach ($coupon->data['roles'] as $role) { |
| 974 | if (in_array($role, $user->roles)) { |
| 975 | $role_found = TRUE; |
| 976 | break; |
| 977 | } |
| 978 | } |
| 979 | if (!$role_found) { |
| 980 | $result->message = t('You do not have the correct permission to use this coupon.'); |
| 981 | return $result; |
| 982 | } |
| 983 | } |
| 984 | |
| 985 | // CHECK USER PERMISSIONS |
| 986 | // 1 - both wholesale and retail any user |
| 987 | // 2 - wholesale only -> users with 'coupon wholesale pricing' |
| 988 | // 3 - retail only -> users without 'coupon wholesale pricing' |
| 989 | if ($coupon->data['wholesale'] > 1) { |
| 990 | if ($coupon->data['wholesale'] == 2) { |
| 991 | if (!user_access('coupon wholesale pricing')) { |
| 992 | $result->message = t('You do not have the correct permission to use this coupon.'); |
| 993 | return $result; |
| 994 | } |
| 995 | } |
| 996 | else if ($coupon->data['wholesale'] == 3) { |
| 997 | if (user_access('coupon wholesale pricing')) { |
| 998 | $result->message = t('You do not have the correct permission to use this coupon.'); |
| 999 | return $result; |
| 1000 | } |
| 1001 | } |
| 1002 | } |
| 1003 | |
| 1004 | $result->valid = TRUE; |
| 1005 | $result->code = $code; |
| 1006 | $result->cid = $coupon->cid; |
| 1007 | $result->title = t('Coupon: @code', array('@code' => $code)); |
| 1008 | |
| 1009 | if ($coupon->type == 'percentage') { |
| 1010 | $result->amount = $applicable_total * $coupon->value / 100; |
| 1011 | } |
| 1012 | else if ($coupon->type == 'price') { |
| 1013 | $result->amount = min($applicable_total, $applicable_qty * $coupon->value); |
| 1014 | } |
| 1015 | |
| 1016 | return $result; |
| 1017 | } |
| 1018 | |
| 1019 | /** |
| 1020 | * Implementation of hook_cart_pane(). |
| 1021 | */ |
| 1022 | function uc_coupon_cart_pane($items) { |
| 1023 | $panes[] = array( |
| 1024 | 'id' => 'coupon', |
| 1025 | 'body' => drupal_get_form('uc_cart_pane_coupon'), |
| 1026 | 'title' => t('Coupon discount'), |
| 1027 | 'desc' => t('Allows shoppers to use a coupon during checkout for order discounts.'), |
| 1028 | 'weight' => 1, |
| 1029 | 'enabled' => TRUE, |
| 1030 | ); |
| 1031 | return $panes; |
| 1032 | } |
| 1033 | |
| 1034 | /** |
| 1035 | * Cart pane coupon form. |
| 1036 | */ |
| 1037 | function uc_cart_pane_coupon($form_state) { |
| 1038 | $form['code'] = |