| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306 | 
							- <?php
 
- /**
 
-  * @file
 
-  * Provides discount codes and gift certificates for Ubercart.
 
-  *
 
-  * Version: 2.x
 
-  * Drupal Core: 7.x
 
-  * Ubercart Core: 3.x
 
-  *
 
-  * Original code by Blake Lucchesi (www.boldsource.com)
 
-  *
 
-  * Maintained by
 
-  *   Chris Oden (wodenx@gmail.com)
 
-  *   David Long (dave@longwaveconsulting.com)
 
-  *
 
-  * Please submit issues, questions or feedback to the issue queue at
 
-  * http://drupal.org/project/uc_coupon
 
-  */
 
- /**
 
-  * Implements hook_menu().
 
-  */
 
- function uc_coupon_menu() {
 
-   $items = array();
 
-   $items['admin/store/coupons'] = array(
 
-     'title' => 'Coupons',
 
-     'description' => 'Manage store discount coupons.',
 
-     'page callback' => 'uc_coupon_display',
 
-     'page arguments' => array('active'),
 
-     'access arguments' => array('view store coupons'),
 
-     'type' => MENU_NORMAL_ITEM,
 
-     'file' => 'uc_coupon.admin.inc',
 
-   );
 
-   $items['admin/store/coupons/list'] = array(
 
-     'title' => 'Active coupons',
 
-     'description' => 'View active coupons.',
 
-     'page callback' => 'uc_coupon_display',
 
-     'page arguments' => array('active'),
 
-     'access arguments' => array('view store coupons'),
 
-     'type' => MENU_NORMAL_ITEM,
 
-     'file' => 'uc_coupon.admin.inc',
 
-     'weight' => 0,
 
-   );
 
-   $items['admin/store/coupons/inactive'] = array(
 
-     'title' => 'Inactive coupons',
 
-     'description' => 'View inactive coupons.',
 
-     'page callback' => 'uc_coupon_display',
 
-     'page arguments' => array('inactive'),
 
-     'access arguments' => array('view store coupons'),
 
-     'type' => MENU_NORMAL_ITEM,
 
-     'file' => 'uc_coupon.admin.inc',
 
-     'weight' => 1,
 
-   );
 
-   $items['admin/store/coupons/add'] = array(
 
-     'title' => 'Add new coupon',
 
-     'description' => 'Add a new coupon.',
 
-     'page callback' => 'drupal_get_form',
 
-     'page arguments' => array('uc_coupon_add_form'),
 
-     'access arguments' => array('manage store coupons'),
 
-     'type' => MENU_NORMAL_ITEM,
 
-     'file' => 'uc_coupon.admin.inc',
 
-     'weight' => 2,
 
-   );
 
-   $items['admin/store/coupons/%uc_coupon'] = array(
 
-     'title callback' => 'uc_coupon_title',
 
-     'title arguments' => array(3),
 
-     'description' => 'View coupon details.',
 
-     'page callback' => 'uc_coupon_view',
 
-     'page arguments' => array(3),
 
-     'access arguments' => array('view store coupons'),
 
-     'type' => MENU_CALLBACK,
 
-     'file' => 'uc_coupon.admin.inc',
 
-     'weight' => 3,
 
-   );
 
-   $items['admin/store/coupons/%uc_coupon/view'] = array(
 
-     'title' => 'View',
 
-     'description' => 'View coupon details.',
 
-     'access arguments' => array('view store coupons'),
 
-     'type' => MENU_DEFAULT_LOCAL_TASK,
 
-     'file' => 'uc_coupon.admin.inc',
 
-     'weight' => 0,
 
-   );
 
-   $items['admin/store/coupons/%uc_coupon/print'] = array(
 
-     'title' => 'Print',
 
-     'description' => 'Print coupon.',
 
-     'page callback' => 'uc_coupon_print',
 
-     'page arguments' => array(3, 5, 'print'),
 
-     'access arguments' => array('view store coupons'),
 
-     'type' => MENU_LOCAL_TASK,
 
-     'file' => 'uc_coupon.admin.inc',
 
-     'weight' => 1,
 
-   );
 
-   $items['admin/store/coupons/%uc_coupon/edit'] = array(
 
-     'title' => 'Edit',
 
-     'description' => 'Edit an existing coupon.',
 
-     'page callback' => 'drupal_get_form',
 
-     'page arguments' => array('uc_coupon_add_form', 3),
 
-     'access arguments' => array('manage store coupons'),
 
-     'type' => MENU_LOCAL_TASK,
 
-     'file' => 'uc_coupon.admin.inc',
 
-     'weight' => 2,
 
-   );
 
-   $items['admin/store/coupons/%uc_coupon/delete'] = array(
 
-     'title' => 'Delete',
 
-     'description' => 'Delete a coupon.',
 
-     'page callback' => 'drupal_get_form',
 
-     'page arguments' => array('uc_coupon_delete_confirm', 3),
 
-     'access arguments' => array('manage store coupons'),
 
-     'type' => MENU_LOCAL_TASK,
 
-     'file' => 'uc_coupon.admin.inc',
 
-     'weight' => 3,
 
-   );
 
-   $items['admin/store/coupons/%uc_coupon/codes'] = array(
 
-     'title' => 'Download bulk coupon codes',
 
-     'description' => 'Download the list of bulk coupon codes as a CSV file.',
 
-     'page callback' => 'uc_coupon_codes_csv',
 
-     'page arguments' => array(3),
 
-     'access arguments' => array('view store coupons'),
 
-     'file' => 'uc_coupon.admin.inc',
 
-     'type' => MENU_CALLBACK,
 
-   );
 
-   $items['admin/store/coupons/autocomplete/node'] = array(
 
-     'title' => 'Node autocomplete',
 
-     'page callback' => 'uc_coupon_autocomplete_node',
 
-     'access arguments' => array('manage store coupons'),
 
-     'type' => MENU_CALLBACK,
 
-     'file' => 'uc_coupon.admin.inc',
 
-   );
 
-   $items['admin/store/coupons/autocomplete/term'] = array(
 
-     'title' => 'Term autocomplete',
 
-     'page callback' => 'uc_coupon_autocomplete_term',
 
-     'access arguments' => array('manage store coupons'),
 
-     'type' => MENU_CALLBACK,
 
-     'file' => 'uc_coupon.admin.inc',
 
-   );
 
-   $items['admin/store/coupons/autocomplete/user'] = array(
 
-     'title' => 'User autocomplete',
 
-     'page callback' => 'uc_coupon_autocomplete_user',
 
-     'access arguments' => array('manage store coupons'),
 
-     'type' => MENU_CALLBACK,
 
-     'file' => 'uc_coupon.admin.inc',
 
-   );
 
-   $items['admin/store/coupons/autocomplete/role'] = array(
 
-     'title' => 'Role autocomplete',
 
-     'page callback' => 'uc_coupon_autocomplete_role',
 
-     'access arguments' => array('manage store coupons'),
 
-     'type' => MENU_CALLBACK,
 
-     'file' => 'uc_coupon.admin.inc',
 
-   );
 
-   $items['admin/store/settings/coupon'] = array(
 
-     'title' => 'Coupon module settings',
 
-     'description' => 'Configure the discount coupon module settings.',
 
-     'page callback' => 'drupal_get_form',
 
-     'page arguments' => array('uc_coupon_settings_form'),
 
-     'access arguments' => array('administer store'),
 
-     'file' => 'uc_coupon.admin.inc',
 
-     'type' => MENU_NORMAL_ITEM,
 
-   );
 
-   $items['admin/store/settings/coupon/settings'] = array(
 
-     'title' => 'Settings',
 
-     'description' => 'Edit the basic coupon settings.',
 
-     'type' => MENU_DEFAULT_LOCAL_TASK,
 
-     'weight' => -10,
 
-   );
 
-   $items['admin/store/reports/coupon'] = array(
 
-     'title' => 'Coupon usage reports',
 
-     'description' => 'View coupon usage reports.',
 
-     'page callback' => 'uc_coupon_reports',
 
-     'access arguments' => array('view reports'),
 
-     'file' => 'uc_coupon.reports.inc',
 
-     'type' => MENU_NORMAL_ITEM,
 
-   );
 
-   return $items;
 
- }
 
- /**
 
-  * Properly handle %uc_coupon wildcard.
 
-  * (Necessary to prevent PHP runtime notice.)
 
-  */
 
- function uc_coupon_to_arg($arg) {
 
-   return $arg;
 
- }
 
- /**
 
-  * Title callback for coupon print preview.
 
-  */
 
- function uc_coupon_title($coupon) {
 
-   return $coupon->name;
 
- }
 
- /**
 
-  * Implements hook_permission().
 
-  */
 
- function uc_coupon_permission() {
 
-   $perms = array(
 
-     'view store coupons' => array(
 
-       'title' => t('view store coupons'),
 
-       'description' => t('Display information about discount coupons.'),
 
-     ),
 
-     'manage store coupons' => array(
 
-       'title' => t('manage store coupons'),
 
-       'description' => t('Create, edit and delete discoutn coupons.'),
 
-     ),
 
-   );
 
-   if (!module_exists('uc_reports')) {
 
-     $perms['view reports'] = array(
 
-       'title' => t('view reports'),
 
-       'description' => t('Display coupon usage reports.')
 
-     );
 
-   }
 
-   return $perms;
 
- }
 
- /**
 
-  * Implements hook_init().
 
-  */
 
- function uc_coupon_init() {
 
-   global $conf;
 
-   $conf['i18n_variables'][] = 'uc_coupon_pane_description';
 
-   // Auto apply coupon from query string, if configured.
 
-   if ($param = variable_get('uc_coupon_querystring', '')) {
 
-     if (isset($_GET[$param]) && $_GET[$param]) {
 
-       // We retain the querystring coupon so that it will validate if/when appropriate conditions are met.
 
-       uc_coupon_session_add($_GET[$param], 'retain');
 
-     }
 
-   }
 
- }
 
- /**
 
-  * Implements hook_theme().
 
-  */
 
- function uc_coupon_theme() {
 
-   return array(
 
-     'uc_coupon_automatic_discounts' => array(
 
-       'render element' => 'form',
 
-     ),
 
-     'uc_coupon_form' => array(
 
-       'render element' => 'form',
 
-     ),
 
-     'uc_coupon_actions' => array(
 
-       'variables' => array('coupon' => NULL),
 
-       'file' => 'uc_coupon.admin.inc',
 
-     ),
 
-     'uc_coupon_code' => array(
 
-       'variables' => array('coupon' => NULL),
 
-       'file' => 'uc_coupon.admin.inc',
 
-     ),
 
-     'uc_coupon_discount' => array(
 
-       'variables' => array('coupon' => NULL, 'currency' => TRUE),
 
-     ),
 
-     'uc_coupon_certificate' => array(
 
-       'variables' => array('coupon' => NULL, 'code' => NULL),
 
-       'template' => 'uc-coupon-certificate',
 
-       'path' => drupal_get_path('module', 'uc_coupon') . '/theme',
 
-     ),
 
-     'uc_coupon_page' => array(
 
-       'variables' => array('content' => NULL),
 
-       'template' => 'uc-coupon-page',
 
-       'path' => drupal_get_path('module', 'uc_coupon') . '/theme',
 
-     ),
 
-   );
 
- }
 
- /**
 
-  * Implements hook_theme_registry_alter().
 
-  */
 
- function uc_coupon_theme_registry_alter(&$registry) {
 
-   // Override the default theme for the cart block content - but only if not already overridden.
 
-   if ($registry['uc_cart_block_content']['function'] == 'theme_uc_cart_block_content') {
 
-     $registry['uc_cart_block_content']['function'] = 'uc_coupon_theme_uc_cart_block_content';
 
-   }
 
- }
 
- /**
 
-  * Count usage of a coupon.
 
-  *
 
-  * @param $cid
 
-  *   The coupon id to count.
 
-  * @param $uid
 
-  *   (optional) The user id to count. Defaults to the current user.
 
-  * @param array $exclude_oids
 
-  *   (optional) If supplied, will exclude usage for the specified order ids.
 
-  *
 
-  * @return
 
-  *   An associative array containing:
 
-  *   - codes: An associative array of code => usage count.
 
-  *   - user: The usage count by the specified (or current) user.
 
-  */
 
