Projet

Général

Profil

Paste
Télécharger (20 ko) Statistiques
| Branche: | Révision:

root / drupal7 / sites / all / modules / media / includes / media.fields.inc @ ca0757b9

1 85ad3d82 Assos Assos
<?php
2
3
/**
4
 * @file
5 ca0757b9 Assos Assos
 * Provide the media selector widget and media field formatters to the Fields
6
 * API.
7 85ad3d82 Assos Assos
 */
8
9
/**
10
 * Implements hook_field_widget_info().
11
 */
12
function media_field_widget_info() {
13
  return array(
14
    'media_generic' => array(
15 ca0757b9 Assos Assos
      'label' => t('Media browser'),
16 85ad3d82 Assos Assos
      'field types' => array('file', 'image'),
17
      'settings' => array(
18
        'allowed_types' => array('image'),
19
        'browser_plugins' => array(),
20
        'allowed_schemes' => array('public', 'private'),
21
      ),
22
      'behaviors' => array(
23 ca0757b9 Assos Assos
        'multiple values' => FIELD_BEHAVIOR_CUSTOM,
24 85ad3d82 Assos Assos
        'default value' => FIELD_BEHAVIOR_NONE,
25
      ),
26
    ),
27
  );
28
}
29
30
/**
31
 * Implements hook_field_widget_settings_form().
32
 */
33
function media_field_widget_settings_form($field, $instance) {
34
  $widget = $instance['widget'];
35
  $settings = $widget['settings'];
36
37 ca0757b9 Assos Assos
  $plugins = media_get_browser_plugin_info();
38
  $options = array();
39
  foreach ($plugins as $key => $plugin) {
40
    $options[$key] = check_plain($plugin['title']);
41
  }
42
43
  $form['browser_plugins'] = array(
44
    '#type' => 'checkboxes',
45
    '#title' => t('Enabled browser plugins'),
46
    '#options' => $options,
47
    '#default_value' => $settings['browser_plugins'],
48
    '#description' => t('Media browser plugins which are allowed for this field. If no plugins are selected, they will all be available.'),
49
  );
50 85ad3d82 Assos Assos
51
  $form['allowed_types'] = array(
52
    '#type' => 'checkboxes',
53 ca0757b9 Assos Assos
    '#title' => t('Allowed file types'),
54 85ad3d82 Assos Assos
    '#options' => file_entity_type_get_names(),
55
    '#default_value' => $settings['allowed_types'],
56 ca0757b9 Assos Assos
    '#description' => t('File types which are allowed for this field. If no file types are selected, they will all be available.'),
57 85ad3d82 Assos Assos
  );
58
59 ca0757b9 Assos Assos
  $visible_steam_wrappers = file_get_stream_wrappers(STREAM_WRAPPERS_VISIBLE);
60 85ad3d82 Assos Assos
  $options = array();
61 ca0757b9 Assos Assos
  foreach ($visible_steam_wrappers as $scheme => $information) {
62
    $options[$scheme] = check_plain($information['name']);
63 85ad3d82 Assos Assos
  }
64 ca0757b9 Assos Assos
65 85ad3d82 Assos Assos
  $form['allowed_schemes'] = array(
66
    '#type' => 'checkboxes',
67
    '#title' => t('Allowed URI schemes'),
68
    '#options' => $options,
69
    '#default_value' => $settings['allowed_schemes'],
70 ca0757b9 Assos Assos
    '#description' => t('URI schemes which are allowed for this field. If no schemes are selected, they will all be available.'),
71 85ad3d82 Assos Assos
  );
72
73
  return $form;
74
}
75
76
/**
77
 * Implements hook_field_widget_form().
78
 */
