Project

General

Profile

Paste
Download (12.9 KB) Statistics
| Branch: | Revision:

root / drupal7 / sites / all / modules / views / includes / base.inc @ 4003efde

1
<?php
2

    
3
/**
4
 * @file
5
 * Definition of views_object.
6
 */
7

    
8
/**
9
 * Provides the basic object definitions used by plugins and handlers.
10
 */
11
class views_object {
12

    
13
  /**
14
   * Except for displays, options for the object will be held here.
15
   */
16
  public $options = array();
17

    
18
  /**
19
   * The top object of a view.
20
   *
21
   * @var view
22
   */
23
  public $view = NULL;
24

    
25
  /**
26
   * Handler's definition.
27
   *
28
   * @var array
29
   */
30
  public $definition;
31

    
32
  /**
33
   * Information about options for all kinds of purposes will be held here.
34
   *
35
   * @code
36
   * 'option_name' => array(
37
   *  - 'default' => default value,
38
   *  - 'translatable' => (optional) TRUE/FALSE (wrap in t() on export if true),
39
   *  - 'contains' => (optional) array of items this contains, with its own
40
   *      defaults, etc. If contains is set, the default will be ignored and
41
   *      assumed to be array().
42
   *  - 'bool' => (optional) TRUE/FALSE Is the value a boolean value. This will
43
   *      change the export format to TRUE/FALSE instead of 1/0.
44
   *  - 'export' => (optional) FALSE or a callback for special export handling
45
   *      if necessary.
46
   *  - 'unpack_translatable' => (optional) callback for special handling for
47
   *      translating data within the option, if necessary.
48
   *  ),
49
   *
50
   * @return array
51
   *   Returns the options of this handler/plugin.
52
   *
53
   * @see views_object::export_option()
54
   * @see views_object::export_option_always()
55
   * @see views_object::unpack_translatable()
56
   */
57
  public function option_definition() {
58
    return array();
59
  }
60

    
61
  /**
62
   * Collect this handler's option definition and alter them, ready for use.
63
   *
64
   * @return array
65
   *   Returns the options of this handler/plugin after allowing for alters.
66
   *
67
   * @see hook_views_plugin_option_definition_alter()
68
   * @see hook_views_handler_option_definition_alter()
69
   */
70
  function altered_option_definition() {
71
    $definition = $this->option_definition();
72
    if (!empty($this->is_plugin)) {
73
      // Trigger hook_views_plugin_option_definition_alter().
74
      drupal_alter('views_plugin_option_definition', $definition, $this);
75
    }
76
    else {
77
      // Trigger hook_views_handler_option_definition_alter().
78
      drupal_alter('views_handler_option_definition', $definition, $this);
79
    }
80
    return $definition;
81
  }
82

    
83
  /**
84
   * Views handlers use a special construct function.
85
   *
86
   * Allows it to more easily construct them with variable arguments.
87
   */
88
  public function construct() {
89
    $this->set_default_options();
90
  }
91

    
92
  /**
93
   * Set default options on this object.
94
   *
95
   * Called by the constructor in a complex chain to deal with backward
96
   * compatibility.
97
   *
98
   * @deprecated since views2
99
   */
100
  public function options(&$options) {
101
  }
102

    
103
  /**
104
   * Set default options.
105
   *
106
   * For backward compatibility, it sends the options array; this is a feature
107
   * that will likely disappear at some point.
108
   */
109
  public function set_default_options() {
110
    $this->_set_option_defaults($this->options, $this->altered_option_definition());
111

    
112
    // Retained for complex defaults plus backward compatibility.
113
    $this->options($this->options);
114
  }
115

    
116
  /**
117
   *
118
   */
119
  public function _set_option_defaults(&$storage, $options, $level = 0) {
120
    foreach ($options as $option => $definition) {
121
      if (isset($definition['contains']) && is_array($definition['contains'])) {
122
        $storage[$option] = array();
123
        $this->_set_option_defaults($storage[$option], $definition['contains'], $level++);
124
      }
125
      elseif (!empty($definition['translatable']) && !empty($definition['default'])) {
126
        $storage[$option] = t($definition['default']);
127
      }
128
      else {
129
        $storage[$option] = isset($definition['default']) ? $definition['default'] : NULL;
130
      }
131
    }
132
  }
133

    
134
  /**
135
   * Unpack options over our existing defaults, drilling down into arrays so
136
   * that defaults don't get totally blown away.
137
   */
138
  public function unpack_options(&$storage, $options, $definition = NULL, $all = TRUE, $check = TRUE, $localization_keys = array()) {
139
    if ($check && !is_array($options)) {
140
      return;
141
    }
142

    
143
    if (!isset($definition)) {
144
      $definition = $this->altered_option_definition();
145
    }
146

    
147
    if (!empty($this->view)) {
148
      // Ensure we have a localization plugin.
149
      $this->view->init_localization();
150

    
151
      // Set up default localization keys. Handlers and such set this for us.
152
      if (empty($localization_keys) && isset($this->localization_keys)) {
153
        $localization_keys = $this->localization_keys;
154
      }
155
      // but plugins don't because there isn't a common init() these days.
156
      elseif (!empty($this->is_plugin) && empty($localization_keys)) {
157
        if ($this->plugin_type != 'display') {
158
          $localization_keys = array($this->view->current_display);
159
          $localization_keys[] = $this->plugin_type;
160
        }
161
      }
162
    }
163

    
164
    foreach ($options as $key => $value) {
165
      if (is_array($value)) {
166
        // Ignore arrays with no definition.
167
        if (!$all && empty($definition[$key])) {
168
          continue;
169
        }
170

    
171
        if (!isset($storage[$key]) || !is_array($storage[$key])) {
172
          $storage[$key] = array();
173
        }
174

    
175
        // If we're just unpacking our known options, and we're dropping an
176
        // unknown array (as might happen for a dependent plugin fields) go
177
        // ahead and drop that in.
178
        if (!$all && isset($definition[$key]) && !isset($definition[$key]['contains'])) {
179
          $storage[$key] = $value;
180
          continue;
181
        }
182

    
183
        $this->unpack_options($storage[$key], $value, isset($definition[$key]['contains']) ? $definition[$key]['contains'] : array(), $all, FALSE, array_merge($localization_keys, array($key)));
184
      }
185
      // Don't localize strings during editing. When editing, we need to work
186
      // with the original data, not the translated version.
187
      elseif (empty($this->view->editing) && !empty($definition[$key]['translatable']) && !empty($value) || !empty($definition['contains'][$key]['translatable']) && !empty($value)) {
188
        if (!empty($this->view) && $this->view->is_translatable()) {
189
          // Allow other modules to make changes to the string before it's
190
          // sent for translation.
191
          // The $keys array is built from the view name, any localization keys
192
          // sent in, and the name of the property being processed.
193
          $format = NULL;
194
          if (isset($definition[$key]['format_key']) && isset($options[$definition[$key]['format_key']])) {
195
            $format = $options[$definition[$key]['format_key']];
196
          }
197
          $translation_data = array(
198
            'value' => $value,
199
            'format' => $format,
200
            'keys' => array_merge(array($this->view->name), $localization_keys, array($key)),
201
          );
202
          $storage[$key] = $this->view->localization_plugin->translate($translation_data);
203
        }
204
        // Otherwise, this is a code-based string, so we can use t().
205
        else {
206
          $storage[$key] = t($value);
207
        }
208
      }
209
      elseif ($all || !empty($definition[$key])) {
210
        $storage[$key] = $value;
211
      }
212
    }
213
  }
214

    
215
  /**
216
   * Let the handler know what its full definition is.
217
   */
218
  public function set_definition($definition) {
219
    $this->definition = $definition;
220
    if (isset($definition['field'])) {
221
      $this->real_field = $definition['field'];
222
    }
223
  }
224

    
225
  /**
226
   * Destructor.
227
   */
228
  public function destroy() {
229
    if (isset($this->view)) {
230
      unset($this->view);
231
    }
232

    
233
    if (isset($this->display)) {
234
      unset($this->display);
235
    }
236

    
237
    if (isset($this->query)) {
238
      unset($this->query);
239
    }
240
  }
241

    
242
  /**
243
   *
244
   */
245
  public function export_options($indent, $prefix) {
246
    $output = '';
247
    foreach ($this->altered_option_definition() as $option => $definition) {
248
      $output .= $this->export_option($indent, $prefix, $this->options, $option, $definition, array());
249
    }
250

    
251
    return $output;
252
  }
253

    
254
  /**
255
   *
256
   */
257
  public function export_option($indent, $prefix, $storage, $option, $definition, $parents) {
258
    // Do not export options for which we have no settings.
259
    if (!isset($storage[$option])) {
260
      return;
261
    }
262

    
263
    if (isset($definition['export'])) {
264
      if ($definition['export'] === FALSE) {
265
        return;
266
      }
267

    
268
      // Special handling for some items.
269
      if (method_exists($this, $definition['export'])) {
270
        return $this->{$definition['export']}($indent, $prefix, $storage, $option, $definition, $parents);
271
      }
272
    }
273

    
274
    // Add the current option to the parents tree.
275
    $parents[] = $option;
276
    $output = '';
277

    
278
    // If it has child items, export those separately.
279
    if (isset($definition['contains'])) {
280
      foreach ($definition['contains'] as $sub_option => $sub_definition) {
281
        $output .= $this->export_option($indent, $prefix, $storage[$option], $sub_option, $sub_definition, $parents);
282
      }
283
    }
284
    // Otherwise export just this item.
285
    else {
286
      $default = isset($definition['default']) ? $definition['default'] : NULL;
287
      $value = $storage[$option];
288
      if (isset($definition['bool'])) {
289
        $value = (bool) $value;
290
      }
291

    
292
      if ($value !== $default) {
293
        $output .= $indent . $prefix . "['" . implode("']['", $parents) . "'] = ";
294
        if (isset($definition['bool'])) {
295
          $output .= empty($storage[$option]) ? 'FALSE' : 'TRUE';
296
        }
297
        else {
298
          $output .= views_var_export($storage[$option], $indent);
299
        }
300

    
301
        $output .= ";\n";
302
      }
303
    }
304
    return $output;
305
  }
306

    
307
  /**
308
   * Always exports the option, regardless of the default value.
309
   */
310
  public function export_option_always($indent, $prefix, $storage, $option, $definition, $parents) {
311
    // If there is no default, the option will always be exported.
312
    unset($definition['default']);
313
    // Unset our export method to prevent recursion.
314
    unset($definition['export']);
315
    return $this->export_option($indent, $prefix, $storage, $option, $definition, $parents);
316
  }
317

    
318
  /**
319
   * Unpacks each handler to store translatable texts.
320
   */
321
  public function unpack_translatables(&$translatable, $parents = array()) {
322
    foreach ($this->altered_option_definition() as $option => $definition) {
323
      $this->unpack_translatable($translatable, $this->options, $option, $definition, $parents, array());
324
    }
325
  }
326

    
327
  /**
328
   * Unpack a single option definition.
329
   *
330
   * This function run's through all suboptions recursive.
331
   *
332
   * @param array $translatable
333
   *   Stores all available translatable items.
334
   * @param array $storage
335
   * @param string $option
336
   * @param string $definition
337
   * @param array $parents
338
   * @param array $keys
339
   */
340
  public function unpack_translatable(&$translatable, $storage, $option, $definition, $parents, $keys = array()) {
341
    // Do not export options for which we have no settings.
342
    if (!isset($storage[$option])) {
343
      return;
344
    }
345

    
346
    // Special handling for some items.
347
    if (isset($definition['unpack_translatable']) && method_exists($this, $definition['unpack_translatable'])) {
348
      return $this->{$definition['unpack_translatable']}($translatable, $storage, $option, $definition, $parents, $keys);
349
    }
350

    
351
    if (isset($definition['translatable'])) {
352
      if ($definition['translatable'] === FALSE) {
353
        return;
354
      }
355
    }
356

    
357
    // Add the current option to the parents tree.
358
    $parents[] = $option;
359

    
360
    // If it has child items, unpack those separately.
361
    if (isset($definition['contains'])) {
362
      foreach ($definition['contains'] as $sub_option => $sub_definition) {
363
        $translation_keys = array_merge($keys, array($sub_option));
364
        $this->unpack_translatable($translatable, $storage[$option], $sub_option, $sub_definition, $parents, $translation_keys);
365
      }
366
    }
367

    
368
    // @todo Figure out this double definition stuff.
369
    $options = $storage[$option];
370
    if (is_array($options)) {
371
      foreach ($options as $key => $value) {
372
        $translation_keys = array_merge($keys, array($key));
373
        if (is_array($value)) {
374
          $this->unpack_translatable($translatable, $options, $key, $definition, $parents, $translation_keys);
375
        }
376
        elseif (!empty($definition[$key]['translatable']) && !empty($value)) {
377
          // Build source data and add to the array.
378
          $format = NULL;
379
          if (isset($definition['format_key']) && isset($options[$definition['format_key']])) {
380
            $format = $options[$definition['format_key']];
381
          }
382
          $translatable[] = array(
383
            'value' => $value,
384
            'keys' => $translation_keys,
385
            'format' => $format,
386
          );
387
        }
388
      }
389
    }
390
    elseif (!empty($definition['translatable']) && !empty($options)) {
391
      $value = $options;
392
      // Build source data and add to the array.
393
      $format = NULL;
394
      if (isset($definition['format_key']) && isset($storage[$definition['format_key']])) {
395
        $format = $storage[$definition['format_key']];
396
      }
397
      $translatable[] = array(
398
        'value' => $value,
399
        'keys' => isset($translation_keys) ? $translation_keys : $parents,
400
        'format' => $format,
401
      );
402
    }
403
  }
404

    
405
}