uc_order.order_pane.inc 43 KB

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