rules_core.rules.inc 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338
  1. <?php
  2. /**
  3. * @file Rules core integration providing data types and conditions and
  4. * actions to invoke configured components.
  5. *
  6. * @addtogroup rules
  7. * @{
  8. */
  9. /**
  10. * Implements hook_rules_category_info() on behalf of the rules_core.
  11. */
  12. function rules_rules_core_category_info() {
  13. return array(
  14. 'rules_components' => array(
  15. 'label' => t('Components'),
  16. 'equals group' => t('Components'),
  17. 'weight' => 50,
  18. ),
  19. );
  20. }
  21. /**
  22. * Implements hook_rules_file_info() on behalf of the pseudo rules_core module.
  23. *
  24. * @see rules_core_modules()
  25. */
  26. function rules_rules_core_file_info() {
  27. return array('modules/rules_core.eval');
  28. }
  29. /**
  30. * Implements hook_rules_data_info() on behalf of the pseudo rules_core module.
  31. *
  32. * @see rules_core_modules()
  33. */
  34. function rules_rules_core_data_info() {
  35. $return = array(
  36. 'text' => array(
  37. 'label' => t('text'),
  38. 'ui class' => 'RulesDataUIText',
  39. 'token type' => 'rules_text',
  40. ),
  41. 'token' => array(
  42. 'label' => t('text token'),
  43. 'parent' => 'text',
  44. 'ui class' => 'RulesDataUITextToken',
  45. 'token type' => 'rules_token',
  46. ),
  47. // A formatted text as used by entity metadata.
  48. 'text_formatted' => array(
  49. 'label' => t('formatted text'),
  50. 'ui class' => 'RulesDataUITextFormatted',
  51. 'wrap' => TRUE,
  52. 'property info' => entity_property_text_formatted_info(),
  53. ),
  54. 'decimal' => array(
  55. 'label' => t('decimal number'),
  56. 'parent' => 'text',
  57. 'ui class' => 'RulesDataUIDecimal',
  58. 'token type' => 'rules_decimal',
  59. ),
  60. 'integer' => array(
  61. 'label' => t('integer'),
  62. 'class' => 'RulesIntegerWrapper',
  63. 'parent' => 'decimal',
  64. 'ui class' => 'RulesDataUIInteger',
  65. 'token type' => 'rules_integer',
  66. ),
  67. 'date' => array(
  68. 'label' => t('date'),
  69. 'ui class' => 'RulesDataUIDate',
  70. 'token type' => 'rules_date',
  71. ),
  72. 'duration' => array(
  73. 'label' => t('duration'),
  74. 'parent' => 'integer',
  75. 'ui class' => 'RulesDataUIDuration',
  76. 'token type' => 'rules_duration',
  77. ),
  78. 'boolean' => array(
  79. 'label' => t('truth value'),
  80. 'ui class' => 'RulesDataUIBoolean',
  81. 'token type' => 'rules_boolean',
  82. ),
  83. 'uri' => array(
  84. 'label' => t('URI'),
  85. 'parent' => 'text',
  86. // Clean inserted tokens with "rawurlencode".
  87. 'cleaning callback' => 'rawurlencode',
  88. 'ui class' => 'RulesDataUIURI',
  89. 'token type' => 'rules_uri',
  90. ),
  91. 'list' => array(
  92. 'label' => t('list', array(), array('context' => 'data_types')),
  93. 'wrap' => TRUE,
  94. 'group' => t('List', array(), array('context' => 'data_types')),
  95. ),
  96. 'list<text>' => array(
  97. 'label' => t('list of text'),
  98. 'ui class' => 'RulesDataUIListText',
  99. 'wrap' => TRUE,
  100. 'group' => t('List', array(), array('context' => 'data_types')),
  101. ),
  102. 'list<integer>' => array(
  103. 'label' => t('list of integer'),
  104. 'ui class' => 'RulesDataUIListInteger',
  105. 'wrap' => TRUE,
  106. 'group' => t('List', array(), array('context' => 'data_types')),
  107. ),
  108. 'list<token>' => array(
  109. 'label' => t('list of text tokens'),
  110. 'ui class' => 'RulesDataUIListToken',
  111. 'wrap' => TRUE,
  112. 'group' => t('List', array(), array('context' => 'data_types')),
  113. ),
  114. 'entity' => array(
  115. 'label' => t('any entity'),
  116. 'group' => t('Entity'),
  117. 'is wrapped' => TRUE,
  118. ),
  119. 'ip_address' => array(
  120. 'label' => t('IP Address'),
  121. 'parent' => 'text',
  122. 'ui class' => 'RulesDataUIIPAddress',
  123. 'token type' => 'rules_text',
  124. ),
  125. );
  126. foreach (entity_get_info() as $type => $info) {
  127. if (!empty($info['label'])) {
  128. $return[$type] = array(
  129. 'label' => strtolower($info['label'][0]) . substr($info['label'], 1),
  130. 'parent' => 'entity',
  131. 'wrap' => TRUE,
  132. 'group' => t('Entity'),
  133. 'ui class' => empty($info['exportable']) ? 'RulesDataUIEntity' : 'RulesDataUIEntityExportable',
  134. );
  135. // If this entity type serves as bundle for another one, provide an
  136. // options list for selecting a bundle entity.
  137. if (!empty($info['bundle of'])) {
  138. $return[$type]['ui class'] = 'RulesDataUIBundleEntity';
  139. }
  140. }
  141. }
  142. if (module_exists('taxonomy')) {
  143. // For exportability identify vocabularies by name.
  144. $return['taxonomy_vocabulary']['wrapper class'] = 'RulesTaxonomyVocabularyWrapper';
  145. $return['taxonomy_vocabulary']['ui class'] = 'RulesDataUITaxonomyVocabulary';
  146. }
  147. return $return;
  148. }
  149. /**
  150. * Implements hook_rules_data_info_alter() on behalf of the pseudo rules_core module.
  151. *
  152. * Makes sure there is a list<type> data type for each type registered.
  153. *
  154. * @see rules_rules_data_info_alter()
  155. */
  156. function rules_rules_core_data_info_alter(&$data_info) {
  157. foreach ($data_info as $type => $info) {
  158. if (!entity_property_list_extract_type($type)) {
  159. $list_type = "list<$type>";
  160. if (!isset($data_info[$list_type])) {
  161. $data_info[$list_type] = array(
  162. 'label' => t('list of @type_label items', array('@type_label' => $info['label'])),
  163. 'wrap' => TRUE,
  164. 'group' => t('List', array(), array('context' => 'data_types')),
  165. );
  166. if (isset($info['parent']) && $info['parent'] == 'entity') {
  167. $data_info[$list_type]['ui class'] = 'RulesDataUIListEntity';
  168. }
  169. }
  170. }
  171. }
  172. }
  173. /**
  174. * Implements hook_rules_evaluator_info() on behalf of the pseudo rules_core
  175. * module.
  176. *
  177. * @see rules_core_modules()
  178. */
  179. function rules_rules_core_evaluator_info() {
  180. return array(
  181. // Process strtotime() inputs to timestamps.
  182. 'date' => array(
  183. 'class' => 'RulesDateInputEvaluator',
  184. 'type' => 'date',
  185. 'weight' => -10,
  186. ),
  187. // Post-process any input value to absolute URIs.
  188. 'uri' => array(
  189. 'class' => 'RulesURIInputEvaluator',
  190. 'type' => 'uri',
  191. 'weight' => 50,
  192. ),
  193. );
  194. }
  195. /**
  196. * Implements hook_rules_data_processor_info() on behalf of the pseudo
  197. * rules_core module.
  198. *
  199. * @see rules_core_modules()
  200. */
  201. function rules_rules_core_data_processor_info() {
  202. return array(
  203. 'date_offset' => array(
  204. 'class' => 'RulesDateOffsetProcessor',
  205. 'type' => 'date',
  206. 'weight' => -2,
  207. ),
  208. 'num_offset' => array(
  209. 'class' => 'RulesNumericOffsetProcessor',
  210. 'type' => array('integer', 'decimal'),
  211. 'weight' => -2,
  212. ),
  213. );
  214. }
  215. /**
  216. * Implements hook_rules_condition_info() on behalf of the pseudo rules_core
  217. * module.
  218. *
  219. * @see rules_core_modules()
  220. */
  221. function rules_rules_core_condition_info() {
  222. $defaults = array(
  223. 'group' => t('Components'),
  224. 'base' => 'rules_element_invoke_component',
  225. 'named parameter' => TRUE,
  226. 'access callback' => 'rules_element_invoke_component_access_callback',
  227. );
  228. $items = array();
  229. foreach (rules_get_components(FALSE, 'condition') as $name => $config) {
  230. $items['component_' . $name] = $defaults + array(
  231. 'label' => $config->plugin() . ': ' . drupal_ucfirst($config->label()),
  232. 'parameter' => $config->parameterInfo(),
  233. );
  234. $items['component_' . $name]['#config_name'] = $name;
  235. }
  236. return $items;
  237. }
  238. /**
  239. * Implements hook_rules_action_info() on behalf of the pseudo rules_core
  240. * module.
  241. *
  242. * @see rules_core_modules()
  243. */
  244. function rules_rules_core_action_info() {
  245. $defaults = array(
  246. 'group' => t('Components'),
  247. 'base' => 'rules_element_invoke_component',
  248. 'named parameter' => TRUE,
  249. 'access callback' => 'rules_element_invoke_component_access_callback',
  250. );
  251. $items = array();
  252. foreach (rules_get_components(FALSE, 'action') as $name => $config) {
  253. $items['component_' . $name] = $defaults + array(
  254. 'label' => $config->plugin() . ': ' . drupal_ucfirst($config->label()),
  255. 'parameter' => $config->parameterInfo(),
  256. 'provides' => $config->providesVariables(),
  257. );
  258. $items['component_' . $name]['#config_name'] = $name;
  259. }
  260. return $items;
  261. }
  262. /**
  263. * Implements RulesPluginUIInterface::operations() for the action.
  264. */
  265. function rules_element_invoke_component_operations(RulesPlugin $element) {
  266. $defaults = $element->extender('RulesPluginUI')->operations();
  267. $info = $element->info();
  268. // Add an operation for editing the component.
  269. $defaults['#links']['component'] = array(
  270. 'title' => t('edit component'),
  271. 'href' => RulesPluginUI::path($info['#config_name']),
  272. );
  273. return $defaults;
  274. }
  275. /**
  276. * Validate callback to make sure the invoked component exists and is not dirty.
  277. *
  278. * @see rules_scheduler_action_schedule_validate()
  279. */
  280. function rules_element_invoke_component_validate(RulesPlugin $element) {
  281. $info = $element->info();
  282. $component = rules_config_load($info['#config_name']);
  283. // Check if a component exists.
  284. if (!$component) {
  285. throw new RulesIntegrityException(t('The component %config does not exist.', array('%config' => $info['#config_name'])), $element);
  286. }
  287. // Check if a component is marked as dirty.
  288. rules_config_update_dirty_flag($component);
  289. if (!empty($component->dirty)) {
  290. throw new RulesIntegrityException(t('The utilized component %config fails the integrity check.', array('%config' => $info['#config_name'])), $element);
  291. }
  292. }
  293. /**
  294. * Implements the features export callback of the RulesPluginFeaturesIntegrationInterace.
  295. */
  296. function rules_element_invoke_component_features_export(&$export, &$pipe, $module_name = '', $element) {
  297. // Add the used component to the pipe.
  298. $info = $element->info();
  299. $pipe['rules_config'][] = $info['#config_name'];
  300. }
  301. /**
  302. * Access callback for the invoke component condition/action.
  303. */
  304. function rules_element_invoke_component_access_callback($type, $name) {
  305. // Cut of the leading 'component_' from the action name.
  306. $component = rules_config_load(substr($name, 10));
  307. if (!$component) {
  308. // Missing component.
  309. return FALSE;
  310. }
  311. // If access is not exposed for this component, default to component access.
  312. if (empty($component->access_exposed)) {
  313. return $component->access();
  314. }
  315. // Apply the permissions.
  316. return user_access('bypass rules access') || user_access("use Rules component $component->name");
  317. }
  318. /**
  319. * @}
  320. */