/**
  * Returns the progress status for a file upload process.
  *
  * @param string $key
  *   The unique key for this upload process.
  *
  * @return \Symfony\Component\HttpFoundation\JsonResponse
  *   A JsonResponse object.
  */
 public function progress($key)
 {
     $progress = array('message' => t('Starting upload...'), 'percentage' => -1);
     $implementation = file_progress_implementation();
     if ($implementation == 'uploadprogress') {
         $status = uploadprogress_get_info($key);
         if (isset($status['bytes_uploaded']) && !empty($status['bytes_total'])) {
             $progress['message'] = t('Uploading... (@current of @total)', array('@current' => format_size($status['bytes_uploaded']), '@total' => format_size($status['bytes_total'])));
             $progress['percentage'] = round(100 * $status['bytes_uploaded'] / $status['bytes_total']);
         }
     } elseif ($implementation == 'apc') {
         $status = apc_fetch('upload_' . $key);
         if (isset($status['current']) && !empty($status['total'])) {
             $progress['message'] = t('Uploading... (@current of @total)', array('@current' => format_size($status['current']), '@total' => format_size($status['total'])));
             $progress['percentage'] = round(100 * $status['current'] / $status['total']);
         }
     }
     return new JsonResponse($progress);
 }
 /**
  * {@inheritdoc}
  */
 public function settingsForm(array $form, FormStateInterface $form_state)
 {
     $element['progress_indicator'] = array('#type' => 'radios', '#title' => t('Progress indicator'), '#options' => array('throbber' => t('Throbber'), 'bar' => t('Bar with progress meter')), '#default_value' => $this->getSetting('progress_indicator'), '#description' => t('The throbber display does not show the status of uploads but takes up less space. The progress bar is helpful for monitoring progress on large uploads.'), '#weight' => 16, '#access' => file_progress_implementation());
     return $element;
 }
Example #3
0
 /**
  * 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.
  */
 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']], '#weight' => -20];
         } elseif ($implementation == 'apc') {
             $element['APC_UPLOAD_PROGRESS'] = ['#type' => 'hidden', '#value' => $upload_progress_key, '#attributes' => ['class' => ['file-progress']], '#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;
 }
Example #4
0
 /**
  * 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.
  */
 public static function processManagedFile(&$element, FormStateInterface $form_state, &$complete_form)
 {
     // Append the '-upload' to the #id so the field label's 'for' attribute
     // corresponds with the file element.
     $element['#id'] .= '-upload';
     // 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;
     $ajax_settings = ['path' => 'file/ajax', 'options' => ['query' => ['element_parents' => implode('/', $element['#array_parents']), 'form_build_id' => $complete_form['form_build_id']['#value']]], 'wrapper' => $element['#id'] . '-ajax-wrapper', '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']], '#weight' => -20];
         } elseif ($implementation == 'apc') {
             $element['APC_UPLOAD_PROGRESS'] = ['#type' => 'hidden', '#value' => $upload_progress_key, '#attributes' => ['class' => ['file-progress']], '#weight' => -20];
         }
         // Add the upload progress callback.
         $element['upload_button']['#ajax']['progress']['path'] = 'file/progress/' . $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];
     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_render($file_link)];
             } else {
                 $element['file_' . $delta]['filename'] = $file_link + ['#weight' => -10];
             }
         }
     }
     // 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']['js'] = [['type' => 'setting', 'data' => ['file' => ['elements' => ['#' . $element['#id'] => $extension_list]]]]];
     }
     // Prefix and suffix used for Ajax replacement.
     $element['#prefix'] = '<div id="' . $element['#id'] . '-ajax-wrapper">';
     $element['#suffix'] = '</div>';
     return $element;
 }
Example #5
0
 /**
  * Render API callback: Expands the embridge_asset element type.
  *
  * Expands the file type to include Upload and Remove buttons, as well as
  * support for a default value.
  *
  * @param array $element
  *   The element.
  * @param \Drupal\Core\Form\FormStateInterface $form_state
  *   The form state.
  * @param array $complete_form
  *   The complete form.
  *
  * @return array
  *   The processed element.
  */
 public static function processEmbridgeAsset(array &$element, FormStateInterface $form_state, array &$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) ? EmbridgeAssetEntity::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' => [[get_called_class(), 'submitHandler']], '#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' => [[get_called_class(), 'submitHandler']], '#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']], '#weight' => -20];
         } elseif ($implementation == 'apc') {
             $element['APC_UPLOAD_PROGRESS'] = ['#type' => 'hidden', '#value' => $upload_progress_key, '#attributes' => ['class' => ['file-progress']], '#weight' => -20];
         }
         // Add the upload progress callback.
         $element['upload_button']['#ajax']['progress']['url'] = Url::fromRoute('file.ajax_progress');
     }
     // 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];
     // Build link for dialog.
     if ($element['#allow_search'] && \Drupal::currentUser()->hasPermission('search embridge assets')) {
         $url_options = ['field_config' => $element['#field_config'], 'delta' => $element['#delta']];
         $link_url = Url::fromRoute('embridge.search.modal', $url_options);
         $link_url->setOptions(array('attributes' => array('class' => array('use-ajax', 'button'), 'data-accepts' => 'application/vnd.drupal-modal', 'data-dialog-type' => 'modal', 'data-dialog-options' => Json::encode(array('width' => 1000)))));
         $modal_link = Link::fromTextAndUrl('Asset search', $link_url);
         // TODO: Why can't we just have another element?
         $element['upload_button']['#suffix'] = $modal_link->toString();
     }
     if (!empty($fids) && $element['#files']) {
         foreach ($element['#files'] as $delta => $file) {
             $file_link = ['#theme' => 'embridge_file_link', '#asset' => $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];
             }
         }
     }
     // 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;
 }