summaryrefslogtreecommitdiffstats
path: root/includes/views/handlers/content_handler_field.inc
blob: f8dfc2f161f1fbb9d669d1c41b6ddf222b6b9857 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
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
229
<?php
// $Id$

/**
 * @file
 * The subclass adds basic field and formatter info,
 * for field-specific subclasses to use if they need to.
 *
 * Fields could extend this class if they want field and formatter handling
 * but don't want the multiple value grouping options created by
 * content_handler_field_multiple.
 */
class content_handler_field extends views_handler_field_node {
  var $content_field;

  function construct() {
    parent::construct();
    $this->content_field = content_fields($this->definition['content_field_name']);
  }

  function init(&$view, $options) {
    $field = $this->content_field;
    parent::init($view, $options);
    if ($field['multiple']) {
      $this->additional_fields['delta'] = 'delta';
    }
    // Make sure we grab enough information to build a pseudo-node with enough
    // credentials at render-time.
    $this->additional_fields['type'] = array('table' => 'node', 'field' => 'type');
    $this->additional_fields['nid'] = array('table' => 'node', 'field' => 'nid');
    $this->additional_fields['vid'] = array('table' => 'node', 'field' => 'vid');
  }

  function option_definition() {
    $options = parent::option_definition();
    $field = $this->content_field;

    // Override views_handler_field_node's default label
    $options['label'] = array('default' => '', 'translatable' => TRUE);
    $options['label_type'] = array('default' => 'widget');
    $options['format'] = array('default' => 'default');

    return $options;
  }

  /**
   * Provide formatter option.
   */
  function options_form(&$form, &$form_state) {
    parent::options_form($form, $form_state);
    // TODO: do we want the 'link to node' checkbox ?
    // That's usually formatters business...

    $field = $this->content_field;
    $options = $this->options;

    $form['label_type'] = array(
      '#title' => t('Label'),
      '#type' => 'radios',
      '#options' => array(
        'none' => t('None'),
        'widget' => t('Widget label (@label)', array('@label' => $field['widget']['label'])),
        'custom' => t('Custom'),
      ),
      '#default_value' => $options['label_type'],
      '#weight' => 2,
    );
    $form['label'] = array(
      '#title' => t('Custom label'),
      '#type' => 'textfield',
      '#default_value' => $options['label'],
      '#process' => array('views_process_dependency'),
      '#dependency' => array('radio:options[label_type]' => array('custom')),
      '#weight' => 3,
     );

    $field_types = _content_field_types();
    $formatters = array();
    if (is_array($field_types[$field['type']]['formatters'])) {
      foreach ($field_types[$field['type']]['formatters'] as $name => $info) {
        $formatters[$name] = $info['label'];
      }
    }
    $form['format'] = array(
      '#title' => t('Format'),
      '#type' => 'select',
      '#options' => $formatters,
      '#required' => TRUE,
      '#default_value' => $options['format'],
      '#weight' => 4,
    );
  }


  /**
   * Make sure some value is stored as a label.
   *
   * Don't use t(), since Views' views_handler_field already has
   * $this->options['label'] marked as a translatable field.
   *
   * @see http://drupal.org/node/285470
   */
  function options_submit($form, &$form_state) {
    switch ($form_state['values']['options']['label_type']) {
      case 'none':
        $form_state['values']['options']['label'] = '';
        break;
      case 'widget':
        $form_state['values']['options']['label'] = $this->content_field['widget']['label'];
        break;
    }
  }

  /**
   * @TODO
   * Now that we save the label in the submit process above we could
   * get rid of this function. Leave it here for now to be sure the
   * label works for fields that haven't been updated since this
   * change was made, since $this->options['label'] will be missing a
   * value until it is updated in the view.
   *
   * Don't use t(), since Views' views_handler_field already has
   * $this->options['label'] marked as a translatable field.
   */
  function label() {
    $field = $this->content_field;
    switch ($this->options['label_type']) {
      case 'none':
        return '';
      case 'widget':
        return $field['widget']['label'];
      default:
        return $this->options['label'];
    }
  }

  /**
   * Return DIV or SPAN based upon the field's element type.
   */
  function element_type($none_supported = FALSE, $default_empty = FALSE) {
    // The 'element_type' property denotes Views 3.x ('semantic views'
    // functionnality). If the property is set, and not set to '' ("default"),
    // let the generic method handle the output.
    if (isset($this->options['element_type']) && $this->options['element_type'] !== '') {
      return parent::element_type($none_supported, $default_empty);
    }

    if ($default_empty) {
      return '';
    }

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

    // TODO Figure out exactly when to return a div or a <span>. Any field
    // that ever needs to be shown inline in Views UI. It needs to return
    // a div for textareas to prevent wrapping a <span> around a <p>.
    // Earl says we need to be sure that other fields we don't know
    // about won't end up wrapping a span around a block-level element.
    if ($this->content_field['widget']['type'] == 'text_textarea') {
      return 'div';
    }
    else {
      return 'span';
    }
  }

  function options_validate($form, &$form_state) { }

  /**
   * Provide text for the administrative summary
   */
  function admin_summary() {
    // Display the formatter name.
    $field = $this->content_field;
    $field_types = _content_field_types();
    if (isset($field_types[$field['type']]['formatters'][$this->options['format']])) {
      return t($field_types[$field['type']]['formatters'][$this->options['format']]['label']);
    }
  }

  function render($values) {
    // We're down to a single node here, so we can retrieve the actual field
    // definition for the node type being considered.
    $field = content_fields($this->content_field['field_name'], $values->{$this->aliases['type']});

    // If the field does not appear in the node type, then we have no value
    // to display, and can just return.
    if (empty($field)) {
      return '';
    }

    $options = $this->options;
    $db_info = content_database_info($field);

    // Build a pseudo-node from the retrieved values.
    $node = drupal_clone($values);
    $node->type = $values->{$this->aliases['type']};
    $node->nid = $values->{$this->aliases['nid']};
    $node->vid = $values->{$this->aliases['vid']};
    // Some formatters need to behave differently depending on the build_mode
    // (for instance: preview), so we provide one.
    $node->build_mode = NODE_BUILD_NORMAL;

    $item = array();
    foreach ($db_info['columns'] as $column => $attributes) {
      $item[$column] = $values->{$this->aliases[$attributes['column']]};
    }

    $item['#delta'] = $field['multiple'] ?  $values->{$this->aliases['delta']} : 0;

    // Render items.
    $formatter_name = $options['format'];
    if ($formatter = _content_get_formatter($formatter_name, $field['type'])) {
      if (content_handle('formatter', 'multiple values', $formatter) == CONTENT_HANDLE_CORE) {
        // Single-value formatter.
        $output = content_format($field, $item, $formatter_name, $node);
      }
      else {
        // Multiple values formatter - we actually have only one value to display.
        $output = content_format($field, array($item), $formatter_name, $node);
      }
      return $this->render_link($output, $values);
    }
    return '';
  }

}