Projet

Général

Profil

Paste
Télécharger (12 ko) Statistiques
| Branche: | Révision:

root / drupal7 / sites / all / modules / rules / includes / rules.processor.inc @ 950416da

1
<?php
2

    
3
/**
4
 * @file
5
 * Contains classes for data processing.
6
 *
7
 * Data processors can be used to process element arguments on evaluation time,
8
 * e.g. to apply input evaluators or to apply simple calculations to number
9
 * arguments.
10
 */
11

    
12
/**
13
 * Common base class for Rules data processors.
14
 */
15
abstract class RulesDataProcessor {
16

    
17
  /**
18
   * The processors' setting value.
19
   */
20
  protected $setting = NULL;
21

    
22
  /**
23
   * Allows chaining processors. If set, the next processor to invoke.
24
   */
25
  protected $processor = NULL;
26

    
27
  /**
28
   * Constructor.
29
   */
30
  protected function __construct($setting, $param_info, $var_info = array(), $processor = NULL) {
31
    $this->setting = $setting;
32
    $this->processor = $processor;
33
  }
34

    
35
  /**
36
   * Return $this or skip this processor by returning the next processor.
37
   */
38
  protected function getPreparedValue() {
39
    return isset($this->setting) && array_filter($this->setting) ? $this : $this->processor;
40
  }
41

    
42
  /**
43
   * Determines whether the current user has permission to edit this chain of
44
   * data processors.
45
   *
46
   * @return bool
47
   *   Whether the current user has permission to edit this chain of data
48
   *   processors.
49
   */
50
  public function editAccess() {
51
    return $this->access() && (!isset($this->processor) || $this->processor->editAccess());
52
  }
53

    
54
  /**
55
   * Prepares the processor for parameters.
56
   *
57
   * It turns the settings into a suitable processor object, which gets invoked
58
   * on evaluation time.
59
   *
60
   * @param $setting
61
   *   The processor settings which are to be prepared.
62
   * @param $param_info
63
   *   The info about the parameter to prepare the processor for.
64
   * @param array $var_info
65
   *   An array of info about the available variables.
66
   */
67
  public static function prepareSetting(&$setting, $param_info, $var_info = array()) {
68
    $processor = NULL;
69
    foreach (self::processors($param_info, FALSE) as $name => $info) {
70
      if (!empty($setting[$name])) {
71
        $object = new $info['class']($setting[$name], $param_info, $var_info, $processor);
72
        $processor = $object->getPreparedValue();
73
      }
74
    }
75
    $setting = $processor;
76
  }
77

    
78
  /**
79
   * Attaches the form of applicable data processors.
80
   */
81
  public static function attachForm(&$form, $settings, $param_info, $var_info, $access_check = TRUE) {
82
    // If $settings is already prepared get the settings from the processors.
83
    if ($settings instanceof RulesDataProcessor) {
84
      $settings = $settings->getChainSettings();
85
    }
86
    foreach (self::processors($param_info, $access_check) as $name => $info) {
87
      $settings += array($name => array());
88
      $form[$name] = call_user_func(array($info['class'], 'form'), $settings[$name], $var_info);
89
      $form[$name]['#weight'] = $info['weight'];
90
    }
91
  }
92

    
93
  /**
94
   * Returns defined data processors applicable for the given parameter.
95
   *
96
   * Optionally also checks access to the processors.
97
   *
98
   * @param $param_info
99
   *   If given, only processors valid for this parameter are returned.
100
   * @param bool $access_check
101
   * @param string $hook
102
   */
103
  public static function processors($param_info = NULL, $access_check = TRUE, $hook = 'data_processor_info') {
104
    static $items = array();
105

    
106
    if (!isset($items[$hook]['all'])) {
107
      $items[$hook]['all'] = rules_fetch_data($hook);
108
      if (isset($items[$hook]['all'])) {
109
        uasort($items[$hook]['all'], array(__CLASS__, '_item_sort'));
110
      }
111
    }
112
    // Data processing isn't supported for multiple types.
113
    if (isset($param_info) && is_array($param_info['type'])) {
114
      return array();
115
    }
116
    // Filter the items by type.
117
    if (isset($param_info['type']) && !isset($items[$hook][$param_info['type']])) {
118
      $items[$hook][$param_info['type']] = array();
119
      foreach ($items[$hook]['all'] as $name => $info) {
120
        // Check whether the parameter type matches the supported types.
121
        $info += array('type' => 'text');
122
        if (RulesData::typesMatch($param_info, $info, FALSE)) {
123
          $items[$hook][$param_info['type']][$name] = $info;
124
        }
125
      }
126
    }
127
    // Apply the access check.
128
    $return = isset($param_info['type']) ? $items[$hook][$param_info['type']] : $items[$hook]['all'];
129
    if ($access_check) {
130
      foreach ($return as $base => $info) {
131
        if (!call_user_func(array($info['class'], 'access'))) {
132
          unset($return[$base]);
133
        }
134
      }
135
    }
136
    return $return;
137
  }
138

    
139
  public static function _item_sort($a, $b) {
140
    return $a['weight'] < $b['weight'] ? -1 : ($a['weight'] > $b['weight'] ? 1 : 0);
141
  }
142

    
143
  /**
144
   * Gets the settings array for this and all contained chained processors.
145
   */
146
  public function getChainSettings() {
147
    foreach ($this->unchain() as $name => $processor) {
148
      $settings[$name] = $processor->getSetting();
149
    }
150
    return isset($settings) ? $settings : array();
151
  }
152

    
153
  /**
154
   * Returns an array of modules which we depend on.
155
   */
156
  public function dependencies() {
157
    $used_processor_info = array_intersect_key($this->processors(), $this->unchain());
158
    $modules = array();
159
    foreach ($used_processor_info as $name => $info) {
160
      $modules[] = $info['module'];
161
    }
162
    return array_filter($modules);
163
  }
164

    
165
  /**
166
   * @return
167
   *   An array of processors keyed by processor name.
168
   */
169
  protected function unchain() {
170
    $processor = $this;
171
    while ($processor instanceof RulesDataProcessor) {
172
      $processors[get_class($processor)] = $processor;
173
      $processor = $processor->processor;
174
    }
175
    // Note: Don't use the static context to call processors() here as we need a
176
    // late binding to invoke the input evaluators version, if needed.
177
    $return = array();
178
    foreach ($this->processors() as $name => $info) {
179
      if (isset($processors[$info['class']])) {
180
        $return[$name] = $processors[$info['class']];
181
      }
182
    }
183
    return $return;
184
  }
185

    
186
  /**
187
   * Gets the settings of this processor.
188
   */
189
  public function getSetting() {
190
    return $this->setting;
191
  }
192

    
193
  /**
194
   * Processes the value.
195
   *
196
   * If $this->processor is set, invoke this processor first so chaining
197
   * multiple processors is working.
198
   *
199
   * @param $value
200
   *   The value to process.
201
   * @param $info
202
   *   Info about the parameter for which we process the value.
203
   * @param RulesState $state
204
   *   The rules evaluation state.
205
   * @param RulesPlugin $element
206
   *   The element for which we process the value.
207
   *
208
   * @return
209
   *   The processed value.
210
   */
211
  abstract public function process($value, $info, RulesState $state, RulesPlugin $element);
212

    
213
  /**
214
   * Return whether the current user has permission to use the processor.
215
   *
216
   * @return bool
217
   *   Whether the current user has permission to use the processor.
218
   */
219
  public static function access() {
220
    return TRUE;
221
  }
222

    
223
  /**
224
   * Defines the processor form element.
225
   *
226
   * @param $settings
227
   *   The settings of the processor.
228
   * @param array $var_info
229
   *   An array of info about the available variables.
230
   *
231
   * @return
232
   *   A form element structure.
233
   */
234
  protected static function form($settings, $var_info) {
235
    return array();
236
  }
237

    
238
}
239

    
240

    
241
/**
242
 * A base processor for use by input evaluators.
243
 *
244
 * Input evaluators are not listed in hook_rules_data_processor_info(). Instead
245
 * they use hook_rules_evaluator_info() and get attached to input forms.
246
 */
