This commit was manufactured as part of Drupal's Great Git Migration to
[project/cck.git] / includes / views / handlers / content_handler_field.inc
1 <?php
2 // $Id$
3
4 /**
5 * @file
6 * The subclass adds basic field and formatter info,
7 * for field-specific subclasses to use if they need to.
8 *
9 * Fields could extend this class if they want field and formatter handling
10 * but don't want the multiple value grouping options created by
11 * content_handler_field_multiple.
12 */
13 class content_handler_field extends views_handler_field_node {
14 var $content_field;
15
16 function construct() {
17 parent::construct();
18 $this->content_field = content_fields($this->definition['content_field_name']);
19 }
20
21 function init(&$view, $options) {
22 $field = $this->content_field;
23 parent::init($view, $options);
24 if ($field['multiple']) {
25 $this->additional_fields['delta'] = 'delta';
26 }
27 // Make sure we grab enough information to build a pseudo-node with enough
28 // credentials at render-time.
29 $this->additional_fields['type'] = array('table' => 'node', 'field' => 'type');
30 $this->additional_fields['nid'] = array('table' => 'node', 'field' => 'nid');
31 $this->additional_fields['vid'] = array('table' => 'node', 'field' => 'vid');
32 }
33
34 function option_definition() {
35 $options = parent::option_definition();
36 $field = $this->content_field;
37
38 // Override views_handler_field_node's default label
39 $options['label'] = array('default' => '', 'translatable' => TRUE);
40 $options['label_type'] = array('default' => 'widget');
41 $options['format'] = array('default' => 'default');
42
43 return $options;
44 }
45
46 /**
47 * Provide formatter option.
48 */
49 function options_form(&$form, &$form_state) {
50 parent::options_form($form, $form_state);
51 // TODO: do we want the 'link to node' checkbox ?
52 // That's usually formatters business...
53
54 $field = $this->content_field;
55 $options = $this->options;
56
57 $form['label_type'] = array(
58 '#title' => t('Label'),
59 '#type' => 'radios',
60 '#options' => array(
61 'none' => t('None'),
62 'widget' => t('Widget label (@label)', array('@label' => $field['widget']['label'])),
63 'custom' => t('Custom'),
64 ),
65 '#default_value' => $options['label_type'],
66 '#weight' => 2,
67 );
68 $form['label'] = array(
69 '#title' => t('Custom label'),
70 '#type' => 'textfield',
71 '#default_value' => $options['label'],
72 '#process' => array('views_process_dependency'),
73 '#dependency' => array('radio:options[label_type]' => array('custom')),
74 '#weight' => 3,
75 );
76
77 $field_types = _content_field_types();
78 $formatters = array();
79 if (is_array($field_types[$field['type']]['formatters'])) {
80 foreach ($field_types[$field['type']]['formatters'] as $name => $info) {
81 $formatters[$name] = $info['label'];
82 }
83 }
84 $form['format'] = array(
85 '#title' => t('Format'),
86 '#type' => 'select',
87 '#options' => $formatters,
88 '#required' => TRUE,
89 '#default_value' => $options['format'],
90 '#weight' => 4,
91 );
92 }
93
94
95 /**
96 * Make sure some value is stored as a label.
97 *
98 * Don't use t(), since Views' views_handler_field already has
99 * $this->options['label'] marked as a translatable field.
100 *
101 * @see http://drupal.org/node/285470
102 */
103 function options_submit($form, &$form_state) {
104 switch ($form_state['values']['options']['label_type']) {
105 case 'none':
106 $form_state['values']['options']['label'] = '';
107 break;
108 case 'widget':
109 $form_state['values']['options']['label'] = $this->content_field['widget']['label'];
110 break;
111 }
112 }
113
114 /**
115 * @TODO
116 * Now that we save the label in the submit process above we could
117 * get rid of this function. Leave it here for now to be sure the
118 * label works for fields that haven't been updated since this
119 * change was made, since $this->options['label'] will be missing a
120 * value until it is updated in the view.
121 *
122 * Don't use t(), since Views' views_handler_field already has
123 * $this->options['label'] marked as a translatable field.
124 */
125 function label() {
126 $field = $this->content_field;
127 switch ($this->options['label_type']) {
128 case 'none':
129 return '';
130 case 'widget':
131 return $field['widget']['label'];
132 default:
133 return $this->options['label'];
134 }
135 }
136
137 /**
138 * Return DIV or SPAN based upon the field's element type.
139 */
140 function element_type($none_supported = FALSE, $default_empty = FALSE) {
141 // The 'element_type' property denotes Views 3.x ('semantic views'
142 // functionnality). If the property is set, and not set to '' ("default"),
143 // let the generic method handle the output.
144 if (isset($this->options['element_type']) && $this->options['element_type'] !== '') {
145 return parent::element_type($none_supported, $default_empty);
146 }
147
148 if ($default_empty) {
149 return '';
150 }
151
152 if (isset($this->definition['element type'])) {
153 return $this->definition['element type'];
154 }
155
156 // TODO Figure out exactly when to return a div or a <span>. Any field
157 // that ever needs to be shown inline in Views UI. It needs to return
158 // a div for textareas to prevent wrapping a <span> around a <p>.
159 // Earl says we need to be sure that other fields we don't know
160 // about won't end up wrapping a span around a block-level element.
161 if ($this->content_field['widget']['type'] == 'text_textarea') {
162 return 'div';
163 }
164 else {
165 return 'span';
166 }
167 }
168
169 function options_validate($form, &$form_state) { }
170
171 /**
172 * Provide text for the administrative summary
173 */
174 function admin_summary() {
175 // Display the formatter name.
176 $field = $this->content_field;
177 $field_types = _content_field_types();
178 if (isset($field_types[$field['type']]['formatters'][$this->options['format']])) {
179 return t($field_types[$field['type']]['formatters'][$this->options['format']]['label']);
180 }
181 }
182
183 function render($values) {
184 // We're down to a single node here, so we can retrieve the actual field
185 // definition for the node type being considered.
186 $field = content_fields($this->content_field['field_name'], $values->{$this->aliases['type']});
187
188 // If the field does not appear in the node type, then we have no value
189 // to display, and can just return.
190 if (empty($field)) {
191 return '';
192 }
193
194 $options = $this->options;
195 $db_info = content_database_info($field);
196
197 // Build a pseudo-node from the retrieved values.
198 $node = drupal_clone($values);
199 $node->type = $values->{$this->aliases['type']};
200 $node->nid = $values->{$this->aliases['nid']};
201 $node->vid = $values->{$this->aliases['vid']};
202 // Some formatters need to behave differently depending on the build_mode
203 // (for instance: preview), so we provide one.
204 $node->build_mode = NODE_BUILD_NORMAL;
205
206 $item = array();
207 foreach ($db_info['columns'] as $column => $attributes) {
208 $item[$column] = $values->{$this->aliases[$attributes['column']]};
209 }
210
211 $item['#delta'] = $field['multiple'] ? $values->{$this->aliases['delta']} : 0;
212
213 // Render items.
214 $formatter_name = $options['format'];
215 if ($formatter = _content_get_formatter($formatter_name, $field['type'])) {
216 if (content_handle('formatter', 'multiple values', $formatter) == CONTENT_HANDLE_CORE) {
217 // Single-value formatter.
218 $output = content_format($field, $item, $formatter_name, $node);
219 }
220 else {
221 // Multiple values formatter - we actually have only one value to display.
222 $output = content_format($field, array($item), $formatter_name, $node);
223 }
224 return $this->render_link($output, $values);
225 }
226 return '';
227 }
228
229 }