79
function media_field_widget_form(&$form, &$form_state, $field, $instance, $langcode, $items, $delta, $element) {
80
81 ca0757b9 Assos Assos
  // Add display_field setting to field because media_field_widget_form() assumes it is set.
82
  if (!isset($field['settings']['display_field'])) {
83
    $field['settings']['display_field'] = 0;
84 85ad3d82 Assos Assos
  }
85
86 ca0757b9 Assos Assos
  $defaults = array(
87
    'fid' => 0,
88
    'display' => !empty($field['settings']['display_default']),
89
    'description' => '',
90
  );
91
92
  // Load the items for form rebuilds from the field state as they might not be
93
  // in $form_state['values'] because of validation limitations. Also, they are
94
  // only passed in as $items when editing existing entities.
95
  $field_state = field_form_get_state($element['#field_parents'], $field['field_name'], $langcode, $form_state);
96
  if (isset($field_state['items'])) {
97
    $items = $field_state['items'];
98
  }
99
100
  $field_settings = $instance['settings'];
101
  $widget_settings = $instance['widget']['settings'];
102
103
  // Essentially we use the media type, extended with some enhancements.
104
  $element_info = element_info('media');
105 85ad3d82 Assos Assos
  $element += array(
106
    '#type' => 'media',
107 ca0757b9 Assos Assos
    '#value_callback' => 'media_field_widget_value',
108
    '#process' => array_merge($element_info['#process'], array('media_field_widget_process')),
109 85ad3d82 Assos Assos
    '#media_options' => array(
110
      'global' => array(
111
        'types' => array_filter($widget_settings['allowed_types']),
112
        'enabledPlugins' => array_filter($instance['widget']['settings']['browser_plugins']),
113 ca0757b9 Assos Assos
        'schemes' => array_filter($widget_settings['allowed_schemes']),
114 85ad3d82 Assos Assos
        'file_directory' => isset($field_settings['file_directory']) ? $field_settings['file_directory'] : '',
115
        'file_extensions' => isset($field_settings['file_extensions']) ? $field_settings['file_extensions'] : variable_get('file_entity_default_allowed_extensions', 'jpg jpeg gif png txt doc docx xls xlsx pdf ppt pptx pps ppsx odt ods odp mp3 mov mp4 m4a m4v mpeg avi ogg oga ogv weba webp webm'),
116
        'max_filesize' => isset($field_settings['max_filesize']) ? $field_settings['max_filesize'] : 0,
117
        'uri_scheme' => !empty($field['settings']['uri_scheme']) ? $field['settings']['uri_scheme'] : file_default_scheme(),
118
      ),
119
    ),
120 ca0757b9 Assos Assos
    // Allows this field to return an array instead of a single value.
121
    '#extended' => TRUE,
122 85ad3d82 Assos Assos
  );
123
124 ca0757b9 Assos Assos
  // Add image field specific validators.
125
  if ($field['type'] == 'image') {
126
    if ($field_settings['min_resolution'] || $field_settings['max_resolution']) {
127
      $element['#media_options']['global']['min_resolution'] = $field_settings['min_resolution'];
128
      $element['#media_options']['global']['max_resolution'] = $field_settings['max_resolution'];
129
    }
130
  }
131
132
  if ($field['cardinality'] == 1) {
133
    // Set the default value.
134
    $element['#default_value'] = !empty($items) ? $items[0] : $defaults;
135
    // If there's only one field, return it as delta 0.
136
    if (empty($element['#default_value']['fid'])) {
137
      $element['#description'] = theme('media_upload_help', array('description' => $element['#description']));
138
    }
139
    $elements = array($element);
140
  }
141
  else {
142
    // If there are multiple values, add an element for each existing one.
143
    foreach ($items as $item) {
144
      $elements[$delta] = $element;
145
      $elements[$delta]['#default_value'] = $item;
146
      $elements[$delta]['#weight'] = $delta;
147
      $delta++;
148
    }
149
    // And then add one more empty row for new uploads except when this is a
150
    // programmed form as it is not necessary.
151
    if (($field['cardinality'] == FIELD_CARDINALITY_UNLIMITED || $delta < $field['cardinality']) && empty($form_state['programmed'])) {
152
      $elements[$delta] = $element;
153
      $elements[$delta]['#default_value'] = $defaults;
154
      $elements[$delta]['#weight'] = $delta;
155
      $elements[$delta]['#required'] = ($element['#required'] && $delta == 0);
156
    }
157
    // The group of elements all-together need some extra functionality
158
    // after building up the full list (like draggable table rows).
159
    $elements['#file_upload_delta'] = $delta;
160
    $elements['#theme'] = 'media_widget_multiple';
161
    $elements['#theme_wrappers'] = array('fieldset');
162
    $elements['#process'] = array('media_field_widget_process_multiple');
163
    $elements['#title'] = $element['#title'];
164
    $elements['#description'] = $element['#description'];
165
    $elements['#field_name'] = $element['#field_name'];
166
    $elements['#language'] = $element['#language'];
167
    $elements['#display_field'] = $field['settings']['display_field'];
168
169
    // Add some properties that will eventually be added to the media upload
170
    // field. These are added here so that they may be referenced easily through
171
    // a hook_form_alter().
172
    $elements['#file_upload_title'] = t('Attach media');
173
    $elements['#file_upload_description'] = theme('media_upload_help', array('description' => ''));
174
  }
175
176
  return $elements;
177
}
178
179
/**
180
 * The #value_callback for the media field element.
181
 */
