Projet

Général

Profil

Paste
Télécharger (10,2 ko) Statistiques
| Branche: | Révision:

root / drupal7 / sites / all / modules / rules / modules / system.eval.inc @ 950416da

1
<?php
2

    
3
/**
4
 * @file
5
 * Contains rules integration for the system module needed during evaluation.
6
 *
7
 * @addtogroup rules
8
 *
9
 * @{
10
 */
11

    
12
/**
13
 * Action: Show a drupal message.
14
 */
15
function rules_action_drupal_message($message, $status, $repeat) {
16
  drupal_set_message(filter_xss_admin($message), $status, $repeat);
17
}
18

    
19
/**
20
 * Action: Page redirect.
21
 *
22
 * @see rules_page_build()
23
 * @see rules_drupal_goto_alter()
24
 */
25
function rules_action_drupal_goto($url, $force = FALSE, $destination = FALSE) {
26
  // Don't let administrators lock them out from Rules administration pages.
27
  if (isset($_GET['q']) && strpos($_GET['q'], 'admin/config/workflow/rules') === 0) {
28
    rules_log('Skipped page redirect on Rules administration page.', array(), RulesLog::WARN);
29
    return;
30
  }
31
  // Do not redirect during batch processing.
32
  if (($batch = batch_get()) && isset($batch['current_set'])) {
33
    rules_log('Skipped page redirect during batch processing.');
34
    return;
35
  }
36

    
37
  // Keep the current destination parameter if there is one set.
38
  if ($destination) {
39
    $url .= strpos($url, '?') === FALSE ? '?' : '&';
40
    $url .= drupal_http_build_query(drupal_get_destination());
41
  }
42
  // If force is enabled, remove any destination parameter.
43
  if ($force && isset($_GET['destination'])) {
44
    unset($_GET['destination']);
45
  }
46
  // We don't invoke drupal_goto() right now, as this would end the current
47
  // page execution unpredictably for modules. So we'll take over drupal_goto()
48
  // calls from somewhere else via hook_drupal_goto_alter() and make sure
49
  // a drupal_goto() is invoked before the page is output with
50
  // rules_page_build().
51
  $GLOBALS['_rules_action_drupal_goto_do'] = array($url, $force);
52
}
53

    
54
/**
55
 * Action: Set breadcrumb.
56
 */
57
function rules_action_breadcrumb_set(array $titles, array $paths) {
58
  $trail = array(l(t('Home'), ''));
59
  foreach ($titles as $i => $title) {
60
    // Skip empty titles.
61
    if ($title = trim($title)) {
62
      // Output plaintext instead of a link if there is a title
63
      // without a path.
64
      $path = trim($paths[$i]);
65
      if (!empty($paths[$i]) && $paths[$i] != '<none>') {
66
        $trail[] = l($title, trim($paths[$i]));
67
      }
68
      else {
69
        $trail[] = check_plain($title);
70
      }
71
    }
72
  }
73
  drupal_set_breadcrumb($trail);
74
}
75

    
76
/**
77
 * Action Implementation: Send mail.
78
 */
79
function rules_action_mail($to, $subject, $message, $from = NULL, $langcode, $settings, RulesState $state, RulesPlugin $element) {
80
  $to = str_replace(array("\r", "\n"), '', $to);
81
  $from = !empty($from) ? str_replace(array("\r", "\n"), '', $from) : NULL;
82
  $params = array(
83
    'subject' => $subject,
84
    'message' => $message,
85
    'langcode' => $langcode,
86
  );
87
  // Set a unique key for this mail.
88
  $name = isset($element->root()->name) ? $element->root()->name : 'unnamed';
89
  $key = 'rules_action_mail_' . $name . '_' . $element->elementId();
90
  $languages = language_list();
91
  $language = isset($languages[$langcode]) ? $languages[$langcode] : language_default();
92

    
93
  $message = drupal_mail('rules', $key, $to, $language, $params, $from);
94
  if ($message['result']) {
95
    watchdog('rules', 'Successfully sent email to %recipient', array('%recipient' => $to));
96
  }
97
}
98

    
99
/**
100
 * Action: Send mail to all users of a specific role group(s).
101
 */
