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