247
abstract class RulesDataInputEvaluator extends RulesDataProcessor {
248

    
249
  /**
250
   * Overridden to invoke prepare().
251
   */
252
  protected function __construct($setting, $param_info, $var_info = array(), $processor = NULL) {
253
    $this->setting = TRUE;
254
    $this->processor = $processor;
255
    $this->prepare($setting, $var_info, $param_info);
256
  }
257

    
258
  /**
259
   * Overridden to generate evaluator $options and invoke evaluate().
260
   */
261
  public function process($value, $info, RulesState $state, RulesPlugin $element, $options = NULL) {
262
    $options = isset($options) ? $options : $this->getEvaluatorOptions($info, $state, $element);
263
    $value = isset($this->processor) ? $this->processor->process($value, $info, $state, $element, $options) : $value;
264
    return $this->evaluate($value, $options, $state);
265
  }
266

    
267
  /**
268
   * Generates the evaluator $options.
269
   */
270
  protected function getEvaluatorOptions($info, $state, $element) {
271
    $cache = rules_get_cache();
272
    $languages = language_list();
273
    $info += array(
274
      'cleaning callback' => isset($cache['data info'][$info['type']]['cleaning callback']) ? $cache['data info'][$info['type']]['cleaning callback'] : FALSE,
275
      'sanitize' => FALSE,
276
    );
277
    $options = array_filter(array(
278
      'language' => $info['#langcode'] != LANGUAGE_NONE && isset($languages[$info['#langcode']]) ? $languages[$info['#langcode']] : NULL,
279
      'callback' => $info['cleaning callback'],
280
      'sanitize' => $info['sanitize'],
281
    ));
282
    return $options;
283
  }
284

    
285
  /**
286
   * Overridden to prepare input evaluator processors.
287
   *
288
   * The setting is expected to be the input value to be evaluated later on
289
   * and is replaced by the suitable processor.
290
   */
291
  public static function prepareSetting(&$setting, $param_info, $var_info = array()) {
292
    $processor = NULL;
293
    foreach (self::evaluators($param_info, FALSE) as $name => $info) {
294
      $object = new $info['class']($setting, $param_info, $var_info, $processor);
295
      $processor = $object->getPreparedValue();
296
    }
297
    $setting = $processor;
298
  }
299

    
300
  protected function getPreparedValue() {
301
    return isset($this->setting) ? $this : $this->processor;
302
  }
303

    
304
  /**
305
   * Overrides RulesDataProcessor::attachForm().
306
   *
307
   * Overridden to just attach the help() of evaluators.
308
   */
309
  public static function attachForm(&$form, $settings, $param_info, $var_info, $access_check = TRUE) {
310
    foreach (self::evaluators($param_info, $access_check) as $name => $info) {
311
      $form['help'][$name] = call_user_func(array($info['class'], 'help'), $var_info, $param_info);
312
      $form['help'][$name]['#weight'] = $info['weight'];
313
    }
314
  }
315

    
316
  /**
317
   * Returns all input evaluators that can be applied to the parameters type.
318
   */
319
  public static function evaluators($param_info = NULL, $access_check = TRUE) {
320
    return parent::processors($param_info, $access_check, 'evaluator_info');
321
  }
322

    
323
  /**
324
   * Overrides RulesDataProcessor::processors().
325
   *
326
   * Overridden to default to our hook, thus being equivalent to
327
   * self::evaluators().
328
   */
329
  public static function processors($param_info = NULL, $access_check = TRUE, $hook = 'evaluator_info') {
330
    return parent::processors($param_info, $access_check, $hook);
331
  }
332

    
333
  /**
334
   * Prepares the evaluation.
335
   *
336
   * For example, to determine whether the input evaluator has been used.
337
   * If this evaluator should be skipped just unset $this->setting.
338
   *
339
   * @param string $text
340
   *   The text to evaluate later on.
341
   * @param array $variables
342
   *   An array of info about available variables.
343
   * @param array $param_info
344
   *   (optional) An array of information about the handled parameter value.
345
   *   For backward compatibility, this parameter is not required.
346
   */
347
  abstract public function prepare($text, $variables);
348

    
349
  /**
350
   * Apply the input evaluator.
351
   *
352
   * @param string $text
353
   *   The text to evaluate.
354
   * @param array $options
355
   *   A keyed array of settings and flags to control the processing.
356
   *   Supported options are:
357
   *   - language: A language object to be used when processing.
358
   *   - callback: A callback function that will be used to post-process
359
   *     replacements that might be incorporated, so they can be cleaned in a
360
   *     certain way.
361
   *   - sanitize: A boolean flag indicating whether incorporated replacements
362
   *     should be sanitized.
363
   * @param RulesState $state
364
   *   The rules evaluation state.
365
   *
366
   * @return
367
   *   The evaluated text.
368
   */
369
  abstract public function evaluate($text, $options, RulesState $state);
370

    
371
  /**
372
   * Provide some usage help for the evaluator.
373
   *
374
   * @param array $variables
375
   *   An array of info about available variables.
376
   * @param array $param_info
377
   *   (optional) An array of information about the handled parameter value.
378
   *   For backward compatibility, this parameter is not required.
379
   *
380
   * @return array
381
   *   A renderable array.
382
   */
383
  public static function help($variables) {
384
    return array();
385
  }
386

    
387
}