ManagedFile::processManagedFile

public static ManagedFile::processManagedFile(&$element, FormStateInterface $form_state, &$complete_form)

Render API callback: Expands the managed_file element type.

Expands the file type to include Upload and Remove buttons, as well as support for a default value.

File

core/modules/file/src/Element/ManagedFile.php, line 206

Class

ManagedFile
Provides an AJAX/progress aware widget for uploading and saving a file.

Namespace

Drupal\file\Element

Code

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
public static function processManagedFile(&$element, FormStateInterface $form_state, &$complete_form) {
 
  // This is used sometimes so let's implode it just once.
  $parents_prefix = implode('_', $element['#parents']);
 
  $fids = isset($element['#value']['fids']) ? $element['#value']['fids'] : [];
 
  // Set some default element properties.
  $element['#progress_indicator'] = empty($element['#progress_indicator']) ? 'none' : $element['#progress_indicator'];
  $element['#files'] = !empty($fids) ? File::loadMultiple($fids) : FALSE;
  $element['#tree'] = TRUE;
 
  // Generate a unique wrapper HTML ID.
  $ajax_wrapper_id = Html::getUniqueId('ajax-wrapper');
 
  $ajax_settings = [
    'callback' => [get_called_class(), 'uploadAjaxCallback'],
    'options' => [
      'query' => [
        'element_parents' => implode('/', $element['#array_parents']),
      ],
    ],
    'wrapper' => $ajax_wrapper_id,
    'effect' => 'fade',
    'progress' => [
      'type' => $element['#progress_indicator'],
      'message' => $element['#progress_message'],
    ],
  ];
 
  // Set up the buttons first since we need to check if they were clicked.
  $element['upload_button'] = [
    '#name' => $parents_prefix . '_upload_button',
    '#type' => 'submit',
    '#value' => t('Upload'),
    '#attributes' => ['class' => ['js-hide']],
    '#validate' => [],
    '#submit' => ['file_managed_file_submit'],
    '#limit_validation_errors' => [$element['#parents']],
    '#ajax' => $ajax_settings,
    '#weight' => -5,
  ];
 
  // Force the progress indicator for the remove button to be either 'none' or
  // 'throbber', even if the upload button is using something else.
  $ajax_settings['progress']['type'] = ($element['#progress_indicator'] == 'none') ? 'none' : 'throbber';
  $ajax_settings['progress']['message'] = NULL;
  $ajax_settings['effect'] = 'none';
  $element['remove_button'] = [
    '#name' => $parents_prefix . '_remove_button',
    '#type' => 'submit',
    '#value' => $element['#multiple'] ? t('Remove selected') : t('Remove'),
    '#validate' => [],
    '#submit' => ['file_managed_file_submit'],
    '#limit_validation_errors' => [$element['#parents']],
    '#ajax' => $ajax_settings,
    '#weight' => 1,
  ];
 
  $element['fids'] = [
    '#type' => 'hidden',
    '#value' => $fids,
  ];
 
  // Add progress bar support to the upload if possible.
  if ($element['#progress_indicator'] == 'bar' && $implementation = file_progress_implementation()) {
    $upload_progress_key = mt_rand();
 
    if ($implementation == 'uploadprogress') {
      $element['UPLOAD_IDENTIFIER'] = [
        '#type' => 'hidden',
        '#value' => $upload_progress_key,
        '#attributes' => ['class' => ['file-progress']],
        // Uploadprogress extension requires this field to be at the top of
        // the form.
        '#weight' => -20,
      ];
    }
    elseif ($implementation == 'apc') {
      $element['APC_UPLOAD_PROGRESS'] = [
        '#type' => 'hidden',
        '#value' => $upload_progress_key,
        '#attributes' => ['class' => ['file-progress']],
        // Uploadprogress extension requires this field to be at the top of
        // the form.
        '#weight' => -20,
      ];
    }
 
    // Add the upload progress callback.
    $element['upload_button']['#ajax']['progress']['url'] = Url::fromRoute('file.ajax_progress', ['key' => $upload_progress_key]);
  }
 
  // The file upload field itself.
  $element['upload'] = [
    '#name' => 'files[' . $parents_prefix . ']',
    '#type' => 'file',
    '#title' => t('Choose a file'),
    '#title_display' => 'invisible',
    '#size' => $element['#size'],
    '#multiple' => $element['#multiple'],
    '#theme_wrappers' => [],
    '#weight' => -10,
    '#error_no_message' => TRUE,
  ];
 
  if (!empty($fids) && $element['#files']) {
    foreach ($element['#files'] as $delta => $file) {
      $file_link = [
        '#theme' => 'file_link',
        '#file' => $file,
      ];
      if ($element['#multiple']) {
        $element['file_' . $delta]['selected'] = [
          '#type' => 'checkbox',
          '#title' => \Drupal::service('renderer')->renderPlain($file_link),
        ];
      }
      else {
        $element['file_' . $delta]['filename'] = $file_link + ['#weight' => -10];
      }
      // Anonymous users who have uploaded a temporary file need a
      // non-session-based token added so $this->valueCallback() can check
      // that they have permission to use this file on subsequent submissions
      // of the same form (for example, after an Ajax upload or form
      // validation error).
      if ($file->isTemporary() && \Drupal::currentUser()->isAnonymous()) {
        $element['file_' . $delta]['fid_token'] = array(
          '#type' => 'hidden',
          '#value' => Crypt::hmacBase64('file-' . $delta, \Drupal::service('private_key')->get() . Settings::getHashSalt()),
        );
      }
    }
  }
 
  // Add the extension list to the page as JavaScript settings.
  if (isset($element['#upload_validators']['file_validate_extensions'][0])) {
    $extension_list = implode(',', array_filter(explode(' ', $element['#upload_validators']['file_validate_extensions'][0])));
    $element['upload']['#attached']['drupalSettings']['file']['elements']['#' . $element['#id']] = $extension_list;
  }
 
  // Let #id point to the file element, so the field label's 'for' corresponds
  // with it.
  $element['#id'] = &$element['upload']['#id'];
 
  // Prefix and suffix used for Ajax replacement.
  $element['#prefix'] = '<div id="' . $ajax_wrapper_id . '">';
  $element['#suffix'] = '</div>';
 
  return $element;
}
doc_Drupal
2025-01-10 15:47:30
Comments
Leave a Comment

Please login to continue.