102
function rules_action_mail_to_users_of_role($roles, $subject, $message, $from = NULL, $settings, RulesState $state, RulesPlugin $element) {
103
  $from = !empty($from) ? str_replace(array("\r", "\n"), '', $from) : NULL;
104

    
105
  // All authenticated users, which is everybody.
106
  if (in_array(DRUPAL_AUTHENTICATED_RID, $roles)) {
107
    $result = db_query('SELECT mail FROM {users} WHERE uid > 0');
108
  }
109
  else {
110
    // Avoid sending emails to members of two or more target role groups.
111
    $result = db_query('SELECT DISTINCT u.mail FROM {users} u INNER JOIN {users_roles} r ON u.uid = r.uid WHERE r.rid IN (:rids)', array(':rids' => $roles));
112
  }
113

    
114
  // Now, actually send the mails.
115
  $params = array(
116
    'subject' => $subject,
117
    'message' => $message,
118
  );
119
  // Set a unique key for this mail.
120
  $name = isset($element->root()->name) ? $element->root()->name : 'unnamed';
121
  $key = 'rules_action_mail_to_users_of_role_' . $name . '_' . $element->elementId();  $languages = language_list();
122

    
123
  $message = array('result' => TRUE);
124
  foreach ($result as $row) {
125
    $message = drupal_mail('rules', $key, $row->mail, language_default(), $params, $from);
126
    // If $message['result'] is FALSE, then it's likely that email sending is
127
    // failing at the moment, and we should just abort sending any more. If
128
    // however, $message['result'] is NULL, then it's likely that a module has
129
    // aborted sending this particular email to this particular user, and we
130
    // should just keep on sending emails to the other users.
131
    // For more information on the result value, see drupal_mail().
132
    if ($message['result'] === FALSE) {
133
      break;
134
    }
135
  }
136
  if ($message['result'] !== FALSE) {
137
    $role_names = array_intersect_key(user_roles(TRUE), array_flip($roles));
138
    watchdog('rules', 'Successfully sent email to the role(s) %roles.', array('%roles' => implode(', ', $role_names)));
139
  }
140
}
141

    
142
/**
143
 * Implements hook_mail().
144
 *
145
 * Sets the message subject and body as configured.
146
 */
147
function rules_mail($key, &$message, $params) {
148

    
149
  $message['subject'] .= str_replace(array("\r", "\n"), '', $params['subject']);
150
  $message['body'][] = $params['message'];
151
}
152

    
153
/**
154
 * Action: Block an IP address.
155
 */
156
function rules_action_block_ip($ip_address = NULL) {
157
  if (empty($ip_address)) {
158
    $ip_address = ip_address();
159
  }
160
  db_insert('blocked_ips')->fields(array('ip' => $ip_address))->execute();
161
  watchdog('rules', 'Banned IP address %ip', array('%ip' => $ip_address));
162
}
163

    
164
/**
165
 * A class implementing a rules input evaluator processing tokens.
166
 */