- function uc_coupon_count_usage($cid, $uid = NULL, $exclude_oids = array()) {
 
-   global $user;
 
-   $weight = uc_order_status_data(variable_get('uc_coupon_used_order_status', 'processing'), 'weight');
 
-   $usage = array('codes' => array(), 'value' => array('codes' => array()));
 
-   $exclude_where = empty($exclude_oids) ? '' : 'AND uo.order_id NOT IN (:oids)';
 
-   $result = db_query("SELECT uco.code, COUNT(*) AS uses, SUM(uco.value) AS value 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 >= :weight AND uco.cid = :cid $exclude_where GROUP BY uco.code",
 
-     array( ':weight' => $weight, ':cid' => $cid, ':oids' => $exclude_oids));
 
-   foreach ($result as $row) {
 
-     $usage['codes'][$row->code] = $row->uses;
 
-     $usage['value']['codes'][$row->code] = $row->value;
 
-   }
 
-   if (is_null($uid)) {
 
-     $uid = $user->uid;
 
-   }
 
-   $usage['user'] = 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 >= :weight AND uco.cid = :cid AND uo.uid = :uid",
 
-     array( ':weight' => $weight, ':cid' => $cid, ':uid' => $uid))->fetchField();
 
-   // Allow other modules to implement usage counts.
 
-   drupal_alter('uc_coupon_usage', $usage, $cid, $uid);
 
-   return $usage;
 
- }
 
- /**
 
-  * Theme for a coupon discount.
 
-  * @param $variables
 
-  *   'coupon' => The coupon whose discount is to be themed.
 
-  *   'currency' => TRUE to include currency symbols.
 
-  */
 
- function theme_uc_coupon_discount($variables) {
 
-   $coupon = $variables['coupon'];
 
-   $currency = isset($variables['currency']) ? $variables['currency'] : TRUE;
 
-   return _uc_coupon_format_discount($coupon, $currency);
 
- }
 
- /**
 
-  * Format a coupon's value depending on the type, optionally including currency symbols.
 
-  */
 
- function _uc_coupon_format_discount($coupon, $currency = TRUE) {
 
-   switch ($coupon->type) {
 
-     case 'price':
 
-     case 'credit':
 
-       return $currency ? uc_currency_format($coupon->value) : $coupon->value;
 
-     case 'percentage':
 
-       return (float) $coupon->value . '%';
 
-     case 'set_price':
 
-       return '=' . ($currency ? uc_currency_format($coupon->value) : $coupon->value);
 
-   }
 
- }
 
- /**
 
-  * Generate a single bulk coupon code.
 
-  */
 
- function uc_coupon_get_bulk_code($coupon, $id) {
 
-   // If this coupon has been validated, then $coupon->code is already a bulk code.
 
-   if (isset($coupon->valid)) {
 
-     $prefix = drupal_substr($coupon->code, 0, strlen($coupon->code) - $coupon->data['bulk_length']);
 
-   }
 
-   else {
 
-     $prefix = $coupon->code;
 
-   }
 
-   $id = str_pad(dechex($id), strlen(dechex($coupon->data['bulk_number'])), '0', STR_PAD_LEFT);
 
-   $length = strlen($prefix) + $coupon->data['bulk_length'];
 
-   return strtoupper(substr($prefix . $id . md5($coupon->bulk_seed . $id), 0, $length));
 
- }
 
- /**
 
-  * Load a coupon (single or bulk) from the supplied code.
 
-  * @param $code
 
-  *     The coupon code to search for.
 
-  * @param $reset
 
-  *    If TRUE the cache of codes for this request will be purged.  Any function which modifies
 
-  *    a coupon should purge the cache.
 
-  */
 
- function uc_coupon_find($code, $reset = FALSE) {
 
-   // This is expensive and can be called many times during coupon processing, so we
 
-   // use a simple static cache.
 
-   static $cached = array();
 
-   if ($reset) {
 
-     $cached = array();
 
-   }
 
-   if (!$code) {
 
-     return FALSE;
 
-   }
 
-   elseif (array_key_exists($code, $cached)) {
 
-     return $cached[$code];
 
-   }
 
-   // Look for matching single coupon first.
 
-   $coupon = db_query("SELECT cid FROM {uc_coupons}
 
-     WHERE code = :code AND status = 1 AND bulk = 0 AND valid_from < :now AND (valid_until = 0 OR valid_until > :now)",
 
-     array(':code' => $code, ':now' => REQUEST_TIME))
 
-     ->fetchObject();
 
-   if ($coupon) {
 
-     $cached[$code] = uc_coupon_load($coupon->cid);
 
-     return $cached[$code];
 
-   }
 
-   // Look through bulk coupons.
 
-   $result = db_query("SELECT cid, code, data, bulk_seed FROM {uc_coupons}
 
-     WHERE status = 1 AND bulk = 1 AND valid_from < :now AND (valid_until = 0 OR valid_until > :now)",
 
-     array(':now' => REQUEST_TIME));
 
-   foreach ($result as $coupon) {
 
-     // Check coupon prefix.
 
-     $prefix_length = strlen($coupon->code);
 
-     if (substr($code, 0, $prefix_length) != $coupon->code) {
 
-       continue;
 
-     }
 
-     if ($coupon->data) {
 
-       $coupon->data = unserialize($coupon->data);
 
-     }
 
-     // Check coupon sequence ID.
 
-     $id = substr($code, $prefix_length, strlen(dechex($coupon->data['bulk_number'])));
 
-     if (!preg_match("/^[0-9A-F]+$/", $id)) {
 
-       continue;
 
-     }
 
-     $id = hexdec($id);
 
-     if ($id < 0 || $id > $coupon->data['bulk_number']) {
 
-       continue;
 
-     }
 
-     // Check complete coupon code.
 
-     if ($code == uc_coupon_get_bulk_code($coupon, $id)) {
 
-       $cached[$code] = uc_coupon_load($coupon->cid);
 
-       return $cached[$code];
 
-     }
 
-   }
 
-   $cached[$code] = FALSE;
 
-   return $cached[$code];
 
- }
 
- /**
 
-  * Adds or updates a coupon code for the current session.
 
-  *
 
-  * @param $code
 
-  *     The code to add or update.
 
-  * @param $op
 
-  *     Specifies the way the code should be handled the next time session codes are validated.
 
-  *     - 'submit' - If the code fails validation it is removed from the session; otherwise it is retained.
 
-  *       A success or failure message is displayed.  This is the default operation performed when
 
-  *       a customer enters a coupon code manually.
 
-  *     - 'retain' - The code remains in the session whether or not it passes validation.  A success
 
-  *       message is displayed the first time the coupon passes. This is useful for
 
-  *       codes which are added automatically in response to events occurring before any products
 
-  *       have been added to the cart (e.g. via the querystring).
 
-  *     - 'auto' - The code is removed from the session whether or not it passes validation.  However, if
 
-  *       it does validate, the corresponding coupon will be considered valid for the current request only.
 
-  *       This is useful for modules implementing hook_uc_coupon_revalidate(), which can decide whether or not
 
-  *       to add their codes each time the valid coupon cache is rebuilt (e.g. automatic discounts based on
 
-  *       additional conditions).
 
-  */
 
- function uc_coupon_session_add($code, $op = 'submit') {
 
-   if (!variable_get('uc_coupon_allow_multiple', FALSE)) {
 
-     $_SESSION['uc_coupons'] = array($code => $op);
 
-   }
 
-   else {
 
-     $_SESSION['uc_coupons'][$code] = $op;
 
-   }
 
- }
 
- /**
 
-  * Removes one (or all) coupon codes from the session.
 
-  *
 
-  * @param $code
 
-  *		The code to remove, or NULL to remove all codes.
 
-  * @param $is_update
 
-  * 		TRUE (the default) if removing this code represents an update of the session; that is, if the code
 
-  *		was previously validated. FALSE otherwise (e.g. for removal of automatic discounts).  Ignored if
 
-  *		a specific code is not specified.		
 
-  */
 
- function uc_coupon_session_clear($code = NULL) {
 
-   if (isset($code)) {
 
-     unset($_SESSION['uc_coupons'][$code]);
 
-   }
 
-   else {
 
-     unset($_SESSION['uc_coupons']);
 
-   }
 
- }
 
- /**
 
-  * Checks to see if a given code is present in the session, or returns an associative array
 
-  * of all codes in the session.
 
-  *
 
-  * @param $code
 
-  *     (optional) The code to chec for.  If not specified, will return all codes.
 
-  *
 
-  * @return
 
-  *     If a code is specified, returns TRUE if that code exists in the session, FALSE otherwise.  If no
 
-  *     code is specified, returns an array of the form $code=>$op for all codes in the session.
 
-  */
 
- function uc_coupon_session_get($code = NULL) {
 
-   if (isset($code)) {
 
-     return isset($_SESSION['uc_coupons'][$code]);
 
-   }
 
-   elseif (isset($_SESSION['uc_coupons'])) {
 
-     return $_SESSION['uc_coupons'];
 
-   }
 
-   else {
 
-     return array();
 
-   }
 
- }
 
- /**
 
-  * Validates all coupons in the current session.  The validated coupons are statically
 
-  * cached for each request.  The cache is rebuilt the first time this function is called,
 
-  * or every time the cart contents are rebuilt.
 
-  *
 
-  * @param $order
 
-  *   An order against which to validate the currently applied codes. If specified
 
-  *   the cached list of valid coupons is rebuilt by revalidating all the codes in
 
-  *   the session against that order.
 
-  *
 
-  * @return
 
-  *     An array of fully validated coupon objects, indexed by code.
 
-  */
 
- function uc_coupon_session_validate($order = NULL) {
 
-   static $valids = NULL;
 
-   // If a list of products is specified, then rebuild the list.
 
-   if (isset($order)) {
 
-     $valids = array();
 
-     $order = clone $order; // We don't want to modify the order passed in.
 
-     // Allow modules an opportunity to add or remove coupons from the session.
 
-     module_invoke_all('uc_coupon_revalidate', $order);
 
-     // Fetch all codes in the session.
 
-     $session = uc_coupon_session_get();
 
-     if (!empty($session)) {
 
-       // Process all coupons in the session.
 
-       global $user;
 
-       $order->data['coupons'] = array();
 
-       foreach ($session as $code => $op) {
 
-         $coupon = uc_coupon_validate($code, $order, $user);
 
-         if ($coupon->valid) { // Process valid coupons.
 
-           $valids[$code] = $coupon;
 
-           $order->data['coupons'][$code] = $coupon->discounts;
 
-           switch ($op) {
 
-             case 'submit':
 
-             case 'retain':
 
-               // For coupons which were not valid (new submissions) we notify user and modules.
 
-               drupal_set_message($coupon->message);
 
-               module_invoke_all('uc_coupon_apply', $coupon);
 
-               // And we mark them for revalidation.
 
-               uc_coupon_session_add($code, 'revalidate');
 
-               break;
 
-             case 'auto':
 
-               // Automatic coupons are never added to the session.
 
-               uc_coupon_session_clear($code);
 
-               break;
 
-           }
 
-         }
 
-         else { // Process invalid coupons.
 
-           switch ($op) {
 
-             case 'submit':
 
-               // For new coupon submissions, just issue an error and remove from session.
 
-               drupal_set_message($coupon->message, 'error');
 
-               uc_coupon_session_clear($code);
 
-               break;
 
-             case 'revalidate':
 
-               if (!empty($products)) { // Only issue a message if the cart is not empty.
 
-                 drupal_set_message(t('%title is no longer applicable to your order', array('%title' => $coupon->title)));
 
-               }
 
-               module_invoke_all('uc_coupon_remove', $coupon);
 
-               // Keep code in the session in case it becomes valid again.
 
-               uc_coupon_session_add($code, 'retain');
 
-               break;
 
-             case 'auto':
 
-               // Automatic coupons are never added to the session.
 
-               uc_coupon_session_clear($code);
 
-               break;
 
-           }
 
-         }
 
-       }
 
-     }
 
-   }
 
-   // If no argument specified and the cache has not been built, we rebuild the cart to force validation.
 
-   elseif (!isset($valids)) {
 
-     uc_cart_get_contents();
 
-   }
 
-   return $valids;
 
- }
 