182
function media_field_widget_value($element, $input = FALSE, $form_state) {
183
  if ($input) {
184
    // Checkboxes lose their value when empty.
185
    // If the display field is present make sure its unchecked value is saved.
186
    $field = field_widget_field($element, $form_state);
187
    if (empty($input['display'])) {
188
      $input['display'] = $field['settings']['display_field'] ? 0 : 1;
189
    }
190 85ad3d82 Assos Assos
  }
191
192 ca0757b9 Assos Assos
  // We depend on the media element to handle uploads.
193
  $return = media_file_value($element, $input, $form_state);
194
195
  // Ensure that all the required properties are returned even if empty.
196
  $return += array(
197
    'fid' => 0,
198
    'display' => 1,
199
    'description' => '',
200
  );
201
202
  return $return;
203
}
204
205
/**
206
 * An element #process callback for the media field type.
207
 *
208
 * Expands the media type to include the description and display fields.
209
 */
210
function media_field_widget_process($element, &$form_state, $form) {
211
  $item = $element['#value'];
212
  $item['fid'] = $element['fid']['#value'];
213
214
  $field = field_widget_field($element, $form_state);
215
  $instance = field_widget_instance($element, $form_state);
216
  $settings = $instance['widget']['settings'];
217
218
  $element['#theme'] = 'media_widget';
219
220
  // Add the display field if enabled.
221
  if (!empty($field['settings']['display_field']) && $item['fid']) {
222 85ad3d82 Assos Assos
    $element['display'] = array(
223 ca0757b9 Assos Assos
      '#type' => empty($item['fid']) ? 'hidden' : 'checkbox',
224
      '#title' => t('Include file in display'),
225
      '#value' => isset($item['display']) ? $item['display'] : $field['settings']['display_default'],
226
      '#attributes' => array('class' => array('file-display')),
227
    );
228
  }
229
  else {
230
    $element['display'] = array(
231
      '#type' => 'hidden',
232
      '#value' => '1',
233 85ad3d82 Assos Assos
    );
234
  }
235
236 ca0757b9 Assos Assos
  // Add the description field if enabled.
237
  if (!empty($instance['settings']['description_field']) && $item['fid']) {
238
    $element['description'] = array(
239
      '#type' => variable_get('file_description_type', 'textfield'),
240
      '#title' => t('Description'),
241
      '#value' => isset($item['description']) ? $item['description'] : '',
242
      '#maxlength' => variable_get('file_description_length', 128),
243
      '#description' => t('The description may be used as the label of the link to the file.'),
244
    );
245
  }
246
247
  // Adjust the Ajax settings so that on upload and remove of any individual
248
  // file, the entire group of file fields is updated together.
249
  if ($field['cardinality'] != 1) {
250
    $parents = array_slice($element['#array_parents'], 0, -1);
251
    $new_path = 'media/ajax/' . implode('/', $parents) . '/' . $form['form_build_id']['#value'];
252
    $field_element = drupal_array_get_nested_value($form, $parents);
253
    $new_wrapper = $field_element['#id'] . '-ajax-wrapper';
254
    foreach (element_children($element) as $key) {
255
      if (isset($element[$key]['#ajax'])) {
256
        $element[$key]['#ajax']['path'] = $new_path;
257
        $element[$key]['#ajax']['wrapper'] = $new_wrapper;
258
      }
259
    }
260
    unset($element['#prefix'], $element['#suffix']);
261
  }
262
263
  // Add another submit handler to the upload and remove buttons, to implement
264
  // functionality needed by the field widget. This submit handler, along with
265
  // the rebuild logic in media_field_widget_form() requires the entire field,
266
  // not just the individual item, to be valid.
267
  foreach (array('attach_button', 'remove_button') as $key) {
268
    $element[$key]['#submit'][] = 'media_field_widget_submit';
269
    $element[$key]['#limit_validation_errors'] = array(array_slice($element['#parents'], 0, -1));
270
  }
271
272
  return $element;
273
}
274
275
/**
276
 * An element #process callback for a group of media fields.
277
 *
278
 * Adds the weight field to each row so it can be ordered and adds a new Ajax
279
 * wrapper around the entire group so it can be replaced all at once.
280
 */
