FieldPluginBase.php 58 KB
Newer Older
Earl Miles's avatar
Earl Miles committed
1
2
3
4
<?php

/**
 * @file
5
 * Definition of Drupal\views\Plugin\views\field\FieldPluginBase.
Earl Miles's avatar
Earl Miles committed
6
7
 */

8
namespace Drupal\views\Plugin\views\field;
9

10
use Drupal\views\Plugin\views\HandlerBase;
11
use Drupal\views\Plugin\views\display\DisplayPluginBase;
12
use Drupal\views\ViewExecutable;
13

Earl Miles's avatar
Earl Miles committed
14
15
16
17
18
19
20
21
/**
 * @defgroup views_field_handlers Views field handlers
 * @{
 * Handlers to tell Views how to build and display fields.
 *
 */

/**
22
 * Indicator of the renderText() method for rendering a single item.
Earl Miles's avatar
Earl Miles committed
23
24
25
26
27
 * (If no render_item() is present).
 */
define('VIEWS_HANDLER_RENDER_TEXT_PHASE_SINGLE_ITEM', 0);

/**
28
 * Indicator of the renderText() method for rendering the whole element.
Earl Miles's avatar
Earl Miles committed
29
30
31
32
33
 * (if no render_item() method is available).
 */
define('VIEWS_HANDLER_RENDER_TEXT_PHASE_COMPLETELY', 1);

/**
34
 * Indicator of the renderText() method for rendering the empty text.
Earl Miles's avatar
Earl Miles committed
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
 */
define('VIEWS_HANDLER_RENDER_TEXT_PHASE_EMPTY', 2);

/**
 * Base field handler that has no options and renders an unformatted field.
 *
 * Definition terms:
 * - additional fields: An array of fields that should be added to the query
 *                      for some purpose. The array is in the form of:
 *                      array('identifier' => array('table' => tablename,
 *                      'field' => fieldname); as many fields as are necessary
 *                      may be in this array.
 * - click sortable: If TRUE, this field may be click sorted.
 *
 * @ingroup views_field_handlers
 */
51
abstract class FieldPluginBase extends HandlerBase {
52

Earl Miles's avatar
Earl Miles committed
53
54
55
  var $field_alias = 'unknown';
  var $aliases = array();

56
57
58
59
60
61
62
  /**
   * The field value prior to any rewriting.
   *
   * @var mixed
   */
  public $original_value = NULL;

Earl Miles's avatar
Earl Miles committed
63
64
65
66
67
68
69
70
  /**
   * @var array
   * Stores additional fields which get's added to the query.
   * The generated aliases are stored in $aliases.
   */
  var $additional_fields = array();

  /**
71
   * Overrides Drupal\views\Plugin\views\HandlerBase::init().
Earl Miles's avatar
Earl Miles committed
72
   */
73
74
  public function init(ViewExecutable $view, DisplayPluginBase $display, array &$options = NULL) {
    parent::init($view, $display, $options);
Earl Miles's avatar
Earl Miles committed
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91

    $this->additional_fields = array();
    if (!empty($this->definition['additional fields'])) {
      $this->additional_fields = $this->definition['additional fields'];
    }

    if (!isset($this->options['exclude'])) {
      $this->options['exclude'] = '';
    }
  }

  /**
   * Determine if this field can allow advanced rendering.
   *
   * Fields can set this to FALSE if they do not wish to allow
   * token based rewriting or link-making.
   */
92
  protected function allowAdvancedRender() {
Earl Miles's avatar
Earl Miles committed
93
94
95
96
97
98
    return TRUE;
  }

  /**
   * Called to add the field to a query.
   */
99
  public function query() {
100
    $this->ensureMyTable();
Earl Miles's avatar
Earl Miles committed
101
102
    // Add the field.
    $params = $this->options['group_type'] != 'group' ? array('function' => $this->options['group_type']) : array();
103
    $this->field_alias = $this->query->addField($this->tableAlias, $this->realField, NULL, $params);
Earl Miles's avatar
Earl Miles committed
104

105
    $this->addAdditionalFields();
Earl Miles's avatar
Earl Miles committed
106
107
108
109
110
111
112
113
114
115
116
117
  }

  /**
   * Add 'additional' fields to the query.
   *
   * @param $fields
   * An array of fields. The key is an identifier used to later find the
   * field alias used. The value is either a string in which case it's
   * assumed to be a field on this handler's table; or it's an array in the
   * form of
   * @code array('table' => $tablename, 'field' => $fieldname) @endcode
   */
118
  protected function addAdditionalFields($fields = NULL) {
Earl Miles's avatar
Earl Miles committed
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
    if (!isset($fields)) {
      // notice check
      if (empty($this->additional_fields)) {
        return;
      }
      $fields = $this->additional_fields;
    }

    $group_params = array();
    if ($this->options['group_type'] != 'group') {
      $group_params = array(
        'function' => $this->options['group_type'],
      );
    }

    if (!empty($fields) && is_array($fields)) {
      foreach ($fields as $identifier => $info) {
        if (is_array($info)) {
          if (isset($info['table'])) {
138
            $table_alias = $this->query->ensureTable($info['table'], $this->relationship);
Earl Miles's avatar
Earl Miles committed
139
140
          }
          else {
141
            $table_alias = $this->tableAlias;
Earl Miles's avatar
Earl Miles committed
142
143
144
145
146
147
148
149
150
151
152
153
154
155
          }

          if (empty($table_alias)) {
            debug(t('Handler @handler tried to add additional_field @identifier but @table could not be added!', array('@handler' => $this->definition['handler'], '@identifier' => $identifier, '@table' => $info['table'])));
            $this->aliases[$identifier] = 'broken';
            continue;
          }

          $params = array();
          if (!empty($info['params'])) {
            $params = $info['params'];
          }

          $params += $group_params;
156
          $this->aliases[$identifier] = $this->query->addField($table_alias, $info['field'], NULL, $params);
Earl Miles's avatar
Earl Miles committed
157
158
        }
        else {
159
          $this->aliases[$info] = $this->query->addField($this->tableAlias, $info, NULL, $group_params);
Earl Miles's avatar
Earl Miles committed
160
161
162
163
164
165
166
167
        }
      }
    }
  }