- /**
 
-  * Validates a list of coupon codes against a specified order and account.
 
-  *
 
-  * @param $codes
 
-  *   The codes to be validated.
 
-  * @param $order
 
-  *   The order that the coupon is being applied to.
 
-  *   If NULL, the current cart contents will be used.
 
-  *   If FALSE, product and order validation will be bypassed.
 
-  * @param $account
 
-  *   The user who is attempting to use the coupon.
 
-  *   If NULL, the current user will be assumed.
 
-  *   If FALSE, user validation will be bypassed.
 
-  *
 
-  * @see uc_coupon_validate()
 
-  * @see uc_coupon_session_validate()
 
-  */
 
- function uc_coupon_validate_multiple($codes, $order, $account) {
 
-   $order = clone $order; // We don't want to modify the order passed in.
 
-   $order->data['coupons'] = array();
 
-   $valids = array();
 
-   $invalids = array();
 
-   foreach ($codes as $code) {
 
-     $coupon = uc_coupon_validate($code, $order, $account);
 
-     if ($coupon->valid) { // Process valid coupons.
 
-       $valids[$code] = $coupon;
 
-       $order->data['coupons'][$code] = $coupon->discounts;
 
-     }
 
-     else {
 
-       $invalids[$code] = $code;
 
-     }
 
-   }
 
-   return array('valid' => $valids, 'invalid' => $invalids);
 
- }
 
- /**
 
-  * Validate a coupon, and optionally calculate the order discount.
 
-  *
 
-  * @param $code
 
-  *   The coupon code entered at the checkout screen.
 
-  * @param $order
 
-  *   The order that the coupon is being applied to.
 
-  *   If NULL, the current cart contents will be used.
 
-  *   If FALSE, product and order validation will be bypassed.
 
-  * @param $account
 
-  *   The user who is attempting to use the coupon.
 
-  *   If NULL, the current user will be assumed.
 
-  *   If FALSE, user validation will be bypassed.
 
-  *
 
-  * @return
 
-  *   A coupon object with extended information about the validation:
 
-  *   - $coupon->valid: TRUE if the code was valid, FALSE otherwise.
 
-  *   - $coupon->code: The specific code to be applied (even for bulk coupons).
 
-  *   - $coupon->title: The line item title for the discount.
 
-  *   - $coupon->message: A message to be displayed accepting the acceptance or rejection of this coupon.
 
-  *   - $coupon->amount: If $order !== FALSE, the discount that should be applied.
 
-  *   - $coupon->discounts: if $order !== FALSE, an array discounts on individual products indexed by nid,
 
-  *      containing the following fields:
 
-  *       -> 'discount' = The full value of the discount on that item.
 
-  *       -> 'pretax_discount' => The actual pre-tax discount. For fixed discounts to products with
 
-  *          taxes included, we apply the face value of the coupon tax-inclusively also; that is,
 
-  *          the actual discount is calculated so that the face value is correct after taxes.
 
-  */
 
- function uc_coupon_validate($code, $order = NULL, $account = NULL) {
 
-   global $user;
 
-   if (is_null($order)) {
 
-     $order = new stdClass();
 
-     $order->products = uc_cart_get_contents();
 
-   }
 
-   if (is_null($account)) {
 
-     $account = $user;
 
-   }
 
-   // Look for an active coupon matching the code.
 
-   $code = trim(strtoupper($code));
 
-   $coupon = uc_coupon_find($code);
 
-   if (!$coupon) {
 
-     $coupon = new stdClass();
 
-     $coupon->valid = FALSE;
 
-     $coupon->message = t('This coupon code is invalid or has expired.');
 
-     $coupon->title = t('Unknown');
 
-     return $coupon;
 
-   }
 
-   // Count usage for this coupon.
 
-   $uid = !empty($account) ? $account->uid : NULL;
 
-   // If the order exists, don't count it towards coupon usage.
 
-   $oids = !empty($order->order_id) ? array($order->order_id) : array();
 
-   $coupon->usage = uc_coupon_count_usage($coupon->cid, $uid, $oids);
 
-   // Calculate the discounts (if any).
 
-   uc_coupon_prepare($coupon, $code, uc_coupon_calculate_discounts($coupon, $order));
 
-   // Invoke validation hook.
 
-   foreach (module_implements('uc_coupon_validate') as $module) {
 
-     $callback = $module . '_uc_coupon_validate';
 
-     $result = $callback($coupon, $order, $account);
 
-     if ($result === TRUE) {
 
-       // This module wishes the coupon to be accepted.
 
-       $coupon->valid = TRUE;
 
-     }
 
-     elseif (!is_null($result)) {
 
-       // This module wishes the coupon to be rejected.
 
-       $coupon->valid = FALSE;
 
-       $coupon->message = $result;
 
-     }
 
-   }
 
-   // Create a success message.
 
-   if ($coupon->valid && !isset($coupon->message)) {
 
-     if (isset($coupon->data['apply_message'])) {
 
-       $coupon->message = token_replace(check_plain($coupon->data['apply_message']), array('uc_coupon' => $coupon));
 
-     }
 
-     else {
 
-       $amount = theme('uc_price', array('price' => $coupon->amount));
 
-       if (isset($order) || variable_get('uc_coupon_show_in_cart', TRUE)) {
 
-         $coupon->message = t('A discount of !amount has been applied to your order.', array('!amount' => $amount));
 
-       }
 
-       else {
 
-         $coupon->message = t('A discount of !amount will be applied at checkout.', array('!amount' => $amount));
 
-       }
 
-     }
 
-   }
 
-   return $coupon;
 
- }
 
- /**
 
-  * Prepares a coupon for validation and application to an order.
 
-  *
 
-  * @param $coupon
 
-  *   A raw coupon object.
 
-  * @param $discounts
 
-  *   An associative array of the discounts to be applied, keyed by nid or -lid. Or a string
 
-  *   containing a message indicating why there are no discounts available.
 
-  *
 
-  * @return
 
-  *   A fully validated coupon object with all additional properties set.  This is returned
 
-  *   for convenience, as the $coupon provided is passed by reference and modified directly.
 
-  *
 
-  * @see uc_coupon_validate().
 
-  */
 
- function uc_coupon_prepare($coupon, $code, $discounts) {
 
-   $coupon->code = $code;
 
-   $coupon->valid = TRUE;
 
-   $coupon->amount = 0;
 
-   $coupon->pretax_amount = 0;
 
-   if (!is_array($discounts)) {
 
-     $coupon->discounts = array();
 
-     $coupon->message = $discounts;
 
-   }
 
-   else {
 
-     $coupon->discounts = $discounts;
 
-     foreach ($coupon->discounts as $item) {
 
-       $coupon->amount += $item->discount;
 
-       $coupon->pretax_amount += isset($item->pretax_discount) ? $item->pretax_discount : $item->discount;
 
-     }
 
-     $coupon->amount = round($coupon->amount, variable_get('uc_currency_prec', 2));
 
-     unset($coupon->message);
 
-   }
 
-   // Create the line item title for this coupon.
 
-   $format = !empty($coupon->data['line_item_format']) ? $coupon->data['line_item_format'] :
 
-      variable_get('uc_coupon_line_item_format', t('Coupon !code', array('!code' => '[uc_coupon:code]')));
 
-   $coupon->title = token_replace(check_plain($format), array('uc_coupon' => $coupon));
 
-   return $coupon;
 
- }
 
- /**
 
-  * Implements hook_uc_coupon_validate().
 
-  *
 
-  * We implement our own hook to allow other modules a chance to run before us.
 
-  *
 
-  * @param $coupon
 
-  *   The coupon object to validate, with special fields set as follows:
 
-  *   - $coupon->code: The specific code to be applied (even for bulk coupons).
 
-  *   - $coupon->amount: If $order !== FALSE, the discount that should be applied.
 
-  *   - $coupon->usage: Coupon usage data from uc_coupon_count_usage().
 
-  * @param $order
 
-  *   The order against which this coupon is to be applied, or FALSE to bypass
 
-  *   order validation.
 
-  * @param $account
 
-  *   The account of the user trying to use the coupon, or FALSE to bypass user
 
-  *   validation.
 
-  *
 
-  * @return
 
-  *   TRUE if the coupon should be accepted.
 
-  *   NULL to allow other modules to determine validation.
 
-  *   Otherwise, a string describing the reason for failure.
 
-  */
 
- function uc_coupon_uc_coupon_validate(&$coupon, $order, $account) {
 
-   // Coupons which produce no discount are not valid unless they are store credit
 
-   // type, or have no face value (e.g. free shipping).
 
-   if ($coupon->type !== 'credit' && $coupon->value != 0 && $coupon->amount == 0) {
 
-     $coupon->valid = FALSE;
 
-     return !empty($coupon->message) ? $coupon->message : t('This coupon is not applicable to your order.');
 
-   }
 
-   // Check for allowed combinations.
 
-   if (!empty($order->data['coupons'])) {
 
-     foreach (array_keys($order->data['coupons']) as $code) {
 
-       $other = uc_coupon_find($code);
 
-       $other_listed = !empty($coupon->data['combinations']) && in_array($other->cid, $coupon->data['combinations']);
 
-       $this_ok = (isset($coupon->data['negate_combinations']) xor $other_listed);
 
-       $this_listed = !empty($other->data['combinations']) && in_array($coupon->cid, $other->data['combinations']);
 
-       $other_ok = (isset($other->data['negate_combinations']) xor $this_listed);
 
-       if (!$this_ok || !$other_ok) {
 
-         return t('This coupon combination is not allowed.');
 
-       }
 
-     }
 
-   }
 
-   if ($coupon->type !== 'credit') {
 
-     // Check maximum usage per code.
 
-     if ($coupon->max_uses > 0 && !empty($coupon->usage['codes'][$coupon->code]) && $coupon->usage['codes'][$coupon->code] >= $coupon->max_uses) {
 
-       return t('This coupon has reached the maximum redemption limit.');
 
-     }
 
-     // Check maximum usage per user.
 
-     if ($account && isset($coupon->data['max_uses_per_user']) && $coupon->usage['user'] >= $coupon->data['max_uses_per_user']) {
 
-       return t('This coupon has reached the maximum redemption limit.');
 
-     }
 
-   }
 
-   else {
 
-     if (!empty($coupon->usage['value']['codes'][$coupon->code]) && $coupon->usage['value']['codes'][$coupon->code] >= $coupon->value) {
 
-       return t('This coupon has reached the maximum redemption limit.');
 
-     }
 
-   }
 
-   // Check user ID.
 
-   if ($account && isset($coupon->data['users'])) {
 
-     if (in_array("$account->uid", $coupon->data['users'], TRUE) xor !isset($coupon->data['negate_users'])) {
 
-       return t('Your user ID is not allowed to use this coupon.');
 
-     }
 
-   }
 
-   // Check roles.
 
-   if ($account && isset($coupon->data['roles'])) {
 
-     $role_found = FALSE;
 
-     foreach ($coupon->data['roles'] as $role) {
 
-       if (in_array($role, $account->roles)) {
 
-         $role_found = TRUE;
 
-         break;
 
-       }
 
-     }
 
-     if ($role_found xor !isset($coupon->data['negate_roles'])) {
 
-       return t('You do not have the correct permission to use this coupon.');
 
-     }
 
-   }
 
- }
 
- /**
 
-  * Find items that a coupon will apply to and calculate the discounts.
 
-  *
 
-  * @param $coupon
 
-  *   A coupon object to apply, or a coupon code as a string.
 
-  * @param $order
 
-  *   The order object to which the coupon should be applied.
 
-  *
 
-  * @return
 
-  *   An array of discounts.
 
-  */
 