281
function media_field_widget_process_multiple($element, &$form_state, $form) {
282
  $element_children = element_children($element, TRUE);
283
  $count = count($element_children);
284
285
  foreach ($element_children as $delta => $key) {
286
    if ($key != $element['#file_upload_delta']) {
287
      $description = _media_field_get_description_from_element($element[$key]);
288
      $element[$key]['_weight'] = array(
289
        '#type' => 'weight',
290
        '#title' => $description ? t('Weight for @title', array('@title' => $description)) : t('Weight for new file'),
291
        '#title_display' => 'invisible',
292
        '#delta' => $count,
293
        '#default_value' => $delta,
294
      );
295
    }
296
    else {
297
      // The title needs to be assigned to the attach field so that validation
298
      // errors include the correct widget label.
299
      $element[$key]['#title'] = $element['#title'];
300
      $element[$key]['_weight'] = array(
301
        '#type' => 'hidden',
302
        '#default_value' => $delta,
303
      );
304 85ad3d82 Assos Assos
    }
305
  }
306
307 ca0757b9 Assos Assos
  // Add a new wrapper around all the elements for Ajax replacement.
308
  $element['#prefix'] = '<div id="' . $element['#id'] . '-ajax-wrapper">';
309
  $element['#suffix'] = '</div>';
310
311 85ad3d82 Assos Assos
  return $element;
312
}
313
314
/**
315 ca0757b9 Assos Assos
 * Retrieves the file description from a media field element.
316 85ad3d82 Assos Assos
 *
317 ca0757b9 Assos Assos
 * This helper function is used by media_field_widget_process_multiple().
318 85ad3d82 Assos Assos
 *
319 ca0757b9 Assos Assos
 * @param $element
320
 *   The element being processed.
321
 *
322
 * @return
323
 *   A description of the file suitable for use in the administrative interface.
324
 */
325
function _media_field_get_description_from_element($element) {
326
  // Use the actual file description, if it's available.
327
  if (!empty($element['#default_value']['description'])) {
328
    return $element['#default_value']['description'];
329
  }
330
  // Otherwise, fall back to the filename.
331
  if (!empty($element['#default_value']['filename'])) {
332
    return $element['#default_value']['filename'];
333
  }
334
  // This is probably a newly uploaded file; no description is available.
335
  return FALSE;
336
}
337
338
/**
339
 * Form submission handler for attach/remove button of media_field_widget_form().
340
 *
341
 * This runs in addition to and after media_field_widget_submit().
342
 *
343
 * @see media_field_widget_submit()
344 85ad3d82 Assos Assos
 * @see media_field_widget_form()
345 ca0757b9 Assos Assos
 * @see media_field_widget_process()
346
 */