  /**
   * Called to determine what to tell the clicksorter.
   */
168
  public function clickSort($order) {
Earl Miles's avatar
Earl Miles committed
169
170
171
172
    if (isset($this->field_alias)) {
      // Since fields should always have themselves already added, just
      // add a sort on the field.
      $params = $this->options['group_type'] != 'group' ? array('function' => $this->options['group_type']) : array();
173
      $this->query->addOrderBy(NULL, NULL, $order, $this->field_alias, $params);
Earl Miles's avatar
Earl Miles committed
174
175
176
177
178
    }
  }

  /**
   * Determine if this field is click sortable.
179
180
181
182
   *
   * @return bool
   *   The value of 'click sortable' from the plugin definition, this defaults
   *   to TRUE if not set.
Earl Miles's avatar
Earl Miles committed
183
   */
184
  public function clickSortable() {
185
    return isset($this->definition['click sortable']) ? $this->definition['click sortable'] : TRUE;
Earl Miles's avatar
Earl Miles committed
186
187
188
189
190
  }

  /**
   * Get this field's label.
   */
191
  public function label() {
Earl Miles's avatar
Earl Miles committed
192
193
194
195
196
197
198
199
200
    if (!isset($this->options['label'])) {
      return '';
    }
    return $this->options['label'];
  }

  /**
   * Return an HTML element based upon the field's element type.
   */
201
  public function elementType($none_supported = FALSE, $default_empty = FALSE, $inline = FALSE) {
Earl Miles's avatar
Earl Miles committed
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
    if ($none_supported) {
      if ($this->options['element_type'] === '0') {
        return '';
      }
    }
    if ($this->options['element_type']) {
      return check_plain($this->options['element_type']);
    }

    if ($default_empty) {
      return '';
    }

    if ($inline) {
      return 'span';
    }

    if (isset($this->definition['element type'])) {
      return $this->definition['element type'];
    }

    return 'span';
  }

  /**
   * Return an HTML element for the label based upon the field's element type.
   */
229
  public function elementLabelType($none_supported = FALSE, $default_empty = FALSE) {
Earl Miles's avatar
Earl Miles committed
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
    if ($none_supported) {
      if ($this->options['element_label_type'] === '0') {
        return '';
      }
    }
    if ($this->options['element_label_type']) {
      return check_plain($this->options['element_label_type']);
    }

    if ($default_empty) {
      return '';
    }

    return 'span';
  }

  /**
   * Return an HTML element for the wrapper based upon the field's element type.
   */
249
  public function elementWrapperType($none_supported = FALSE, $default_empty = FALSE) {
Earl Miles's avatar
Earl Miles committed
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
    if ($none_supported) {
      if ($this->options['element_wrapper_type'] === '0') {
        return 0;
      }
    }
    if ($this->options['element_wrapper_type']) {
      return check_plain($this->options['element_wrapper_type']);
    }

    if ($default_empty) {
      return '';
    }

    return 'div';
  }

  /**
   * Provide a list of elements valid for field HTML.
   *
   * This function can be overridden by fields that want more or fewer
   * elements available, though this seems like it would be an incredibly
   * rare occurence.
   */
273
  public function getElements() {
Earl Miles's avatar
Earl Miles committed
274
275
    static $elements = NULL;
    if (!isset($elements)) {
276
      // @todo Add possible html5 elements.
277
278
279
280
281
      $elements = array(
        '' => t(' - Use default -'),
        '0' => t('- None -')
      );
      $elements += config('views.settings')->get('field_rewrite_elements');
Earl Miles's avatar
Earl Miles committed
282
283
284
285
286
287
288
289
    }

    return $elements;
  }

  /**
   * Return the class of the field.
   */
290
  public function elementClasses($row_index = NULL) {
Earl Miles's avatar
Earl Miles committed
291
292
    $classes = explode(' ', $this->options['element_class']);
    foreach ($classes as &$class) {
293
      $class = $this->tokenizeValue($class, $row_index);
294
      $class = drupal_clean_css_identifier($class);
Earl Miles's avatar
Earl Miles committed
295
296
297
298
299
300
301
302
303
304
    }
    return implode(' ', $classes);
  }