- function uc_coupon_calculate_discounts($coupon, $order) {
 
-   // Can only calculate discounts if an order is provided.
 
-   if (empty($order)) {
 
-     return array();
 
-   }
 
-   if (!is_object($coupon)) {
 
-     // If argument is a code, load the corresponding coupon.
 
-     $coupon = uc_coupon_find($coupon);
 
-   }
 
-   // Discover if any items match the restrictions, and which items the discount should be calculated against.
 
-   $restricted = isset($coupon->data['products']) || isset($coupon->data['skus']) || isset($coupon->data['terms']) || isset($coupon->data['product_types']);
 
-   $matched = 0;
 
-   $matched_price = 0;
 
-   $total_qty = 0;
 
-   $total_price = 0;
 
-   $items = array();
 
-   foreach ($order->products as $item) {
 
-     if (isset($item->module) && $item->module == 'uc_coupon') {
 
-       continue;
 
-     }
 
-     $node = node_load($item->nid);
 
-     $qty = $item->qty;
 
-     if (!$restricted) {
 
-       // Coupons with no restrictions apply to all products.
 
-       $include = TRUE;
 
-     }
 
-     else {
 
-       // Other coupons only apply to matching products.
 
-       $include = FALSE;
 
-       $terms = _uc_coupon_list_terms($node);
 
-       if (isset($coupon->data['products']) && isset($item->data['kit_id'])) {
 
-         // Items that are part of product kits must be included or excluded all together, so we pre-empt other restrictions.
 
-         $include = (isset($coupon->data['negate_products']) xor in_array($item->data['kit_id'], $coupon->data['products']));
 
-       }
 
-       else if (isset($coupon->data['products']) && (isset($coupon->data['negate_products']) xor in_array($item->nid, $coupon->data['products']))) {
 
-         $include = TRUE;
 
-       }
 
-       elseif (isset($coupon->data['products']) && isset($coupon->data['negate_products']) && in_array($item->nid, $coupon->data['products'])) {
 
-         // always exclude if in list of negated products
 
-       }
 
-       elseif (isset($coupon->data['terms']) && (isset($coupon->data['negate_terms']) xor count(array_intersect($terms, $coupon->data['terms'])))) {
 
-         $include = TRUE;
 
-       }
 
-       elseif (isset($coupon->data['terms']) && isset($coupon->data['negate_terms']) && count(array_intersect($terms, $coupon->data['terms']))) {
 
-         // always exclude if one of the terms is in the list of negated terms
 
-       }
 
-       elseif (isset($coupon->data['skus']) && _uc_coupon_match_sku($item->model, $coupon->data['skus'])) {
 
-         $include = TRUE;
 
-       }
 
-       elseif (isset($coupon->data['product_types']) && in_array($node->type, $coupon->data['product_types'])) {
 
-         $include = TRUE;
 
-       }
 
-     }
 
-     // A matching product was found.
 
-     if ($include) {
 
-       $matched += $qty;
 
-       $matched_price += $item->price * $qty;
 
-     }
 
-     $total_qty += $qty;
 
-     $total_price += $item->price * $qty;
 
-     // Include this item. Coupons that apply to the order subtotal affect all products.
 
-     if ($include || $coupon->data['apply_to'] == 'subtotal') {
 
-       $clone = clone $item;
 
-       $clone->type = $node->type;
 
-       $items = array_pad($items, count($items) + $qty, $clone);
 
-     }
 
-   }
 
-   // If no matches were found, there are no discounts to calculate.
 
-   if ($matched == 0) {
 
-     return t('You do not have any applicable products in your cart.');
 
-   }
 
-   $use_matched = (isset($coupon->data['minimum_qty_restrict']) && $coupon->data['minimum_qty_restrict'] != FALSE);
 
-   // Make sure the minimum quantity restriction (if any) is met.
 
-   if (isset($coupon->data['minimum_qty'])) {
 
-     if (($use_matched ? $matched : $total_qty) < (int)$coupon->data['minimum_qty']) {
 
-        return t('You do not have enough applicable products in your cart.');
 
-     }
 
-   }
 
-   // Make sure the minimum order total restriction (if any) is met.
 
-   if ($coupon->minimum_order > 0) {
 
-     if (($use_matched ? $matched_price : $total_price) < $coupon->minimum_order) {
 
-       return $use_matched ?
 
-         t('You have not reached the minimum total of applicable products for this coupon.') :
 
-         t('You have not reached the minimum order total for this coupon.');
 
-     }
 
-   }
 
-   // Ensure that all products match, if specified.
 
-   if (isset($coupon->data['require_match_all']) && $matched < $total_qty) {
 
-     return t('You have non-applicable products in your cart');
 
-   }
 
-   // Slice off applicable products if a limit was set.
 
-   switch ($coupon->data['apply_to']) {
 
-     case 'cheapest':
 
-       usort($items, '_uc_coupon_sort_products');
 
-       $items = array_slice($items, 0, $coupon->data['apply_count']);
 
-       break;
 
-     case 'expensive':
 
-       usort($items, '_uc_coupon_sort_products');
 
-       $items = array_slice($items, -$coupon->data['apply_count']);
 
-       break;
 
-   }
 
-   // Build the discounts array and get the order total.
 
-   $total = 0;
 
-   $discounts = array();
 
-   $included_rates = array();
 
-   foreach ($items as $item) {
 
-     if (!isset($discounts[$item->nid])) { // First entry for this product.
 
-       // Calculate the pre-tax discount proportion for this item.
 
-       // For fixed discounts to products with taxes included, we apply the face value of the coupon
 
-       // tax-inclusively also; that is, the actual discount is reduced so that the face value is
 
-       // realized after taxes. (This already happens automatically for percentage based coupons).
 
-       $included_rate = 1;
 
-       if (module_exists('uc_taxes')) {
 
-         foreach (uc_taxes_rate_load() as $tax) {
 
-           if ($tax->display_include
 
-               && is_array($tax->taxed_line_items) && in_array('coupon', $tax->taxed_line_items)
 
-               && in_array($item->type, $tax->taxed_product_types)
 
-               && ($tax->shippable == 0 || $item->data['shippable'] == 1)) {
 
-             $included_rate += $tax->rate;
 
-           }
 
-         }
 
-       }
 
-       // Adjust the price for any stacked coupons.
 
-       $prior_discount = 0;
 
-       if (!empty($order->data['coupons'])) {
 
-         foreach ($order->data['coupons'] as $stacked) {
 
-           if (isset($stacked[$item->nid])) {
 
-             $prior_discount += $stacked[$item->nid]->pretax_discount;
 
-           }
 
-         }
 
-       }
 
-       $total -= $prior_discount * $included_rate;
 
-       $discounts[$item->nid] = (object) array(
 
-         'qty' => 1,
 
-         'price' => $item->price - $prior_discount,
 
-       );
 
-       $included_rates[$item->nid] = $included_rate;
 
-       unset($item->type);
 
-     }
 
-     else { // An entry for this product already exists.
 
-       // Add this item to the total for the product.
 
-       $discounts[$item->nid]->price += $item->price;
 
-       $discounts[$item->nid]->qty++;
 
-     }
 
-     $total += $item->price * $included_rate;
 
-   }
 
-   // Add in discounts for any included line items.
 
-   $items = uc_order_load_line_items($order);
 
-   if (!empty($order->line_items) && !empty($coupon->data['line_items'])) {
 
-     foreach ($order->line_items as $line_item) {
 
-       if (in_array($line_item['type'], $coupon->data['line_items'])) {
 
-         // Use a negative id to distinguish this from a product discount.
 
-         $lid = $line_item['line_item_id'];
 
-         $lid = is_numeric($lid) ? -$lid : $lid;
 
-         // No tax-inclusive line items in ubercart (yet).
 
-         $included_rate = 1;
 
-         // Adjust the price for any stacked coupons.
 
-         $prior_discount = 0;
 
-         if (!empty($order->data['coupons'])) {
 
-           foreach ($order->data['coupons'] as $stacked) {
 
-             if (isset($stacked[$lid])) {
 
-               $prior_discount += $stacked[$lid]->pretax_discount;
 
-             }
 
-           }
 
-         }
 
-         $discounts[$lid] = (object) array(
 
-           'qty' => 1,
 
-           'price' => $line_item['amount'] - $prior_discount,
 
-         );
 
-         $included_rates[$lid] = $included_rate;
 
-         $total += $discounts[$lid]->price * $included_rate;
 
-       }
 
-     }
 
-   }
 
-   // Calculate the discounts per item.
 
-   $value = $coupon->value;
 
-   if ($coupon->type === 'credit' && !empty($coupon->usage['value']['codes'][$coupon->code])) {
 
-     $value -= $coupon->usage['value']['codes'][$coupon->code];
 
-   }
 
-   foreach ($discounts as $id => $discount) {
 
-     $inclusive_price = $discount->price * $included_rates[$id];
 
-     switch ($coupon->type) {
 
-       case 'percentage':
 
-         $discount->discount = $inclusive_price * $coupon->value / 100;
 
-         break;
 
-       case 'set_price':
 
-         $discount->discount = max($inclusive_price - ($coupon->value * $discount->qty), 0);
 
-         break;
 
-       default:
 
-         if ($coupon->type === 'credit' || $coupon->data['apply_to'] == 'subtotal' || $coupon->data['apply_to'] == 'products_total') {
 
-           // Apply single discount proportionally across all matching items.
 
-           $discount->discount = $total == 0 ? 0 : min($value * ($inclusive_price / $total), $inclusive_price);
 
-         }
 
-         else {
 
-           // Apply full discount value to each matching item.
 
-           $discount->discount = min($value * $discount->qty, $inclusive_price);
 
-         }
 
-     }
 
-     $discount->pretax_discount = $discount->discount / $included_rates[$id];
 
-     unset($discount->price);
 
-     unset($discount->qty);
 
-   }
 
-   return $discounts;
 
- }
 
- function _uc_coupon_match_sku($model, $skus) {
 
-   foreach ($skus as $match) {
 
-     if (preg_match('/^' . str_replace('\*', '.*?', preg_quote($match, '/')) . '$/', $model)) {
 
-       return TRUE;
 
-     }
 
-   }
 
-   return FALSE;
 
- }
 
- function _uc_coupon_sort_products($a, $b) {
 
-   if ($a->price == $b->price) {
 
-     return 0;
 
-   }
 
-   return $a->price > $b->price ? 1 : -1;
 
- }
 
- /**
 
-  * Lists all taxonomy terms contained in 'taxonomy_term_reference' fields for a given node.
 
-  * @param $node
 
-  *   The node whose terms should be listed;
 
-  * @return
 
-  *   An array of any taxonomy term id's.
 
-  */
 
- function _uc_coupon_list_terms($node) {
 
-   $terms = array();
 
-   foreach(array_keys(field_info_instances('node', $node->type)) as $field_name) {
 
-     $field_info = field_info_field($field_name);
 
-     if ($field_info['type'] == 'taxonomy_term_reference') {
 
-       if ($field_values = field_get_items('node', $node, $field_name)) {
 
-         foreach ($field_values as $field_value) {
 
-           $terms[] = $field_value['tid'];
 
-         }
 
-       }
 
-     }
 
-   }
 
-   return $terms;
 
- }
 
- /**
 
-  * Implements hook_block_info().
 
-  */
 
- function uc_coupon_block_info() {
 
-   $blocks = array();
 
-   $blocks['coupon-discount'] = array(
 
-     'info' => t('Coupon discount form'),
 
-   );
 
-   return $blocks;
 
- }
 
- /**
 
-  * Implements hook_block_view().
 
-  */
 
- function uc_coupon_block_view($delta) {
 
-   if ($delta == 'coupon-discount') {
 
-     $block = array(
 
-       'subject' => t('Coupon discount'),
 
-       'content' => drupal_get_form('uc_coupon_form', 'block'),
 
-     );
 
-     return $block;
 
-   }
 
- }
 
- /**
 
-  * Default theme implementation for the coupon submit form.
 
-  */
 