347
function media_field_widget_submit($form, &$form_state) {
348
  // During the form rebuild, media_field_widget_form() will create field item
349
  // widget elements using re-indexed deltas, so clear out $form_state['input']
350
  // to avoid a mismatch between old and new deltas. The rebuilt elements will
351
  // have #default_value set appropriately for the current state of the field,
352
  // so nothing is lost in doing this.
353
  $parents = array_slice($form_state['triggering_element']['#parents'], 0, -2);
354
  drupal_array_set_nested_value($form_state['input'], $parents, NULL);
355
356
  $button = $form_state['triggering_element'];
357
358
  // Go one level up in the form, to the widgets container.
359
  $element = drupal_array_get_nested_value($form, array_slice($button['#array_parents'], 0, -1));
360
  $field_name = $element['#field_name'];
361
  $langcode = $element['#language'];
362
  $parents = $element['#field_parents'];
363
364
  $submitted_values = drupal_array_get_nested_value($form_state['values'], array_slice($button['#parents'], 0, -2));
365
  foreach ($submitted_values as $delta => $submitted_value) {
366
    if (!$submitted_value['fid']) {
367
      unset($submitted_values[$delta]);
368
    }
369
  }
370
371
  // Re-index deltas after removing empty items.
372
  $submitted_values = array_values($submitted_values);
373
374
  // Update form_state values.
375
  drupal_array_set_nested_value($form_state['values'], array_slice($button['#parents'], 0, -2), $submitted_values);
376
377
  // Update items.
378
  $field_state = field_form_get_state($parents, $field_name, $langcode, $form_state);
379
  $field_state['items'] = $submitted_values;
380
  field_form_set_state($parents, $field_name, $langcode, $form_state, $field_state);
381
}
382
383
/**
384
 * Returns HTML for an individual media widget.
385
 *
386
 * @param $variables
387
 *   An associative array containing:
388
 *   - element: A render element representing the widget.
389
 *
390
 * @ingroup themeable
391
 */
392
function theme_media_widget($variables) {
393
  $element = $variables['element'];
394
  $output = '';
395
396
  // The "form-media" class is required for proper Ajax functionality.
397
  $output .= '<div id="' . $element['#id'] . '" class="media-widget form-media clearfix">';
398
  $output .= drupal_render_children($element);
399
  $output .= '</div>';
400
401
  return $output;
402
}
403
404
/**
405
 * Returns HTML for a group of media widgets.
406
 *
407
 * @param $variables
408
 *   An associative array containing:
409
 *   - element: A render element representing the widgets.
410
 *
411
 * @ingroup themeable
412 85ad3d82 Assos Assos
 */