  /**
   * Replace a value with tokens from the last field.
   *
   * This function actually figures out which field was last and uses its
   * tokens so they will all be available.
   */
305
  public function tokenizeValue($value, $row_index = NULL) {
Earl Miles's avatar
Earl Miles committed
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
    if (strpos($value, '[') !== FALSE || strpos($value, '!') !== FALSE || strpos($value, '%') !== FALSE) {
      $fake_item = array(
        'alter_text' => TRUE,
        'text' => $value,
      );

      // Use isset() because empty() will trigger on 0 and 0 is
      // the first row.
      if (isset($row_index) && isset($this->view->style_plugin->render_tokens[$row_index])) {
        $tokens = $this->view->style_plugin->render_tokens[$row_index];
      }
      else {
        // Get tokens from the last field.
        $last_field = end($this->view->field);
        if (isset($last_field->last_tokens)) {
          $tokens = $last_field->last_tokens;
        }
        else {
324
          $tokens = $last_field->getRenderTokens($fake_item);
Earl Miles's avatar
Earl Miles committed
325
326
327
        }
      }

328
      $value = strip_tags($this->renderAltered($fake_item, $tokens));
Earl Miles's avatar
Earl Miles committed
329
330
331
332
333
334
335
336
337
338
339
      if (!empty($this->options['alter']['trim_whitespace'])) {
        $value = trim($value);
      }
    }

    return $value;
  }

  /**
   * Return the class of the field's label.
   */
340
  public function elementLabelClasses($row_index = NULL) {
Earl Miles's avatar
Earl Miles committed
341
342
    $classes = explode(' ', $this->options['element_label_class']);
    foreach ($classes as &$class) {
343
      $class = $this->tokenizeValue($class, $row_index);
344
      $class = drupal_clean_css_identifier($class);
Earl Miles's avatar
Earl Miles committed
345
346
347
348
349
350
351
    }
    return implode(' ', $classes);
  }

  /**
   * Return the class of the field's wrapper.
   */
352
  public function elementWrapperClasses($row_index = NULL) {
Earl Miles's avatar
Earl Miles committed
353
354
    $classes = explode(' ', $this->options['element_wrapper_class']);
    foreach ($classes as &$class) {
355
      $class = $this->tokenizeValue($class, $row_index);
356
      $class = drupal_clean_css_identifier($class);
Earl Miles's avatar
Earl Miles committed
357
358
359
360
    }
    return implode(' ', $classes);
  }

361
  /**
362
   * Gets the entity matching the current row and relationship.
363
   *
364
   * @param \stdClass $values
365
   *   An object containing all retrieved values.
366
367
368
   *
   * @return \Drupal\Core\Entity\EntityInterface
   *   Returns the entity matching the values.
369
   */
370
  public function getEntity(\stdClass $values) {
371
372
373
374
375
376
377
378
379
    $relationship_id = $this->options['relationship'];
    if ($relationship_id == 'none') {
      return $values->_entity;
    }
    else {
      return $values->_relationship_entities[$relationship_id];
    }
  }

Earl Miles's avatar
Earl Miles committed
380
381
382
383
384
385
386
387
388
389
390
  /**
   * Get the value that's supposed to be rendered.
   *
   * This api exists so that other modules can easy set the values of the field
   * without having the need to change the render method as well.
   *
   * @param $values
   *   An object containing all retrieved values.
   * @param $field
   *   Optional name of the field where the value is stored.
   */
391
  public function getValue($values, $field = NULL) {
Earl Miles's avatar
Earl Miles committed
392
393
394
395
396
397
    $alias = isset($field) ? $this->aliases[$field] : $this->field_alias;
    if (isset($values->{$alias})) {
      return $values->{$alias};
    }
  }

398
399
400
401
402
403
404
  /**
   * Determines if this field will be available as an option to group the result
   * by in the style settings.
   *
   * @return bool
   *  TRUE if this field handler is groupable, otherwise FALSE.
   */
405
  public function useStringGroupBy() {
406
407
408
    return TRUE;
  }

409
410
  protected function defineOptions() {
    $options = parent::defineOptions();
Earl Miles's avatar
Earl Miles committed
411
412
413
414
415
416
417
418

    $options['label'] = array('default' => $this->definition['title'], 'translatable' => TRUE);
    $options['exclude'] = array('default' => FALSE, 'bool' => TRUE);
    $options['alter'] = array(
      'contains' => array(
        'alter_text' => array('default' => FALSE, 'bool' => TRUE),
        'text' => array('default' => '', 'translatable' => TRUE),
        'make_link' => array('default' => FALSE, 'bool' => TRUE),
419
        'path' => array('default' => ''),
Earl Miles's avatar
Earl Miles committed
420
421
422
423
424
425
426
427
428
429
        'absolute' => array('default' => FALSE, 'bool' => TRUE),
        'external' => array('default' => FALSE, 'bool' => TRUE),
        'replace_spaces' => array('default' => FALSE, 'bool' => TRUE),
        'path_case' => array('default' => 'none', 'translatable' => FALSE),
        'trim_whitespace' => array('default' => FALSE, 'bool' => TRUE),
        'alt' => array('default' => '', 'translatable' => TRUE),
        'rel' => array('default' => ''),
        'link_class' => array('default' => ''),
        'prefix' => array('default' => '', 'translatable' => TRUE),
        'suffix' => array('default' => '', 'translatable' => TRUE),
430
        'target' => array('default' => ''),
Earl Miles's avatar
Earl Miles committed
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
        'nl2br' => array('default' => FALSE, 'bool' => TRUE),
        'max_length' => array('default' => ''),
        'word_boundary' => array('default' => TRUE, 'bool' => TRUE),
        'ellipsis' => array('default' => TRUE, 'bool' => TRUE),
        'more_link' => array('default' => FALSE, 'bool' => TRUE),
        'more_link_text' => array('default' => '', 'translatable' => TRUE),
        'more_link_path' => array('default' => ''),
        'strip_tags' => array('default' => FALSE, 'bool' => TRUE),
        'trim' => array('default' => FALSE, 'bool' => TRUE),
        'preserve_tags' => array('default' => ''),
        'html' => array('default' => FALSE, 'bool' => TRUE),
      ),
    );
    $options['element_type'] = array('default' => '');
    $options['element_class'] = array('default' => '');

    $options['element_label_type'] = array('default' => '');
    $options['element_label_class'] = array('default' => '');
    $options['element_label_colon'] = array('default' => TRUE, 'bool' => TRUE);

    $options['element_wrapper_type'] = array('default' => '');
    $options['element_wrapper_class'] = array('default' => '');

    $options['element_default_classes'] = array('default' => TRUE, 'bool' => TRUE);

    $options['empty'] = array('default' => '', 'translatable' => TRUE);
    $options['hide_empty'] = array('default' => FALSE, 'bool' => TRUE);
    $options['empty_zero'] = array('default' => FALSE, 'bool' => TRUE);
    $options['hide_alter_empty'] = array('default' => TRUE, 'bool' => TRUE);

    return $options;
  }