- function theme_uc_coupon_form($variables) {
 
-   $form = $variables['form'];
 
-   $output = '';
 
-   if ($form['#uc_coupon_form_context'] == 'cart') {
 
-     $output .= '<h3>' . t('Coupon discounts') . '</h3>';
 
-   }
 
-   elseif ($form['#uc_coupon_form_context'] == 'block') {
 
-     if (isset($form['code'])) {
 
-       $form['code']['#size'] = 15;
 
-     }
 
-   }
 
-   $output .= drupal_render_children($form);
 
-   return $output;
 
- }
 
- /**
 
-  * Implements hook_uc_cart_pane().
 
-  */
 
- function uc_coupon_uc_cart_pane($items) {
 
-   drupal_add_css(drupal_get_path('module', 'uc_coupon') . '/uc_coupon.css');
 
-   // The coupon entry cart pane.
 
-   $body = drupal_get_form('uc_coupon_form', 'cart') + array(
 
-     '#prefix' => '<div id="uc-cart-pane-coupon">',
 
-     '#suffix' => '</div>'
 
-   );
 
-   $panes[] = array(
 
-     'id' => 'coupon',
 
-     'body' => $body,
 
-     'title' => t('Coupon discount'),
 
-     'desc' => t('Allows shoppers to use a coupon during checkout for order discounts.'),
 
-     'weight' => 1,
 
-     'enabled' => TRUE,
 
-   );
 
-   // The "Special Discounts" cart pane.
 
-   $body = array();
 
-   $discounts = _uc_coupon_options_list(uc_coupon_session_validate(), FALSE);
 
-   if (!empty($discounts)) {
 
-     $body = array(
 
-       '#theme' => 'uc_coupon_automatic_discounts',
 
-       '#prefix' => '<div id="uc-cart-pane-coupon-automatic">',
 
-       '#title' => t('Special discounts'),
 
-       '#suffix' => '</div>',
 
-       'discounts' => array(
 
-         '#theme' => 'item_list',
 
-         '#items' => _uc_coupon_options_list(uc_coupon_session_validate(), FALSE),
 
-         '#title' => t('Special discounts'),
 
-       )
 
-     );
 
-   }
 
-   $panes[] = array(
 
-     'id' => 'coupon_auto',
 
-     'body' => $body,
 
-     'title' => t('Special Discounts'),
 
-     'desc' => t('Displays a list of automatic discounts.'),
 
-     'weight' => 1,
 
-     'enabled' => TRUE,
 
-   );
 
-   return $panes;
 
- }
 
- function theme_uc_coupon_automatic_discounts($variables) {
 
-   $form = $variables['form'];
 
-   /*
 
-   $items = $form['discounts']['#items'];
 
-   $title = isset($form['discounts']['#title']) ? $form['discounts']['#title'] : NULL;
 
-   $rows = array();
 
-   foreach($items as $item) {
 
-     $rows[] = array($item);
 
-   }
 
-   $form['discounts'] = array(
 
-     '#theme' => 'table',
 
-     '#rows' => $rows,
 
-   );
 
-   if (isset($title)) {
 
-     $form['discounts']['#header'] = array($title);
 
-   }
 
-   */
 
-   return drupal_render_children($form);
 
- }
 
- /**
 
-  * Create a tapir table of validated coupons with a "Remove" button for each.
 
-  *
 
-  * @param $coupons
 
-  *     An array of coupon options of the form code => title
 
-  * @param $submit
 
-  *     An array of additional options to attach to the form's submit elements (e.g. #ajax, #submit)
 
-  */
 
- function uc_coupon_table($coupons, $submit = FALSE) {
 
-   $table = array(
 
-     '#type' => 'tapir_table',
 
-   );
 
-   $table['#columns'] = array(
 
-     'title' => array(
 
-       'cell' => t('Active coupons'),
 
-       'weight' => 0,
 
-     ),
 
-     'remove' => array(
 
-       'cell' => t('Remove'),
 
-       'weight' => 1,
 
-     ),
 
-   );
 
-   $i = 0;
 
-   foreach ($coupons as $code => $title) {
 
-     $table[$i] = array(
 
-       'title' => array('#markup' => $title),
 
-       'remove' => array(
 
-         '#type' =>  'submit',
 
-         '#value' => t('Remove'),
 
-         '#name' => 'uc-coupon-remove-' . $code,
 
-       ),
 
-     );
 
-     if ($submit) {
 
-       // Add ajax functionality to this table.
 
-       $table[$i]['remove'] += $submit;
 
-     }
 
-     $i++;
 
-   }
 
-   return $table;
 
- }
 
- /**
 
-  * Helper function to create a list of coupons for form elements.
 
-  * @param $coupons
 
-  *     An array of validated coupon objects to include in the list.
 
-  * @param $in_session
 
-  *     TRUE to include only coupons currently added to the session.
 
-  *     FALSE to include those not in the session (e.g. automatic coupons).
 
-  * @return
 
-  *     An associative array mapping coupon code to coupon title.
 
-  */
 
- function _uc_coupon_options_list($coupons, $in_session = TRUE) {
 
-   $options = array();
 
-   if (!empty($coupons)) {
 
-     foreach ($coupons as $coupon) {
 
-       if (!$in_session xor uc_coupon_session_get($coupon->code)) {
 
-         $options[$coupon->code] = $coupon->title;
 
-         if ($coupon->type === 'credit') {
 
-           $credit = empty($coupon->usage['value']['codes'][$coupon->code]) ? 0 : $coupon->usage['value']['codes'][$coupon->code];
 
-           $credit += empty($coupon->amount) ? 0 : $coupon->amount;
 
-           $credit = $credit > $coupon->value ? 0 : $coupon->value - $credit;
 
-           $options[$coupon->code] .= ' (' . t('@credit credit remaining', array('@credit' => uc_currency_format($credit))) . ')';
 
-         }
 
-       }
 
-     }
 
-   }
 
-   return $options;
 
- }
 
- function uc_coupon_checkout_submit($form, &$form_state) {
 
-   $form_state['rebuild'] = TRUE;
 
-   unset($form_state['checkout_valid']);
 
-   $form_state['redirect'] = 'cart/checkout';
 
- }
 
- function uc_coupon_order_submit($form, &$form_state) {
 
-   $form_state['rebuild'] = TRUE;
 
-   uc_coupon_form_submit($form, $form_state);
 
-   $coupons = uc_coupon_get_order_coupons($form_state['order']);
 
-   uc_coupon_apply_to_order($form_state['order'], uc_coupon_get_order_coupons($form_state['order']));
 
-   // !TODO: Shouldn't save the order here because we prevent reverting changes
 
-   // made by other panes?
 
-   uc_order_save($form_state['order']);
 
- }
 
- /**
 
-  * Form builder for the uc_coupon form.
 
-  *
 
-  * @param $context
 
-  *     Where the form is to appear: 'cart', 'block' or 'checkout'
 
-  * @param $submit
 
-  *     An array of additional options to attach to the form's submit elements (e.g. #ajax, #submit)
 
-  */
 
- function uc_coupon_form($form, $form_state, $context = 'block', $submit = FALSE) {
 
-   //dpm($form_state['order'], 'order build');
 
-   $coupons = ($context == 'order') ? uc_coupon_get_order_coupons($form_state['order']) : uc_coupon_session_validate();
 
-   //dpm($coupons, 'coupons build');
 
-   $components = variable_get('uc_coupon_form_components',
 
-     drupal_map_assoc(variable_get('uc_coupon_allow_multiple', FALSE) ? array('entry') : array('entry', 'list')));
 
-   // Show the coupon code entry component
 
-   if (!empty($components['entry'])) {
 
-     $form['code'] = array(
 
-       '#type' => 'textfield',
 
-       '#size' => 25,
 
-       '#title' => t('Coupon Code'),
 
-       '#description' => t('Enter a coupon code and click "Apply to order" below.'),
 
-     );
 
-     $form['apply'] = array(
 
-       '#type' => 'submit',
 
-       '#value' => t('Apply to order'),
 
-       '#name' => 'uc-coupon-apply',
 
-     );
 
-     if (!variable_get('uc_coupon_allow_multiple', FALSE) && count(uc_coupon_session_get()) > 0) {
 
-       $form['code']['#description'] .= ' ' . t('Apply a blank code to remove the currently applied coupon.');
 
-     }
 
-     drupal_add_css('#uc-coupon-active-coupons, #uc-coupon-other-discounts { clear: left; }', array('type' => 'inline', 'group' => CSS_DEFAULT));
 
-     if ($submit) {
 
-       $form['apply'] += $submit;
 
-     }
 
-   }
 
-   // Add active coupons components (table and/or list).
 
-   $options = _uc_coupon_options_list($coupons, $context != 'order');
 
-   if (!empty($options)) {
 
-     if (!empty($components['table'])) {
 
-       $form['coupons_table'] = tapir_get_table('uc_coupon_table', $options, $submit);
 
-     }
 
-     if (!empty($components['list'])) {
 
-       $form['coupons'] = array(
 
-         '#prefix' => '<div id="uc-coupon-active-coupons">',
 
-         '#suffix' => '</div>',
 
-         '#type' => 'checkboxes',
 
-         '#title' => t('Active Coupons'),
 
-         '#options' => $options,
 
-         '#default_value' => array_keys($options),
 
-         '#description' => t('These coupons have been applied to your order. To remove one, uncheck the box and click "Remove coupons" below.'),
 
-       );
 
-       $form['coupons']['#description'] = t('These coupons have been applied to your order. To remove one, uncheck the box next to the coupon name and click "Update order" below.');
 
-       $form['remove'] = array(
 
-         '#type' => 'submit',
 
-         '#value' => t('Update order'),
 
-         '#name' => 'uc-coupon-remove',
 
-       );
 
-       if ($submit) {
 
-         $form['remove'] += $submit;
 
-       }
 
-     }
 
-   }
 
-   // Add context to help out themers.
 
-   $form['#uc_coupon_form_context'] = $context;
 
-   return $form;
 
- }
 
- /**
 
-  * Implements hook_uc_order().
 
-  */
 
- function uc_coupon_uc_order($op, &$order) {
 
-   if ($op == 'presave') {
 
-     // Apply any session coupons to the current cart order.
 
-     if (_uc_coupon_is_checkout_order($order)) {
 
-       $coupons = uc_coupon_session_validate($order);
 
-       uc_coupon_apply_to_order($order, $coupons);
 
-     }
 
-     // Make sure any fake cart items don't get saved with the order if the checkout page is skipped
 
-     // (e.g. Paypal Express Checkout, Google Checkout)
 
-     foreach ($order->products as $key => $product) {
 
-       if (isset($product->module) && $product->module == 'uc_coupon') {
 
-         unset($order->products[$key]);
 
-       }
 
-     }
 
-   }
 
- }
 
- /**
 
-  * Apply a set of coupons to an order.  
 
-  * 
 
-  * Line items and entries in the uc_coupons_orders table will be added for each coupon.  Any coupon line items
 
-  * or entries which are not in the list of coupons will be removed.  Additionally, the coupons' discount
 
-  * arrays will be added to the order object's data array.
 
-  * 
 
-  * @param $order
 
-  *     The order to which the coupons should be applied.
 
-  * @param $coupons
 
-  *    An associative array of fully validated coupon objects, keyed by the coupon code.
 
-  */
 
