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

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
2016-10-29 09:25:27
Comments
Leave a Comment

Please login to continue.