data.rules.inc 25 KB

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