Projet

Général

Profil

Paste
Télécharger (17,8 ko) Statistiques
| Branche: | Révision:

root / drupal7 / sites / all / modules / views / modules / field.views.inc @ 5d12d676

1
<?php
2

    
3
/**
4
 * @file
5
 * Provide Views data and handlers for field.module.
6
 *
7
 * @ingroup views_module_handlers
8
 */
9

    
10
/**
11
 * Implements hook_views_data().
12
 *
13
 * Field modules can implement hook_field_views_data() to override
14
 * the default behavior for adding fields.
15
 */
16
function field_views_data() {
17
  $data = array();
18
  foreach (field_info_fields() as $field) {
19
    if ($field['storage']['type'] != 'field_sql_storage') {
20
      continue;
21
    }
22

    
23
    $module = $field['module'];
24
    $result = (array) module_invoke($module, 'field_views_data', $field);
25

    
26
    if (empty($result)) {
27
      $result = field_views_field_default_views_data($field);
28
    }
29
    drupal_alter('field_views_data', $result, $field, $module);
30

    
31
    if (is_array($result)) {
32
      $data = drupal_array_merge_deep($result, $data);
33
    }
34
  }
35

    
36
  return $data;
37
}
38

    
39
/**
40
 * Implements hook_views_data_alter().
41
 *
42
 * Field modules can implement hook_field_views_data_views_data_alter() to
43
 * alter the views data on a per field basis. This is weirdly named so as
44
 * not to conflict with the drupal_alter('field_views_data') in
45
 * field_views_data.
46
 */
47
function field_views_data_alter(&$data) {
48
  foreach (field_info_fields() as $field) {
49
    if ($field['storage']['type'] != 'field_sql_storage') {
50
      continue;
51
    }
52

    
53
    $function = $field['module'] . '_field_views_data_views_data_alter';
54
    if (function_exists($function)) {
55
      $function($data, $field);
56
    }
57
  }
58
}
59

    
60
/**
61
 * Returns the label of a certain field.
62
 *
63
 * Therefore it looks up in all bundles to find the most used instance.
64
 */
65
function field_views_field_label($field_name) {
66
  $label_counter = array();
67
  $all_labels = array();
68
  // Count the amount of instances per label per field.
69
  $instances = field_info_instances();
70
  foreach ($instances as $entity_name => $entity_type) {
71
    foreach ($entity_type as $bundle) {
72
      if (isset($bundle[$field_name])) {
73
        $label_counter[$bundle[$field_name]['label']] = isset($label_counter[$bundle[$field_name]['label']]) ? ++$label_counter[$bundle[$field_name]['label']] : 1;
74
        $all_labels[$entity_name][$bundle[$field_name]['label']] = TRUE;
75
      }
76
    }
77
  }
78
  if (empty($label_counter)) {
79
    return array($field_name, $all_labels);
80
  }
81
  // Sort the field lables by it most used label and return the most used one.
82
  arsort($label_counter);
83
  $label_counter = array_keys($label_counter);
84
  return array($label_counter[0], $all_labels);
85
}
86

    
87
/**
88
 * Default views data implementation for a field.
89
 */
