diff --git a/core/includes/file.inc b/core/includes/file.inc index 102a9d4..b217edb 100644 --- a/core/includes/file.inc +++ b/core/includes/file.inc @@ -1063,18 +1063,18 @@ function file_unmanaged_delete_recursive($path, $callback = NULL) { * - source: Path to the file before it is moved. * - destination: Path to the file after it is moved (same as 'uri'). */ -function file_save_upload($source, $validators = array(), $destination = FALSE, $delta = FALSE, $replace = FILE_EXISTS_RENAME) { +function file_save_upload($source, $validators = array(), $destination = FALSE, $position = FALSE, $replace = FILE_EXISTS_RENAME) { global $user; static $upload_cache; // Return cached objects without processing since the file will have // already been processed and the paths in _FILES will be invalid. if (isset($upload_cache[$source])) { - if ($delta === FALSE) { + if ($position === FALSE) { return $upload_cache[$source]; } else { - return $upload_cache[$source][$delta]; + return $upload_cache[$source][$position]; } } @@ -1247,11 +1247,11 @@ function file_save_upload($source, $validators = array(), $destination = FALSE, // Add file to the cache. $upload_cache[$source] = $files; - if ($delta === FALSE) { + if ($position === FALSE) { return $files; } else { - return $files[$delta]; + return $files[$position]; } return $files; diff --git a/core/modules/file/file.field.inc b/core/modules/file/file.field.inc index e166b82..9dd0373 100644 --- a/core/modules/file/file.field.inc +++ b/core/modules/file/file.field.inc @@ -387,7 +387,7 @@ function file_field_widget_value($element, $input = FALSE, $form_state) { // Ensure that all the required properties are returned even if empty. $return += array( - 'fid' => 0, + 'fids' => array(), 'display' => 1, 'description' => '', ); @@ -404,7 +404,7 @@ function file_field_widget_value($element, $input = FALSE, $form_state) { */ function file_field_widget_process($element, &$form_state, $form) { $item = $element['#value']; - $item['fid'] = $element['fid']['#value']; + $item['fids'] = $element['fids']['#value']; $field = field_widget_field($element, $form_state); $instance = field_widget_instance($element, $form_state); @@ -413,9 +413,9 @@ function file_field_widget_process($element, &$form_state, $form) { $element['#theme'] = 'file_widget'; // Add the display field if enabled. - if (!empty($field['settings']['display_field']) && $item['fid']) { + if (!empty($field['settings']['display_field']) && $item['fids']) { $element['display'] = array( - '#type' => empty($item['fid']) ? 'hidden' : 'checkbox', + '#type' => empty($item['fids']) ? 'hidden' : 'checkbox', '#title' => t('Include file in display'), '#value' => isset($item['display']) ? $item['display'] : $field['settings']['display_default'], '#attributes' => array('class' => array('file-display')), @@ -429,7 +429,7 @@ function file_field_widget_process($element, &$form_state, $form) { } // Add the description field if enabled. - if (!empty($instance['settings']['description_field']) && $item['fid']) { + if (!empty($instance['settings']['description_field']) && $item['fids']) { $config = config('file.settings'); $element['description'] = array( '#type' => $config->get('description.type'), @@ -561,13 +561,24 @@ function file_field_widget_submit($form, &$form_state) { $submitted_values = NestedArray::getValue($form_state['values'], array_slice($button['#array_parents'], 0, -2)); foreach ($submitted_values as $delta => $submitted_value) { - if (!$submitted_value['fid']) { + if (empty($submitted_value['fids'])) { unset($submitted_values[$delta]); } } + // If there are more files uploaded via same widget, we have to + // separate them, as we display each file in it's own widget. + $new_values = array(); + foreach ($submitted_values as $delta => $submitted_value) { + foreach ($submitted_value['fids'] as $fid) { + $new_value = $submitted_value; + $new_value['fids'] = array($fid); + $new_values[] = $new_value; + } + } + // Re-index deltas after removing empty items. - $submitted_values = array_values($submitted_values); + $submitted_values = array_values($new_values); // Update form_state values. NestedArray::setValue($form_state['values'], array_slice($button['#array_parents'], 0, -2), $submitted_values); @@ -593,9 +604,10 @@ function theme_file_widget($variables) { // The "form-managed-file" class is required for proper Ajax functionality. $output .= '
'; - if ($element['fid']['#value'] != 0) { + if (!empty($element['fids']['#value'])) { // Add the file size after the file name. - $element['filename']['#markup'] .= ' (' . format_size($element['#file']->filesize) . ') '; + $file = reset($element['#files']); + $element['file_' . $file->fid]['filename']['#markup'] .= ' (' . format_size($file->filesize) . ') '; } $output .= drupal_render_children($element); $output .= '
'; @@ -642,7 +654,7 @@ function theme_file_widget_multiple($variables) { $rows = array(); foreach ($widgets as $key => &$widget) { // Save the uploading row for last. - if ($widget['#file'] == FALSE) { + if (empty($widget['#files'])) { $widget['#title'] = $element['#file_upload_title']; $widget['#description'] = $element['#file_upload_description']; continue; diff --git a/core/modules/file/file.module b/core/modules/file/file.module index c4592ed..6981752 100644 --- a/core/modules/file/file.module +++ b/core/modules/file/file.module @@ -1017,7 +1017,7 @@ function($item) { // Process any input and save new uploads. if ($input !== FALSE) { - $input = array('fids' => $fids); + $input['fids'] = $fids; $return = $input; // Uploads take priority over all other values. @@ -1162,7 +1162,7 @@ function file_managed_file_submit($form, &$form_state) { $fids = $values['fids']; } - array_diff($values['fids'], $fids); + $values['fids'] = array_diff($values['fids'], $fids); foreach ($fids as $fid) { // If it's a temporary file we can safely remove it immediately, otherwise diff --git a/core/modules/file/lib/Drupal/file/Plugin/field/widget/FileWidget.php b/core/modules/file/lib/Drupal/file/Plugin/field/widget/FileWidget.php index 98a7a96..e6973a6 100644 --- a/core/modules/file/lib/Drupal/file/Plugin/field/widget/FileWidget.php +++ b/core/modules/file/lib/Drupal/file/Plugin/field/widget/FileWidget.php @@ -166,7 +166,7 @@ protected function formMultipleElements(EntityInterface $entity, array $items, $ */ public function formElement(array $items, $delta, array $element, $langcode, array &$form, array &$form_state) { $defaults = array( - 'fid' => 0, + 'fids' => array(), 'display' => !empty($this->field['settings']['display_default']), 'description' => '', ); @@ -186,13 +186,40 @@ public function formElement(array $items, $delta, array $element, $langcode, arr ); $element['#weight'] = $delta; + + // If we just loaded from DB we have to translate value to + // multivalue file widgets. + if (!isset($items[$delta]['fids']) && isset($items[$delta]['fid'])) { + $items[$delta]['fids'][0] = $items[$delta]['fid']; + } $element['#default_value'] = !empty($items[$delta]) ? $items[$delta] : $defaults; - if (empty($element['#default_value']['fid'])) { + if (empty($element['#default_value']['fids'])) { $element['#description'] = theme('file_upload_help', array('description' => $element['#description'], 'upload_validators' => $element['#upload_validators'])); + $element['#multiple'] = $this->field['cardinality'] != 0 ? TRUE : FALSE; } return $element; } + /** + * Implements Drupal\field\Plugin\Type\Widget\WidgetInterface::massageFormValues(). + */ + public function massageFormValues(array $values, array $form, array &$form_state) { + // Since file upload widget now supports uploads of more than one file at + // the time it always returns array of fids. We have to translate this to + // a single fid, as field expects single value. + $new_values = array(); + foreach ($values as &$value) { + foreach ($value['fids'] as $fid) { + $new_value = $value; + $new_value['fid'] = $fid; + unset($new_value['fids']); + $new_values[] = $new_value; + } + } + + return $new_values; + } + }