data.rules.inc 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762
  1. <?php
  2. /**
  3. * @file General data related rules integration
  4. *
  5. * @addtogroup rules
  6. * @{
  7. */
  8. /**
  9. * Implements hook_rules_category_info() on behalf of the pseudo data module.
  10. */
  11. function rules_data_category_info() {
  12. return array(
  13. 'rules_data' => array(
  14. 'label' => t('Data'),
  15. 'equals group' => t('Data'),
  16. 'weight' => -50,
  17. ),
  18. );
  19. }
  20. /**
  21. * Implements hook_rules_file_info() on behalf of the pseudo data module.
  22. * @see rules_core_modules()
  23. */
  24. function rules_data_file_info() {
  25. return array('modules/data.eval');
  26. }
  27. /**
  28. * Implements hook_rules_action_info() on behalf of the pseudo data module.
  29. * @see rules_core_modules()
  30. */
  31. function rules_data_action_info() {
  32. $return['data_set'] = array(
  33. 'label' => t('Set a data value'),
  34. 'parameter' => array(
  35. 'data' => array(
  36. 'type' => '*',
  37. 'label' => t('Data'),
  38. 'description' => t('Specifies the data to be modified using a data selector, e.g. "node:author:name".'),
  39. 'restriction' => 'selector',
  40. 'wrapped' => TRUE,
  41. 'allow null' => TRUE,
  42. ),
  43. 'value' => array(
  44. 'type' => '*',
  45. 'label' => t('Value'),
  46. 'description' => t('The new value to set for the specified data.'),
  47. 'allow null' => TRUE,
  48. 'optional' => TRUE,
  49. ),
  50. ),
  51. 'group' => t('Data'),
  52. 'base' => 'rules_action_data_set',
  53. );
  54. $return['data_calc'] = array(
  55. 'label' => t('Calculate a value'),
  56. 'parameter' => array(
  57. 'input_1' => array(
  58. 'type' => array('decimal', 'date'),
  59. 'label' => t('Input value 1'),
  60. 'description' => t('The first input value for the calculation.'),
  61. ),
  62. 'op' => array(
  63. 'type' => 'text',
  64. 'label' => t('Operator'),
  65. 'description' => t('The calculation operator.'),
  66. 'options list' => 'rules_action_data_calc_operator_options',
  67. 'restriction' => 'input',
  68. 'default value' => '+',
  69. ),
  70. 'input_2' => array(
  71. 'type' => 'decimal',
  72. 'label' => t('Input value 2'),
  73. 'description' => t('The second input value.'),
  74. ),
  75. ),
  76. 'group' => t('Data'),
  77. 'base' => 'rules_action_data_calc',
  78. 'provides' => array(
  79. 'result' => array(
  80. 'type' => 'unknown',
  81. 'label' => t('Calculation result'),
  82. ),
  83. ),
  84. );
  85. $return['list_add'] = array(
  86. 'label' => t('Add an item to a list'),
  87. 'parameter' => array(
  88. 'list' => array(
  89. 'type' => 'list',
  90. 'label' => t('List', array(), array('context' => 'data_types')),
  91. 'description' => t('The data list, to which an item is to be added.'),
  92. 'restriction' => 'selector',
  93. 'allow null' => TRUE,
  94. 'save' => TRUE,
  95. ),
  96. 'item' => array(
  97. 'type' => 'unknown',
  98. 'label' => t('Item to add'),
  99. ),
  100. 'unique' => array(
  101. 'type' => 'boolean',
  102. 'label' => t('Enforce uniqueness'),
  103. 'description' => t('Only add the item to the list if it is not yet contained.'),
  104. 'optional' => TRUE,
  105. 'default value' => FALSE,
  106. ),
  107. 'pos' => array(
  108. 'type' => 'text',
  109. 'label' => t('Insert position'),
  110. 'optional' => TRUE,
  111. 'default value' => 'end',
  112. 'options list' => 'rules_action_data_list_add_positions',
  113. ),
  114. ),
  115. 'group' => t('Data'),
  116. 'base' => 'rules_action_data_list_add',
  117. 'callbacks' => array(
  118. 'info_alter' => 'rules_data_list_info_alter',
  119. 'form_alter' => 'rules_data_list_form_alter',
  120. ),
  121. );
  122. $return['list_remove'] = array(
  123. 'label' => t('Remove an item from a list'),
  124. 'parameter' => array(
  125. 'list' => array(
  126. 'type' => 'list',
  127. 'label' => t('List', array(), array('context' => 'data_types')),
  128. 'description' => t('The data list for which an item is to be removed.'),
  129. 'restriction' => 'selector',
  130. 'save' => TRUE,
  131. ),
  132. 'item' => array(
  133. 'type' => 'unknown',
  134. 'label' => t('Item to remove'),
  135. ),
  136. ),
  137. 'group' => t('Data'),
  138. 'base' => 'rules_action_data_list_remove',
  139. 'callbacks' => array(
  140. 'info_alter' => 'rules_data_list_info_alter',
  141. 'form_alter' => 'rules_data_list_form_alter',
  142. ),
  143. );
  144. $return['variable_add'] = array(
  145. 'label' => t('Add a variable'),
  146. 'named parameter' => TRUE,
  147. 'parameter' => array(
  148. 'type' => array(
  149. 'type' => 'text',
  150. 'label' => t('Type'),
  151. 'options list' => 'rules_data_action_variable_add_options',
  152. 'description' => t('Specifies the type of the variable that should be added.'),
  153. 'restriction' => 'input',
  154. ),
  155. 'value' => array(
  156. 'type' => 'unknown',
  157. 'label' => t('Value'),
  158. 'optional' => TRUE,
  159. 'description' => t('Optionally, specify the initial value of the variable.')
  160. ),
  161. ),
  162. 'provides' => array(
  163. 'variable_added' => array(
  164. 'type' => 'unknown',
  165. 'label' => t('Added variable'),
  166. ),
  167. ),
  168. 'group' => t('Data'),
  169. 'base' => 'rules_action_variable_add',
  170. 'callbacks' => array(
  171. 'form_alter' => 'rules_action_type_form_alter',
  172. 'validate' => 'rules_action_create_type_validate',
  173. ),
  174. );
  175. if (rules_data_action_data_create_options()) {
  176. $return['data_create'] = array(
  177. 'label' => t('Create a data structure'),
  178. 'named parameter' => TRUE,
  179. 'parameter' => array(
  180. 'type' => array(
  181. 'type' => 'text',
  182. 'label' => t('Type'),
  183. 'options list' => 'rules_data_action_data_create_options',
  184. 'description' => t('Specifies the type of the data structure that should be created.'),
  185. 'restriction' => 'input',
  186. ),
  187. // Further needed parameters depend on the type.
  188. ),
  189. 'provides' => array(
  190. 'data_created' => array(
  191. 'type' => 'unknown',
  192. 'label' => t('Created data'),
  193. ),
  194. ),
  195. 'group' => t('Data'),
  196. 'base' => 'rules_action_data_create',
  197. 'callbacks' => array(
  198. 'form_alter' => 'rules_action_type_form_alter',
  199. 'validate' => 'rules_action_create_type_validate',
  200. ),
  201. );
  202. }
  203. $return['data_convert'] = array(
  204. 'label' => t('Convert data type'),
  205. 'parameter' => array(
  206. 'type' => array(
  207. 'type' => 'token',
  208. 'label' => t('Target type'),
  209. 'description' => t('The data type to convert a value to.'),
  210. 'options list' => 'rules_action_data_convert_types_options',
  211. 'restriction' => 'input',
  212. ),
  213. 'value' => array(
  214. 'type' => array('decimal', 'integer', 'text', 'token'),
  215. 'label' => t('Value to convert'),
  216. 'default mode' => 'selector',
  217. ),
  218. // For to-integer conversion only.
  219. 'rounding_behavior' => array(
  220. 'type' => 'token',
  221. 'label' => t('Rounding behavior'),
  222. 'description' => t('The rounding behavior the conversion should use.'),
  223. 'options list' => 'rules_action_data_convert_rounding_behavior_options',
  224. 'restriction' => 'input',
  225. 'default value' => 'round',
  226. 'optional' => TRUE,
  227. ),
  228. ),
  229. 'provides' => array(
  230. 'conversion_result' => array(
  231. 'type' => 'unknown',
  232. 'label' => t('Conversion result'),
  233. ),
  234. ),
  235. 'group' => t('Data'),
  236. 'base' => 'rules_action_data_convert',
  237. 'named parameter' => TRUE,
  238. 'callbacks' => array(
  239. 'form_alter' => 'rules_action_type_form_alter',
  240. ),
  241. );
  242. return $return;
  243. }
  244. /**
  245. * Data conversation action: Options list callback for the target type.
  246. */
  247. function rules_action_data_convert_types_options(RulesPlugin $element, $param_name) {
  248. return array(
  249. 'decimal' => t('Decimal'),
  250. 'integer' => t('Integer'),
  251. 'text' => t('Text'),
  252. 'token' => t('Token'),
  253. );
  254. }
  255. /**
  256. * Data conversation action: Options list callback for rounding behavior.
  257. */
  258. function rules_action_data_convert_rounding_behavior_options(RulesPlugin $element, $param_name) {
  259. return array(
  260. 'down' => t('Always down (9.5 -> 9)'),
  261. 'round' => t('Round, half up (9.5 -> 10)'),
  262. 'up' => t('Always up (9.5 -> 10)'),
  263. );
  264. }
  265. /**
  266. * Customize access check for data set action.
  267. */
  268. function rules_action_data_set_access(RulesAbstractPlugin $element) {
  269. if (isset($element->settings['data:select']) && $wrapper = $element->applyDataSelector($element->settings['data:select'])) {
  270. return $wrapper instanceof EntityMetadataWrapper && $wrapper->access('edit');
  271. }
  272. }
  273. /**
  274. * Custom validation callback for the data set action.
  275. */
  276. function rules_action_data_set_validate(RulesAbstractPlugin $element) {
  277. $element->settings += array('data:select' => NULL);
  278. $info = $element->applyDataSelector($element->settings['data:select'])->info();
  279. if (strpos($element->settings['data:select'], ':') !== FALSE && empty($info['setter callback'])) {
  280. throw new RulesIntegrityException(t("The selected data property doesn't support writing."), array($element, 'parameter', 'data'));
  281. }
  282. }
  283. /**
  284. * Form alter callback for the data_set action.
  285. */
  286. function rules_action_data_set_form_alter(&$form, &$form_state, $options, RulesAbstractPlugin $element) {
  287. if (!empty($options['init']) && !isset($form_state['rules_element_step'])) {
  288. $form['negate']['#access'] = FALSE;
  289. unset($form['parameter']['value']);
  290. unset($form['parameter']['language']);
  291. $form['submit'] = array(
  292. '#type' => 'submit',
  293. '#value' => t('Continue'),
  294. '#limit_validation_errors' => array(array('parameter', 'data')),
  295. '#submit' => array('rules_form_submit_rebuild'),
  296. );
  297. $form_state['rules_element_step'] = 'data_value';
  298. // Clear the parameter mode for the value parameter, so its gets the proper
  299. // default value based upon the type of the the selected data on rebuild.
  300. unset($form_state['parameter_mode']['value']);
  301. }
  302. else {
  303. // Change the data parameter to be not editable.
  304. $form['parameter']['data']['settings']['#access'] = FALSE;
  305. // TODO: improve display
  306. $form['parameter']['data']['info'] = array(
  307. '#prefix' => '<p>',
  308. '#markup' => t('<strong>Selected data:</strong> %selector', array('%selector' => $element->settings['data:select'])),
  309. '#suffix' => '</p>',
  310. );
  311. }
  312. }
  313. /**
  314. * Form alter callback for the data calculation action.
  315. */
  316. function rules_action_data_calc_form_alter(&$form, &$form_state, $options, RulesAbstractPlugin $element) {
  317. $form['reload'] = array(
  318. '#weight' => 5,
  319. '#type' => 'submit',
  320. '#name' => 'reload',
  321. '#value' => t('Reload form'),
  322. '#limit_validation_errors' => array(array('parameter', 'input_1')),
  323. '#submit' => array('rules_form_submit_rebuild'),
  324. '#ajax' => rules_ui_form_default_ajax(),
  325. );
  326. }
  327. /**
  328. * Custom validate callback for entity create, add variable and data create
  329. * action.
  330. */
  331. function rules_action_create_type_validate($element) {
  332. if (!isset($element->settings['type'])) {
  333. throw new RulesIntegrityException(t('Invalid type specified.'), array($element, 'parameter', 'type'));
  334. }
  335. }
  336. /**
  337. * Form alter callback for the list add and remove actions.
  338. *
  339. * Use multiple steps to configure the action to update the item configuration
  340. * form once we know the data type.
  341. *
  342. * @see rules_data_list_info_alter()
  343. */
  344. function rules_data_list_form_alter(&$form, &$form_state, $options, RulesAbstractPlugin $element) {
  345. if (!empty($options['init']) && !isset($form_state['rules_element_step'])) {
  346. unset($form['parameter']['item'], $form['parameter']['pos']);
  347. $form_state['rules_element_step'] = 1;
  348. $form['negate']['#access'] = FALSE;
  349. $form['parameter']['unique']['#access'] = FALSE;
  350. $form['submit'] = array(
  351. '#type' => 'submit',
  352. '#value' => t('Continue'),
  353. '#limit_validation_errors' => array(array('parameter', 'list')),
  354. '#submit' => array('rules_form_submit_rebuild'),
  355. );
  356. }
  357. else {
  358. // Change the list parameter to be not editable any more.
  359. $form['parameter']['list']['settings']['#access'] = FALSE;
  360. $form['parameter']['list']['info'] = array(
  361. '#prefix' => '<p>',
  362. '#markup' => t('<strong>Selected list:</strong> %selector', array('%selector' => $element->settings['list:select'])),
  363. '#suffix' => '</p>',
  364. );
  365. }
  366. }
  367. /**
  368. * Form alter callback for actions relying on the entity type or the data type.
  369. */
  370. function rules_action_type_form_alter(&$form, &$form_state, $options, RulesAbstractPlugin $element) {
  371. $first_step = empty($element->settings['type']);
  372. $form['reload'] = array(
  373. '#weight' => 5,
  374. '#type' => 'submit',
  375. '#name' => 'reload',
  376. '#value' => $first_step ? t('Continue') : t('Reload form'),
  377. '#limit_validation_errors' => array(array('parameter', 'type')),
  378. '#submit' => array('rules_action_type_form_submit_rebuild'),
  379. '#ajax' => rules_ui_form_default_ajax(),
  380. );
  381. // Use ajax and trigger as the reload button.
  382. $form['parameter']['type']['settings']['type']['#ajax'] = $form['reload']['#ajax'] + array(
  383. 'event' => 'change',
  384. 'trigger_as' => array('name' => 'reload'),
  385. );
  386. if ($first_step) {
  387. // In the first step show only the type select.
  388. foreach (element_children($form['parameter']) as $key) {
  389. if ($key != 'type') {
  390. unset($form['parameter'][$key]);
  391. }
  392. }
  393. unset($form['submit']);
  394. unset($form['provides']);
  395. // Disable #ajax for the first step as it has troubles with lazy-loaded JS.
  396. // @todo: Re-enable once JS lazy-loading is fixed in core.
  397. unset($form['parameter']['type']['settings']['type']['#ajax']);
  398. unset($form['reload']['#ajax']);
  399. }
  400. else {
  401. // Hide the reload button in case js is enabled and it's not the first step.
  402. $form['reload']['#attributes'] = array('class' => array('rules-hide-js'));
  403. }
  404. }
  405. /**
  406. * FAPI submit callback for reloading the type form for entities or data types.
  407. */
  408. function rules_action_type_form_submit_rebuild($form, &$form_state) {
  409. rules_form_submit_rebuild($form, $form_state);
  410. // Clear the parameter modes for the parameters, so they get the proper
  411. // default values based upon the data types on rebuild.
  412. $form_state['parameter_mode'] = array();
  413. }
  414. /**
  415. * Options list callback for possible insertion positions.
  416. */
  417. function rules_action_data_list_add_positions() {
  418. return array(
  419. 'end' => t('Append the item to the end.'),
  420. 'start' => t('Prepend the item to the front.'),
  421. );
  422. }
  423. /**
  424. * Options list callback for variable add action.
  425. */
  426. function rules_data_action_variable_add_options() {
  427. return RulesPluginUI::getOptions('data');
  428. }
  429. /**
  430. * Options list callback for the data calculation action.
  431. */
  432. function rules_action_data_calc_operator_options(RulesPlugin $element, $param_name) {
  433. $options = array(
  434. '+' => '( + )',
  435. '-' => '( - )',
  436. '*' => '( * )',
  437. '/' => '( / )',
  438. 'min' => 'min',
  439. 'max' => 'max',
  440. );
  441. // Only show +/- in case a date has been selected.
  442. if (($info = $element->getArgumentInfo('input_1')) && $info['type'] == 'date') {
  443. unset($options['*']);
  444. unset($options['/']);
  445. }
  446. return $options;
  447. }
  448. /**
  449. * Options list callback for data create action.
  450. */
  451. function rules_data_action_data_create_options() {
  452. $cache = rules_get_cache();
  453. $data_info = $cache['data_info'];
  454. $entity_info = entity_get_info();
  455. // Remove entities.
  456. $data_info = array_diff_key($data_info, $entity_info);
  457. $options = array();
  458. foreach ($data_info as $type => $properties) {
  459. if (isset($properties['creation callback'])) {
  460. // Add data types with creation callback only.
  461. $options[$type] = $properties['label'];
  462. }
  463. }
  464. natcasesort($options);
  465. return $options;
  466. }
  467. /**
  468. * Implements hook_rules_condition_info() on behalf of the pseudo data module.
  469. * @see rules_core_modules()
  470. */
  471. function rules_data_condition_info() {
  472. return array(
  473. 'data_is' => array(
  474. 'label' => t('Data comparison'),
  475. 'parameter' => array(
  476. 'data' => array(
  477. 'type' => '*',
  478. 'label' => t('Data to compare'),
  479. 'description' => t('The data to be compared, specified by using a data selector, e.g. "node:author:name".'),
  480. 'allow null' => TRUE,
  481. ),
  482. 'op' => array(
  483. 'type' => 'text',
  484. 'label' => t('Operator'),
  485. 'description' => t('The comparison operator.'),
  486. 'optional' => TRUE,
  487. 'default value' => '==',
  488. 'options list' => 'rules_condition_data_is_operator_options',
  489. 'restriction' => 'input',
  490. ),
  491. 'value' => array(
  492. 'type' => '*',
  493. 'label' => t('Data value'),
  494. 'description' => t('The value to compare the data with.'),
  495. 'allow null' => TRUE,
  496. ),
  497. ),
  498. 'group' => t('Data'),
  499. 'base' => 'rules_condition_data_is',
  500. ),
  501. 'data_is_empty' => array(
  502. 'label' => t('Data value is empty'),
  503. 'parameter' => array(
  504. 'data' => array(
  505. 'type' => '*',
  506. 'label' => t('Data to check'),
  507. 'description' => t('The data to be checked to be empty, specified by using a data selector, e.g. "node:author:name".'),
  508. 'allow null' => TRUE,
  509. 'wrapped' => TRUE,
  510. ),
  511. ),
  512. 'group' => t('Data'),
  513. 'base' => 'rules_condition_data_is_empty',
  514. ),
  515. 'list_contains' => array(
  516. 'label' => t('List contains item'),
  517. 'parameter' => array(
  518. 'list' => array(
  519. 'type' => 'list',
  520. 'label' => t('List', array(), array('context' => 'data_types')),
  521. 'restriction' => 'selector',
  522. ),
  523. 'item' => array(
  524. 'type' => 'unknown',
  525. 'label' => t('Item'),
  526. 'description' => t('The item to check for.'),
  527. ),
  528. ),
  529. 'group' => t('Data'),
  530. 'base' => 'rules_condition_data_list_contains',
  531. 'callbacks' => array(
  532. 'info_alter' => 'rules_data_list_info_alter',
  533. 'form_alter' => 'rules_data_list_form_alter',
  534. ),
  535. ),
  536. 'list_count_is' => array(
  537. 'label' => t('List count comparison'),
  538. 'parameter' => array(
  539. 'list' => array(
  540. 'type' => 'list',
  541. 'label' => t('List to check'),
  542. 'description' => t('A multi value data element to have its count compared, specified by using a data selector, eg node:author:roles.'),
  543. ),
  544. 'op' => array(
  545. 'type' => 'text',
  546. 'label' => t('Operator'),
  547. 'description' => t('The comparison operator.'),
  548. 'optional' => TRUE,
  549. 'default value' => '==',
  550. 'options list' => 'rules_condition_data_list_count_is_operator_options',
  551. 'restriction' => 'input',
  552. ),
  553. 'value' => array(
  554. 'type' => 'integer',
  555. 'label' => t('Count'),
  556. 'description' => t('The count to compare the data count with.'),
  557. ),
  558. ),
  559. 'group' => t('Data'),
  560. 'base' => 'rules_condition_data_list_count_is',
  561. ),
  562. 'text_matches' => array(
  563. 'label' => t('Text comparison'),
  564. 'parameter' => array(
  565. 'text' => array(
  566. 'type' => 'text',
  567. 'label' => t('Text'),
  568. 'restriction' => 'selector',
  569. ),
  570. 'match' => array(
  571. 'type' => 'text',
  572. 'label' => t('Matching text'),
  573. ),
  574. 'operation' => array(
  575. 'type' => 'text',
  576. 'label' => t('Comparison operation'),
  577. 'options list' => 'rules_data_text_comparison_operation_list',
  578. 'restriction' => 'input',
  579. 'default value' => 'contains',
  580. 'optional' => TRUE,
  581. 'description' => t('In case the comparison operation @regex is selected, the matching pattern will be interpreted as a <a href="@regex-wikipedia">regular expression</a>. Tip: <a href="@RegExr">RegExr: Online Regular Expression Testing Tool</a> is helpful for learning, writing, and testing Regular Expressions.', array('@regex-wikipedia' => 'http://en.wikipedia.org/wiki/Regular_expression', '@RegExr' => 'http://gskinner.com/RegExr/', '@regex' => t('regular expression'))),
  582. ),
  583. ),
  584. 'group' => t('Data'),
  585. 'base' => 'rules_data_text_comparison',
  586. ),
  587. );
  588. }
  589. /**
  590. * If the bundle is compared, add the metadata assertion so other elements
  591. * can make use of properties specific to the bundle.
  592. */
  593. function rules_condition_data_is_assertions($element) {
  594. // Assert the bundle of entities, if its compared.
  595. if ($wrapper = $element->applyDataSelector($element->settings['data:select'])) {
  596. $info = $wrapper->info();
  597. if (isset($info['parent']) && $info['parent'] instanceof EntityDrupalWrapper) {
  598. $entity_info = $info['parent']->entityInfo();
  599. if (isset($entity_info['entity keys']['bundle']) && $entity_info['entity keys']['bundle'] == $info['name']) {
  600. // Assert that the entity is of bundle $value.
  601. $value = is_array($element->settings['value']) ? $element->settings['value'] : array($element->settings['value']);
  602. // Chop of the last part of the selector.
  603. $parts = explode(':', $element->settings['data:select'], -1);
  604. return array(implode(':', $parts) => array('bundle' => $value));
  605. }
  606. }
  607. }
  608. }
  609. /**
  610. * Form alter callback for the condition data_is.
  611. *
  612. * Use multiple steps to configure the condition as the needed type of the value
  613. * depends on the selected data.
  614. */
  615. function rules_condition_data_is_form_alter(&$form, &$form_state, $options, RulesAbstractPlugin $element) {
  616. if (!empty($options['init']) && !isset($form_state['rules_element_step'])) {
  617. unset($form['parameter']['op'], $form['parameter']['value']);
  618. $form['negate']['#access'] = FALSE;
  619. $form_state['rules_element_step'] = 'data_value';
  620. $form['submit'] = array(
  621. '#type' => 'submit',
  622. '#value' => t('Continue'),
  623. '#limit_validation_errors' => array(array('parameter', 'data'), array('parameter', 'op')),
  624. '#submit' => array('rules_form_submit_rebuild'),
  625. );
  626. // Clear the parameter mode for the value parameter, so its gets the proper
  627. // default value based upon the type of the the selected data on rebuild.
  628. unset($form_state['parameter_mode']['value']);
  629. }
  630. else {
  631. // Change the data parameter to be not editable.
  632. $form['parameter']['data']['settings']['#access'] = FALSE;
  633. // TODO: improve display
  634. $form['parameter']['data']['info'] = array(
  635. '#prefix' => '<p>',
  636. '#markup' => t('<strong>Selected data:</strong> %selector', array('%selector' => $element->settings['data:select'])),
  637. '#suffix' => '</p>',
  638. );
  639. // Limit the operations to what makes sense for the selected data type.
  640. $info = $element->pluginParameterInfo();
  641. $data_info = $info['value'];
  642. if ($element->settings['op'] == 'IN') {
  643. $data_info['type'] = entity_property_list_extract_type($data_info['type']);
  644. }
  645. if (!RulesData::typesMatch($data_info, array('type' => array('decimal', 'date')))) {
  646. $options =& $form['parameter']['op']['settings']['op']['#options'];
  647. unset($options['<'], $options['>']);
  648. }
  649. // Remove 'contains' if it is not selected, as it is deprecated by the
  650. // text comparison condition.
  651. if ($element->settings['op'] != 'contains') {
  652. unset($form['parameter']['op']['settings']['op']['#options']['contains']);
  653. }
  654. // Auto-refresh the form if the operation is changed, so the input form
  655. // changes in case "is one of" requires a list value.
  656. $form['parameter']['op']['settings']['op']['#ajax'] = rules_ui_form_default_ajax() + array(
  657. 'trigger_as' => array('name' => 'reload'),
  658. );
  659. // Provide a reload button for non-JS users.
  660. $form['reload'] = array(
  661. '#type' => 'submit',
  662. '#value' => t('Reload form'),
  663. '#limit_validation_errors' => array(array('parameter', 'data'), array('parameter', 'op')),
  664. '#submit' => array('rules_form_submit_rebuild'),
  665. '#ajax' => rules_ui_form_default_ajax(),
  666. '#weight' => 5,
  667. );
  668. // Hide the reload button in case JS is enabled.
  669. $form['reload']['#attributes'] = array('class' => array('rules-hide-js'));
  670. }
  671. }
  672. /**
  673. * Provides configuration help for the data_is condition.
  674. */
  675. function rules_condition_data_is_help() {
  676. return array('#markup' => t('Compare two data values of the same type with each other.'));
  677. }
  678. /**
  679. * Options list callback for condition data_is.
  680. */
  681. function rules_condition_data_is_operator_options() {
  682. return array(
  683. '==' => t('equals'),
  684. 'IN' => t('is one of'),
  685. '<' => t('is lower than'),
  686. '>' => t('is greater than'),
  687. // Note: This is deprecated by the text comparison condition.
  688. 'contains' => t('contains'),
  689. );
  690. }
  691. /**
  692. * Options list callback for condition text_matches.
  693. */
  694. function rules_data_text_comparison_operation_list() {
  695. return array(
  696. 'contains' => t('contains'),
  697. 'starts' => t('starts with'),
  698. 'ends' => t('ends with'),
  699. 'regex' => t('regular expression'),
  700. );
  701. }
  702. /**
  703. * Returns the options list as specified by the selected property of the first parameter.
  704. *
  705. * @see rules_data_list_info_alter()
  706. * @see rules_action_data_set_info_alter()
  707. * @see rules_condition_data_is_info_alter()
  708. */
  709. function rules_data_selector_options_list(RulesAbstractPlugin $element) {
  710. $name = rules_array_key($element->pluginParameterInfo());
  711. // If the selected data property has an option list, make use of it.
  712. if (isset($element->settings[$name . ':select']) && $wrapper = $element->applyDataSelector($element->settings[$name . ':select'])) {
  713. return $wrapper->optionsList($element instanceof RulesActionInterface ? 'edit' : 'view');
  714. }
  715. }
  716. /**
  717. * Options list callback for condition list_count_is.
  718. */
  719. function rules_condition_data_list_count_is_operator_options() {
  720. return array(
  721. '==' => t('equals'),
  722. '<' => t('is lower than'),
  723. '>' => t('is greater than'),
  724. );
  725. }
  726. /**
  727. * @}
  728. */