ca.inc 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540
  1. <?php
  2. /**
  3. * @file
  4. * Helper functions for upgrade from Ubercart 2.x to Ubercart 3.x.
  5. */
  6. /**
  7. * Base helper function to convert CA predicates to Rules configurations.
  8. */
  9. function ca_convert_predicate($predicate) {
  10. // Convert event names to corresponding triggers.
  11. if ($predicate->ca_trigger == 'calculate_taxes') {
  12. return ca_extract_conditions($predicate, $predicate->pid);
  13. }
  14. elseif (strpos($predicate->ca_trigger, 'get_quote_from_') === 0) {
  15. return ca_extract_conditions($predicate, $predicate->ca_trigger);
  16. }
  17. $rule = rules_reaction_rule();
  18. if (is_numeric($predicate->pid)) {
  19. $rule->name = $predicate->ca_trigger . '_' . $predicate->pid;
  20. }
  21. else {
  22. $rule->name = $predicate->pid;
  23. }
  24. $rule->label = $predicate->title;
  25. $rule->active = (bool) $predicate->status;
  26. $rule->event($predicate->ca_trigger);
  27. ca_add_conditions($rule, $predicate->conditions['#conditions']);
  28. ca_add_actions($rule, $predicate->actions);
  29. $rule->save();
  30. }
  31. /**
  32. * Saves the conditions of the predicate as a separate component.
  33. *
  34. * @param $predicate
  35. * An object row from {ca_predicates}.
  36. * @param $name
  37. * The name to give the Rules component.
  38. */
  39. function ca_extract_conditions($predicate, $name) {
  40. $component = rules_and(array('order' => array('uc_order', 'label' => t('Order'))));
  41. $component->name = $name;
  42. $component->label = t('@title conditions', array('@title' => $predicate->title));
  43. // CA predicates always have an AND at the root level.
  44. ca_add_conditions($component, $predicate->conditions['#conditions']);
  45. $component->save();
  46. }
  47. /**
  48. * Reads a predicate's conditions array and add them to a component.
  49. *
  50. * @param &$component
  51. * A RulesConditionContainer or a Rule to receive conditions.
  52. * @param $conditions
  53. * A predicate's array of conditions.
  54. */
  55. function ca_add_conditions(&$component, $conditions) {
  56. foreach ($conditions as $condition) {
  57. // Handle condition containers.
  58. if (isset($condition['#conditions'])) {
  59. switch ($condition['#operator']) {
  60. case 'AND':
  61. $sub_tree = rules_and();
  62. break;
  63. case 'OR':
  64. $sub_tree = rules_or();
  65. break;
  66. }
  67. // Recurse.
  68. ca_add_conditions($sub_tree, $condition['#conditions']);
  69. if ($sub_tree->getIterator()->hasChildren()) {
  70. $component->condition($sub_tree);
  71. }
  72. }
  73. // Handle individual conditions.
  74. else {
  75. // Handle certain conditions as a generic "data_is" condition.
  76. $map = ca_data_map();
  77. if (isset($map[$condition['#name']])) {
  78. $name = 'data_is';
  79. }
  80. else {
  81. $name = $condition['#name'];
  82. }
  83. $settings = array();
  84. // The argument maps are like data selectors pointing to event variables.
  85. foreach ($condition['#argument_map'] as $key => $value) {
  86. if ($name == 'data_is') {
  87. $settings['data:select'] = $map[$condition['#name']]['data'];
  88. }
  89. // Special case: parameter changed, but doesn't use 'data_is'.
  90. elseif ($name == 'uc_attribute_ordered_product_option' && $key == 'order') {
  91. $settings['product:select'] = $value;
  92. }
  93. else {
  94. $key .= ':select';
  95. $settings[$key] = $value;
  96. }
  97. }
  98. $negate = FALSE;
  99. foreach ($condition['#settings'] as $key => $value) {
  100. // Save negation for later.
  101. if ($key == 'negate') {
  102. $negate = TRUE;
  103. continue;
  104. }
  105. if ($condition['#name'] == 'ca_condition_date' && $key == 'date') {
  106. $settings['date'] = $settings['date']['year'] . '/' . $settings['date']['month'] . '/' . $settings['date']['day'];
  107. }
  108. else {
  109. $settings[$key] = $value;
  110. }
  111. }
  112. if ($name == 'data_is') {
  113. $settings['#info'] = $map[$condition['#name']]['#info'];
  114. // data_is doesn't handle multiple values. Use a condition container.
  115. if (count($settings[$map[$condition['#name']]['value']]) > 1) {
  116. if (isset($map[$condition['#name']]['op']) && $settings[$map[$condition['#name']]['op']] == 'AND') {
  117. $rules_condition = rules_and();
  118. }
  119. else {
  120. $rules_condition = rules_or();
  121. }
  122. foreach ($settings[$map[$condition['#name']]['value']] as $value) {
  123. $rules_condition->condition('data_is', array('data:select' => $settings['data:select'], 'op' => 'contains', 'value' => $value, '#info' => $settings['#info']));
  124. }
  125. }
  126. elseif (is_array($settings[$map[$condition['#name']]['value']])) {
  127. $rules_condition = rules_condition('data_is', array('data:select' => $settings['data:select'], 'op' => 'contains', 'value' => $settings[$map[$condition['#name']]['value']], '#info' => $settings['#info']));
  128. }
  129. else {
  130. // Translate operator settings.
  131. if (isset($map[$condition['#name']]['op'])) {
  132. switch ($settings[$map[$condition['#name']]['op']]) {
  133. case 'before':
  134. case 'less':
  135. $ops = '<';
  136. break;
  137. case 'less_equal':
  138. $ops = array('<', '==');
  139. break;
  140. case 'only':
  141. case 'equal':
  142. $ops = '==';
  143. break;
  144. case 'not':
  145. $negate = !$negate;
  146. $settings['operator'] = '==';
  147. break;
  148. case 'after':
  149. case 'greater':
  150. $ops = '>';
  151. break;
  152. case 'greater_equal':
  153. $ops = array('>', '==');
  154. break;
  155. case 'begins':
  156. case 'contains':
  157. case 'ends':
  158. $settings['operator'] = 'contains';
  159. break;
  160. case 'yes':
  161. $settings['operator'] = '==';
  162. $settings['value'] = TRUE;
  163. break;
  164. case 'no':
  165. $settings['operator'] = '==';
  166. $settings['value'] = FALSE;
  167. break;
  168. }
  169. if ($condition['#name'] == 'node_field_comparison') {
  170. switch ($settings['field']) {
  171. case 'nid':
  172. case 'vid':
  173. case 'uid':
  174. $type = 'integer';
  175. break;
  176. case 'type':
  177. case 'title':
  178. $type = 'text';
  179. break;
  180. case 'status':
  181. case 'promote':
  182. case 'sticky':
  183. $type = 'boolean';
  184. break;
  185. }
  186. $settings = array(
  187. 'data:select' => array_shift($settings) . ':' . $settings['field'],
  188. 'op' => $settings['operator'],
  189. 'value' => $settings['value'],
  190. '#info' => array(
  191. 'parameter' => array(
  192. 'value' => array(
  193. 'type' => $type,
  194. ),
  195. ),
  196. ),
  197. );
  198. }
  199. // data_is only provides <, =, and > for numeric data. Use two
  200. // separate conditions for <= and >= cases.
  201. if (is_array($ops)) {
  202. $data_condition = data_or();
  203. foreach ($ops as $op) {
  204. $data_condition->condition('data_is', array('data:select' => $settings['data:select'], 'op' => $op, 'value' => $settings[$map[$condition['#name']]['value']], '#info' => $settings['#info']));
  205. }
  206. $rules_condition = rules_condition($data_condition);
  207. }
  208. else {
  209. $rules_condition = rules_condition('data_is', array('data:select' => $settings['data:select'], 'op' => $ops, 'value' => $settings[$map[$condition['#name']]['value']], '#info' => $settings['#info']));
  210. }
  211. }
  212. // Standard data_is check that 'data' is equal to 'value'.
  213. else {
  214. $rules_condition = rules_condition('data_is', array('data:select' => $settings['data:select'], 'value' => $settings[$map[$condition['#name']]['value']], '#info' => $settings['#info']));
  215. }
  216. }
  217. }
  218. else {
  219. if ($name == 'ca_condition_custom_php') {
  220. $name = 'php_eval';
  221. $settings = array('code' => $settings['php']);
  222. }
  223. $rules_condition = rules_condition($name, $settings);
  224. }
  225. if ($negate) {
  226. $rules_condition->negate();
  227. }
  228. $component->condition($rules_condition);
  229. }
  230. }
  231. }
  232. /**
  233. * Reads a predicate's actions array and add them to a Rule.
  234. *
  235. * @param Rule &$rule
  236. * The configuration to receive actions.
  237. * @param $actions
  238. * The predicate's actions array.
  239. */
  240. function ca_add_actions(&$rule, $actions) {
  241. foreach ($actions as $action) {
  242. $settings = array();
  243. // The argument maps are like data selectors pointing to event variables.
  244. foreach ($action['#argument_map'] as $key => $value) {
  245. $key .= ':select';
  246. $settings[$key] = $value;
  247. }
  248. foreach ($action['#settings'] as $key => $value) {
  249. $settings[$key] = $value;
  250. }
  251. switch ($action['#name']) {
  252. case 'ca_drupal_set_message':
  253. $name = 'drupal_message';
  254. $settings = array(
  255. 'message' => $settings['message_text'],
  256. 'error' => $settings['message_type'] == 'error',
  257. );
  258. break;
  259. case 'ca_action_custom_php':
  260. $name = 'php_eval';
  261. $settings = array('code' => $settings['php']);
  262. break;
  263. default:
  264. $name = $action['#name'];
  265. break;
  266. }
  267. $rule->action($name, $settings);
  268. }
  269. }
  270. /**
  271. * Maps obsolete conditions to correct settings for 'data_is'.
  272. */
  273. function ca_data_map() {
  274. return array(
  275. 'ca_condition_date' => array(
  276. 'data' => 'system:date', // @todo: use the correct selector
  277. 'op' => 'operator',
  278. 'value' => 'date',
  279. '#info' => array(
  280. 'parameter' => array(
  281. 'value' => array(
  282. 'type' => 'date',
  283. ),
  284. ),
  285. ),
  286. ),
  287. 'ca_condition_user_roles' => array(
  288. 'data' => 'user:roles',
  289. 'value' => 'roles',
  290. 'op' => 'operator',
  291. '#info' => array(
  292. 'parameter' => array(
  293. 'value' => array(
  294. 'type' => 'list<integer>',
  295. 'options list' => 'entity_metadata_user_roles',
  296. ),
  297. ),
  298. ),
  299. ),
  300. 'node_field_comparison' => array(
  301. 'data' => '*',
  302. 'op' => 'operator',
  303. 'value' => 'value',
  304. '#info' => array(
  305. 'parameter' => array(
  306. 'value' => array(
  307. 'type' => '*',
  308. ),
  309. ),
  310. ),
  311. ),
  312. 'uc_cart_condition_product_class' => array(
  313. 'data' => 'product:type',
  314. 'value' => 'class',
  315. '#info' => array(
  316. 'parameter' => array(
  317. 'value' => array(
  318. 'type' => 'list<text>',
  319. 'options list' => 'node_type_get_names',
  320. ),
  321. ),
  322. ),
  323. ),
  324. 'uc_quote_condition_product_shipping_type' => array(
  325. 'data' => 'product:shipping-type',
  326. 'value' => 'type',
  327. '#info' => array(
  328. 'parameter' => array(
  329. 'value' => array(
  330. 'type' => 'text',
  331. 'options list' => 'uc_quote_shipping_type_options',
  332. ),
  333. ),
  334. ),
  335. ),
  336. 'uc_order_condition_payment_method' => array(
  337. 'data' => 'order:payment-method',
  338. 'value' => 'payment_method',
  339. '#info' => array(
  340. 'parameter' => array(
  341. 'value' => array(
  342. 'type' => 'text',
  343. ),
  344. ),
  345. ),
  346. ),
  347. 'uc_order_status_condition' => array(
  348. 'data' => 'order:order-status',
  349. 'value' => 'order_status',
  350. '#info' => array(
  351. 'parameter' => array(
  352. 'value' => array(
  353. 'type' => 'text',
  354. 'options list' => 'uc_order_status_list',
  355. ),
  356. ),
  357. ),
  358. ),
  359. 'uc_order_condition_total' => array(
  360. 'data' => 'order:order-total',
  361. 'value' => 'order_total_value',
  362. 'op' => 'order_total_comparison',
  363. '#info' => array(
  364. 'parameter' => array(
  365. 'value' => array(
  366. 'type' => 'decimal',
  367. ),
  368. ),
  369. ),
  370. ),
  371. 'uc_order_condition_delivery_postal_code' => array(
  372. 'data' => 'order:delivery-address:postal-code',
  373. 'value' => 'pattern',
  374. '#info' => array(
  375. 'parameter' => array(
  376. 'value' => array(
  377. 'type' => 'text',
  378. ),
  379. ),
  380. ),
  381. ),
  382. 'uc_order_condition_delivery_zone' => array(
  383. 'data' => 'order:delivery-address:zone',
  384. 'value' => 'zones',
  385. '#info' => array(
  386. 'parameter' => array(
  387. 'value' => array(
  388. 'type' => 'list<integer>',
  389. 'options list' => 'uc_zone_option_list',
  390. ),
  391. ),
  392. ),
  393. ),
  394. 'uc_order_condition_delivery_country' => array(
  395. 'data' => 'order:delivery-address:country',
  396. 'value' => 'countries',
  397. '#info' => array(
  398. 'parameter' => array(
  399. 'value' => array(
  400. 'type' => 'list<integer>',
  401. 'options list' => 'uc_country_option_list',
  402. ),
  403. ),
  404. ),
  405. ),
  406. 'uc_order_condition_billing_postal_code' => array(
  407. 'data' => 'order:billing-address:postal-code',
  408. 'value' => 'pattern',
  409. '#info' => array(
  410. 'parameter' => array(
  411. 'value' => array(
  412. 'type' => 'text',
  413. ),
  414. ),
  415. ),
  416. ),
  417. 'uc_order_condition_billing_zone' => array(
  418. 'data' => 'order:billing-address:zone',
  419. 'value' => 'zones',
  420. '#info' => array(
  421. 'parameter' => array(
  422. 'value' => array(
  423. 'type' => 'list<integer>',
  424. 'options list' => 'uc_zone_option_list',
  425. ),
  426. ),
  427. ),
  428. ),
  429. 'uc_order_condition_billing_country' => array(
  430. 'data' => 'order:billing-address:country',
  431. 'value' => 'countries',
  432. '#info' => array(
  433. 'parameter' => array(
  434. 'value' => array(
  435. 'type' => 'list<integer>',
  436. 'options list' => 'uc_country_option_list',
  437. ),
  438. ),
  439. ),
  440. ),
  441. 'uc_order_condition_user_name' => array(
  442. 'data' => 'user:name',
  443. 'value' => 'name',
  444. '#info' => array(
  445. 'parameter' => array(
  446. 'value' => array(
  447. 'type' => 'text',
  448. ),
  449. ),
  450. ),
  451. ),
  452. 'uc_order_condition_user_email' => array(
  453. 'data' => 'user:mail',
  454. 'value' => 'mail',
  455. '#info' => array(
  456. 'parameter' => array(
  457. 'value' => array(
  458. 'type' => 'text',
  459. ),
  460. ),
  461. ),
  462. ),
  463. 'uc_order_condition_user_created' => array(
  464. 'data' => 'user:created',
  465. 'value' => 'created',
  466. 'op' => 'operator',
  467. '#info' => array(
  468. 'parameter' => array(
  469. 'value' => array(
  470. 'type' => 'date',
  471. ),
  472. ),
  473. ),
  474. ),
  475. 'uc_order_condition_user_login' => array(
  476. 'data' => 'user:login',
  477. 'value' => 'login',
  478. 'op' => 'operator',
  479. '#info' => array(
  480. 'parameter' => array(
  481. 'value' => array(
  482. 'type' => 'date',
  483. ),
  484. ),
  485. ),
  486. ),
  487. 'uc_order_condition_user_language' => array(
  488. 'data' => 'user:language',
  489. 'value' => 'language',
  490. '#info' => array(
  491. 'parameter' => array(
  492. 'value' => array(
  493. 'type' => 'text',
  494. ),
  495. ),
  496. ),
  497. ),
  498. 'uc_order_condition_user_roles' => array(
  499. 'data' => 'user:roles',
  500. 'value' => 'roles',
  501. 'op' => 'operator',
  502. '#info' => array(
  503. 'parameter' => array(
  504. 'value' => array(
  505. 'type' => 'list<integer>',
  506. 'options list' => 'entity_metadata_user_roles',
  507. ),
  508. ),
  509. ),
  510. ),
  511. );
  512. }