413 ca0757b9 Assos Assos
function theme_media_widget_multiple($variables) {
414
  $element = $variables['element'];
415
416
  // Special ID and classes for draggable tables.
417
  $weight_class = $element['#id'] . '-weight';
418
  $table_id = $element['#id'] . '-table';
419 85ad3d82 Assos Assos
420 ca0757b9 Assos Assos
  // Build up a table of applicable fields.
421
  $headers = array();
422
  $headers[] = t('File information');
423
  if ($element['#display_field']) {
424
    $headers[] = array(
425
      'data' => t('Display'),
426
      'class' => array('checkbox'),
427
    );
428 85ad3d82 Assos Assos
  }
429 ca0757b9 Assos Assos
  $headers[] = t('Weight');
430
  $headers[] = t('Operations');
431 85ad3d82 Assos Assos
432 ca0757b9 Assos Assos
  // Get our list of widgets in order (needed when the form comes back after
433
  // preview or failed validation).
434
  $widgets = array();
435
  foreach (element_children($element) as $key) {
436
    $widgets[] = &$element[$key];
437 85ad3d82 Assos Assos
  }
438 ca0757b9 Assos Assos
  usort($widgets, '_field_sort_items_value_helper');
439 85ad3d82 Assos Assos
440 ca0757b9 Assos Assos
  $rows = array();
441
  foreach ($widgets as $key => &$widget) {
442
    // Save the uploading row for last.
443
    if ($widget['#file'] == FALSE) {
444
      $widget['#title'] = $element['#file_upload_title'];
445
      $widget['#description'] = $element['#file_upload_description'];
446
      continue;
447
    }
448
449
    // Delay rendering of the buttons, so that they can be rendered later in the
450
    // "operations" column.
451
    $operations_elements = array();
452
    foreach (element_children($widget) as $sub_key) {
453
      if (isset($widget[$sub_key]['#type']) && $widget[$sub_key]['#type'] == 'submit') {
454
        hide($widget[$sub_key]);
455
        $operations_elements[] = &$widget[$sub_key];
456
      }
457
    }
458
459
    // Delay rendering of the "Display" option and the weight selector, so that
460
    // each can be rendered later in its own column.
461
    if ($element['#display_field']) {
462
      hide($widget['display']);
463
    }
464
    hide($widget['_weight']);
465
466
    // Render everything else together in a column, without the normal wrappers.
467
    $widget['#theme_wrappers'] = array();
468
    $information = drupal_render($widget);
469
470
    // Render the previously hidden elements, using render() instead of
471
    // drupal_render(), to undo the earlier hide().
472
    $operations = '';
473
    foreach ($operations_elements as $operation_element) {
474
      $operations .= render($operation_element);
475
    }
476
    $display = '';
477
    if ($element['#display_field']) {
478
      unset($widget['display']['#title']);
479
      $display = array(
480
        'data' => render($widget['display']),
481
        'class' => array('checkbox'),
482
      );
483
    }
484
    $widget['_weight']['#attributes']['class'] = array($weight_class);
485
    $weight = render($widget['_weight']);
486
487
    // Arrange the row with all of the rendered columns.
488
    $row = array();
489
    $row[] = $information;
490
    if ($element['#display_field']) {
491
      $row[] = $display;
492
    }
493
    $row[] = $weight;
494
    $row[] = $operations;
495
    $rows[] = array(
496
      'data' => $row,
497
      'class' => isset($widget['#attributes']['class']) ? array_merge($widget['#attributes']['class'], array('draggable')) : array('draggable'),
498
    );
499
  }
500
501
  drupal_add_tabledrag($table_id, 'order', 'sibling', $weight_class);
502
503
  $output = '';
504
  $output = empty($rows) ? '' : theme('table', array('header' => $headers, 'rows' => $rows, 'attributes' => array('id' => $table_id)));
505
  $output .= drupal_render_children($element);
506
  return $output;
507
}
508
509
/**
510
 * Returns HTML for help text.
511
 *
512
 * @param $variables
513
 *   An associative array containing:
514
 *   - description: The normal description for this field, specified by the
515
 *     user.
516
 *
517
 * @ingroup themeable
518
 */
519
function theme_media_upload_help($variables) {
520
  $description = $variables['description'];
521
522
  $descriptions = array();
523
524
  if (strlen($description)) {
525
    $descriptions[] = $description;
526
  }
527
528
  return implode('<br />', $descriptions);
529
}
530
531
/**
532
 * Implements hook_field_formatter_info().
533
 *
534
 * Provides legacy support for the "Large filetype icon" file field formatter.
535
 * This was originally used when media entities contained file fields. The
536
 * current file entity architecture no longer needs this, but people may
537
 * have used this formatter for other file fields on their website.
538
 *
539
 * @todo Some day, remove this.
540
 */
541
function media_field_formatter_info() {
542
  $formatters = array(
543
    'media_large_icon' => array(
544
      'label' => t('Large filetype icon'),
545
      'field types' => array('file'),
546
    ),
547 85ad3d82 Assos Assos
  );
548 ca0757b9 Assos Assos
  return $formatters;
549
}
550 85ad3d82 Assos Assos
551 ca0757b9 Assos Assos
/**
552
 * Implements hook_field_formatter_view().
553
 *
554
 * Legacy support for the "Large filetype icon" file field formatter.
555
 * @see media_field_formatter_info()
556
 */
557
function media_field_formatter_view($entity_type, $entity, $field, $instance, $langcode, $items, $display) {
558
  $element = array();
559
560
  if ($display['type'] == 'media_large_icon') {
561
    // Use the media_thumbnail image style so that the output in media browser
562
    // is consistent.
563
    foreach ($items as $delta => $item) {
564
      $element[$delta] = array(
565
        '#theme' => 'media_formatter_large_icon',
566
        '#file' => (object) $item,
567
      );
568
    }
569
  }
570
571
  return $element;
572 85ad3d82 Assos Assos
}