1 | <?php |
---|
2 | |
---|
3 | /** |
---|
4 | * @file |
---|
5 | * Provides basic rules module support. |
---|
6 | */ |
---|
7 | |
---|
8 | /** |
---|
9 | * Implementation of hook_rules_action_info(). |
---|
10 | */ |
---|
11 | function content_rules_action_info() { |
---|
12 | $info = array(); |
---|
13 | $info['content_rules_action_populate_field'] = array( |
---|
14 | 'label' => t('Populate a field'), |
---|
15 | 'arguments' => array( |
---|
16 | 'node' => array( |
---|
17 | 'type' => 'node', |
---|
18 | 'label' => t('Content'), |
---|
19 | ), |
---|
20 | ), |
---|
21 | 'eval input' => array('code'), |
---|
22 | 'help' => t('You should make sure that the used field exists in the given content type.'), |
---|
23 | 'module' => 'CCK', |
---|
24 | ); |
---|
25 | return $info; |
---|
26 | } |
---|
27 | |
---|
28 | /** |
---|
29 | * Action: populate a field. |
---|
30 | */ |
---|
31 | function content_rules_action_populate_field($node, $settings, $element, &$state) { |
---|
32 | // Get information about the field. |
---|
33 | $field = content_fields($settings['field_name'], $node->type); |
---|
34 | $value = _content_rules_get_field_value($settings, $state); |
---|
35 | |
---|
36 | if (!empty($field) && is_array($value)) { |
---|
37 | $node->$settings['field_name'] = $value; |
---|
38 | return array('node' => $node); |
---|
39 | } |
---|
40 | } |
---|
41 | |
---|
42 | |
---|
43 | /** |
---|
44 | * Action "populate a field" configuration form. |
---|
45 | * This is a multistep form! |
---|
46 | */ |
---|
47 | function content_rules_action_populate_field_form($settings, &$form, &$form_state) { |
---|
48 | $settings += array('field_name' => '', 'code' => '', 'value' => NULL); |
---|
49 | if (empty($settings['field_name'])) { |
---|
50 | $form['settings']['field_name'] = array( |
---|
51 | '#type' => 'select', |
---|
52 | '#title' => t('Field'), |
---|
53 | '#options' => content_rules_get_field_names_by_type(), |
---|
54 | '#default_value' => $settings['field_name'], |
---|
55 | '#description' => t('Select the machine-name of the field.'), |
---|
56 | '#required' => TRUE, |
---|
57 | ); |
---|
58 | // Hide some form elements in the first step. |
---|
59 | $form['negate']['#access'] = FALSE; |
---|
60 | $form['input_help']['#access'] = FALSE; |
---|
61 | $form['weight']['#access'] = FALSE; |
---|
62 | |
---|
63 | // Replace the usual submit handlers with a own handler. |
---|
64 | $form['submit']['#submit'] = array('content_rules_action_populate_field_form_step_submit'); |
---|
65 | $form['submit']['#value'] = t('Continue'); |
---|
66 | } |
---|
67 | else { |
---|
68 | // Show the fields form here. |
---|
69 | module_load_include('inc', 'content', 'includes/content.node_form'); |
---|
70 | $field = content_fields($settings['field_name']); |
---|
71 | |
---|
72 | $form['#node'] = (object)array('type' => '', $settings['field_name'] => $settings['value']); |
---|
73 | $form['#field_info'][$field['field_name']] = $field; |
---|
74 | // We can't put it into $form['settings'] as this would break AHAH callbacks |
---|
75 | $form += (array) content_field_form($form, $form_state, $field); |
---|
76 | $form[ $settings['field_name'] ]['#weight'] = 4; |
---|
77 | |
---|
78 | unset($form['#cache']); |
---|
79 | |
---|
80 | // Advanced: PHP code. |
---|
81 | $form['advanced_options'] = array( |
---|
82 | '#type' => 'fieldset', |
---|
83 | '#title' => t('Advanced: Specify the fields value with PHP code'), |
---|
84 | '#collapsible' => TRUE, |
---|
85 | '#collapsed' => empty($settings['code']), |
---|
86 | '#weight' => 5, |
---|
87 | ); |
---|
88 | |
---|
89 | $db_info = content_database_info($field); |
---|
90 | $columns = array_keys($db_info['columns']); |
---|
91 | foreach ($columns as $key => $column) { |
---|
92 | $columns[$key] = t("'@column' => value for @column", array('@column' => $column)); |
---|
93 | } |
---|
94 | $sample = t("return array(\n 0 => array(@columns),\n // You'll usually want to stop here. Provide more values\n // if you want your 'default value' to be multi-valued:\n 1 => array(@columns),\n 2 => ...\n);", array('@columns' => implode(', ', $columns))); |
---|
95 | |
---|
96 | $form['advanced_options']['code'] = array( |
---|
97 | '#type' => 'textarea', |
---|
98 | '#title' => t('Code'), |
---|
99 | '#default_value' => $settings['code'], |
---|
100 | '#rows' => 6, |
---|
101 | '#description' => t('Advanced usage only: PHP code that returns the value to set. Should not include <?php ?> delimiters. If this field is filled out, the value returned by this code will override any value specified above. Expected format: <pre>!sample</pre>Using <a href="@link_devel">devel.module\'s</a> \'devel load\' tab on a content page might help you figure out the expected format.', array( |
---|
102 | '!sample' => $sample, |
---|
103 | '@link_devel' => 'http://www.drupal.org/project/devel', |
---|
104 | )), |
---|
105 | ); |
---|
106 | |
---|
107 | // Add this file to be included when the form is built by rules |
---|
108 | // as it's needed by CCKs add more button. |
---|
109 | // See rules_after_build_include_files(). |
---|
110 | $form['#includes'][] = './'. drupal_get_path('module', 'node') .'/node.pages.inc'; |
---|
111 | } |
---|
112 | } |
---|
113 | |
---|
114 | function content_rules_action_populate_field_form_step_submit($form, &$form_state) { |
---|
115 | $form_state['element']['#settings']['field_name'] = $form_state['values']['settings']['field_name']; |
---|
116 | } |
---|
117 | |
---|
118 | /** |
---|
119 | * Validate the chosen value or php code. |
---|
120 | */ |
---|
121 | function content_rules_action_populate_field_validate($form, &$form_state) { |
---|
122 | if (!isset($form_state['element']['#settings']['field_name'])) { |
---|
123 | //Just validate the last step. |
---|
124 | return; |
---|
125 | } |
---|
126 | |
---|
127 | if (isset($form_state['values']['code']) && ($php = $form_state['values']['code'])) { |
---|
128 | if (strpos($php, 'return') === FALSE) { |
---|
129 | form_set_error('code', t('You have to return the default value in the expected format.')); |
---|
130 | } |
---|
131 | } |
---|
132 | else { |
---|
133 | // Validate the field. |
---|
134 | $settings = $form_state['element']['#settings']; |
---|
135 | $field = content_fields($settings['field_name']); |
---|
136 | $field_types = _content_field_types(); |
---|
137 | $function = $field_types[$field['type']]['module'] .'_field'; |
---|
138 | if (function_exists($function)) { |
---|
139 | $form['#node'] = (object)array('type' => '', $settings['field_name'] => $form_state['values'][$settings['field_name']]); |
---|
140 | $items = isset($form['#node']->$field['field_name']) ? $form['#node']->$field['field_name'] : array(); |
---|
141 | |
---|
142 | //Make sure AHAH 'add more' button isn't sent to the fields |
---|
143 | // for processing. |
---|
144 | unset($items[$field['field_name'] .'_add_more']); |
---|
145 | |
---|
146 | $function('validate', $form['#node'], $field, $items, $form, NULL); |
---|
147 | content_field('validate', $form['#node'], $field, $items, $form, NULL); |
---|
148 | } |
---|
149 | } |
---|
150 | } |
---|
151 | |
---|
152 | function content_rules_action_populate_field_submit(&$settings, $form, &$form_state) { |
---|
153 | // Take over field values and filter out private properties added by CCK |
---|
154 | $settings['value'] = array_filter($form_state['values'][$settings['field_name']], 'is_array'); |
---|
155 | |
---|
156 | foreach ($settings['value'] as $key => $data) { |
---|
157 | foreach (array_filter(array_keys($data)) as $col) { |
---|
158 | if ($col[0] == '_') { |
---|
159 | unset($settings['value'][$key][$col]); |
---|
160 | } |
---|
161 | } |
---|
162 | if ($key && count(array_filter($settings['value'][$key])) == 0) { |
---|
163 | // For multi-valued fields don't check for any additional empty values. |
---|
164 | unset($settings['value'][$key]); |
---|
165 | } |
---|
166 | } |
---|
167 | |
---|
168 | $settings['code'] = $form_state['values']['code']; |
---|
169 | |
---|
170 | if (function_exists('rules_action_custom_php_submit')) { |
---|
171 | // Support adding variables to the php code, if php module is present. |
---|
172 | rules_action_custom_php_submit($settings, $form, $form_state); |
---|
173 | } |
---|
174 | |
---|
175 | // Add all values to the input evaluator, so that textfields / textares can |
---|
176 | // make use of it. |
---|
177 | $names = array('code'); |
---|
178 | |
---|
179 | foreach ($settings['value'] as $key => $data) { |
---|
180 | foreach (array_filter($data, 'is_string') as $col => $value) { |
---|
181 | $names[] = "value|$key|$col"; |
---|
182 | } |
---|
183 | } |
---|
184 | $form_state['element']['#info']['eval input'] = $names; |
---|
185 | } |
---|
186 | |
---|
187 | |
---|
188 | /** |
---|
189 | * Label callback: Improve the label of the action. |
---|
190 | */ |
---|
191 | function content_rules_action_populate_field_label($settings, $argument_labels) { |
---|
192 | return t("Populate @node's field '@field'", array('@field' => $settings['field_name']) + $argument_labels); |
---|
193 | } |
---|
194 | |
---|
195 | function workflow_ng_action_populate_field_upgrade(&$element) { |
---|
196 | $element['#name'] = 'content_rules_action_populate_field'; |
---|
197 | $element['#settings']['code'] = $element['#settings']['default_value_php']; |
---|
198 | $element['#settings'][$element['#settings']['field_name']] = array(); |
---|
199 | unset($element['#settings']['default_value_php']); |
---|
200 | } |
---|
201 | |
---|
202 | |
---|
203 | /** |
---|
204 | * Implementation of hook_rules_condition_info(). |
---|
205 | */ |
---|
206 | function content_rules_condition_info() { |
---|
207 | $info = array(); |
---|
208 | $info['content_rules_field_has_value'] = array( |
---|
209 | 'label' => t('Field has value'), |
---|
210 | 'arguments' => array( |
---|
211 | 'node' => array('type' => 'node', 'label' => t('Content')), |
---|
212 | ), |
---|
213 | 'eval input' => array('code'), |
---|
214 | 'help' => t('You should make sure that the used field exists in the given content type. The condition returns TRUE, if the selected field has the given value.'), |
---|
215 | 'module' => 'CCK', |
---|
216 | ); |
---|
217 | $info['content_rules_field_changed'] = array( |
---|
218 | 'label' => t('Field has changed'), |
---|
219 | 'arguments' => array( |
---|
220 | 'node' => array('type' => 'node', 'label' => t('Content containing changes')), |
---|
221 | 'node_unchanged' => array('type' => 'node', 'label' => t('Content not containing changes')), |
---|
222 | ), |
---|
223 | 'help' => t('You should make sure that the used field exists in the given content type.'), |
---|
224 | 'module' => 'CCK', |
---|
225 | ); |
---|
226 | return $info; |
---|
227 | } |
---|
228 | |
---|
229 | /** |
---|
230 | * Condition: Check the value of a field. |
---|
231 | */ |
---|
232 | function content_rules_field_has_value($node, $settings) { |
---|
233 | // Get information about the field. |
---|
234 | $field = content_fields($settings['field_name'], $node->type); |
---|
235 | $value = _content_rules_get_field_value($settings, $state); |
---|
236 | |
---|
237 | if (empty($field) || !is_array($value)) { |
---|
238 | return FALSE; |
---|
239 | } |
---|
240 | |
---|
241 | return _content_rules_field_has_value($node->$settings['field_name'], $value); |
---|
242 | } |
---|
243 | |
---|
244 | /** |
---|
245 | * Use the same configuration form as the "populate field" action. |
---|
246 | */ |
---|
247 | function content_rules_field_has_value_form($settings, &$form, &$form_state) { |
---|
248 | content_rules_action_populate_field_form($settings, $form, $form_state); |
---|
249 | } |
---|
250 | function content_rules_field_has_value_validate($form, &$form_state) { |
---|
251 | content_rules_action_populate_field_validate($form, $form_state); |
---|
252 | } |
---|
253 | function content_rules_field_has_value_submit(&$settings, $form, &$form_state) { |
---|
254 | content_rules_action_populate_field_submit($settings, $form, $form_state); |
---|
255 | } |
---|
256 | |
---|
257 | function content_rules_field_has_value_label($settings, $argument_labels) { |
---|
258 | return t("@node's field '@field' has value", array('@field' => $settings['field_name']) + $argument_labels); |
---|
259 | } |
---|
260 | |
---|
261 | /** |
---|
262 | * Condition: Check if the field has changed. |
---|
263 | */ |
---|
264 | function content_rules_field_changed($node1, $node2, $settings) { |
---|
265 | // Get information about the field. |
---|
266 | $field = content_fields($settings['field_name'], $node1->type); |
---|
267 | |
---|
268 | return !empty($field) && !_content_rules_field_has_value($node1->$settings['field_name'], $node2->$settings['field_name']); |
---|
269 | } |
---|
270 | |
---|
271 | function content_rules_field_changed_form($settings, &$form, &$form_state) { |
---|
272 | $settings += array('field_name' => ''); |
---|
273 | $form['settings']['field_name'] = array( |
---|
274 | '#type' => 'select', |
---|
275 | '#title' => t('Field'), |
---|
276 | '#options' => content_rules_get_field_names_by_type(), |
---|
277 | '#default_value' => $settings['field_name'], |
---|
278 | '#description' => t('Select the machine-name of the field to look at.'), |
---|
279 | '#required' => TRUE, |
---|
280 | ); |
---|
281 | } |
---|
282 | |
---|
283 | function content_rules_field_changed_label($settings, $argument_labels) { |
---|
284 | return t("@node's field '@field' has been changed", array('@field' => $settings['field_name']) + $argument_labels); |
---|
285 | } |
---|
286 | |
---|
287 | |
---|
288 | /** |
---|
289 | * Returns the fields of a given field type only. |
---|
290 | * Suitable for using it with #options. |
---|
291 | */ |
---|
292 | function content_rules_get_field_names_by_type($type = NULL) { |
---|
293 | $fields = array(); |
---|
294 | foreach (content_fields() as $field) { |
---|
295 | if (!isset($type) || $field['type'] == $type) { |
---|
296 | $fields[$field['field_name']] = $field['field_name']; |
---|
297 | } |
---|
298 | } |
---|
299 | asort($fields); |
---|
300 | return $fields; |
---|
301 | } |
---|
302 | |
---|
303 | function _content_rules_get_field_value($settings, &$state) { |
---|
304 | if ($settings['code']) { |
---|
305 | if (function_exists('rules_input_evaluator_php_apply')) { |
---|
306 | // Support adding variables to the php code, if php module is present. |
---|
307 | $value = rules_input_evaluator_php_apply($settings['code'], $settings['vars'], $state, FALSE); |
---|
308 | } |
---|
309 | else { |
---|
310 | ob_start(); |
---|
311 | $value = eval($settings['code']); |
---|
312 | ob_end_clean(); |
---|
313 | } |
---|
314 | } |
---|
315 | else { |
---|
316 | $value = $settings['value']; |
---|
317 | } |
---|
318 | return $value; |
---|
319 | } |
---|
320 | |
---|
321 | /** |
---|
322 | * Checks whether both field values match in a robust way. |
---|
323 | * |
---|
324 | * It returns TRUE, only if the number of multiple values matches and |
---|
325 | * each property of the cck field's value is the same in the node. |
---|
326 | * |
---|
327 | * @param $node_value The value present in the node. |
---|
328 | * @param $value The value to check for. |
---|
329 | */ |
---|
330 | function _content_rules_field_has_value($node_value, $value) { |
---|
331 | if (count($value) != count($node_value)) { |
---|
332 | return FALSE; |
---|
333 | } |
---|
334 | // Loop over multiple fields |
---|
335 | foreach ($value as $delta => $sub_value) { |
---|
336 | // Check if all properties of the value are there in the node value too |
---|
337 | if (is_array($sub_value) && is_array($node_value[$delta])) { |
---|
338 | if (count(array_diff_assoc($sub_value, $node_value[$delta])) != 0) { |
---|
339 | return FALSE; |
---|
340 | } |
---|
341 | } |
---|
342 | elseif ($sub_value !== $node_value[$delta]) { |
---|
343 | return FALSE; |
---|
344 | } |
---|
345 | } |
---|
346 | return TRUE; |
---|
347 | } |
---|