- function uc_coupon_apply_to_order($order, $coupons) {
 
-   // Index existing line items by coupon code.
 
-   $items = array();
 
-   foreach ($order->line_items as $index => $line) {
 
-     if ($line['type'] == 'coupon') {
 
-       // For orders created before multi-coupons were enabled, the code was not saved with the line item.
 
-       // In this case, we retreive it from the uc_coupons_orders table.
 
-       $code = isset($line['data']['code']) ? $line['data']['code'] :
 
-           db_query('SELECT code FROM {uc_coupons_orders} WHERE oid = :oid', array(':oid' => $order_id))->fetchField();
 
-       $items[$code] = $index;
 
-     }
 
-   }
 
-   // Index existing entries in {uc_coupons_orders} by coupon code.
 
-   $entries = db_query('SELECT code, cuid FROM {uc_coupons_orders} WHERE oid = :oid',
 
-     array(':oid' => $order->order_id))->fetchAllKeyed(0,1);
 
-   // Update, insert or delete line items and entries in uc_coupons_orders.
 
-   $insert = array();
 
-   $order->data['coupons'] = array();
 
-   foreach($coupons as $coupon) {
 
-     $order->data['coupons'][$coupon->code] = $coupon->discounts;
 
-     // Handle entries in {uc_coupons_orders}.
 
-     if (isset($entries[$coupon->code])) {
 
-       db_update('uc_coupons_orders')->condition('cuid', $entries[$coupon->code])
 
-         ->fields(array('cid' => $coupon->cid, 'value' => $coupon->amount))
 
-         ->execute();
 
-       unset($entries[$coupon->code]);
 
-     }
 
-     else {
 
-       $insert[] = array($coupon->cid, $order->order_id, $coupon->code, $coupon->value);
 
-     }
 
-     // Handle line items.
 
-     if (isset($items[$coupon->code])) {
 
-       $line =& $order->line_items[$items[$coupon->code]];
 
-       $line['title'] = $coupon->title;
 
-       $line['amount'] = -$coupon->pretax_amount;
 
-       $line['data']['code'] = $coupon->code;
 
-       uc_order_update_line_item($line['line_item_id'], $line['title'], $line['amount'], $line['data']);
 
-       unset($items[$coupon->code]);
 
-     }
 
-     else {
 
-       // Create a new line item.
 
-       $order->line_items[] = uc_order_line_item_add($order->order_id, 'coupon',
 
-         $coupon->title,
 
-         -$coupon->pretax_amount,
 
-         _uc_line_item_data('coupon', 'weight'),
 
-         array('code' => $coupon->code)
 
-       );
 
-     }
 
-   }
 
-   // Insert new entries in {uc_coupons_orders}
 
-   if (!empty($insert)) {
 
-     $query = db_insert('uc_coupons_orders');
 
-     $query->fields(array('cid', 'oid', 'code', 'value'));
 
-     foreach ($insert as $fields) {
 
-       $query->values($fields);
 
-     }
 
-     $query->execute();
 
-   }
 
-   // Delete orphaned entries in {uc_coupons_orders}
 
-   if (!empty($entries)) {
 
-     db_delete('uc_coupons_orders')->condition('cuid', $entries)->execute();
 
-   }
 
-   // Remove orphaned line-items.
 
-   foreach ($items as $index) {
 
-     uc_order_delete_line_item($order->line_items[$index]['line_item_id']);
 
-     unset($order->line_items[$index]);
 
-   }
 
-   usort($order->line_items, 'uc_weight_sort');
 
- }
 
- /**
 
-  * Implements hook_uc_checkout_pane().
 
-  *
 
-  * Show a pane just above the order total that allows shoppers to enter a coupon
 
-  * for a discount.
 
-  */
 
- function uc_coupon_uc_checkout_pane() {
 
-   $panes[] = array(
 
-     'id' => 'coupon',
 
-     'callback' => 'uc_checkout_pane_coupon',
 
-     'title' => t('Coupon discount'),
 
-     'desc' => t('Allows shoppers to use a coupon during checkout for order discounts.'),
 
-     'weight' => 5,
 
-     'process' => TRUE,
 
-   );
 
-   $panes[] = array(
 
-     'id' => 'coupon_automatic',
 
-     'callback' => 'uc_checkout_pane_coupon_automatic',
 
-     'title' => t('Special Discounts'),
 
-     'desc' => t('Displays a list of all automatic coupon discounts.'),
 
-     'weight' => 5,
 
-     'process' => FALSE,
 
-   );
 
-   return $panes;
 
- }
 
- /**
 
-  * Ajax callback for checkout form.
 
-  */
 
- function uc_coupon_checkout_update($form, $form_state) {
 
-   $commands[] = ajax_command_replace('#coupon-pane', trim(drupal_render($form['panes']['coupon'])));
 
-   if (isset($form['panes']['coupon_automatic'])) {
 
-     $commands[] = ajax_command_replace('#coupon_automatic-pane', trim(drupal_render($form['panes']['coupon_automatic'])));
 
-   }
 
-   if (isset($form['panes']['quotes'])) {
 
-     $commands[] = ajax_command_replace('#quotes-pane', drupal_render($form['panes']['quotes']));
 
-   }
 
-   if (isset($form['panes']['payment'])) {
 
-     $commands[] = ajax_command_replace('#payment-pane', trim(drupal_render($form['panes']['payment'])));
 
-   }
 
-   if (variable_get('uc_coupon_show_in_cart', TRUE) && isset($form['panes']['cart']['cart_review_table'])) {
 
-     $commands[] = ajax_command_html('#cart-pane>div', drupal_render($form['panes']['cart']['cart_review_table']));
 
-   }
 
-   // Clear the coupon code, but only if the submission was successful.
 
-   if (count(drupal_get_messages('error', FALSE)) == 0) {
 
-     $commands[] = ajax_command_invoke('#coupon-pane input[type=text]', 'val', array(''));
 
-   }
 
-   // Make sure all checkboxes are checked.
 
-   $commands[] = ajax_command_invoke('#coupon-pane input[type=checkbox]', 'attr', array('checked', 'true'));
 
-   // Show any messages.
 
-   $commands[] = ajax_command_html('#coupon-messages', theme('status_messages'));
 
-   return array('#type' => 'ajax', '#commands' => $commands);
 
- }
 
- /**
 
-  * A checkout pane listing any automatic discounts.
 
-  */
 
- function uc_checkout_pane_coupon_automatic($op, &$order, $form = NULL, &$form_state = NULL) {
 
-   if ($op == 'view') {
 
-     $discounts = _uc_coupon_options_list(uc_coupon_session_validate(), FALSE);
 
-     if (empty($discounts)) {
 
-       $inner_contents = array(
 
-         '#markup' => t('None.'),
 
-       );
 
-     }
 
-     else {
 
-       $inner_contents = array(
 
-         '#theme' => 'item_list',
 
-         '#items' => _uc_coupon_options_list(uc_coupon_session_validate(), FALSE)
 
-       );
 
-     }
 
-     return array(
 
-       'theme' => 'uc_coupon_automatic_discounts',
 
-       'contents' => array(
 
-         'discounts' => $inner_contents,
 
-       ),
 
-     );
 
-   }
 
- }
 
- /**
 
-  * Checkout Pane callback function.
 
-  *
 
-  * Used to display a form in the checkout process so that customers
 
-  * can enter discount coupons.
 
-  */
 
- function uc_checkout_pane_coupon($op, &$order, $form = NULL, &$form_state = NULL) {
 
-   switch ($op) {
 
-     case 'prepare':
 
-       // Remove fake cart items from the order.
 
-       foreach ($order->products as $key => $product) {
 
-         if (isset($product->module) && $product->module == 'uc_coupon') {
 
-           unset($order->products[$key]);
 
-         }
 
-       }
 
-       break;
 
-     case 'view':
 
-       // Revalidate the session coupons against the actual order.
 
-       drupal_add_css('#coupon-messages { clear: both; }', array('type' => 'inline', 'group' => CSS_DEFAULT));
 
-       $description = variable_get('uc_coupon_pane_description', t('Enter a coupon code for this order.'));
 
-       $submit = array(
 
-         '#limit_validation_errors' => array(),
 
-         '#ajax' => array(
 
-           'callback' => 'uc_coupon_checkout_update',
 
-         ),
 
-         '#submit' => array('uc_coupon_checkout_submit'),
 
-       );
 
-       $contents = uc_coupon_form(array(), $form_state, 'checkout', $submit);
 
-       $contents['message'] = array(
 
-         '#markup' => '<div id="coupon-messages"></div>',
 
-         '#weight' => 2,
 
-       );
 
-       return array(
 
-         'description' => $description,
 
-         'contents' => $contents,
 
-         'theme' => 'uc_coupon_form',
 
-       );
 
-     case 'process':
 
-       $trigger = $form_state['triggering_element']['#name'];
 
-       if (substr($trigger, 0, 9) == 'uc-coupon') {
 
-         $form_state['rebuild'] = TRUE;
 
-         uc_coupon_form_submit($form['panes']['coupon'], $form_state);
 
-         return FALSE; // Prevent redirection.
 
-       }
 
-       else {
 
-         // !TODO Coupon will not be submitted if "Apply to order" is not clicked. Is this what we want?
 
-         return TRUE;
 
-       }
 
-     case 'settings':
 
-       $form['uc_coupon_collapse_pane'] = array(
 
-         '#type' => 'checkbox',
 
-         '#title' => t('Collapse checkout pane by default.'),
 
-         '#default_value' => variable_get('uc_coupon_collapse_pane', FALSE),
 
-       );
 
-       $form['uc_coupon_pane_description'] = array(
 
-         '#type' => 'textarea',
 
-         '#title' => t('Checkout pane message'),
 
-         '#default_value' => variable_get('uc_coupon_pane_description', t('Enter a coupon code for this order.')),
 
-       );
 
-       return $form;
 
-   }
 
- }
 
- /**
 
-  * Submit handler for the uc_coupon form.
 
-  */
 
- function uc_coupon_form_submit($form, &$form_state) {
 
-   $trigger = $form_state['triggering_element']['#name'];
 
-   // Determine where the values are (they will be in a subarray if called from checkout or order page).
 
-   switch ($context = $form['#uc_coupon_form_context']) {
 
-     case 'checkout':
 
-       $values = $form_state['values']['panes']['coupon'];
 
-       break;
 
-     case 'order':
 
-       $values = $form_state['values']['coupon'];
 
-       break;
 
-     default:
 
-       $values = $form_state['values'];
 
-   }
 
-   // If this was the result of a 'remove' submission.
 
-   if (substr($trigger, 0, 16) == 'uc-coupon-remove') {
 
-     // See if there was an individual remove button clicked.
 
-     $code = substr($trigger, 17);
 
-     if (!empty($code)) {
 
-       if ($context == 'order') {
 
-         unset($form_state['order']->data['coupons']['code']);
 
-       }
 
-       else {
 
-         uc_coupon_session_clear($code);
 
-         drupal_set_message(t('Coupon "%code" has been removed from your order', array('%code' => $code)));
 
-         module_invoke_all('uc_coupon_remove', uc_coupon_find($code));
 
-       }
 
-     }
 
-     // Otherwise see if it's a checkbox submission.
 
-     elseif (isset($values['coupons'])) {
 
-       $removed = array();
 
-       foreach ($values['coupons'] as $code => $selected) {
 
-         if (!$selected) {
 
-           $removed[] = $code;
 
-           if ($context == 'order') {
 
-             unset($form_state['order']->data['coupons'][$code]);
 
-           }
 
-           else {
 
-             uc_coupon_session_clear($code);
 
-             module_invoke_all('uc_coupon_remove', uc_coupon_find($code));
 
-           }
 
-         }
 
-       }
 
-       $n = count($removed);
 
-       if ($n > 1) {
 
-         $last = $removed[$n - 1];
 
-         $rest = implode(', ', array_slice($removed, 0, $n - 1));
 
-         drupal_set_message(t('Coupons %rest and %last have been removed from your order.', array('%rest' => $rest, '%last' => $last)));
 
-       }
 
-       elseif (!empty($removed)) {
 
-         drupal_set_message(t('Coupon %code has been removed from your order', array('%code' => $removed[0])));
 
-       }
 
-     }
 
-   }
 
-   // Otherwise try to apply.
 
-   else {
 
-     $code = empty($values['code']) ? '' : strtoupper(trim($values['code']));
 
-     $removed = FALSE;
 
-     // If multiple codes are not enabled, then remove any codes currently applied.
 
-     if (!variable_get('uc_coupon_allow_multiple', FALSE) && count($session = uc_coupon_session_get()) > 0) {
 
-       if ($context == 'order') {
 
-         unset($form_state['order']->data['coupons']);
 
-       }
 
-       else {
 
-         foreach (array_keys($session) as $remove_code) {
 
-           uc_coupon_session_clear($remove_code);
 
-           drupal_set_message(t('Coupon "%code" has been removed from your order', array('%code' => $remove_code)));
 
-           module_invoke_all('uc_coupon_remove', uc_coupon_find($remove_code));
 
-         }
 
-         $removed = TRUE;
 
-       }
 
-     }
 
-     if (!empty($code)) {
 
-       if ($context == 'order') {
 
-         $coupon = uc_coupon_validate($code, $form_state['order'], user_load($form_state['order']->uid));
 
-         if ($coupon->valid) {
 
-           $form_state['order']->data['coupons'][$code] = $coupon->discounts;
 
-         }
 
-         else {
 
-           drupal_set_message($coupon->message, 'error');
 
-         }
 
-       }
 
-       else {
 
-         uc_coupon_session_add($code, 'submit');
 
-       }
 
-     }
 
-     elseif (!$removed) {
 
-       drupal_set_message(t("You must enter a valid coupon code."), 'error');
 
-     }
 
-   }
 
- }
 
