uc_order.rules.inc 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922
  1. <?php
  2. /**
  3. * @file
  4. * This file contains the Rules hooks and functions necessary to make the order
  5. * related entity, conditions, events, and actions work.
  6. */
  7. /**
  8. * Implements hook_rules_data_info().
  9. */
  10. function uc_order_rules_data_info() {
  11. $types['uc_order'] = array(
  12. 'label' => t('Ubercart order object'),
  13. 'wrap' => TRUE,
  14. 'group' => t('Ubercart'),
  15. );
  16. $types['uc_order_product'] = array(
  17. 'label' => t('Ubercart ordered product'),
  18. 'wrap' => TRUE,
  19. 'parent' => 'node',
  20. 'group' => t('Ubercart'),
  21. );
  22. $types['uc_line_item'] = array(
  23. 'label' => t('Order line item'),
  24. 'wrap' => TRUE,
  25. 'group' => t('Ubercart'),
  26. 'token type' => FALSE,
  27. );
  28. return $types;
  29. }
  30. /**
  31. * Implements hook_rules_event_info().
  32. */
  33. function uc_order_rules_event_info() {
  34. $events['uc_order_status_update'] = array(
  35. 'label' => t('Order status gets updated'),
  36. 'group' => t('Order'),
  37. 'variables' => array(
  38. 'order' => array(
  39. 'type' => 'uc_order',
  40. 'label' => t('Original order'),
  41. ),
  42. 'updated_order' => array(
  43. 'type' => 'uc_order',
  44. 'label' => t('Updated order'),
  45. ),
  46. ),
  47. );
  48. $events['uc_order_status_email_update'] = array(
  49. 'label' => t('E-mail requested for order status update'),
  50. 'group' => t('Order'),
  51. 'variables' => array(
  52. 'order' => array(
  53. 'type' => 'uc_order',
  54. 'label' => t('Order'),
  55. ),
  56. ),
  57. );
  58. $events['uc_order_delete'] = array(
  59. 'label' => t('An order is being deleted'),
  60. 'group' => t('Order'),
  61. 'variables' => array(
  62. 'order' => array(
  63. 'type' => 'uc_order',
  64. 'label' => t('Order'),
  65. ),
  66. ),
  67. );
  68. return $events;
  69. }
  70. /**
  71. * Implements hook_rules_condition_info().
  72. */
  73. function uc_order_rules_condition_info() {
  74. $conditions['uc_order_condition_order_state'] = array(
  75. 'label' => t("Check an order's state"),
  76. 'group' => t('Order'),
  77. 'parameter' => array(
  78. 'order' => array(
  79. 'type' => 'uc_order',
  80. 'label' => t('Order'),
  81. ),
  82. 'order_state' => array(
  83. 'type' => 'text',
  84. 'label' => t('Order state'),
  85. 'options list' => 'uc_order_condition_order_state_options',
  86. 'restriction' => 'input',
  87. ),
  88. ),
  89. );
  90. $conditions['uc_order_condition_delivery_country'] = array(
  91. 'label' => t("Check an order's shipping country"),
  92. 'group' => t('Order'),
  93. 'parameter' => array(
  94. 'order' => array(
  95. 'type' => 'uc_order',
  96. 'label' => t('Order'),
  97. ),
  98. 'countries' => array(
  99. 'type' => 'list<integer>',
  100. 'label' => t('Countries'),
  101. 'options list' => 'uc_country_option_list',
  102. 'restriction' => 'input',
  103. ),
  104. ),
  105. );
  106. $conditions['uc_order_condition_billing_country'] = array(
  107. 'label' => t("Check an order's billing country"),
  108. 'group' => t('Order'),
  109. 'parameter' => array(
  110. 'order' => array(
  111. 'type' => 'uc_order',
  112. 'label' => t('Order'),
  113. ),
  114. 'countries' => array(
  115. 'type' => 'list<integer>',
  116. 'label' => t('Countries'),
  117. 'options list' => 'uc_country_option_list',
  118. 'restriction' => 'input',
  119. ),
  120. ),
  121. );
  122. $conditions['uc_order_condition_has_products'] = array(
  123. 'label' => t("Check an order's products"),
  124. 'group' => t('Order: Product'),
  125. 'base' => 'uc_order_condition_has_products',
  126. 'parameter' => array(
  127. 'order' => array(
  128. 'type' => 'uc_order',
  129. 'label' => t('Order'),
  130. ),
  131. 'products' => array(
  132. 'type' => 'list<text>',
  133. 'label' => t('Products'),
  134. 'options list' => 'uc_order_condition_has_products_options',
  135. 'restriction' => 'input',
  136. ),
  137. 'required' => array(
  138. 'type' => 'boolean',
  139. 'label' => t('Require all selected products'),
  140. 'description' => t('Select to require that order must contain all selected products. Otherwise, order must contain at least one of the selected products.'),
  141. ),
  142. 'forbidden' => array(
  143. 'type' => 'boolean',
  144. 'label' => t('Forbid other products'),
  145. ),
  146. ),
  147. );
  148. $conditions['uc_order_condition_count_products'] = array(
  149. 'label' => t("Check an order's number of products"),
  150. 'group' => t('Order: Product'),
  151. 'base' => 'uc_order_condition_count_products',
  152. 'parameter' => array(
  153. 'order' => array(
  154. 'type' => 'uc_order',
  155. 'label' => t('Order'),
  156. ),
  157. 'products' => array(
  158. 'type' => 'list<integer>',
  159. 'label' => t('Products'),
  160. 'options list' => 'uc_order_condition_products_options',
  161. 'restriction' => 'input',
  162. ),
  163. 'product_count_value' => array(
  164. 'type' => 'integer',
  165. 'label' => t('Product count value'),
  166. ),
  167. 'product_count_comparison' => array(
  168. 'type' => 'text',
  169. 'label' => t('Operator'),
  170. 'options list' => 'uc_order_condition_value_operator_options',
  171. ),
  172. ),
  173. );
  174. $conditions['uc_order_condition_products_weight'] = array(
  175. 'label' => t("Check an order's total weight"),
  176. 'group' => t('Order: Product'),
  177. 'help' => t('Compare the weight of all of the products, or the weight of just one type in the order.'),
  178. 'base' => 'uc_order_condition_products_weight',
  179. 'parameter' => array(
  180. 'order' => array(
  181. 'type' => 'uc_order',
  182. 'label' => t('Order'),
  183. ),
  184. 'products' => array(
  185. 'type' => 'list<integer>',
  186. 'label' => t('Products'),
  187. 'options list' => 'uc_order_condition_products_options',
  188. 'restriction' => 'input',
  189. ),
  190. 'weight_units' => array(
  191. 'type' => 'text',
  192. 'label' => t('Unit of measurement'),
  193. 'options list' => 'uc_order_condition_weight_units_options',
  194. ),
  195. 'product_weight_value' => array(
  196. 'type' => 'decimal',
  197. 'label' => t('Product weight value'),
  198. ),
  199. 'product_weight_comparison' => array(
  200. 'type' => 'text',
  201. 'label' => t('Operator'),
  202. 'options list' => 'uc_order_condition_value_operator_options',
  203. ),
  204. ),
  205. );
  206. $conditions['uc_order_condition_is_shippable'] = array(
  207. 'label' => t('Check if an order can be shipped'),
  208. 'group' => t('Order'),
  209. 'base' => 'uc_order_condition_is_shippable',
  210. 'parameter' => array(
  211. 'order' => array(
  212. 'type' => 'uc_order',
  213. 'label' => t('Order'),
  214. ),
  215. ),
  216. );
  217. $conditions['uc_order_condition_has_product_class'] = array(
  218. 'label' => t("Check an order's product classes"),
  219. 'group' => t('Order: Product'),
  220. 'base' => 'uc_order_condition_has_product_class',
  221. 'parameter' => array(
  222. 'order' => array(
  223. 'type' => 'uc_order',
  224. 'label' => t('Order'),
  225. ),
  226. 'product_classes' => array(
  227. 'type' => 'list<text>',
  228. 'label' => t('Product Classes'),
  229. 'options list' => 'uc_order_condition_has_product_class_classes_options',
  230. 'restriction' => 'input',
  231. ),
  232. 'required' => array(
  233. 'type' => 'boolean',
  234. 'label' => t('Require all selected product classes'),
  235. 'description' => t('Select to require that order must contain all selected product classes. Otherwise, order must contain at least one of the selected product classes.'),
  236. ),
  237. 'forbidden' => array(
  238. 'type' => 'boolean',
  239. 'label' => t('Forbid other product classes'),
  240. ),
  241. ),
  242. );
  243. $conditions['uc_order_condition_total'] = array(
  244. 'label' => t("Check an order's total"),
  245. 'group' => t('Order'),
  246. 'base' => 'uc_order_condition_total',
  247. 'parameter' => array(
  248. 'order' => array(
  249. 'type' => 'uc_order',
  250. 'label' => t('Order'),
  251. ),
  252. 'op' => array(
  253. 'type' => 'text',
  254. 'label' => t('Operator'),
  255. 'description' => t('The comparison operator.'),
  256. 'default value' => '==',
  257. 'options list' => 'uc_order_condition_value_operator_options',
  258. 'restriction' => 'input',
  259. ),
  260. 'value' => array(
  261. 'type' => 'decimal',
  262. 'label' => t('Data value'),
  263. 'description' => t('The value to compare the data with.'),
  264. ),
  265. ),
  266. );
  267. $conditions['uc_order_condition_subtotal'] = array(
  268. 'label' => t("Check an order's subtotal"),
  269. 'group' => t('Order'),
  270. 'base' => 'uc_order_condition_subtotal',
  271. 'parameter' => array(
  272. 'order' => array(
  273. 'type' => 'uc_order',
  274. 'label' => t('Order'),
  275. ),
  276. 'op' => array(
  277. 'type' => 'text',
  278. 'label' => t('Operator'),
  279. 'description' => t('The comparison operator.'),
  280. 'default value' => '==',
  281. 'options list' => 'uc_order_condition_value_operator_options',
  282. 'restriction' => 'input',
  283. ),
  284. 'value' => array(
  285. 'type' => 'decimal',
  286. 'label' => t('Data value'),
  287. 'description' => t('The value to compare the data with.'),
  288. ),
  289. ),
  290. );
  291. return $conditions;
  292. }
  293. /**
  294. * Implements hook_rules_action_info().
  295. */
  296. function uc_order_rules_action_info() {
  297. $order_arg = array(
  298. 'type' => 'uc_order',
  299. 'label' => t('Order'),
  300. );
  301. $actions['uc_order_update_status'] = array(
  302. 'label' => t('Update the order status'),
  303. 'group' => t('Order'),
  304. 'base' => 'uc_order_action_update_status',
  305. 'parameter' => array(
  306. 'order' => $order_arg,
  307. 'order_status' => array(
  308. 'type' => 'text',
  309. 'label' => t('Status'),
  310. 'options list' => 'uc_order_action_update_status_options',
  311. ),
  312. ),
  313. );
  314. $actions['uc_order_action_add_comment'] = array(
  315. 'label' => t('Add a comment to the order'),
  316. 'group' => t('Order'),
  317. 'base' => 'uc_order_action_add_comment',
  318. 'parameter' => array(
  319. 'order' => $order_arg,
  320. 'comment' => array(
  321. 'type' => 'text',
  322. 'label' => t('Comment'),
  323. ),
  324. 'comment_type' => array(
  325. 'type' => 'text',
  326. 'label' => t('Comment type'),
  327. 'restriction' => 'input',
  328. 'options list' => 'uc_order_action_order_comment_types',
  329. ),
  330. ),
  331. );
  332. $actions['uc_order_email'] = array(
  333. 'label' => t('Send an order email'),
  334. 'group' => t('Order'),
  335. 'base' => 'uc_order_action_email',
  336. 'parameter' => array(
  337. 'order' => $order_arg,
  338. 'from' => array(
  339. 'type' => 'text',
  340. 'label' => t('Sender'),
  341. 'description' => t("Enter the 'From' email address, or leave blank to use your store email address. You may use order tokens for dynamic email addresses."),
  342. 'optional' => TRUE,
  343. ),
  344. 'addresses' => array(
  345. 'type' => 'text',
  346. 'label' => t('Recipients'),
  347. 'description' => t('Enter the email addresses to receive the notifications, one on each line. You may use order tokens for dynamic email addresses.'),
  348. ),
  349. 'subject' => array(
  350. 'type' => 'text',
  351. 'label' => t('Subject'),
  352. 'translatable' => TRUE,
  353. ),
  354. 'message' => array(
  355. 'type' => 'text',
  356. 'label' => t('Message'),
  357. 'translatable' => TRUE,
  358. ),
  359. 'format' => array(
  360. 'type' => 'text',
  361. 'label' => t('Message format'),
  362. 'options list' => 'uc_order_message_formats',
  363. ),
  364. ),
  365. );
  366. $actions['uc_order_email_invoice'] = array(
  367. 'label' => t('Email an order invoice'),
  368. 'group' => t('Order'),
  369. 'base' => 'uc_order_action_email_invoice',
  370. 'parameter' => array(
  371. 'order' => $order_arg,
  372. 'from' => array(
  373. 'type' => 'text',
  374. 'label' => t('Sender'),
  375. 'description' => t("Enter the 'From' email address, or leave blank to use your store email address. You may use order tokens for dynamic email addresses."),
  376. 'optional' => TRUE,
  377. ),
  378. 'addresses' => array(
  379. 'type' => 'text',
  380. 'label' => t('Recipients'),
  381. 'description' => t('Enter the email addresses to receive the invoice, one on each line. You may use order tokens for dynamic email addresses.'),
  382. ),
  383. 'subject' => array(
  384. 'type' => 'text',
  385. 'label' => t('Subject'),
  386. 'translatable' => TRUE,
  387. ),
  388. 'template' => array(
  389. 'type' => 'text',
  390. 'label' => t('Invoice template'),
  391. 'options list' => 'uc_order_template_options',
  392. 'restriction' => 'input',
  393. ),
  394. 'view' => array(
  395. 'type' => 'text',
  396. 'label' => t('Included information'),
  397. 'options list' => 'uc_order_action_email_invoice_view_options',
  398. 'restriction' => 'input',
  399. ),
  400. ),
  401. );
  402. return $actions;
  403. }
  404. /**
  405. * Checks the current order state.
  406. */
  407. function uc_order_condition_order_state($order, $order_state) {
  408. return uc_order_status_data($order->order_status, 'state') == $order_state;
  409. }
  410. /**
  411. * Options callback.
  412. *
  413. * @see uc_order_condition_order_state()
  414. */
  415. function uc_order_condition_order_state_options() {
  416. foreach (uc_order_state_list('general') as $id => $state) {
  417. $options[$id] = $state['title'];
  418. }
  419. foreach (uc_order_state_list('specific') as $id => $state) {
  420. $options[$id] = $state['title'];
  421. }
  422. return $options;
  423. }
  424. /**
  425. * Checks that the order has one of the selected delivery countries.
  426. */
  427. function uc_order_condition_delivery_country($order, $countries) {
  428. return in_array($order->delivery_country, $countries);
  429. }
  430. /**
  431. * Checks that the order has one of the selected billing countries.
  432. */
  433. function uc_order_condition_billing_country($order, $countries) {
  434. return in_array($order->billing_country, $countries);
  435. }
  436. /**
  437. * Checks that the order has the selected combination of product classes.
  438. *
  439. * @param object $order
  440. * The order to check.
  441. * @param array $product_classes
  442. * An array of strings containing the product classes (node content
  443. * types) to check against.
  444. * @param boolean $required
  445. * TRUE to require all product classes be present in the order. FALSE
  446. * to require at least one be present.
  447. * @param boolean $forbidden
  448. * TRUE to require that only the listed product classes be present. FALSE
  449. * to allow products with other classes.
  450. *
  451. * @return boolean
  452. * Whether the order meets the specified conditions.
  453. */
  454. function uc_order_condition_has_product_class($order, $product_classes, $required, $forbidden) {
  455. $order_product_classes = array();
  456. foreach ($order->products as $product) {
  457. if (!empty($product->type)) {
  458. // If present, use the product type from {uc_order_products}.data.type.
  459. $order_product_classes[] = $product->type;
  460. }
  461. else {
  462. // Otherwise, use the node type. If the node can't be loaded, ignore
  463. // this product.
  464. $node = node_load($product->nid);
  465. if (!empty($node)) {
  466. $order_product_classes[] = $node->type;
  467. }
  468. }
  469. }
  470. $required_product_classes = array_intersect($product_classes, $order_product_classes);
  471. if ($required) {
  472. $required_check = ($required_product_classes == $product_classes);
  473. }
  474. else {
  475. $required_check = (bool) count($required_product_classes);
  476. }
  477. if ($forbidden) {
  478. $forbidden_product_classes = array_diff($order_product_classes, $product_classes);
  479. $forbidden_check = (bool) count($forbidden_product_classes);
  480. }
  481. else {
  482. $forbidden_check = FALSE;
  483. }
  484. return $required_check && !$forbidden_check;
  485. }
  486. /**
  487. * Options callback.
  488. *
  489. * @return array
  490. * Associative array of all Ubercart product classes indexed by class ID.
  491. *
  492. * @see uc_order_condition_has_product_class()
  493. */
  494. function uc_order_condition_has_product_class_classes_options() {
  495. $options = array();
  496. $result = db_query('SELECT * FROM {uc_product_classes}');
  497. foreach ($result as $class) {
  498. $options += array($class->pcid => $class->name);
  499. }
  500. return $options;
  501. }
  502. /**
  503. * Checks that the order has the selected combination of products.
  504. */
  505. function uc_order_condition_has_products($order, $products, $required, $forbidden) {
  506. $order_products = array();
  507. foreach ($order->products as $product) {
  508. $order_products[] = $product->model;
  509. }
  510. $required_products = array_intersect($products, $order_products);
  511. if ($required) {
  512. $required_check = $required_products == $products;
  513. }
  514. else {
  515. $required_check = (bool)count($required_products);
  516. }
  517. if ($forbidden) {
  518. $forbidden_products = array_diff($order_products, $products);
  519. $forbidden_check = (bool)count($forbidden_products);
  520. }
  521. else {
  522. $forbidden_check = FALSE;
  523. }
  524. return $required_check && !$forbidden_check;
  525. }
  526. /**
  527. * Options callback.
  528. *
  529. * @see uc_order_condition_has_products()
  530. */
  531. function uc_order_condition_has_products_options() {
  532. $options = array();
  533. $result = db_query('SELECT nid FROM {uc_products}');
  534. foreach ($result as $row) {
  535. $options += uc_product_get_models($row->nid, FALSE);
  536. }
  537. asort($options);
  538. return $options;
  539. }
  540. /**
  541. * Checks that the order has the selected number of products.
  542. *
  543. * @see uc_order_condition_count_products_form()
  544. */
  545. function uc_order_condition_count_products($order, $products, $count, $op) {
  546. $totals = array('all' => 0);
  547. $total = 0;
  548. foreach ($order->products as $product) {
  549. $totals['all'] += $product->qty;
  550. if (isset($totals[$product->nid])) {
  551. $totals[$product->nid] += $product->qty;
  552. }
  553. else {
  554. $totals[$product->nid] = $product->qty;
  555. }
  556. }
  557. if (in_array('all', $products)) {
  558. $total = $totals['all'];
  559. }
  560. else {
  561. foreach ($products as $product) {
  562. if (isset($totals[$product])) {
  563. $total += $totals[$product];
  564. }
  565. }
  566. }
  567. return uc_order_condition_value_operator_comparison($total, $op, $count);
  568. }
  569. /**
  570. * Product options callback.
  571. */
  572. function uc_order_condition_products_options() {
  573. $options = array('all' => t('- All products -'));
  574. $options += db_query('SELECT nid, model FROM {uc_products} ORDER BY model')->fetchAllKeyed();
  575. return $options;
  576. }
  577. /**
  578. * Operator options callback.
  579. */
  580. function uc_order_condition_value_operator_options() {
  581. return array(
  582. 'less' => t('Total is less than specified value.'),
  583. 'less_equal' => t('Total is less than or equal to specified value.'),
  584. 'equal' => t('Total is equal to specified value.'),
  585. 'greater_equal' => t('Total is greater than or equal to specified value.'),
  586. 'greater' => t('Total is greater than specified value.'),
  587. );
  588. }
  589. /**
  590. * Checks the weight of the order's products.
  591. *
  592. * @see uc_order_condition_products_weight_form()
  593. */
  594. function uc_order_condition_products_weight($order, $products, $weight_units, $weight_value, $op) {
  595. $totals = array('all' => 0);
  596. $total = 0;
  597. foreach ($order->products as $product) {
  598. $unit_conversion = uc_weight_conversion($product->weight_units, $weight_units);
  599. $totals['all'] += $product->qty * $product->weight * $unit_conversion;
  600. $totals[$product->nid] = $product->qty * $product->weight * $unit_conversion;
  601. }
  602. if (in_array('all', $products)) {
  603. $total = $totals['all'];
  604. }
  605. else {
  606. foreach ($products as $product) {
  607. if (isset($totals[$product])) {
  608. $total += $totals[$product];
  609. }
  610. }
  611. }
  612. return uc_order_condition_value_operator_comparison($total, $op, $weight_value);
  613. }
  614. /**
  615. * Weight units options callback.
  616. */
  617. function uc_order_condition_weight_units_options() {
  618. return array(
  619. 'lb' => t('Pounds'),
  620. 'kg' => t('Kilograms'),
  621. 'oz' => t('Ounces'),
  622. 'g' => t('Grams'),
  623. );
  624. }
  625. /**
  626. * Checks that the order is shippable.
  627. */
  628. function uc_order_condition_is_shippable($order, $settings) {
  629. return uc_order_is_shippable($order);
  630. }
  631. /**
  632. * Updates an order's status.
  633. *
  634. * @see uc_order_action_update_status_form()
  635. */
  636. function uc_order_action_update_status($order, $status) {
  637. if (uc_order_update_status($order->order_id, $status)) {
  638. $order->order_status = $status;
  639. }
  640. }
  641. /**
  642. * @see uc_order_action_update_status()
  643. */
  644. function uc_order_action_update_status_options() {
  645. $options = array();
  646. foreach (uc_order_status_list('general') as $status) {
  647. $options[$status['id']] = $status['title'];
  648. }
  649. foreach (uc_order_status_list('specific') as $status) {
  650. $options[$status['id']] = $status['title'];
  651. }
  652. return $options;
  653. }
  654. /**
  655. * Adds a comment to an order.
  656. *
  657. * @see uc_order_action_add_comment_form()
  658. */
  659. function uc_order_action_add_comment($order, $comment, $comment_type) {
  660. uc_order_comment_save($order->order_id, 0,
  661. token_replace($comment, array('uc_order' => $order)),
  662. $comment_type == 'admin' ? 'admin' : 'order',
  663. $order->order_status, $comment_type == 'notified');
  664. }
  665. /**
  666. * @see uc_order_action_add_comment()
  667. */
  668. function uc_order_action_order_comment_types() {
  669. return array(
  670. 'admin' => t('Enter this as an admin comment.'),
  671. 'order' => t('Enter this as a customer order comment.'),
  672. 'notified' => t('Enter this as a customer order comment with a notified icon.'),
  673. );
  674. }
  675. /**
  676. * Sends an email concerning an order.
  677. *
  678. * The 'Sender', 'Recipients', 'Subject', and 'Message' fields accept
  679. * order token replacements.
  680. *
  681. * @see uc_order_action_email_form()
  682. */
  683. function uc_order_action_email($order, $from, $addresses, $subject, $message, $format) {
  684. $settings = array(
  685. 'from' => $from,
  686. 'addresses' => $addresses,
  687. 'subject' => $subject,
  688. 'message' => $message,
  689. 'format' => $format,
  690. );
  691. // Token replacements for the subject and body
  692. $settings['replacements'] = array(
  693. 'uc_order' => $order,
  694. );
  695. // Apply token replacements to the 'from' e-mail address.
  696. $from = token_replace($settings['from'], $settings['replacements']);
  697. if (empty($from)) {
  698. $from = uc_store_email_from();
  699. }
  700. // Apply token replacements to 'recipient' e-mail addresses.
  701. $addresses = token_replace($settings['addresses'], $settings['replacements']);
  702. // Split up our recipient e-mail addresses.
  703. $recipients = array();
  704. foreach (explode("\n", $addresses) as $address) {
  705. $address = trim($address);
  706. // Remove blank lines
  707. if (!empty($address)) {
  708. $recipients[] = $address;
  709. }
  710. }
  711. foreach ($recipients as $email) {
  712. $sent = drupal_mail('uc_order', 'action-mail', $email, uc_store_mail_recipient_language($email), $settings, $from);
  713. if (!$sent['result']) {
  714. watchdog('uc_order', 'Attempt to e-mail @email concerning order @order_id failed.', array('@email' => $email, '@order_id' => $order->order_id), WATCHDOG_ERROR);
  715. }
  716. }
  717. }
  718. /**
  719. * Options list callback for message formats.
  720. */
  721. function uc_order_message_formats() {
  722. global $user;
  723. $options = array();
  724. $formats = filter_formats($user);
  725. foreach ($formats as $format) {
  726. $options[$format->format] = $format->name;
  727. }
  728. return $options;
  729. }
  730. /**
  731. * Emails an invoice.
  732. *
  733. * The 'Sender', 'Subject' and 'Addresses' fields take order token replacements.
  734. */
  735. function uc_order_action_email_invoice($order, $from, $addresses, $subject, $template, $view) {
  736. $settings = array(
  737. 'from' => $from,
  738. 'addresses' => $addresses,
  739. 'subject' => $subject,
  740. 'template' => $template,
  741. 'view' => $view,
  742. );
  743. // Token replacements for the from, subject and body
  744. $settings['replacements'] = array(
  745. 'uc_order' => $order,
  746. );
  747. // Apply token replacements to the 'from' e-mail address.
  748. $from = token_replace($settings['from'], $settings['replacements']);
  749. if (empty($from)) {
  750. $from = uc_store_email_from();
  751. }
  752. // Apply token replacements to 'recipient' e-mail addresses.
  753. $addresses = token_replace($settings['addresses'], $settings['replacements']);
  754. // Split up our recipient e-mail addresses.
  755. $recipients = array();
  756. foreach (explode("\n", $addresses) as $address) {
  757. $address = trim($address);
  758. // Remove blank lines
  759. if (!empty($address)) {
  760. $recipients[] = $address;
  761. }
  762. }
  763. $settings['message'] = theme('uc_order', array('order' => $order, 'op' => $settings['view'], 'template' => $settings['template']));
  764. foreach ($recipients as $email) {
  765. $sent = drupal_mail('uc_order', 'action-mail', $email, uc_store_mail_recipient_language($email), $settings, $from);
  766. if (!$sent['result']) {
  767. watchdog('uc_order', 'Attempt to e-mail invoice for order @order_id to @email failed.', array('@email' => $email, '@order_id' => $order->order_id), WATCHDOG_ERROR);
  768. }
  769. }
  770. }
  771. /**
  772. * @see uc_order_action_email_invoice()
  773. */
  774. function uc_order_action_email_invoice_view_options() {
  775. return array(
  776. 'print' => t('Show the business header and shipping method.'),
  777. 'admin-mail' => t('Show all of the above plus the help text, email text, and store footer.'),
  778. 'checkout-mail' => t('Show all of the above plus the "thank you" message.'),
  779. );
  780. }
  781. /**
  782. * Value comparison.
  783. *
  784. * @param float $source
  785. * The source value.
  786. * @param string $op
  787. * The comparison operator.
  788. * @param float $target
  789. * The target value.
  790. *
  791. * @return bool
  792. * Whether the comparison meets the specified conditions.
  793. *
  794. * @see uc_order_condition_value_operator_options
  795. */
  796. function uc_order_condition_value_operator_comparison($source, $op, $target) {
  797. switch ($op) {
  798. case 'less':
  799. return $source < $target;
  800. case 'less_equal':
  801. return $source <= $target;
  802. case 'equal':
  803. return $source == $target;
  804. case 'greater_equal':
  805. return $source >= $target;
  806. case 'greater':
  807. return $source > $target;
  808. }
  809. }
  810. /**
  811. * Compare order total.
  812. *
  813. * @param object $order
  814. * The order to check.
  815. * @param string $op
  816. * The comparison operator.
  817. * @param float $value
  818. * The target value.
  819. *
  820. * @return bool
  821. * Whether the order total meets the specified condition.
  822. *
  823. * @see uc_order_condition_value_operator_options
  824. */
  825. function uc_order_condition_total($order, $op, $value) {
  826. return uc_order_condition_value_operator_comparison($order->order_total, $op, $value);
  827. }
  828. /**
  829. * Compare order subtotal.
  830. *
  831. * @param object $order
  832. * The order to check.
  833. * @param string $op
  834. * The comparison operator.
  835. * @param float $value
  836. * The target value.
  837. *
  838. * @return bool
  839. * Whether the order subtotal meets the specified condition.
  840. *
  841. * @see uc_order_condition_value_operator_options
  842. */
  843. function uc_order_condition_subtotal($order, $op, $value) {
  844. if (is_array($order->line_items)) {
  845. foreach ($order->line_items as $line_item) {
  846. if ($line_item['type'] == 'subtotal') {
  847. $subtotal = $line_item['amount'];
  848. return uc_order_condition_value_operator_comparison($subtotal, $op, $value);
  849. }
  850. }
  851. }
  852. return FALSE;
  853. }