uc_order.order_pane.inc 43 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390
  1. <?php
  2. /**
  3. * @file
  4. * This file contains the callbacks for the default order panes supplied with
  5. * Ubercart and their corresponding helper functions.
  6. *
  7. * Order panes are defined using hook_uc_order_pane() and use a callback to
  8. * handle the different processes involved in order viewing/editing. The
  9. * default order panes are defined in uc_order_order_pane() in uc_order.module.
  10. */
  11. /**
  12. * Handles the "Print button" order pane.
  13. */
  14. function uc_order_pane_print_button($op, $order, &$form = NULL, &$form_state = NULL) {
  15. switch ($op) {
  16. case 'customer':
  17. if (user_access('view own invoices')) {
  18. $link = t('Click to open a window with a printable invoice.');
  19. $build = array(
  20. '#markup' => l($link, 'user/' . $order->uid . '/orders/' . $order->order_id . '/print', array(
  21. 'html' => TRUE,
  22. 'attributes' => array(
  23. 'onclick' => "window.open(this.href, '" . t('Invoice') . "', 'toolbar=0,scrollbars=1,location=0,statusbar=0,menubar=0,resizable=1,width=600,height=480,left=50,top=50'); return false;",
  24. ),
  25. )),
  26. );
  27. return $build;
  28. }
  29. }
  30. }
  31. /**
  32. * Handles the "Ship to" order pane.
  33. */
  34. function uc_order_pane_ship_to($op, $order, &$form = NULL, &$form_state = NULL) {
  35. switch ($op) {
  36. case 'customer':
  37. if (!uc_order_is_shippable($order)) {
  38. return;
  39. }
  40. case 'view':
  41. $build = array('#markup' => uc_order_address($order, 'delivery') . '<br />' . check_plain($order->delivery_phone));
  42. return $build;
  43. case 'edit-form':
  44. $form['ship_to'] = array(
  45. '#type' => 'uc_address',
  46. '#default_value' => $order,
  47. '#required' => FALSE,
  48. '#attributes' => array('class' => array('uc-store-address-field')),
  49. '#key_prefix' => 'delivery',
  50. );
  51. return $form;
  52. case 'edit-theme':
  53. $output = '<div class="order-pane-icons">';
  54. $output .= ' <img src="' . base_path() . drupal_get_path('module', 'uc_store')
  55. . '/images/address_book.gif" alt="' . t('Select from address book.') . '" '
  56. . 'title="' . t('Select from address book.') . '" onclick="load_address_select(' . $form['order_uid']['#value'] . ', \'#delivery_address_select\', \'delivery\');" />';
  57. $output .= ' <img src="' . base_path() . drupal_get_path('module', 'uc_store')
  58. . '/images/copy.gif" alt="' . t('Copy billing information.') . '" title="'
  59. . t('Copy billing information.') . '" onclick="uc_order_copy_billing_to_shipping();" />';
  60. $output .= '</div>';
  61. $output .= '<div id="delivery_address_select"></div>';
  62. return $output . drupal_render($form['ship_to']);
  63. case 'edit-process':
  64. $changes = array();
  65. foreach ($form_state['values'] as $key => $value) {
  66. if (substr($key, 0, 9) == 'delivery_') {
  67. if (uc_address_field_enabled(substr($key, 9))) {
  68. $changes[$key] = $value;
  69. }
  70. }
  71. }
  72. return $changes;
  73. }
  74. }
  75. /**
  76. * Handles the "Bill to" order pane.
  77. */
  78. function uc_order_pane_bill_to($op, $order, &$form = NULL, &$form_state = NULL) {
  79. switch ($op) {
  80. case 'view':
  81. case 'customer':
  82. $build = array('#markup' => uc_order_address($order, 'billing') . '<br />' . check_plain($order->billing_phone));
  83. return $build;
  84. case 'edit-form':
  85. $form['bill_to'] = array(
  86. '#type' => 'uc_address',
  87. '#default_value' => $order,
  88. '#required' => FALSE,
  89. '#attributes' => array('class' => array('uc-store-address-field')),
  90. '#key_prefix' => 'billing',
  91. );
  92. return $form;
  93. case 'edit-theme':
  94. $output = '<div class="order-pane-icons">';
  95. $output .= ' <img src="' . base_path() . drupal_get_path('module', 'uc_store')
  96. . '/images/address_book.gif" alt="' . t('Select from address book.') . '" '
  97. . 'title="' . t('Select from address book.') . '" onclick="load_address_select(' . $form['order_uid']['#value'] . ', \'#billing_address_select\', \'billing\');" />';
  98. $output .= ' <img src="' . base_path() . drupal_get_path('module', 'uc_store')
  99. . '/images/copy.gif" alt="' . t('Copy shipping information.') . '" title="'
  100. . t('Copy shipping information.') . '" onclick="uc_order_copy_shipping_to_billing();" />';
  101. $output .= '</div>';
  102. $output .= '<div id="billing_address_select"></div>';
  103. return $output . drupal_render($form['bill_to']);
  104. case 'edit-process':
  105. $changes = array();
  106. foreach ($form_state['values'] as $key => $value) {
  107. if (substr($key, 0, 8) == 'billing_') {
  108. if (uc_address_field_enabled(substr($key, 8))) {
  109. $changes[$key] = $value;
  110. }
  111. }
  112. }
  113. return $changes;
  114. }
  115. }
  116. /**
  117. * Handles the "Customer Info" order pane.
  118. */
  119. function uc_order_pane_customer($op, $order, &$form = NULL, &$form_state = NULL) {
  120. switch ($op) {
  121. case 'view':
  122. $build['uid'] = array('#markup' => t('Customer number: !user_link', array('!user_link' => $order->uid ? l($order->uid, 'user/' . $order->uid) : '0')));
  123. $build['primary_email'] = array('#markup' => '<br />' . t('Primary e-mail:') . '<br />' . check_plain($order->primary_email));
  124. return $build;
  125. case 'edit-form':
  126. $form['customer']['uid'] = array(
  127. '#type' => 'hidden',
  128. '#default_value' => $order->uid,
  129. );
  130. $form['customer']['uid_text'] = array(
  131. '#type' => 'textfield',
  132. '#title' => t('Customer number'),
  133. '#default_value' => $order->uid,
  134. '#maxlength' => 10,
  135. '#size' => 10,
  136. '#disabled' => TRUE,
  137. );
  138. $form['customer']['primary_email'] = array(
  139. '#type' => 'textfield',
  140. '#title' => t('E-mail address'),
  141. '#default_value' => $order->primary_email,
  142. '#maxlength' => 64,
  143. '#size' => 32,
  144. );
  145. return $form;
  146. case 'edit-theme':
  147. $output = '<div class="order-pane-icons">';
  148. $output .= ' <img src="' . base_path() . drupal_get_path('module', 'uc_store')
  149. . '/images/order_view.gif" alt="' . t('Search for an existing customer.') . '" '
  150. . 'title="' . t('Search for an existing customer.') . '" onclick="load_customer_search();" />';
  151. $output .= ' <img src="' . base_path() . drupal_get_path('module', 'uc_store')
  152. . '/images/menu_customers_small.gif" alt="' . t('Create a new customer.') . '" '
  153. . 'title="' . t('Create a new customer.') . '" onclick="load_new_customer_form();" />';
  154. $output .= '</div>';
  155. $output .= '<div id="customer-select"></div>';
  156. $output .= drupal_render($form['customer']);
  157. return $output;
  158. case 'edit-process':
  159. $changes = array();
  160. $changes['uid'] = $form_state['values']['uid'];
  161. $changes['primary_email'] = $form_state['values']['primary_email'];
  162. return $changes;
  163. }
  164. }
  165. /**
  166. * Handles the "Products" order pane.
  167. */
  168. function uc_order_pane_products($op, $order, &$form = NULL, &$form_state = NULL) {
  169. switch ($op) {
  170. case 'view':
  171. return tapir_get_table('uc_op_products_view_table', $order);
  172. case 'customer':
  173. return tapir_get_table('uc_op_products_customer_table', $order);
  174. case 'edit-form':
  175. $form['add_product_button'] = array(
  176. '#type' => 'submit',
  177. '#value' => t('Add product'),
  178. '#submit' => array('uc_order_pane_products_select'),
  179. '#ajax' => array(
  180. 'callback' => 'uc_order_pane_products_ajax_callback',
  181. 'wrapper' => 'product-controls',
  182. ),
  183. );
  184. $form['add_blank_line_button'] = array(
  185. '#type' => 'submit',
  186. '#value' => t('Add blank line'),
  187. '#submit' => array('uc_order_edit_products_add_blank'),
  188. '#ajax' => array(
  189. 'callback' => 'uc_order_pane_products_ajax_callback',
  190. 'wrapper' => 'product-controls',
  191. ),
  192. );
  193. $form['product_controls'] = array(
  194. '#tree' => TRUE,
  195. '#prefix' => '<div id="product-controls">',
  196. '#suffix' => '</div>',
  197. );
  198. $controls = array();
  199. if (isset($form_state['products_action'])) {
  200. switch ($form_state['products_action']) {
  201. case 'select':
  202. $controls = uc_order_product_select_form($form['product_controls'], $form_state, $order);
  203. break;
  204. case 'add_product':
  205. $controls = uc_order_add_product_form($form['product_controls'], $form_state, $order, $form_state['node']);
  206. break;
  207. }
  208. }
  209. $form['product_controls'] += $controls;
  210. $form += uc_order_edit_products_form($form, $form_state, $order->products);
  211. return $form;
  212. case 'edit-theme':
  213. $output = drupal_render($form['add_product_button']);
  214. $output .= drupal_render($form['add_blank_line_button']);
  215. $output .= drupal_render($form['product_controls']);
  216. $output .= drupal_render($form['products']);
  217. return $output;
  218. case 'edit-process':
  219. if (isset($form_state['values']['products'])) {
  220. foreach ($form_state['values']['products'] as $key => $product) {
  221. $product['data'] = unserialize($product['data']);
  222. uc_order_product_save($order->order_id, (object) $product);
  223. }
  224. }
  225. break;
  226. }
  227. }
  228. /**
  229. * Form to choose a product to add to the order.
  230. *
  231. * @ingroup forms
  232. */
  233. function uc_order_product_select_form($form, &$form_state, $order) {
  234. $options = $form_state['product_select_options'];
  235. $ajax = array(
  236. 'callback' => 'uc_order_pane_products_ajax_callback',
  237. 'wrapper' => 'product-controls',
  238. );
  239. $form['nid'] = array(
  240. '#type' => 'select',
  241. '#options' => $options,
  242. '#size' => 7,
  243. '#ajax' => $ajax + array(
  244. 'event' => 'dblclick',
  245. 'trigger_as' => array(
  246. 'name' => 'op',
  247. 'value' => t('Select'),
  248. ),
  249. ),
  250. );
  251. $form['product_search'] = array(
  252. '#type' => 'textfield',
  253. '#title' => t('Search by name or model/SKU (* is the wildcard)'),
  254. );
  255. $form['actions'] = array('#type' => 'actions');
  256. $form['actions']['select'] = array(
  257. '#type' => 'submit',
  258. '#value' => t('Select'),
  259. '#validate' => array('uc_order_product_select_form_validate'),
  260. '#submit' => array('uc_order_pane_products_add'),
  261. '#ajax' => $ajax,
  262. '#weight' => 0,
  263. );
  264. $form['actions']['search'] = array(
  265. '#type' => 'submit',
  266. '#value' => t('Search'),
  267. '#submit' => array('uc_order_pane_products_select'),
  268. '#ajax' => $ajax,
  269. '#weight' => 1,
  270. );
  271. $form['actions']['close'] = array(
  272. '#type' => 'submit',
  273. '#value' => t('Close'),
  274. '#submit' => array('uc_order_pane_products_close'),
  275. '#ajax' => $ajax,
  276. '#weight' => 2,
  277. );
  278. return $form;
  279. }
  280. /**
  281. * Validation handler for uc_order_product_select_form().
  282. */
  283. function uc_order_product_select_form_validate($form, &$form_state) {
  284. if (empty($form_state['values']['product_controls']['nid'])) {
  285. form_set_error('product_controls][nid', t('Please select a product.'));
  286. }
  287. }
  288. /**
  289. * Sets the quantity and attributes of a product added to the order.
  290. *
  291. * @see uc_order_add_product_form()
  292. * @ingroup forms
  293. */
  294. function uc_order_add_product_form($form, &$form_state, $order, $node) {
  295. $data = array();
  296. if (isset($form_state['values']['product_controls']['qty'])) {
  297. $data += module_invoke_all('uc_add_to_cart_data', $form_state['values']['product_controls']);
  298. }
  299. if (!empty($node->data) && is_array($node->data)) {
  300. $data += $node->data;
  301. }
  302. $node = uc_product_load_variant(intval($form_state['values']['product_controls']['nid']), $data);
  303. $form['title'] = array(
  304. '#markup' => '<h3>' . check_plain($node->title) . '</h3>',
  305. );
  306. $form['nid'] = array(
  307. '#type' => 'hidden',
  308. '#value' => $node->nid,
  309. );
  310. $form['qty'] = array(
  311. '#type' => 'uc_quantity',
  312. '#title' => theme('uc_qty_label'),
  313. '#default_value' => 1,
  314. );
  315. $form['actions'] = array('#type' => 'actions');
  316. $form['actions']['submit'] = array(
  317. '#type' => 'submit',
  318. '#value' => t('Add to order'),
  319. '#submit' => array('uc_order_edit_products_add'),
  320. '#ajax' => array(
  321. 'callback' => 'uc_order_pane_products_ajax_callback',
  322. 'wrapper' => 'product-controls',
  323. ),
  324. );
  325. $form['actions']['cancel'] = array(
  326. '#type' => 'submit',
  327. '#value' => t('Cancel'),
  328. '#submit' => array('uc_order_pane_products_select'),
  329. '#ajax' => array(
  330. 'callback' => 'uc_order_pane_products_ajax_callback',
  331. 'wrapper' => 'product-controls',
  332. ),
  333. '#limit_validation_errors' => array(),
  334. );
  335. $form['node'] = array(
  336. '#type' => 'value',
  337. '#value' => $node,
  338. );
  339. uc_form_alter($form, $form_state, __FUNCTION__);
  340. return $form;
  341. }
  342. /**
  343. * Form to allow ordered products' data to be changed.
  344. *
  345. * @see uc_op_products_edit_table()
  346. * @see theme_uc_order_edit_products_form()
  347. */
  348. function uc_order_edit_products_form($form, &$form_state, $products) {
  349. if (($product_count = count($products)) > 0) {
  350. $form['products'] = tapir_get_table('uc_op_products_edit_table');
  351. for ($i = 0, $product = reset($products); $i < $product_count; $i++, $product = next($products)) {
  352. $form['products'][$i]['remove'] = array(
  353. '#type' => 'image_button',
  354. '#title' => t('Remove this product.'),
  355. '#src' => drupal_get_path('module', 'uc_store') . '/images/error.gif',
  356. '#button_type' => 'remove',
  357. '#submit' => array('uc_order_edit_products_remove', 'uc_order_edit_form_submit'),
  358. '#return_value' => $product->order_product_id,
  359. );
  360. $form['products'][$i]['order_product_id'] = array(
  361. '#type' => 'hidden',
  362. '#value' => $product->order_product_id,
  363. );
  364. $form['products'][$i]['nid'] = array(
  365. '#type' => 'hidden',
  366. '#value' => $product->nid,
  367. );
  368. $form['products'][$i]['qty'] = array(
  369. '#type' => 'uc_quantity',
  370. '#title' => theme('uc_qty_label'),
  371. '#title_display' => 'invisible',
  372. '#default_value' => $product->qty,
  373. );
  374. $form['products'][$i]['title'] = array(
  375. '#type' => 'textfield',
  376. '#title' => t('Title'),
  377. '#title_display' => 'invisible',
  378. '#default_value' => $product->title,
  379. '#size' => 30,
  380. '#maxlength' => 255,
  381. );
  382. $form['products'][$i]['model'] = array(
  383. '#type' => 'textfield',
  384. '#title' => t('SKU'),
  385. '#title_display' => 'invisible',
  386. '#default_value' => $product->model,
  387. '#size' => 6,
  388. );
  389. $form['products'][$i]['weight'] = array(
  390. '#type' => 'textfield',
  391. '#title' => t('Weight'),
  392. '#title_display' => 'invisible',
  393. '#default_value' => $product->weight,
  394. '#size' => 3,
  395. );
  396. $units = array(
  397. 'lb' => t('Pounds'),
  398. 'kg' => t('Kilograms'),
  399. 'oz' => t('Ounces'),
  400. 'g' => t('Grams'),
  401. );
  402. $form['products'][$i]['weight_units'] = array(
  403. '#type' => 'select',
  404. '#title' => t('Units'),
  405. '#title_display' => 'invisible',
  406. '#default_value' => $product->weight_units,
  407. '#options' => $units,
  408. );
  409. $form['products'][$i]['cost'] = array(
  410. '#type' => 'uc_price',
  411. '#title' => t('Cost'),
  412. '#title_display' => 'invisible',
  413. '#default_value' => $product->cost,
  414. '#size' => 5,
  415. );
  416. $form['products'][$i]['price'] = array(
  417. '#type' => 'uc_price',
  418. '#title' => t('Price'),
  419. '#title_display' => 'invisible',
  420. '#default_value' => $product->price,
  421. '#size' => 5,
  422. );
  423. $form['products'][$i]['data'] = array(
  424. '#type' => 'hidden',
  425. '#value' => serialize($product->data),
  426. );
  427. }
  428. }
  429. else {
  430. $form['products'] = array(
  431. '#markup' => t('This order contains no products.'),
  432. '#prefix' => '<div id="order-edit-products">',
  433. '#suffix' => '</div>',
  434. );
  435. }
  436. return $form;
  437. }
  438. /**
  439. * Sets the order pane to show the product selection form.
  440. */
  441. function uc_order_pane_products_select($form, &$form_state) {
  442. $types = uc_product_types();
  443. $options = array();
  444. $query = db_select('node', 'n')
  445. ->fields('n', array('nid', 'title'))
  446. ->condition('n.type', $types, 'IN')
  447. ->orderBy('n.title')
  448. ->addTag('node_access');
  449. if (!empty($form_state['values']['product_controls']['product_search'])) {
  450. $search = strtolower(str_replace('*', '%', $form_state['values']['product_controls']['product_search']));
  451. $query->leftJoin('uc_products', 'p', 'n.nid = p.nid');
  452. $query->condition(db_or()
  453. ->condition('n.title', $search, 'LIKE')
  454. ->condition('p.model', $search, 'LIKE')
  455. );
  456. }
  457. $result = $query->execute();
  458. foreach ($result as $row) {
  459. $options[$row->nid] = $row->title;
  460. }
  461. if (count($options) == 0) {
  462. $options[0] = t('No products found.');
  463. }
  464. $form_state['products_action'] = 'select';
  465. $form_state['product_select_options'] = $options;
  466. unset($form_state['refresh_products']);
  467. $form_state['rebuild'] = TRUE;
  468. }
  469. /**
  470. * Sets the order pane to show the add product to order form.
  471. */
  472. function uc_order_pane_products_add($form, &$form_state) {
  473. $form_state['products_action'] = 'add_product';
  474. $form_state['node'] = node_load($form_state['values']['product_controls']['nid']);
  475. unset($form_state['refresh_products']);
  476. $form_state['rebuild'] = TRUE;
  477. }
  478. /**
  479. * Hides the form to add another product to the order.
  480. */
  481. function uc_order_pane_products_close($form, &$form_state) {
  482. unset($form_state['products_action']);
  483. unset($form_state['refresh_products']);
  484. unset($form_state['product_select_options']);
  485. $form_state['rebuild'] = TRUE;
  486. }
  487. /**
  488. * Form submit callback: add a blank line product to an order.
  489. */
  490. function uc_order_edit_products_add_blank($form, &$form_state) {
  491. $form_state['refresh_products'] = TRUE;
  492. $form_state['rebuild'] = TRUE;
  493. $order = $form_state['build_info']['args'][0];
  494. $product = new stdClass();
  495. $product->qty = 1;
  496. $product->order_id = $order->order_id;
  497. $product->data = NULL;
  498. uc_order_product_save($order->order_id, $product);
  499. $order->products[] = $product;
  500. uc_order_log_changes($order->order_id, array('add' => t('Added new product line to order.')));
  501. }
  502. /**
  503. * Form submit callback: add a product to an order.
  504. */
  505. function uc_order_edit_products_add($form, &$form_state) {
  506. $form_state['products_action'] = 'products_select';
  507. $form_state['refresh_products'] = TRUE;
  508. $form_state['rebuild'] = TRUE;
  509. $order = $form_state['build_info']['args'][0];
  510. $data = module_invoke_all('uc_add_to_cart_data', $form_state['values']['product_controls']);
  511. $product = uc_product_load_variant(intval($form_state['values']['product_controls']['nid']), $data);
  512. $product->qty = isset($form_state['values']['product_controls']['qty']) ? $form_state['values']['product_controls']['qty'] : $product->default_qty;
  513. drupal_alter('uc_order_product', $product, $order);
  514. uc_order_product_save($order->order_id, $product);
  515. $order->products[] = $product;
  516. uc_order_log_changes($order->order_id, array('add' => t('Added (@qty) @title to order.', array('@qty' => $product->qty, '@title' => $product->title))));
  517. // Decrement stock.
  518. if (module_exists('uc_stock')) {
  519. uc_stock_adjust_product_stock($product, 0, $order);
  520. }
  521. // Add this product to the form values for accurate tax calculations.
  522. $form_state['values']['products'][] = (array) $product;
  523. }
  524. /**
  525. * Form submit callback: remove a product from an order.
  526. */
  527. function uc_order_edit_products_remove($form, &$form_state) {
  528. $form_state['refresh_products'] = TRUE;
  529. $order_product_id = intval($form_state['triggering_element']['#return_value']);
  530. if (module_exists('uc_stock')) {
  531. // Replace stock immediately.
  532. $product = uc_order_product_load($order_product_id);
  533. uc_stock_adjust($product->model, $product->qty);
  534. }
  535. uc_order_product_delete($order_product_id);
  536. $order = $form_state['build_info']['args'][0];
  537. $matches = array();
  538. preg_match('/products\[(\d+)\]/', $form_state['triggering_element']['#name'], $matches);
  539. $key = $matches[1];
  540. unset($order->products[$key]);
  541. $order->products = array_values($order->products);
  542. }
  543. /**
  544. * AJAX callback to render the order product controls.
  545. */
  546. function uc_order_pane_products_ajax_callback($form, &$form_state) {
  547. $commands[] = ajax_command_replace('#product-controls', trim(drupal_render($form['product_controls'])));
  548. $commands[] = ajax_command_prepend('#product-controls', trim(theme('status_messages')));
  549. if (isset($form_state['refresh_products']) && $form_state['refresh_products']) {
  550. $commands[] = ajax_command_replace('#order-edit-products', trim(drupal_render($form['products'])));
  551. $commands[] = ajax_command_replace('#order-line-items', trim(drupal_render($form['line_items'])));
  552. $commands[] = ajax_command_prepend('#order-edit-products', trim(theme('status_messages')));
  553. }
  554. // Remove the field so we only refresh the admin comments item-list.
  555. unset($form['admin_comment_field']);
  556. $commands[] = ajax_command_replace('#order-pane-admin_comments .item-list', uc_order_pane_admin_comments('edit-theme', $form['#order'], $form, $form_state));
  557. return array('#type' => 'ajax', '#commands' => $commands);
  558. }
  559. /**
  560. * Handles the "Line Items" order pane.
  561. */
  562. function uc_order_pane_line_items($op, $order, &$form = NULL, &$form_state = NULL) {
  563. switch ($op) {
  564. case 'view':
  565. case 'customer':
  566. $line_items = $order->line_items;
  567. $items = _uc_line_item_list();
  568. foreach ($items as $item) {
  569. if (isset($item['display_only']) && $item['display_only'] == TRUE) {
  570. $result = $item['callback']('display', $order);
  571. if (is_array($result)) {
  572. foreach ($result as $line) {
  573. $line_items[] = array(
  574. 'title' => $line['title'],
  575. 'amount' => $line['amount'],
  576. 'weight' => $item['weight'],
  577. );
  578. }
  579. }
  580. }
  581. }
  582. usort($line_items, 'uc_weight_sort');
  583. $build['line_items'] = array(
  584. '#prefix' => '<table class="line-item-table">',
  585. '#suffix' => '</table>',
  586. );
  587. foreach ($line_items as $item) {
  588. $table_row = array(
  589. '#prefix' => '<tr>',
  590. '#suffix' => '</tr>',
  591. );
  592. $table_row['title'] = array(
  593. '#markup' => check_plain($item['title']),
  594. '#prefix' => '<td class="li-title">',
  595. '#suffix' => '</td>',
  596. );
  597. $table_row['amount'] = array(
  598. '#theme' => 'uc_price',
  599. '#price' => $item['amount'],
  600. '#prefix' => '<td class="li-amount">',
  601. '#suffix' => '</td>',
  602. );
  603. $build['line_items'][] = $table_row;
  604. }
  605. return $build;
  606. case 'edit-form':
  607. $options = array();
  608. $items = _uc_line_item_list();
  609. $line_items = $order->line_items;
  610. foreach ($items as $item) {
  611. if (isset($item['add_list']) && $item['add_list'] === TRUE) {
  612. $options[$item['id']] = check_plain($item['title']);
  613. }
  614. if (isset($item['display_only']) && $item['display_only'] == TRUE) {
  615. $result = $item['callback']('display', $order);
  616. if (is_array($result)) {
  617. foreach ($result as $line) {
  618. $line_items[] = array(
  619. 'line_item_id' => $line['id'],
  620. 'title' => $line['title'],
  621. 'amount' => $line['amount'],
  622. 'weight' => $item['weight'],
  623. );
  624. }
  625. }
  626. }
  627. }
  628. usort($line_items, 'uc_weight_sort');
  629. $form['add_line_item'] = array('#type' => 'container');
  630. $form['add_line_item']['li_type_select'] = array(
  631. '#type' => 'select',
  632. '#title' => t('Add a line item'),
  633. '#options' => $options,
  634. );
  635. $form['add_line_item']['submit'] = array(
  636. '#type' => 'submit',
  637. '#value' => t('Add line'),
  638. '#submit' => array('uc_order_pane_line_items_submit', 'uc_order_pane_line_items_add'),
  639. '#ajax' => array(
  640. 'callback' => 'uc_order_pane_line_items_update',
  641. ),
  642. );
  643. $form['line_items'] = array(
  644. '#tree' => TRUE,
  645. '#theme' => 'uc_order_pane_line_items',
  646. '#prefix' => '<div id="order-line-items">',
  647. '#suffix' => '</div>',
  648. );
  649. foreach ($line_items as $item) {
  650. $form['line_items'][$item['line_item_id']]['li_id'] = array(
  651. '#type' => 'hidden',
  652. '#value' => $item['line_item_id'],
  653. );
  654. if (isset($item['type']) && _uc_line_item_data($item['type'], 'stored') == TRUE) {
  655. $form['line_items'][$item['line_item_id']]['remove'] = array(
  656. '#type' => 'image_button',
  657. '#title' => t('Remove line item.'),
  658. '#src' => drupal_get_path('module', 'uc_store') . '/images/error.gif',
  659. '#button_type' => 'remove',
  660. '#submit' => array('uc_order_pane_line_items_submit', 'uc_order_pane_line_items_remove'),
  661. '#ajax' => array(
  662. 'callback' => 'uc_order_pane_line_items_update',
  663. ),
  664. '#return_value' => $item['line_item_id'],
  665. );
  666. $form['line_items'][$item['line_item_id']]['title'] = array(
  667. '#type' => 'textfield',
  668. '#title' => t('Title'),
  669. '#default_value' => $item['title'],
  670. '#size' => 40,
  671. '#maxlength' => 128,
  672. );
  673. $form['line_items'][$item['line_item_id']]['amount'] = array(
  674. '#type' => 'uc_price',
  675. '#title' => t('Amount'),
  676. '#default_value' => $item['amount'],
  677. '#size' => 6,
  678. '#allow_negative' => TRUE,
  679. );
  680. }
  681. else {
  682. $form['line_items'][$item['line_item_id']]['title'] = array(
  683. '#markup' => check_plain($item['title']),
  684. );
  685. $form['line_items'][$item['line_item_id']]['amount'] = array(
  686. '#theme' => 'uc_price',
  687. '#price' => $item['amount'],
  688. );
  689. }
  690. }
  691. return $form;
  692. case 'edit-theme':
  693. return drupal_render($form['add_line_item'])
  694. . drupal_render($form['line_items']);
  695. case 'edit-process':
  696. uc_order_pane_line_items_submit($form, $form_state);
  697. return;
  698. }
  699. }
  700. /**
  701. * @ingroup themeable
  702. */
  703. function theme_uc_order_pane_line_items($variables) {
  704. $form = $variables['form'];
  705. $output = '<table class="line-item-table">';
  706. foreach (element_children($form) as $field) {
  707. $form[$field]['title']['#title'] = '';
  708. $form[$field]['amount']['#title'] = '';
  709. $output .= '<tr><td class="li-title">'
  710. . drupal_render($form[$field]['li_id'])
  711. . drupal_render($form[$field]['remove'])
  712. . drupal_render($form[$field]['title'])
  713. . ':</td><td class="li-amount">'
  714. . drupal_render($form[$field]['amount'])
  715. . '</td></tr>';
  716. }
  717. $output .= '</table>' . drupal_render_children($form);
  718. return $output;
  719. }
  720. /**
  721. * Form submit callback: Update line items titles and amounts in an order.
  722. */
  723. function uc_order_pane_line_items_submit($form, &$form_state) {
  724. $values = $form_state['values'];
  725. if (is_array($values['line_items'])) {
  726. foreach ($values['line_items'] as $line) {
  727. if (is_numeric($line['li_id']) && intval($line['li_id']) > 0 && isset($line['title']) && isset($line['amount'])) {
  728. uc_order_update_line_item($line['li_id'], $line['title'], $line['amount']);
  729. }
  730. }
  731. }
  732. }
  733. /**
  734. * Order pane submit callback: Add a line item to an order.
  735. */
  736. function uc_order_pane_line_items_add($form, &$form_state) {
  737. $order = &$form_state['order'];
  738. $type = $form_state['values']['li_type_select'];
  739. uc_order_line_item_add($order->order_id, $type, _uc_line_item_data($type, 'title'), 0);
  740. $order->line_items = uc_order_load_line_items($order);
  741. $form_state['rebuild'] = TRUE;
  742. }
  743. /**
  744. * Order pane submit callback: Remove a line item from an order.
  745. */
  746. function uc_order_pane_line_items_remove($form, &$form_state) {
  747. $order = &$form_state['order'];
  748. $line_item_id = intval($form_state['triggering_element']['#return_value']);
  749. uc_order_delete_line_item($line_item_id);
  750. $order->line_items = uc_order_load_line_items($order);
  751. $form_state['rebuild'] = TRUE;
  752. }
  753. /**
  754. * AJAX callback to render the line items.
  755. */
  756. function uc_order_pane_line_items_update($form, &$form_state) {
  757. $commands[] = ajax_command_replace('#order-line-items', trim(drupal_render($form['line_items'])));
  758. $commands[] = ajax_command_prepend('#order-line-items', theme('status_messages'));
  759. return array('#type' => 'ajax', '#commands' => $commands);
  760. }
  761. /**
  762. * Handles the "Order Comments" order pane.
  763. */
  764. function uc_order_pane_order_comments($op, $order, &$form = NULL, &$form_state = NULL) {
  765. switch ($op) {
  766. case 'view':
  767. $comments = uc_order_comments_load($order->order_id);
  768. return tapir_get_table('uc_op_order_comments_view_table', $comments);
  769. case 'customer':
  770. $comments = uc_order_comments_load($order->order_id);
  771. $header = array(t('Date'), t('Status'), t('Message'));
  772. $rows[] = array(
  773. array('data' => format_date($order->created, 'uc_store'), 'class' => array('date')),
  774. array('data' => '-', 'class' => array('status')),
  775. array('data' => t('Order created.'), 'class' => array('message')),
  776. );
  777. if (count($comments) > 0) {
  778. foreach ($comments as $comment) {
  779. $rows[] = array(
  780. array('data' => format_date($comment->created, 'uc_store'), 'class' => array('date')),
  781. array('data' => $comment->title, 'class' => array('status')),
  782. array('data' => check_plain($comment->message), 'class' => array('message')),
  783. );
  784. }
  785. }
  786. $build = array(
  787. '#theme' => 'table',
  788. '#header' => $header,
  789. '#rows' => $rows,
  790. '#attributes' => array('class' => array('uc-order-comments')),
  791. );
  792. return $build;
  793. }
  794. }
  795. /**
  796. * Handles the "Admin Comments" order pane.
  797. */
  798. function uc_order_pane_admin_comments($op, $order, &$form = NULL, &$form_state = NULL) {
  799. global $user;
  800. switch ($op) {
  801. case 'view':
  802. $comments = uc_order_comments_load($order->order_id, TRUE);
  803. return tapir_get_table('uc_op_admin_comments_view_table', $comments);
  804. case 'edit-form':
  805. $form['admin_comment_field'] = array(
  806. '#type' => 'fieldset',
  807. '#title' => t('Add an admin comment'),
  808. '#collapsible' => TRUE,
  809. '#collapsed' => TRUE,
  810. );
  811. $form['admin_comment_field']['admin_comment'] = array(
  812. '#type' => 'textarea',
  813. '#description' => t('Admin comments are only seen by store administrators.'),
  814. );
  815. return $form;
  816. case 'edit-theme':
  817. $comments = uc_order_comments_load($form['order_id']['#value'], TRUE);
  818. if (is_array($comments) && count($comments) > 0) {
  819. foreach ($comments as $comment) {
  820. $items[] = '[' . theme('uc_uid', array('uid' => $comment->uid)) . '] ' . filter_xss_admin($comment->message);
  821. }
  822. }
  823. else {
  824. $items = array(t('No admin comments have been entered for this order.'));
  825. }
  826. $output = theme('item_list', array('items' => $items)) . drupal_render($form['admin_comment_field']);
  827. return $output;
  828. case 'edit-process':
  829. if (!empty($form_state['values']['admin_comment'])) {
  830. uc_order_comment_save($form_state['values']['order_id'], $user->uid, $form_state['values']['admin_comment']);
  831. }
  832. return;
  833. }
  834. }
  835. /**
  836. * Handles the "Update" order pane.
  837. */
  838. function uc_order_pane_update($op, $order, &$form = NULL, &$form_state = NULL) {
  839. switch ($op) {
  840. case 'view':
  841. return drupal_get_form('uc_order_view_update_form', $order);
  842. }
  843. }
  844. /**
  845. * Form to save order comments and update the order status.
  846. *
  847. * @see uc_order_view_update_form_submit()
  848. * @ingroup forms
  849. */
  850. function uc_order_view_update_form($form, &$form_state, $order) {
  851. $form['order_comment_field'] = array(
  852. '#type' => 'fieldset',
  853. '#title' => t('Add an order comment'),
  854. '#collapsible' => TRUE,
  855. '#collapsed' => TRUE,
  856. );
  857. $form['order_comment_field']['order_comment'] = array(
  858. '#type' => 'textarea',
  859. '#description' => t('Order comments are used primarily to communicate with the customer.'),
  860. );
  861. $form['admin_comment_field'] = array(
  862. '#type' => 'fieldset',
  863. '#title' => t('Add an admin comment'),
  864. '#collapsible' => TRUE,
  865. '#collapsed' => TRUE,
  866. );
  867. $form['admin_comment_field']['admin_comment'] = array(
  868. '#type' => 'textarea',
  869. '#description' => t('Admin comments are only seen by store administrators.'),
  870. );
  871. $form['current_status'] = array(
  872. '#type' => 'hidden',
  873. '#value' => $order->order_status,
  874. );
  875. $form['order_id'] = array(
  876. '#type' => 'hidden',
  877. '#value' => $order->order_id,
  878. );
  879. $form['controls'] = array(
  880. '#type' => 'container',
  881. '#attributes' => array('class' => array('uc-inline-form', 'clearfix')),
  882. '#weight' => 10,
  883. );
  884. foreach (uc_order_status_list() as $status) {
  885. $options[$status['id']] = $status['title'];
  886. }
  887. $form['controls']['status'] = array(
  888. '#type' => 'select',
  889. '#title' => t('Order status'),
  890. '#default_value' => $order->order_status,
  891. '#options' => $options,
  892. );
  893. $form['controls']['notify'] = array(
  894. '#type' => 'checkbox',
  895. '#title' => t('Send e-mail notification on update.'),
  896. );
  897. $form['controls']['actions'] = array('#type' => 'actions');
  898. $form['controls']['actions']['submit'] = array(
  899. '#type' => 'submit',
  900. '#value' => t('Update'),
  901. );
  902. return $form;
  903. }
  904. /**
  905. * Form submit handler for uc_order_view_update_form().
  906. *
  907. * @see uc_order_view_update_form()
  908. */
  909. function uc_order_view_update_form_submit($form, &$form_state) {
  910. global $user;
  911. if (!empty($form_state['values']['order_comment'])) {
  912. uc_order_comment_save($form_state['values']['order_id'], $user->uid, $form_state['values']['order_comment'], 'order', $form_state['values']['status'], $form_state['values']['notify']);
  913. }
  914. if (!empty($form_state['values']['admin_comment'])) {
  915. uc_order_comment_save($form_state['values']['order_id'], $user->uid, $form_state['values']['admin_comment']);
  916. }
  917. if ($form_state['values']['status'] != $form_state['values']['current_status']) {
  918. if (uc_order_update_status($form_state['values']['order_id'], $form_state['values']['status'])) {
  919. if (empty($form_state['values']['order_comment'])) {
  920. uc_order_comment_save($form_state['values']['order_id'], $user->uid, '-', 'order', $form_state['values']['status'], $form_state['values']['notify']);
  921. }
  922. }
  923. }
  924. // Let Rules send email if requested.
  925. if ($form_state['values']['notify']) {
  926. $order = uc_order_load($form_state['values']['order_id']);
  927. rules_invoke_event('uc_order_status_email_update', $order);
  928. }
  929. drupal_set_message(t('Order updated.'));
  930. }
  931. /**
  932. * Builds the order view products table.
  933. */
  934. function uc_op_products_view_table($order) {
  935. $table = array(
  936. '#type' => 'tapir_table',
  937. '#attributes' => array('class' => array('order-pane-table')),
  938. );
  939. $table['#columns']['qty'] = array(
  940. 'cell' => array(
  941. 'data' => theme('uc_qty_label'),
  942. 'class' => array('qty'),
  943. ),
  944. 'weight' => 0,
  945. );
  946. $table['#columns']['product'] = array(
  947. 'cell' => array(
  948. 'data' => t('Product'),
  949. 'class' => array('product'),
  950. ),
  951. 'weight' => 1,
  952. );
  953. $table['#columns']['model'] = array(
  954. 'cell' => array(
  955. 'data' => t('SKU'),
  956. 'class' => array('sku'),
  957. ),
  958. 'weight' => 2,
  959. );
  960. if (user_access('administer products')) {
  961. $table['#columns']['cost'] = array(
  962. 'cell' => array(
  963. 'data' => t('Cost'),
  964. 'class' => array('cost'),
  965. ),
  966. 'weight' => 3,
  967. );
  968. }
  969. $table['#columns']['price'] = array(
  970. 'cell' => array(
  971. 'data' => t('Price'),
  972. 'class' => array('price'),
  973. ),
  974. 'weight' => 4,
  975. );
  976. $table['#columns']['total'] = array(
  977. 'cell' => array(
  978. 'data' => t('Total'),
  979. 'class' => array('total'),
  980. ),
  981. 'weight' => 5,
  982. );
  983. if (!empty($order->products)) {
  984. $build = uc_order_product_view_multiple($order->products);
  985. $table['#rows'] = $build['uc_order_product'];
  986. }
  987. else {
  988. $table['#rows'][]['product'] = array(
  989. '#markup' => t('This order contains no products.'),
  990. '#cell_attributes' => array('colspan' => 'full'),
  991. );
  992. }
  993. return $table;
  994. }
  995. /**
  996. * Builds the order customer's view products table.
  997. */
  998. function uc_op_products_customer_table($order) {
  999. $table = array(
  1000. '#type' => 'tapir_table',
  1001. '#attributes' => array('class' => array('order-pane-table')),
  1002. );
  1003. $table['#columns']['qty'] = array(
  1004. 'cell' => array(
  1005. 'data' => theme('uc_qty_label'),
  1006. 'class' => array('qty'),
  1007. ),
  1008. 'weight' => 0,
  1009. );
  1010. $table['#columns']['product'] = array(
  1011. 'cell' => array(
  1012. 'data' => t('Product'),
  1013. 'class' => array('product'),
  1014. ),
  1015. 'weight' => 1,
  1016. );
  1017. $table['#columns']['model'] = array(
  1018. 'cell' => array(
  1019. 'data' => t('SKU'),
  1020. 'class' => array('sku'),
  1021. ),
  1022. 'weight' => 2,
  1023. );
  1024. if (user_access('administer products')) {
  1025. $table['#columns']['cost'] = array(
  1026. 'cell' => array(
  1027. 'data' => t('Cost'),
  1028. 'class' => array('cost'),
  1029. ),
  1030. 'weight' => 3,
  1031. );
  1032. }
  1033. $table['#columns']['price'] = array(
  1034. 'cell' => array(
  1035. 'data' => t('Price'),
  1036. 'class' => array('price'),
  1037. ),
  1038. 'weight' => 4,
  1039. );
  1040. $table['#columns']['total'] = array(
  1041. 'cell' => array(
  1042. 'data' => t('Total'),
  1043. 'class' => array('total'),
  1044. ),
  1045. 'weight' => 5,
  1046. );
  1047. if (!empty($order->products)) {
  1048. $build = uc_order_product_view_multiple($order->products);
  1049. $table['#rows'] = $build['uc_order_product'];
  1050. }
  1051. else {
  1052. $table['#rows'][]['product'] = array(
  1053. '#markup' => t('This order contains no products.'),
  1054. '#cell_attributes' => array('colspan' => 'full'),
  1055. );
  1056. }
  1057. return $table;
  1058. }
  1059. /**
  1060. * TAPIr table for products pane on the order edit page.
  1061. */
  1062. function uc_op_products_edit_table() {
  1063. $table = array(
  1064. '#type' => 'tapir_table',
  1065. '#tree' => TRUE,
  1066. '#attributes' => array('id' => 'order-edit-products', 'class' => array('order-pane-table')),
  1067. );
  1068. $table['#columns']['remove'] = array(
  1069. 'cell' => t('Remove'),
  1070. 'weight' => 0,
  1071. );
  1072. $table['#columns']['qty'] = array(
  1073. 'cell' => theme('uc_qty_label'),
  1074. 'weight' => 1,
  1075. );
  1076. $table['#columns']['title'] = array(
  1077. 'cell' => t('Name'),
  1078. 'weight' => 2,
  1079. );
  1080. $table['#columns']['model'] = array(
  1081. 'cell' => t('SKU'),
  1082. 'weight' => 3,
  1083. );
  1084. $table['#columns']['weight'] = array(
  1085. 'cell' => t('Weight'),
  1086. 'weight' => 4,
  1087. );
  1088. $table['#columns']['weight_units'] = array(
  1089. 'cell' => t('Units'),
  1090. 'weight' => 5,
  1091. );
  1092. $table['#columns']['cost'] = array(
  1093. 'cell' => t('Cost'),
  1094. 'weight' => 6,
  1095. );
  1096. $table['#columns']['price'] = array(
  1097. 'cell' => t('Price'),
  1098. 'weight' => 7,
  1099. );
  1100. return $table;
  1101. }
  1102. /**
  1103. * Builds the order comments table.
  1104. */
  1105. function uc_op_order_comments_view_table($comments) {
  1106. $table = array(
  1107. '#type' => 'tapir_table',
  1108. '#attributes' => array('class' => array('order-pane-table uc-order-comments')),
  1109. );
  1110. $table['#columns']['date'] = array(
  1111. 'cell' => array('data' => t('Date'), 'class' => array('date')),
  1112. 'weight' => 0,
  1113. );
  1114. $table['#columns']['user'] = array(
  1115. 'cell' => array('data' => t('User'), 'class' => array('user')),
  1116. 'weight' => 1,
  1117. );
  1118. $table['#columns']['notified'] = array(
  1119. 'cell' => array('data' => t('Notified'), 'class' => array('notified')),
  1120. 'weight' => 2,
  1121. );
  1122. $table['#columns']['status'] = array(
  1123. 'cell' => array('data' => t('Status'), 'class' => array('status')),
  1124. 'weight' => 3,
  1125. );
  1126. $table['#columns']['comment'] = array(
  1127. 'cell' => array('data' => t('Comment'), 'class' => array('message')),
  1128. 'weight' => 4,
  1129. );
  1130. if (is_array($comments) && !empty($comments)) {
  1131. foreach ($comments as $comment) {
  1132. $data = array();
  1133. $data['date'] = array(
  1134. '#markup' => format_date($comment->created, 'short'),
  1135. '#cell_attributes' => array('class' => 'date'),
  1136. );
  1137. $data['user'] = array(
  1138. '#markup' => theme('uc_uid', array('uid' => $comment->uid)),
  1139. '#cell_attributes' => array('class' => 'user'),
  1140. );
  1141. $icon = $comment->notified ? 'true-icon.gif' : 'false-icon.gif';
  1142. $data['notified'] = array(
  1143. '#markup' => theme('image', array('path' => drupal_get_path('module', 'uc_order') . '/images/' . $icon)),
  1144. '#cell_attributes' => array('class' => 'notified'),
  1145. );
  1146. $data['status'] = array(
  1147. '#markup' => $comment->title,
  1148. '#cell_attributes' => array('class' => 'status'),
  1149. );
  1150. $data['comment'] = array(
  1151. '#markup' => check_plain($comment->message),
  1152. '#cell_attributes' => array('class' => 'message'),
  1153. );
  1154. $table['#rows'][] = $data;
  1155. }
  1156. }
  1157. else {
  1158. $data['comment'] = array(
  1159. '#markup' => t('This order has no comments associated with it.'),
  1160. '#cell_attributes' => array('colspan' => 'full'),
  1161. );
  1162. $table['#rows'][] = $data;
  1163. }
  1164. return $table;
  1165. }
  1166. /**
  1167. * Builds the order admin comments table.
  1168. */
  1169. function uc_op_admin_comments_view_table($comments) {
  1170. $table = array(
  1171. '#type' => 'tapir_table',
  1172. '#attributes' => array('class' => array('order-pane-table uc-order-comments')),
  1173. );
  1174. $table['#columns']['date'] = array(
  1175. 'cell' => array('data' => t('Date'), 'class' => array('date')),
  1176. 'weight' => 0,
  1177. );
  1178. $table['#columns']['user'] = array(
  1179. 'cell' => array('data' => t('User'), 'class' => array('user')),
  1180. 'weight' => 1,
  1181. );
  1182. $table['#columns']['comment'] = array(
  1183. 'cell' => array('data' => t('Comment'), 'class' => array('message')),
  1184. 'weight' => 2,
  1185. );
  1186. if (is_array($comments) && !empty($comments)) {
  1187. foreach ($comments as $comment) {
  1188. $data = array();
  1189. $data['date'] = array(
  1190. '#markup' => format_date($comment->created, 'short'),
  1191. '#cell_attributes' => array('class' => 'date'),
  1192. );
  1193. $data['user'] = array(
  1194. '#markup' => theme('uc_uid', array('uid' => $comment->uid)),
  1195. '#cell_attributes' => array('class' => 'user'),
  1196. );
  1197. $data['comment'] = array(
  1198. '#markup' => filter_xss_admin($comment->message),
  1199. '#cell_attributes' => array('class' => 'message'),
  1200. );
  1201. $table['#rows'][] = $data;
  1202. }
  1203. }
  1204. else {
  1205. $data['comment'] = array(
  1206. '#markup' => t('This order has no admin comments associated with it.'),
  1207. '#cell_attributes' => array('colspan' => 'full'),
  1208. );
  1209. $table['#rows'][] = $data;
  1210. }
  1211. return $table;
  1212. }
  1213. /**
  1214. * Builds a list of order panes defined in the enabled modules.
  1215. */
  1216. function _uc_order_pane_list($view = 'view') {
  1217. static $panes = array();
  1218. if (count($panes) > 0) {
  1219. return $panes;
  1220. }
  1221. foreach (module_invoke_all('uc_order_pane') as $id => $pane) {
  1222. // Preserve backward compatibility for panes with no key specified.
  1223. if (is_numeric($id)) {
  1224. $id = $pane['id'];
  1225. }
  1226. // Set defaults.
  1227. $pane += array(
  1228. 'id' => $id,
  1229. 'enabled' => TRUE,
  1230. 'weight' => 0,
  1231. );
  1232. $panes[$id] = $pane;
  1233. }
  1234. // Allow other modules to alter the defaults.
  1235. drupal_alter('uc_order_pane', $panes);
  1236. uasort($panes, 'uc_weight_sort');
  1237. return $panes;
  1238. }
  1239. /**
  1240. * Returns data from an order pane by pane ID and the array key.
  1241. */
  1242. function _uc_order_pane_data($pane_id, $key) {
  1243. $panes = _uc_order_pane_list();
  1244. return $panes[$pane_id][$key];
  1245. }