167
class RulesTokenEvaluator extends RulesDataInputEvaluator {
168

    
169
  /**
170
   * Overrides RulesDataInputEvaluator::prepare().
171
   */
172
  public function prepare($text, $var_info) {
173
    $text = is_array($text) ? implode('', $text) : $text;
174
    // Skip this evaluator if there are no tokens.
175
    $this->setting = token_scan($text) ? TRUE : NULL;
176
  }
177

    
178
  /**
179
   * Evaluate tokens.
180
   *
181
   * We replace the tokens on our own as we cannot use token_replace(), because
182
   * token usually assumes that $data['node'] is a of type node, which doesn't
183
   * hold in general in our case.
184
   * So we properly map variable names to variable data types and then run the
185
   * replacement ourself.
186
   */
187
  public function evaluate($text, $options, RulesState $state) {
188
    $var_info = $state->varInfo();
189
    $options += array('sanitize' => FALSE);
190

    
191
    $replacements = array();
192
    $data = array();
193
    // We also support replacing tokens in a list of textual values.
194
    $whole_text = is_array($text) ? implode('', $text) : $text;
195
    foreach (token_scan($whole_text) as $var_name => $tokens) {
196
      $var_name = str_replace('-', '_', $var_name);
197
      if (isset($var_info[$var_name]) && ($token_type = _rules_system_token_map_type($var_info[$var_name]['type']))) {
198
        // We have to key $data with the type token uses for the variable.
199
        $data = rules_unwrap_data(array($token_type => $state->get($var_name)), array($token_type => $var_info[$var_name]));
200
        $replacements += token_generate($token_type, $tokens, $data, $options);
201
      }
202
      else {
203
        $replacements += token_generate($var_name, $tokens, array(), $options);
204
      }
205
      // Remove tokens if no replacement value is found. As token_replace() does
206
      // if 'clear' is set.
207
      $replacements += array_fill_keys($tokens, '');
208
    }
209

    
210
    // Optionally clean the list of replacement values.
211
    if (!empty($options['callback']) && function_exists($options['callback'])) {
212
      $function = $options['callback'];
213
      $function($replacements, $data, $options);
214
    }
215

    
216
    // Actually apply the replacements.
217
    $tokens = array_keys($replacements);
218
    $values = array_values($replacements);
219
    if (is_array($text)) {
220
      foreach ($text as $i => $text_item) {
221
        $text[$i] = str_replace($tokens, $values, $text_item);
222
      }
223
      return $text;
224
    }
225
    return str_replace($tokens, $values, $text);
226
  }
227

    
228
  /**
229
   * Create documentation about the available replacement patterns.
230
   *
231
   * @param array $var_info
232
   *   Array with the available variables.
233
   *
234
   * @return array
235
   *   Renderable array with the replacement pattern documentation.
236
   */
237
  public static function help($var_info) {
238
    $render = array(
239
      '#type' => 'fieldset',
240
      '#title' => t('Replacement patterns'),
241
      '#collapsible' => TRUE,
242
      '#collapsed' => TRUE,
243
      '#description' => t('Note that token replacements containing chained objects – such as [node:author:uid] – are not listed here, but are still available. The <em>data selection</em> input mode may help you find more complex replacement patterns. See <a href="@url">the online documentation</a> for more information about complex replacement patterns.',
244
        array('@url' => rules_external_help('chained-tokens'))),
245
    );
246
    $token_info = token_info();
247
    foreach ($var_info as $name => $info) {
248
      $token_types[$name] = _rules_system_token_map_type($info['type']);
249
    }
250

    
251
    foreach ($token_types as $name => $token_type) {
252
      if (isset($token_info['types'][$token_type])) {
253
        $render[$name] = array(
254
          '#theme' => 'table',
255
          '#header' => array(t('Token'), t('Label'), t('Description')),
256
          '#prefix' => '<h3>' . t('Replacement patterns for %label', array('%label' => $var_info[$name]['label'])) . '</h3>',
257
        );
258
        foreach ($token_info['tokens'][$token_type] as $token => $info) {
259
          $token = '[' . str_replace('_', '-', $name) . ':' . $token . ']';
260
          $render[$name]['#rows'][$token] = array(
261
            check_plain($token),
262
            check_plain($info['name']),
263
            check_plain($info['description']),
264
          );
265
        }
266
      }
267
    }
268
    return $render;
269
  }
270

    
271
}
272

    
273
/**
274
 * Looks for a token type mapping. Defaults to passing through the type.
275
 */
276
function _rules_system_token_map_type($type) {
277
  $entity_info = entity_get_info();
278
  if (isset($entity_info[$type]['token type'])) {
279
    return $entity_info[$type]['token type'];
280
  }
281
  $cache = rules_get_cache();
282
  if (isset($cache['data_info'][$type]['token type'])) {
283
    return $cache['data_info'][$type]['token type'];
284
  }
285
  return $type;
286
}
287

    
288
/**
289
 * @}
290
 */