  /**
   * Performs some cleanup tasks on the options array before saving it.
   */
467
  public function submitOptionsForm(&$form, &$form_state) {
Earl Miles's avatar
Earl Miles committed
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
    $options = &$form_state['values']['options'];
    $types = array('element_type', 'element_label_type', 'element_wrapper_type');
    $classes = array_combine(array('element_class', 'element_label_class', 'element_wrapper_class'), $types);

    foreach ($types as $type) {
      if (!$options[$type . '_enable']) {
        $options[$type] = '';
      }
    }

    foreach ($classes as $class => $type) {
      if (!$options[$class . '_enable'] || !$options[$type . '_enable']) {
        $options[$class] = '';
      }
    }

    if (empty($options['custom_label'])) {
      $options['label'] = '';
      $options['element_label_colon'] = FALSE;
    }
  }

  /**
   * Default options form that provides the label widget that all fields
   * should have.
   */
494
495
  public function buildOptionsForm(&$form, &$form_state) {
    parent::buildOptionsForm($form, $form_state);
Earl Miles's avatar
Earl Miles committed
496
497
498
499
500
501
502
503
504
505
506
507

    $label = $this->label();
    $form['custom_label'] = array(
      '#type' => 'checkbox',
      '#title' => t('Create a label'),
      '#default_value' => $label !== '',
      '#weight' => -103,
    );
    $form['label'] = array(
      '#type' => 'textfield',
      '#title' => t('Label'),
      '#default_value' => $label,
508
509
510
511
      '#states' => array(
        'visible' => array(
          ':input[name="options[custom_label]"]' => array('checked' => TRUE),
        ),
Earl Miles's avatar
Earl Miles committed
512
513
514
515
516
517
518
      ),
      '#weight' => -102,
    );
    $form['element_label_colon'] = array(
      '#type' => 'checkbox',
      '#title' => t('Place a colon after the label'),
      '#default_value' => $this->options['element_label_colon'],
519
520
521
522
      '#states' => array(
        'visible' => array(
          ':input[name="options[custom_label]"]' => array('checked' => TRUE),
        ),
Earl Miles's avatar
Earl Miles committed
523
524
525
526
527
528
529
530
531
532
533
534
535
      ),
      '#weight' => -101,
    );

    $form['exclude'] = array(
      '#type' => 'checkbox',
      '#title' => t('Exclude from display'),
      '#default_value' => $this->options['exclude'],
      '#description' => t('Enable to load this field as hidden. Often used to group fields, or to use as token in another field.'),
      '#weight' => -100,
    );

    $form['style_settings'] = array(
536
      '#type' => 'details',
Earl Miles's avatar
Earl Miles committed
537
      '#title' => t('Style settings'),
538
      '#collapsed' => TRUE,
Earl Miles's avatar
Earl Miles committed
539
540
541
542
543
544
545
546
547
548
549
      '#weight' => 99,
    );

    $form['element_type_enable'] = array(
      '#type' => 'checkbox',
      '#title' => t('Customize field HTML'),
      '#default_value' => !empty($this->options['element_type']) || (string) $this->options['element_type'] == '0' || !empty($this->options['element_class']) || (string) $this->options['element_class'] == '0',
      '#fieldset' => 'style_settings',
    );
    $form['element_type'] = array(
      '#title' => t('HTML element'),
550
      '#options' => $this->getElements(),
Earl Miles's avatar
Earl Miles committed
551
552
553
      '#type' => 'select',
      '#default_value' => $this->options['element_type'],
      '#description' => t('Choose the HTML element to wrap around this field, e.g. H1, H2, etc.'),
554
555
556
557
      '#states' => array(
        'visible' => array(
          ':input[name="options[element_type_enable]"]' => array('checked' => TRUE),
        ),
Earl Miles's avatar
Earl Miles committed
558
559
560
561
562
563
564
      ),
      '#fieldset' => 'style_settings',
    );

    $form['element_class_enable'] = array(
      '#type' => 'checkbox',
      '#title' => t('Create a CSS class'),
565
566
567
568
      '#states' => array(
        'visible' => array(
          ':input[name="options[element_type_enable]"]' => array('checked' => TRUE),
        ),
Earl Miles's avatar
Earl Miles committed
569
570
571
572
573
574
575
576
577
      ),
      '#default_value' => !empty($this->options['element_class']) || (string) $this->options['element_class'] == '0',
      '#fieldset' => 'style_settings',
    );
    $form['element_class'] = array(
      '#title' => t('CSS class'),
      '#description' => t('You may use token substitutions from the rewriting section in this class.'),
      '#type' => 'textfield',
      '#default_value' => $this->options['element_class'],
578
579
580
581
582
      '#states' => array(
        'visible' => array(
          ':input[name="options[element_type_enable]"]' => array('checked' => TRUE),
          ':input[name="options[element_class_enable]"]' => array('checked' => TRUE),
        ),
Earl Miles's avatar
Earl Miles committed
583
584
585
586
587
588
589
590
591
592
593
594
      ),
      '#fieldset' => 'style_settings',
    );

    $form['element_label_type_enable'] = array(
      '#type' => 'checkbox',
      '#title' => t('Customize label HTML'),
      '#default_value' => !empty($this->options['element_label_type']) || (string) $this->options['element_label_type'] == '0' || !empty($this->options['element_label_class']) || (string) $this->options['element_label_class'] == '0',
      '#fieldset' => 'style_settings',
    );
    $form['element_label_type'] = array(
      '#title' => t('Label HTML element'),
595
      '#options' => $this->getElements(FALSE),
Earl Miles's avatar
Earl Miles committed
596
597
598
      '#type' => 'select',
      '#default_value' => $this->options['element_label_type'],
      '#description' => t('Choose the HTML element to wrap around this label, e.g. H1, H2, etc.'),
599
600
601
602
      '#states' => array(
        'visible' => array(
          ':input[name="options[element_label_type_enable]"]' => array('checked' => TRUE),
        ),
Earl Miles's avatar
Earl Miles committed
603
604
605
606
607
608
      ),
      '#fieldset' => 'style_settings',
    );
    $form['element_label_class_enable'] = array(
      '#type' => 'checkbox',
      '#title' => t('Create a CSS class'),
609
610
611
612
      '#states' => array(
        'visible' => array(
          ':input[name="options[element_label_type_enable]"]' => array('checked' => TRUE),
        ),
Earl Miles's avatar
Earl Miles committed
613
614
615
616
617
618
619
620
621
      ),
      '#default_value' => !empty($this->options['element_label_class']) || (string) $this->options['element_label_class'] == '0',
      '#fieldset' => 'style_settings',
    );
    $form['element_label_class'] = array(
      '#title' => t('CSS class'),
      '#description' => t('You may use token substitutions from the rewriting section in this class.'),
      '#type' => 'textfield',
      '#default_value' => $this->options['element_label_class'],
622
623
624
625
626
      '#states' => array(
        'visible' => array(
          ':input[name="options[element_label_type_enable]"]' => array('checked' => TRUE),
          ':input[name="options[element_label_class_enable]"]' => array('checked' => TRUE),
        ),
Earl Miles's avatar
Earl Miles committed
627
628
629
630
631
632
633
634
635
636
637
638
      ),
      '#fieldset' => 'style_settings',
    );

    $form['element_wrapper_type_enable'] = array(
      '#type' => 'checkbox',
      '#title' => t('Customize field and label wrapper HTML'),
      '#default_value' => !empty($this->options['element_wrapper_type']) || (string) $this->options['element_wrapper_type'] == '0' || !empty($this->options['element_wrapper_class']) || (string) $this->options['element_wrapper_class'] == '0',
      '#fieldset' => 'style_settings',
    );
    $form['element_wrapper_type'] = array(
      '#title' => t('Wrapper HTML element'),
639
      '#options' => $this->getElements(FALSE),
Earl Miles's avatar
Earl Miles committed
640
641
642
      '#type' => 'select',
      '#default_value' => $this->options['element_wrapper_type'],
      '#description' => t('Choose the HTML element to wrap around this field and label, e.g. H1, H2, etc. This may not be used if the field and label are not rendered together, such as with a table.'),
643
644
645
646
      '#states' => array(
        'visible' => array(
          ':input[name="options[element_wrapper_type_enable]"]' => array('checked' => TRUE),
        ),
Earl Miles's avatar
Earl Miles committed
647
648
649
650
651
652
653
      ),
      '#fieldset' => 'style_settings',
    );

    $form['element_wrapper_class_enable'] = array(
      '#type' => 'checkbox',
      '#title' => t('Create a CSS class'),
654
655
656
657
      '#states' => array(
        'visible' => array(
          ':input[name="options[element_wrapper_type_enable]"]' => array('checked' => TRUE),
        ),
Earl Miles's avatar
Earl Miles committed
658
659
660
661
662
663
664
665
666
      ),
      '#default_value' => !empty($this->options['element_wrapper_class']) || (string) $this->options['element_wrapper_class'] == '0',
      '#fieldset' => 'style_settings',
    );
    $form['element_wrapper_class'] = array(
      '#title' => t('CSS class'),
      '#description' => t('You may use token substitutions from the rewriting section in this class.'),
      '#type' => 'textfield',
      '#default_value' => $this->options['element_wrapper_class'],
667
668
669
670
671
      '#states' => array(
        'visible' => array(
          ':input[name="options[element_wrapper_class_enable]"]' => array('checked' => TRUE),
          ':input[name="options[element_wrapper_type_enable]"]' => array('checked' => TRUE),
        ),
Earl Miles's avatar
Earl Miles committed
672
673
674
675
676
677
678
679
680
681
682
683
684
685
      ),
      '#fieldset' => 'style_settings',
    );

    $form['element_default_classes'] = array(
      '#type' => 'checkbox',
      '#title' => t('Add default classes'),
      '#default_value' => $this->options['element_default_classes'],
      '#description' => t('Use default Views classes to identify the field, field label and field content.'),
      '#fieldset' => 'style_settings',
    );

    $form['alter'] = array(
      '#title' => t('Rewrite results'),
686
      '#type' => 'details',
687
      '#collapsed' => TRUE,
Earl Miles's avatar
Earl Miles committed
688
689
690
      '#weight' => 100,
    );

691
    if ($this->allowAdvancedRender()) {
Earl Miles's avatar
Earl Miles committed
692
693
694
      $form['alter']['#tree'] = TRUE;
      $form['alter']['alter_text'] = array(
        '#type' => 'checkbox',
695
        '#title' => t('Override the output of this field with custom text'),
Earl Miles's avatar
Earl Miles committed
696
697
698
699
700
701
702
703
        '#default_value' => $this->options['alter']['alter_text'],
      );

      $form['alter']['text'] = array(
        '#title' => t('Text'),
        '#type' => 'textarea',
        '#default_value' => $this->options['alter']['text'],
        '#description' => t('The text to display for this field. You may include HTML. You may enter data from this view as per the "Replacement patterns" below.'),
704
705
706
707
        '#states' => array(
          'visible' => array(
            ':input[name="options[alter][alter_text]"]' => array('checked' => TRUE),
          ),
Earl Miles's avatar
Earl Miles committed
708
709
710
711
712
        ),
      );

      $form['alter']['make_link'] = array(
        '#type' => 'checkbox',
713
        '#title' => t('Output this field as a custom link'),
Earl Miles's avatar
Earl Miles committed
714
715
716
717
718
719
720
        '#default_value' => $this->options['alter']['make_link'],
      );
      $form['alter']['path'] = array(
        '#title' => t('Link path'),
        '#type' => 'textfield',
        '#default_value' => $this->options['alter']['path'],
        '#description' => t('The Drupal path or absolute URL for this link. You may enter data from this view as per the "Replacement patterns" below.'),
721
722
723
724
        '#states' => array(
          'visible' => array(
            ':input[name="options[alter][make_link]"]' => array('checked' => TRUE),
          ),
Earl Miles's avatar
Earl Miles committed
725
726
727
728
729
730
731
        ),
        '#maxlength' => 255,
      );
      $form['alter']['absolute'] = array(
        '#type' => 'checkbox',
        '#title' => t('Use absolute path'),
        '#default_value' => $this->options['alter']['absolute'],
732
733
734
735
        '#states' => array(
          'visible' => array(
            ':input[name="options[alter][make_link]"]' => array('checked' => TRUE),
          ),
Earl Miles's avatar
Earl Miles committed
736
737
738
739
740
741
        ),
      );
      $form['alter']['replace_spaces'] = array(
        '#type' => 'checkbox',
        '#title' => t('Replace spaces with dashes'),
        '#default_value' => $this->options['alter']['replace_spaces'],
742
743
744
745
        '#states' => array(
          'visible' => array(
            ':input[name="options[alter][make_link]"]' => array('checked' => TRUE),
          ),
Earl Miles's avatar
Earl Miles committed
746
747
748
749
750
751
752
        ),
      );
      $form['alter']['external'] = array(
        '#type' => 'checkbox',
        '#title' => t('External server URL'),
        '#default_value' => $this->options['alter']['external'],
        '#description' => t("Links to an external server using a full URL: e.g. 'http://www.example.com' or 'www.example.com'."),
753
754
755
756
        '#states' => array(
          'visible' => array(
            ':input[name="options[alter][make_link]"]' => array('checked' => TRUE),
          ),
Earl Miles's avatar
Earl Miles committed
757
758
759
760
761
762
        ),
      );
      $form['alter']['path_case'] = array(
        '#type' => 'select',
        '#title' => t('Transform the case'),
        '#description' => t('When printing url paths, how to transform the case of the filter value.'),
763
764
765
766
        '#states' => array(
          'visible' => array(
            ':input[name="options[alter][make_link]"]' => array('checked' => TRUE),
          ),
Earl Miles's avatar
Earl Miles committed
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
        ),
       '#options' => array(
          'none' => t('No transform'),
          'upper' => t('Upper case'),
          'lower' => t('Lower case'),
          'ucfirst' => t('Capitalize first letter'),
          'ucwords' => t('Capitalize each word'),
        ),
        '#default_value' => $this->options['alter']['path_case'],
      );
      $form['alter']['link_class'] = array(
        '#title' => t('Link class'),
        '#type' => 'textfield',
        '#default_value' => $this->options['alter']['link_class'],
        '#description' => t('The CSS class to apply to the link.'),
782
783
784
785
        '#states' => array(
          'visible' => array(
            ':input[name="options[alter][make_link]"]' => array('checked' => TRUE),
          ),
Earl Miles's avatar
Earl Miles committed
786
787
788
789
790
791
792
        ),
      );
      $form['alter']['alt'] = array(
        '#title' => t('Title text'),
        '#type' => 'textfield',
        '#default_value' => $this->options['alter']['alt'],
        '#description' => t('Text to place as "title" text which most browsers display as a tooltip when hovering over the link.'),
793
794
795
796
        '#states' => array(
          'visible' => array(
            ':input[name="options[alter][make_link]"]' => array('checked' => TRUE),
          ),
Earl Miles's avatar
Earl Miles committed
797
798
799
800
801
802
803
        ),
      );
      $form['alter']['rel'] = array(
        '#title' => t('Rel Text'),
        '#type' => 'textfield',
        '#default_value' => $this->options['alter']['rel'],
        '#description' => t('Include Rel attribute for use in lightbox2 or other javascript utility.'),
804
805
806
807
        '#states' => array(
          'visible' => array(
            ':input[name="options[alter][make_link]"]' => array('checked' => TRUE),
          ),
Earl Miles's avatar
Earl Miles committed
808
809
810
811
812
813
814
        ),
      );
      $form['alter']['prefix'] = array(
        '#title' => t('Prefix text'),
        '#type' => 'textfield',
        '#default_value' => $this->options['alter']['prefix'],
        '#description' => t('Any text to display before this link. You may include HTML.'),
815
816
817
818
        '#states' => array(
          'visible' => array(
            ':input[name="options[alter][make_link]"]' => array('checked' => TRUE),
          ),
Earl Miles's avatar
Earl Miles committed
819
820
821
822
823
824
825
        ),
      );
      $form['alter']['suffix'] = array(
        '#title' => t('Suffix text'),
        '#type' => 'textfield',
        '#default_value' => $this->options['alter']['suffix'],
        '#description' => t('Any text to display after this link. You may include HTML.'),
826
827
828
829
        '#states' => array(
          'visible' => array(
            ':input[name="options[alter][make_link]"]' => array('checked' => TRUE),
          ),
Earl Miles's avatar
Earl Miles committed
830
831
832
833
834
835
836
        ),
      );
      $form['alter']['target'] = array(
        '#title' => t('Target'),
        '#type' => 'textfield',
        '#default_value' => $this->options['alter']['target'],
        '#description' => t("Target of the link, such as _blank, _parent or an iframe's name. This field is rarely used."),
837
838
839
840
        '#states' => array(
          'visible' => array(
            ':input[name="options[alter][make_link]"]' => array('checked' => TRUE),
          ),
Earl Miles's avatar
Earl Miles committed
841
842
843
844
845
        ),
      );


      // Get a list of the available fields and arguments for token replacement.
846
847
848
849
850

      // Setup the tokens for fields.
      $previous = $this->getPreviousFieldLabels();
      foreach ($previous as $id => $label) {
        $options[t('Fields')]["[$id]"] = $label;
Earl Miles's avatar
Earl Miles committed
851
      }
852

Earl Miles's avatar
Earl Miles committed
853
      $count = 0; // This lets us prepare the key as we want it printed.
854
      foreach ($this->view->display_handler->getHandlers('argument') as $arg => $handler) {
855
856
        $options[t('Arguments')]['%' . ++$count] = t('@argument title', array('@argument' => $handler->adminLabel()));
        $options[t('Arguments')]['!' . $count] = t('@argument input', array('@argument' => $handler->adminLabel()));
Earl Miles's avatar
Earl Miles committed
857
858
      }

859
      $this->documentSelfTokens($options[t('Fields')]);
Earl Miles's avatar
Earl Miles committed
860
861

      // Default text.
862
      $output = '<p>' . t('You must add some additional fields to this display before using this field. These fields may be marked as <em>Exclude from display</em> if you prefer. Note that due to rendering order, you cannot use fields that come after this field; if you need a field not listed here, rearrange your fields.') . '</p>';
Earl Miles's avatar
Earl Miles committed
863
864
      // We have some options, so make a list.
      if (!empty($options)) {
865
        $output = '<p>' . t("The following tokens are available for this field. Note that due to rendering order, you cannot use fields that come after this field; if you need a field not listed here, rearrange your fields. If you would like to have the characters '[' and ']' use the html entity codes '%5B' or '%5D' or they will get replaced with empty space.") . '</p>';
Earl Miles's avatar
Earl Miles committed
866
867
868
869
870
871
        foreach (array_keys($options) as $type) {
          if (!empty($options[$type])) {
            $items = array();
            foreach ($options[$type] as $key => $value) {
              $items[] = $key . ' == ' . $value;
            }
872
873
874
            $item_list = array(
              '#theme' => 'item_list',
              '#items' => $items,
875
              '#list_type' => $type,
876
877
            );
            $output .= drupal_render($item_list);
Earl Miles's avatar
Earl Miles committed
878
879
880
881
882
883
884
885
          }
        }
      }
      // This construct uses 'hidden' and not markup because process doesn't
      // run. It also has an extra div because the dependency wants to hide
      // the parent in situations like this, so we need a second div to
      // make this work.
      $form['alter']['help'] = array(
886
        '#type' => 'details',
Earl Miles's avatar
Earl Miles committed
887
        '#title' => t('Replacement patterns'),
888
        '#collapsed' => TRUE,
Earl Miles's avatar
Earl Miles committed
889
        '#value' => $output,
890
891
892
893
894
895
896
897
898
899
900
901
        '#states' => array(
          'visible' => array(
            array(
              ':input[name="options[alter][make_link]"]' => array('checked' => TRUE),
            ),
            array(
              ':input[name="options[alter][alter_text]"]' => array('checked' => TRUE),
            ),
            array(
              ':input[name="options[alter][more_link]"]' => array('checked' => TRUE),
            ),
          ),
Earl Miles's avatar
Earl Miles committed
902
903
904
905
906
        ),
      );

      $form['alter']['trim'] = array(
        '#type' => 'checkbox',
907
        '#title' => t('Trim this field to a maximum number of characters'),
Earl Miles's avatar
Earl Miles committed
908
909
910
911
        '#default_value' => $this->options['alter']['trim'],
      );

      $form['alter']['max_length'] = array(
912
        '#title' => t('Maximum number of characters'),
Earl Miles's avatar
Earl Miles committed
913
914
        '#type' => 'textfield',
        '#default_value' => $this->options['alter']['max_length'],
915
916
917
918
        '#states' => array(
          'visible' => array(
            ':input[name="options[alter][trim]"]' => array('checked' => TRUE),
          ),
Earl Miles's avatar
Earl Miles committed
919
920
921
922
923
924
925
926
        ),
      );

      $form['alter']['word_boundary'] = array(
        '#type' => 'checkbox',
        '#title' => t('Trim only on a word boundary'),
        '#description' => t('If checked, this field be trimmed only on a word boundary. This is guaranteed to be the maximum characters stated or less. If there are no word boundaries this could trim a field to nothing.'),
        '#default_value' => $this->options['alter']['word_boundary'],
927
928
929
930
        '#states' => array(
          'visible' => array(
            ':input[name="options[alter][trim]"]' => array('checked' => TRUE),
          ),
Earl Miles's avatar
Earl Miles committed
931
932
933
934
935
        ),
      );

      $form['alter']['ellipsis'] = array(
        '#type' => 'checkbox',
936
        '#title' => t('Add "..." at the end of trimmed text'),
Earl Miles's avatar
Earl Miles committed
937
        '#default_value' => $this->options['alter']['ellipsis'],
938
939
940
941
        '#states' => array(
          'visible' => array(
            ':input[name="options[alter][trim]"]' => array('checked' => TRUE),
          ),
Earl Miles's avatar
Earl Miles committed
942
943
944
945
946
947
948
        ),
      );

      $form['alter']['more_link'] = array(
        '#type' => 'checkbox',
        '#title' => t('Add a read-more link if output is trimmed.'),
        '#default_value' => $this->options['alter']['more_link'],
949
950
951
952
        '#states' => array(
          'visible' => array(
            ':input[name="options[alter][trim]"]' => array('checked' => TRUE),
          ),
Earl Miles's avatar
Earl Miles committed
953
954
955
956
957
        ),
      );

      $form['alter']['more_link_text'] = array(
        '#type' => 'textfield',
958
        '#title' => t('More link label'),
Earl Miles's avatar
Earl Miles committed
959
        '#default_value' => $this->options['alter']['more_link_text'],
960
        '#description' => t('You may use the "Replacement patterns" above.'),
961
962
963
964
965
        '#states' => array(
          'visible' => array(
            ':input[name="options[alter][trim]"]' => array('checked' => TRUE),
            ':input[name="options[alter][more_link]"]' => array('checked' => TRUE),
          ),
Earl Miles's avatar
Earl Miles committed
966
967
968
969
970
971
        ),
      );
      $form['alter']['more_link_path'] = array(
        '#type' => 'textfield',
        '#title' => t('More link path'),
        '#default_value' => $this->options['alter']['more_link_path'],
972
        '#description' => t('This can be an internal Drupal path such as node/add or an external URL such as "http://drupal.org". You may use the "Replacement patterns" above.'),
973
974
975
976
977
        '#states' => array(
          'visible' => array(
            ':input[name="options[alter][trim]"]' => array('checked' => TRUE),
            ':input[name="options[alter][more_link]"]' => array('checked' => TRUE),
          ),
Earl Miles's avatar
Earl Miles committed
978
979
980
981
982
983
        ),
      );

      $form['alter']['html'] = array(
        '#type' => 'checkbox',
        '#title' => t('Field can contain HTML'),
984
        '#description' => t('An HTML corrector will be run to ensure HTML tags are properly closed after trimming.'),
Earl Miles's avatar
Earl Miles committed
985
        '#default_value' => $this->options['alter']['html'],
986
987
988
989
        '#states' => array(
          'visible' => array(
            ':input[name="options[alter][trim]"]' => array('checked' => TRUE),
          ),
Earl Miles's avatar
Earl Miles committed
990
991
992
993
994
995
996
997
998
999
1000
        ),
      );

      $form['alter']['strip_tags'] = array(
        '#type' => 'checkbox',
        '#title' => t('Strip HTML tags'),
        '#default_value' => $this->options['alter']['strip_tags'],
      );

      $form['alter']['preserve_tags'] = array(
        '#type' => 'textfield',
For faster browsing, not all history is shown. View entire blame