90
function field_views_field_default_views_data($field) {
91
  $field_types = field_info_field_types();
92

    
93
  // Check the field module is available.
94
  if (!isset($field_types[$field['type']])) {
95
    return;
96
  }
97

    
98
  $data = array();
99

    
100
  $current_table = _field_sql_storage_tablename($field);
101
  $revision_table = _field_sql_storage_revision_tablename($field);
102

    
103
  // The list of entity:bundle that this field is used in.
104
  $bundles_names = array();
105
  $supports_revisions = FALSE;
106
  $entity_tables = array();
107
  $current_tables = array();
108
  $revision_tables = array();
109
  $groups = array();
110

    
111
  // Store translations to avoid being called thousands of times.
112
  $translations['no_value_bracket'] = t('<No value>');
113
  $translations['no_value_dash'] = t('- No value -');
114
  $translations['field'] = t('Field');
115
  $translations['node'] = t('Node');
116
  $translations['content'] = t('Content');
117

    
118
  $group_name = count($field['bundles']) > 1 ? $translations['field'] : NULL;
119

    
120
  // Build the relationships between the field table and the entity tables.
121
  foreach ($field['bundles'] as $entity => $bundles) {
122
    $entity_info = entity_get_info($entity);
123
    $groups[$entity] = $entity_info['label'];
124

    
125
    // Override Node to Content.
126
    if ($groups[$entity] == $translations['node']) {
127
      $groups[$entity] = $translations['content'];
128
    }
129

    
130
    // If only one bundle use this as the default name.
131
    if (empty($group_name)) {
132
      $group_name = $groups[$entity];
133
    }
134

    
135
    $entity_tables[$entity_info['base table']] = $entity;
136
    $current_tables[$entity] = $entity_info['base table'];
137
    if (isset($entity_info['revision table'])) {
138
      $entity_tables[$entity_info['revision table']] = $entity;
139
      $revision_tables[$entity] = $entity_info['revision table'];
140
    }
141

    
142
    $data[$current_table]['table']['join'][$entity_info['base table']] = array(
143
      'left_field' => $entity_info['entity keys']['id'],
144
      'field' => 'entity_id',
145
      'extra' => array(
146
        array('field' => 'entity_type', 'value' => $entity),
147
        array('field' => 'deleted', 'value' => 0, 'numeric' => TRUE),
148
      ),
149
    );
150

    
151
    if (!empty($entity_info['entity keys']['revision']) && !empty($entity_info['revision table'])) {
152
      $data[$revision_table]['table']['join'][$entity_info['revision table']] = array(
153
        'left_field' => $entity_info['entity keys']['revision'],
154
        'field' => 'revision_id',
155
        'extra' => array(
156
          array('field' => 'entity_type', 'value' => $entity),
157
          array('field' => 'deleted', 'value' => 0, 'numeric' => TRUE),
158
        ),
159
      );
160

    
161
      $supports_revisions = TRUE;
162
    }
163

    
164
    foreach ($bundles as $bundle) {
165
      $bundles_names[] = t('@entity:@bundle', array('@entity' => $entity, '@bundle' => $bundle));
166
    }
167
  }
168

    
169
  $tables = array();
170
  $tables[FIELD_LOAD_CURRENT] = $current_table;
171
  if ($supports_revisions) {
172
    $tables[FIELD_LOAD_REVISION] = $revision_table;
173
  }
174

    
175
  $add_fields = array('delta', 'language', 'bundle');
176
  foreach ($field['columns'] as $column_name => $attributes) {
177
    $add_fields[] = _field_sql_storage_columnname($field['field_name'], $column_name);
178
  }
179

    
180
  // Note: we don't have a label available here, because we are at the field
181
  // level, not at the instance level. So we just go through all instances
182
  // and take the one which is used the most frequently.
183
  $field_name = $field['field_name'];
184
  list($label, $all_labels) = field_views_field_label($field_name);
185

    
186
  $bundle_names_text = implode(', ', $bundles_names);
187
  $translations['appears_in_help'] = t('Appears in: @bundles.', array('@bundles' => $bundle_names_text));
188
  $translations['delta_appears_in_help'] = t('Delta - Appears in: @bundles.', array('@bundles' => $bundle_names_text));
189
  $translations['language_appears_in_help'] = t('Language - Appears in: @bundles.', array('@bundles' => $bundle_names_text));
190
  $translations['group_historical'] = t('@group (historical data)', array('@group' => $group_name));
191
  $translations['alias_help'] = t('This is an alias of @group: @field.', array('@group' => $group_name, '@field' => $label));
192
  $translations['label_short_language'] = t('@label:language', array('@label' => $label));
193

    
194
  foreach ($tables as $type => $table) {
195
    if ($type == FIELD_LOAD_CURRENT) {
196
      $group = $group_name;
197
      $old_column = 'entity_id';
198
      $column = $field['field_name'];
199
    }
200
    else {
201
      $group = $translations['group_historical'];
202
      $old_column = 'revision_id';
203
      $column = $field['field_name'] . '-' . $old_column;
204
    }
205

    
206
    $data[$table][$old_column]['field']['moved to'] = array($table, $column);
207
    $data[$table][$column] = array(
208
      'group' => $group,
209
      'title' => $label,
210
      'title short' => $label,
211
      'help' => $translations['appears_in_help'],
212
    );
213

    
214
    // Go through and create a list of aliases for all possible combinations of
215
    // entity type + name.
216
    $aliases = array();
217
    $also_known = array();
218
    foreach ($all_labels as $entity_name => $labels) {
219
      foreach ($labels as $label_name => $true) {
220
        if ($type == FIELD_LOAD_CURRENT) {
221
          if ($group_name != $groups[$entity_name] || $label != $label_name) {
222
            $aliases[] = array(
223
              'base' => $current_tables[$entity_name],
224
              'group' => $groups[$entity_name],
225
              'title' => $label_name,
226
              'help' => $translations['alias_help'],
227
            );
228
          }
229
          $also_known[] = t('@group: @field', array('@group' => $groups[$entity_name], '@field' => $label_name));
230
        }
231
        else {
232
          if ($group_name != $groups[$entity_name] && $label != $label_name && isset($revision_tables[$entity_name])) {
233
            $aliases[] = array(
234
              'base' => $revision_tables[$entity_name],
235
              'group' => t('@group (historical data)', array('@group' => $groups[$entity_name])),
236
              'title' => $label_name,
237
              'help' => $translations['alias_help'],
238
            );
239
          }
240
          $also_known[] = t('@group (historical data): @field', array('@group' => $groups[$entity_name], '@field' => $label_name));
241
        }
242
      }
243
    }
244
    if ($aliases) {
245
      $data[$table][$column]['aliases'] = $aliases;
246
      $data[$table][$column]['help'] .= ' ' . t('Also known as: !also.', array('!also' => implode(', ', $also_known)));
247
    }
248

    
249
    $keys = array_keys($field['columns']);
250
    $real_field = reset($keys);
251
    $data[$table][$column]['field'] = array(
252
      'table' => $table,
253
      'handler' => 'views_handler_field_field',
254
      'click sortable' => TRUE,
255
      'field_name' => $field['field_name'],
256
      // Provide a real field for group by.
257
      'real field' => $column . '_' . $real_field,
258
      'additional fields' => $add_fields,
259
      'entity_tables' => $entity_tables,
260
      // Default the element type to div, let the UI change it if necessary.
261
      'element type' => 'div',
262
      'is revision' => $type == FIELD_LOAD_REVISION,
263
    );
264
  }
265

    
266
  foreach ($field['columns'] as $column => $attributes) {
267
    $allow_sort = TRUE;
268

    
269
    // Identify likely filters and arguments for each column based on field
270
    // type.
271
    switch ($attributes['type']) {
272
      case 'int':
273
      case 'mediumint':
274
      case 'tinyint':
275
      case 'bigint':
276
      case 'serial':
277
      case 'numeric':
278
      case 'float':
279
        $filter = 'views_handler_filter_numeric';
280
        $argument = 'views_handler_argument_numeric';
281
        $sort = 'views_handler_sort';
282
        break;
283

    
284
      case 'text':
285
      case 'blob':
286
        // It does not make sense to sort by blob or text.
287
        $allow_sort = FALSE;
288
      default:
289
        $filter = 'views_handler_filter_string';
290
        $argument = 'views_handler_argument_string';
291
        $sort = 'views_handler_sort';
292
        break;
293
    }
294

    
295
    if (count($field['columns']) == 1 || $column == 'value') {
296
      $title = t('@label (!name)', array('@label' => $label, '!name' => $field['field_name']));
297
      // CCK used the first 10 characters of $label. Probably doesn't matter.
298
      $title_short = $label;
299
    }
300
    else {
301
      $title = t('@label (!name:!column)', array('@label' => $label, '!name' => $field['field_name'], '!column' => $column));
302
      $title_short = t('@label:!column', array('@label' => $label, '!column' => $column));
303
    }
304

    
305
    foreach ($tables as $type => $table) {
306
      if ($type == FIELD_LOAD_CURRENT) {
307
        $group = $group_name;
308
      }
309
      else {
310
        $group = $translations['group_historical'];
311
      }
312
      $column_real_name = $field['storage']['details']['sql'][$type][$table][$column];
313

    
314
      // Load all the fields from the table by default.
315
      $additional_fields = array_values($field['storage']['details']['sql'][$type][$table]);
316

    
317
      $data[$table][$column_real_name] = array(
318
        'group' => $group,
319
        'title' => $title,
320
        'title short' => $title_short,
321
        'help' => $translations['appears_in_help'],
322
      );
323

    
324
      // Go through and create a list of aliases for all possible combinations
325
      // of entity type + name.
326
      $aliases = array();
327
      $also_known = array();
328
      foreach ($all_labels as $entity_name => $labels) {
329
        foreach ($labels as $label_name => $true) {
330
          if ($group_name != $groups[$entity_name] || $label != $label_name) {
331
            if (count($field['columns']) == 1 || $column == 'value') {
332
              // CCK used the first 10 characters of $label. Probably doesn't
333
              // matter.
334
              $alias_title = t('@label (!name)', array('@label' => $label_name, '!name' => $field['field_name']));
335
            }
336
            else {
337
              $alias_title = t('@label (!name:!column)', array('@label' => $label_name, '!name' => $field['field_name'], '!column' => $column));
338
            }
339
            $aliases[] = array(
340
              'group' => $groups[$entity_name],
341
              'title' => $alias_title,
342
              'help' => t('This is an alias of @group: @field.', array('@group' => $group_name, '@field' => $title)),
343
            );
344
          }
345
          $also_known[] = t('@group: @field', array('@group' => $groups[$entity_name], '@field' => $title));
346
        }
347
      }
348
      if ($aliases) {
349
        $data[$table][$column_real_name]['aliases'] = $aliases;
350
        $data[$table][$column_real_name]['help'] .= ' ' . t('Also known as: !also.', array('!also' => implode(', ', $also_known)));
351
      }
352

    
353
      $data[$table][$column_real_name]['argument'] = array(
354
        'field' => $column_real_name,
355
        'table' => $table,
356
        'handler' => $argument,
357
        'additional fields' => $additional_fields,
358
        'field_name' => $field['field_name'],
359
        'empty field name' => $translations['no_value_dash'],
360
      );
361
      $data[$table][$column_real_name]['filter'] = array(
362
        'field' => $column_real_name,
363
        'table' => $table,
364
        'handler' => $filter,
365
        'additional fields' => $additional_fields,
366
        'field_name' => $field['field_name'],
367
        'allow empty' => TRUE,
368
      );
369
      if (!empty($allow_sort)) {
370
        $data[$table][$column_real_name]['sort'] = array(
371
          'field' => $column_real_name,
372
          'table' => $table,
373
          'handler' => $sort,
374
          'additional fields' => $additional_fields,
375
          'field_name' => $field['field_name'],
376
        );
377
      }
378

    
379
      // Expose additional delta column for multiple value fields.
380
      if ($field['cardinality'] > 1 || $field['cardinality'] == FIELD_CARDINALITY_UNLIMITED) {
381
        $title_delta = t('@label (!name:delta)', array('@label' => $label, '!name' => $field['field_name']));
382
        $title_short_delta = t('@label:delta', array('@label' => $label));
383

    
384
        $data[$table]['delta'] = array(
385
          'group' => $group,
386
          'title' => $title_delta,
387
          'title short' => $title_short_delta,
388
          'help' => $translations['delta_appears_in_help'],
389
        );
390
        $data[$table]['delta']['field'] = array(
391
          'handler' => 'views_handler_field_numeric',
392
        );
393
        $data[$table]['delta']['argument'] = array(
394
          'field' => 'delta',
395
          'table' => $table,
396
          'handler' => 'views_handler_argument_numeric',
397
          'additional fields' => $additional_fields,
398
          'empty field name' => $translations['no_value_dash'],
399
          'field_name' => $field['field_name'],
400
        );
401
        $data[$table]['delta']['filter'] = array(
402
          'field' => 'delta',
403
          'table' => $table,
404
          'handler' => 'views_handler_filter_numeric',
405
          'additional fields' => $additional_fields,
406
          'field_name' => $field['field_name'],
407
          'allow empty' => TRUE,
408
        );
409
        $data[$table]['delta']['sort'] = array(
410
          'field' => 'delta',
411
          'table' => $table,
412
          'handler' => 'views_handler_sort',
413
          'additional fields' => $additional_fields,
414
          'field_name' => $field['field_name'],
415
        );
416
      }
417

    
418
      // Expose additional language column for translatable fields.
419
      if (!empty($field['translatable'])) {
420
        $title_language = t('@label (!name:language)', array('@label' => $label, '!name' => $field['field_name']));
421
        $title_short_language = t('@label:language', array('@label' => $label));
422

    
423
        $data[$table]['language'] = array(
424
          'group' => $group,
425
          'title' => $title_language,
426
          'title short' => $title_short_language,
427
          'help' => t('Language - Appears in: @bundles.', array('@bundles' => implode(', ', $bundles_names))),
428
        );
429
        $data[$table]['language']['field'] = array(
430
          'handler' => 'views_handler_field_locale_language',
431
        );
432
        $data[$table]['language']['argument'] = array(
433
          'field' => 'language',
434
          'table' => $table,
435
          'handler' => 'views_handler_argument_locale_language',
436
          'additional fields' => $additional_fields,
437
          'empty field name' => $translations['no_value_bracket'],
438
          'field_name' => $field['field_name'],
439
        );
440
        $data[$table]['language']['filter'] = array(
441
          'field' => 'language',
442
          'table' => $table,
443
          'handler' => 'views_handler_filter_locale_language',
444
          'additional fields' => $additional_fields,
445
          'field_name' => $field['field_name'],
446
          'allow empty' => TRUE,
447
        );
448
        $data[$table]['language']['sort'] = array(
449
          'field' => 'language',
450
          'table' => $table,
451
          'handler' => 'views_handler_sort',
452
          'additional fields' => $additional_fields,
453
          'field_name' => $field['field_name'],
454
        );
455
      }
456
    }
457
  }
458

    
459
  return $data;
460
}
461

    
462
/**
463
 * Have a different filter handler for lists.
464
 *
465
 * This should allow to select values of the list.
466
 */
467
function list_field_views_data($field) {
468
  $data = field_views_field_default_views_data($field);
469
  foreach ($data as $table_name => $table_data) {
470
    foreach ($table_data as $field_name => $field_data) {
471
      if (isset($field_data['filter']) && $field_name != 'delta') {
472
        if ($field['type'] == 'list_boolean') {
473
          // Special handler for boolean fields.
474
          $data[$table_name][$field_name]['filter']['handler'] = 'views_handler_filter_field_list_boolean';
475
        }
476
        else {
477
          $data[$table_name][$field_name]['filter']['handler'] = 'views_handler_filter_field_list';
478
        }
479
      }
480
      if (isset($field_data['argument']) && $field_name != 'delta') {
481
        if ($field['type'] == 'list_text') {
482
          $data[$table_name][$field_name]['argument']['handler'] = 'views_handler_argument_field_list_string';
483
        }
484
        else {
485
          $data[$table_name][$field_name]['argument']['handler'] = 'views_handler_argument_field_list';
486
        }
487
      }
488
    }
489
  }
490
  return $data;
491
}