- /**
 
-  * Implements hook_uc_line_item().
 
-  */
 
- function uc_coupon_uc_line_item() {
 
-   $items[] = array(
 
-     'id' => 'coupon',
 
-     'title' => t('Coupon discount'),
 
-     'tax_adjustment' => 'uc_coupon_tax_adjustment',
 
-     'weight' => 0,
 
-     'default' => FALSE,
 
-     'stored' => TRUE,
 
-     'add_list' => FALSE,
 
-     'calculated' => TRUE,
 
-   );
 
-   return $items;
 
- }
 
- /**
 
-  * Handle tax on coupons by calculating tax for individual discounted prices.
 
-  */
 
- function uc_coupon_tax_adjustment($price, $order, $tax) {
 
-   $amount = 0;
 
-   if (isset($order->data['coupons'])) {
 
-     foreach ($order->data['coupons'] as $discounts) {
 
-       foreach ($discounts as $id => $item) {
 
-         if (is_numeric($id) && $id > 0) {
 
-           // This is a product discount, so see if the product is taxable.
 
-           $node = node_load($id);
 
-           $adjust = in_array($node->type, $tax->taxed_product_types) && ($tax->shippable == 0 || $node->shippable == 1);
 
-         }
 
-         else {
 
-           // This is a line-item discount, so find the corresponding line item.
 
-           $lid = is_numeric($id) ? -$id : $id; // Convert id to a line item id.
 
-           foreach ($order->line_items as $line_item) {
 
-             if ($line_item['line_item_id'] == $lid) {
 
-               $adjust = in_array($line_item['type'], $tax->taxed_line_items);
 
-               break;
 
-             }
 
-           }
 
-         }
 
-         if ($adjust) {
 
-           $amount += (isset($item->pretax_discount) ? $item->pretax_discount : $item->discount) * ($price > 0 ? 1 : -1);
 
-         }
 
-       }
 
-     }
 
-   }
 
-   return $amount;
 
- }
 
- /**
 
-  * Show a message if PayPal is enabled and "itemized order" is selected.
 
-  */
 
- function _uc_coupon_paypal_check() {
 
-   if (variable_get('uc_payment_method_paypal_wps_checkout', 0) && variable_get('uc_paypal_wps_submit_method', 'single') == 'itemized') {
 
-     drupal_set_message(t('To use coupons with PayPal you must select "Submit the whole order as a single line item". <a href="!url">Click here to change this setting</a>.', array('!url' => url('admin/store/settings/payment/edit/methods'))));
 
-   }
 
- }
 
- /**
 
-  * Implements hook_uc_store_status().
 
-  */
 
- function uc_coupon_uc_store_status() {
 
-   $statuses = array();
 
-   if (variable_get('uc_payment_method_paypal_wps_checkout', 0) && variable_get('uc_paypal_wps_submit_method', 'single') == 'itemized') {
 
-     $statuses[] = array(
 
-       'status' => 'warning',
 
-       'title' => t('Coupons'),
 
-       'desc' => t('To use coupons with PayPal you must select "Submit the whole order as a single line item". <a href="!url">Click here to change this setting</a>.', array('!url' => url('admin/store/settings/payment/edit/methods'))),
 
-     );
 
-   }
 
-   return $statuses;
 
- }
 
- /**
 
-  * Implements hook_uc_cart_alter().
 
-  *
 
-  * This is called every time the cart is rebuild (e.g. when products are added), so it's a good place
 
-  * to revalidate our session coupons.  We also add a fake cart item (if configured to show in cart)
 
-  * for each coupon.  These will be removed at checkout.
 
-  */
 
- function uc_coupon_uc_cart_alter(&$items) {
 
-   // Validate all codes in the session against the cart contents.
 
-   $order = new UcOrder();
 
-   $order->products = $items;
 
-   $order->data = array();
 
-   $coupons = uc_coupon_session_validate($order);
 
-   if (variable_get('uc_coupon_show_in_cart', TRUE) && !empty($coupons)) {
 
-     // If there are some valid coupons, then add them to the cart (but only if
 
-     // they have a non-zero value.
 
-     foreach ($coupons as $code => $coupon) {
 
-       if ($coupon->amount != 0) {
 
-         $items[] = _uc_coupon_cart_item($coupon);
 
-       }
 
-     }
 
-   }
 
- }
 
- /**
 
-  * Creates a fake cart-item corrresponding to this coupon, allowing this coupon to be displayed in the cart.
 
-  *
 
-  * @param $coupon
 
-  *   The coupon to be displayed in the cart.
 
-  */
 
- function _uc_coupon_cart_item($coupon) {
 
-   // Exclude any line-item discounts from the amount shown in the cart.
 
-   $amount = 0;
 
-   foreach ($coupon->discounts as $id => $discount) {
 
-     if (is_numeric($id) && $id > 0) {
 
-       $amount += $discount->discount;
 
-     }
 
-   }
 
-   // Assign this a unique cart_item_id so it will be keyed properly by entity_view().
 
-   $id = -hexdec(substr(sha1($coupon->code), -8));
 
-   return (object) array(
 
-     'cart_item_id' => $id,
 
-     'module' => 'uc_coupon',
 
-     'title' => $coupon->title,
 
-     'nid' => 0,
 
-     'qty' => 1,
 
-     'price' => -$amount,
 
-     'data' => array('module' => 'uc_coupon', 'shippable' => FALSE, 'code' => $coupon->code, 'remove' => uc_coupon_session_get($coupon->code)),
 
-     'model' => 0,
 
-     'weight' => 0
 
-   );
 
- }
 
- /**
 
-  * Implements hook_uc_cart_display().
 
-  */
 
- function uc_coupon_uc_cart_display($item) {
 
-   $display_item =  array(
 
-     'module' => array('#type' => 'value', '#value' => 'uc_coupon'),
 
-     'nid' => array('#type' => 'value', '#value' => 0),
 
-     'title' => array('#markup' => $item->title),
 
-     'description' => array('#markup' => ''),
 
-     'qty' => array('#type' => 'hidden', '#value' => 1, '#default_value' => 1),
 
-     '#total' => $item->price,
 
-     'data' => array('#type' => 'hidden', '#value' => serialize($item->data)),
 
-     '#suffixes' => array(),
 
-   );
 
-   if ($item->data['remove']) {
 
-     $display_item['remove'] = array('#type' => 'submit', '#value' => t('Remove'));
 
-   }
 
-   return $display_item;
 
- }
 
- /**
 
-  * Implements hook_uc_update_cart_item().
 
-  * Remove a coupon from the order when the "Remove" button is clicked.
 
-  */
 
- function uc_coupon_uc_update_cart_item($nid, $data, $qty) {
 
-   if (isset($data['code']) && $qty == 0) {
 
-     uc_coupon_session_clear($data['code']);
 
-     module_invoke_all('uc_coupon_remove', uc_coupon_find($data['code']));
 
-   }
 
- }
 
- /**
 
-  * Theme override for the default cart block content.
 
-  * Removes coupons from the total number of items.
 
-  */
 
- function uc_coupon_theme_uc_cart_block_content($variables) {
 
-   if (variable_get('uc_coupon_show_in_cart', TRUE) && !empty($variables['items'])) {
 
-     foreach ($variables['items'] as &$item) {
 
-       if ($item['nid'] == 0 && $item['price'] <= 0) {
 
-         $item['qty'] = '';
 
-         $variables['item_count']--;
 
-       }
 
-     }
 
-     $variables['item_text'] = format_plural($variables['item_count'], '<span class="num-items">1</span> Item', '<span class="num-items">@count</span> Items');
 
-   }
 
-   return theme_uc_cart_block_content($variables);
 
- }
 
- /**
 
-  * Implements hook_form_FORM_ID_alter() for uc_cart_checkout_form().
 
-  *
 
-  * Remove any coupon cart items from the serialized cart contents and payment-pane
 
-  * order, as coupons will be handled as line items during checkout.
 
-  *
 
-  * Collapse coupon checkout pane, if configured to do so.
 
-  */
 
- function uc_coupon_form_uc_cart_checkout_form_alter(&$form, $form_state) {
 
-   if (variable_get('uc_coupon_collapse_pane', FALSE) && isset($form['panes']['coupon'])) {
 
-     $form['panes']['coupon']['#collapsed'] = TRUE;
 
-   }
 
-   // Show current session coupons in the cart pane (since now they will have been removed from the order).
 
-   if (variable_get('uc_coupon_show_in_cart', TRUE) && isset($form['panes']['cart'])) {
 
-     $coupons = uc_coupon_session_validate();
 
-     // If there are some valid coupons, then add them to the cart.
 
-     foreach ($coupons as $code => $coupon) {
 
-       if ($coupon->amount != 0) {
 
-         $item = _uc_coupon_cart_item($coupon);
 
-         $item->order_product_id = $item->cart_item_id;
 
-         $form['panes']['cart']['cart_review_table']['#items'][] = $item;
 
-       }
 
-     }
 
-   }
 
- }
 
- /**
 
-  * Implements hook_uc_checkout_complete().
 
-  *
 
-  * Ensure the stored coupon code is reset after checkout.
 
-  */
 
- function uc_coupon_uc_checkout_complete($order, $account) {
 
-   uc_coupon_session_clear();
 
- }
 
- /**
 
-  * Preprocess template for a printed coupon certificate.
 
-  * @see uc_coupon-certificate.tpl.php
 
-  */
 
- function template_preprocess_uc_coupon_certificate(&$variables) {
 
-   $coupon = $variables['coupon'];
 
-   // Create variables for each user-added field.
 
-   $fields = field_info_fields();
 
-   foreach ($fields as $name => $field) {
 
-     if (in_array('uc_coupon', array_keys($field['bundles']))) {
 
-       $items = field_get_items('uc_coupon', $coupon, $name);
 
-       $variables[$name] = $items;
 
-     }
 
-   }
 
-   $variables['value'] = theme('uc_coupon_discount', array('coupon' => $coupon));
 
-   $variables['display_name'] = check_plain($coupon->name);
 
-   $n = stripos($variables['display_name'], 'purchased by');
 
-   if ($n) {
 
-     $variables['display_name'] = substr($variables['display_name'], 0, $n -1);
 
-   }
 
-   if ($coupon->valid_until) {
 
-     $variables['not_yet_valid'] = $coupon->valid_from > REQUEST_TIME;
 
-     $variables['valid_from'] = format_date($coupon->valid_from, 'custom', variable_get('date_format_uc_store', 'm/d/Y'));
 
-     $variables['valid_until'] = format_date($coupon->valid_until, 'custom', variable_get('date_format_uc_store', 'm/d/Y'));
 
-   }
 
-   else {
 
-     $variables['not_yet_valid'] = FALSE;
 
-     $variables['valid_from'] = FALSE;
 
-     $variables['valid_until'] = FALSE;
 
-   }
 
-   $variables['max_uses_per_user'] = isset($coupon->data['max_uses_per_user']) ? $coupon->data['max_uses_per_user'] : NULL;
 
-   $variables['include'] = array();
 
-   $variables['exclude'] = array();
 
-   if (isset($coupon->data['product_types'])) {
 
-     foreach ($coupon->data['product_types'] as $type) {
 
-       $variables['include'][] = node_type_get_name($type);
 
-     }
 
-   }
 
-   if (isset($coupon->data['products'])) {
 
-     $key = isset($coupon->data['negate_products']) ? 'exclude' : 'include';
 
-     foreach ($coupon->data['products'] as $nid) {
 
-       $node = node_load($nid);
 
-       $variables[$key][] = $node->title;
 
-     }
 
-   }
 
-   if (isset($coupon->data['skus'])) {
 
-     foreach ($coupon->data['skus'] as $sku) {
 
-       $variables['include'][] = t('SKU') . ' ' . $sku;
 
-     }
 
-   }
 
-   if (isset($coupon->data['terms'])) {
 
-     $key = isset($coupon->data['negate_terms']) ? 'exclude' : 'include';
 
-     foreach ($coupon->data['terms'] as $tid) {
 
-       $term = taxonomy_term_load($tid);
 
-       $variables[$key][] = $term->name;
 
-     }
 
-   }
 
-   // Merge in global tokens.
 
-   $info = token_info();
 
-   foreach ($info['types'] as $type => $type_info) {
 
-     if (empty($type_info['needs-data']) && $type != 'current-user' && $type != 'current-date') {
 
-       $type_key = !empty($type_info['type']) ? $type_info['type'] : $type;
 
-       if (!empty($info['tokens'][$type_key])) {
 
-         foreach (array_keys($info['tokens'][$type_key]) as $token) {
 
-           $variables[str_replace('-', '_', $type_key) . '_' . str_replace('-', '_', $token)] = token_replace("[$type_key:$token]");
 
-         }
 
-       }
 
-     }
 
-   }
 
-   if (isset($variables['coupon']->data['base_cid'])) {
 
-     $variables['theme_hook_suggestions'][] = 'uc_coupon_certificate__base_' . $variables['coupon']->data['base_cid'];
 
-   }
 
-   $variables['theme_hook_suggestions'][] = 'uc_coupon_certificate__' . $variables['coupon']->cid;
 
- }
 
- /**
 
-  * Page template for printed coupons.
 
-  * @see uc_coupon-page.tpl.php
 
-  */
 
- function template_preprocess_uc_coupon_page(&$variables) {
 
-   $variables['styles'] = drupal_get_css();
 
- }
 
- /**
 
-  * Implements hook_uc_coupon_actions().
 
-  */
 
- function uc_coupon_uc_coupon_actions($coupon) {
 
-   $actions = array();
 
-   if (user_access('view store coupons')) {
 
-     $actions[] = array(
 
-       'url' => 'admin/store/coupons/' . $coupon->cid,
 
-       'icon' => drupal_get_path('module', 'uc_store') . '/images/order_view.gif',
 
-       'title' => t('View coupon: @name', array('@name' => $coupon->name)),
 
-     );
 
-     $actions[] = array(
 
-       'url' => 'admin/store/coupons/' . $coupon->cid . '/print',
 
-       'icon' => drupal_get_path('module', 'uc_store') . '/images/print.gif',
 
-       'title' => t('Print coupon: @name', array('@name' => $coupon->name)),
 
-     );
 
-     if ($coupon->bulk) {
 
-       $actions[] = array(
 
-         'url' => 'admin/store/coupons/' . $coupon->cid . '/codes',
 
-         'icon' => drupal_get_path('module', 'uc_store') . '/images/menu_reports_small.gif',
 
-         'title' => t('Download codes as CSV: @name', array('@name' => $coupon->name)),
 
-       );
 
-     }
 
-   }
 
-   if (user_access('manage store coupons')) {
 
-     $actions[] = array(
 
-       'url' => 'admin/store/coupons/' . $coupon->cid . '/edit',
 
-       'icon' => drupal_get_path('module', 'uc_store') . '/images/order_edit.gif',
 
-       'title' => t('Edit coupon: @name', array('@name' => $coupon->name)),
 
-     );
 
-     $actions[] = array(
 
-       'url' => 'admin/store/coupons/' . $coupon->cid . '/delete',
 
-       'icon' => drupal_get_path('module', 'uc_store') . '/images/order_delete.gif',
 
-       'title' => t('Delete coupon: @name', array('@name' => $coupon->name)),
 
-     );
 
-   }
 
-   return $actions;
 
- }
 
- /**
 
-  * Implements hook_views_api().
 
-  */
 
- function uc_coupon_views_api() {
 
-   return array(
 
-     'api' => '2.0',
 
-     'path' => drupal_get_path('module', 'uc_coupon') . '/views',
 
-   );
 
- }
 
- /**
 
-  * Check whether an order is the order being checked out by the current user.
 
-  * @param $order
 
-  */
 
- function _uc_coupon_is_checkout_order($order) {
 
-   global $user;
 
-   return isset($_SESSION['cart_order'])
 
-     && isset($order->order_id)
 
-     && $order->order_id == $_SESSION['cart_order']
 
-     && uc_order_status_data($order->order_status, 'state') == 'in_checkout'
 
-     && $user->uid == $order->uid;
 
- }
 
- /**
 
-  * Implements hook_entity_info();
 
-  */
 
- function uc_coupon_entity_info() {
 
-   return array(
 
-     'uc_coupon' => array(
 
-       'label' => t('Coupon'),
 
-       'controller class' => 'UcCouponController',
 
-       'metadata controller class' => 'UcCouponMetadataController',
 
-       'base table' => 'uc_coupons',
 
-       'fieldable' => TRUE,
 
-       'entity keys' => array(
 
-         'id' => 'cid',
 
-       ),
 
-       'bundles' => array(
 
-         'uc_coupon' => array(
 
-           'label' => t('Coupon'),
 
-           'admin' => array(
 
-             'path' => 'admin/store/settings/coupon',
 
-             'access arguments' => array('manage store coupons'),
 
-           ),
 
-         ),
 
-       ),
 
-       'view modes' => array(
 
-         'full' => array(
 
-           'label' => t('Administrative view'),
 
-         ),
 
-       ),
 
-     ),
 
-   );
 
- }
 
- /**
 
-  * Loads one coupon entity from the database.
 
-  */
 
- function uc_coupon_load($cid, $reset = FALSE) {
 
-   if (is_null($cid) || $cid < 1) {
 
-     return FALSE;
 
-   }
 
-   $coupons = uc_coupon_load_multiple(array($cid), array(), $reset);
 
-   return $coupons ? reset($coupons) : FALSE;
 
- }
 
- /**
 
-  * Loads one or more coupon entities from the database.
 
-  *
 
-  * @param $ids
 
-  *   An array of coupon IDs.
 
-  * @param $conditions
 
-  *   An array of conditions on the {uc_coupons} table in the form
 
-  *  'field' => $value.
 
-  *
 
-  * @return
 
-  *   An array of order objects indexed by order_id.
 
-  */
 
- function uc_coupon_load_multiple($ids, $conditions = array(), $reset = FALSE) {
 
-   return entity_load('uc_coupon', $ids, $conditions, $reset);
 
- }
 
- /**
 
-  * Save a coupon object.
 
-  *
 
-  * If the 'cid' field is set, then this will update an existing coupon.
 
-  * Otherwise, a new bulk seed will be generated, the coupon will be
 
-  * inserted into the database, and $coupon->cid will be set.
 
-  *
 
-  * @param $coupon
 
-  *   The coupon to save.
 
-  *
 
-  * @param $edit
 
-  *   An optional array of extra data that other modules may need to save.
 
-  */
 
- function uc_coupon_save(&$coupon, $edit = array()) {
 
-   entity_save('uc_coupon', $coupon);
 
- }
 
- /**
 
-  * Delete a coupon object.
 
-  *
 
-  * @param $cid
 
-  *   The id of the coupon to delete.
 
-  */
 
- function uc_coupon_delete($cid) {
 
-   entity_delete('uc_coupon', $cid);
 
- }
 
- /**
 
-  * Implements hook_field_extra_fields().
 
-  */
 
- function uc_coupon_field_extra_fields() {
 
-   $extra = array();
 
-   $extra['uc_coupon']['uc_coupon']['display']['admin_summary'] = array(
 
-     'label' => t('Administrative Summary'),
 
-     'description' => t('A summary of all coupon details.'),
 
-     'weight' => 0,
 
-   );
 
-   return $extra;
 
- }
 
- /**
 
-  * Implements hook_uc_order_pane().
 
-  *
 
-  * Defines the shipping quote order pane.
 
-  */
 
- function uc_coupon_uc_order_pane() {
 
-   $panes['coupon'] = array(
 
-     'callback' => 'uc_order_pane_coupon',
 
-     'title' => t('Coupon, Credit or Discount Codes'),
 
-     'desc' => t('Apply a coupon or discount code to the current order.'),
 
-     'class' => 'pos-left',
 
-     'weight' => 7,
 
-     'show' => array('edit'),
 
-   );
 
-   return $panes;  
 
- }
 
- /**
 
-  * Coupon order pane callback.
 
-  *
 
-  * @see uc_quote_order_pane_quotes_submit()
 
-  * @see uc_quote_apply_quote_to_order()
 
-  */
 
- function uc_order_pane_coupon($op, $order, &$form = NULL, &$form_state = NULL) {
 
-   switch ($op) {
 
-     case 'edit-form':
 
-       $submit = array(
 
-         '#limit_validation_errors' => array(array('coupon')),
 
-         '#submit' => array('uc_coupon_order_submit'),
 
-       );
 
-       $form['coupon'] = uc_coupon_form(array(), $form_state, 'order', $submit);
 
-       $form['#uc_coupon_form_context'] = 'order';
 
-       $form['coupon']['#theme'] = 'uc_coupon_form';
 
-       $form['coupon']['#tree'] = TRUE;
 
-       break;
 
-     case 'edit-theme':
 
-       return drupal_render($form['coupon']);
 
-   }
 
- }
 
- /**
 
-  * Implements hook_form_uc_order_edit_form_alter().
 
-  */
 
- function uc_coupon_form_uc_order_edit_form_alter(&$form, &$form_state) {
 
-   $order = $form_state['order'];
 
-   $line_items = $order->line_items;
 
-   foreach ($line_items as $item) {
 
-     // Coupon line items should be changed using the coupon order-edit pane.
 
-     if ($item['type'] == 'coupon') {
 
-       $form['line_items'][$item['line_item_id']]['title'] = array(
 
-         '#markup' => check_plain($item['title']),
 
-       );
 
-       $form['line_items'][$item['line_item_id']]['remove']['#access'] = FALSE;
 
-       $form['line_items'][$item['line_item_id']]['amount'] = array(
 
-         '#theme' => 'uc_price',
 
-         '#price' => $item['amount'],
 
-       );
 
-     }
 
-   }
 
- }
 
- /**
 
-  * Gets the fully validated coupon objects that have been applied to this order.
 
-  *
 
-  * @param $order
 
-  *   The order in question.
 
-  * @param $recalculate
 
-  *   If TRUE, the value of each coupon will be recalculated using the current state
 
-  *   of the order and current coupon settings.
 
-  *   If FALSE (default), the original coupon values will be preserved.
 
-  */
 
- function uc_coupon_get_order_coupons($order, $recalculate = FALSE) {
 
-   $coupons = array();
 
-   if (!empty($order->data['coupons'])) {
 
-     if ($recalculate) {
 
-       $dummy_order = clone $order;
 
-       $dummy_order->data['coupons'] = array();
 
-     }
 
-     foreach ($order->data['coupons'] as $code => $discounts) {
 
-       $coupon = uc_coupon_find($code);
 
-       if (!empty($coupon->cid)) {
 
-         if ($recalculate) {
 
-           $discounts = uc_coupon_calculate_discounts($coupon, $dummy_order);
 
-           $dummy_order->data['coupons'][$code] =  $coupon->discounts;
 
-         }
 
-         $coupons[] = uc_coupon_prepare($coupon, $code, $discounts);
 
-       }
 
-     }
 
-   }
 
-   return $coupons;
 
- }
 
 
  |