Commit 8fd2b477 authored by webchick's avatar webchick

Issue #625958 by slashrsm, quicksketch, eojthebrave, droplet, danlinn, czigor:...

Issue #625958 by slashrsm, quicksketch, eojthebrave, droplet, danlinn, czigor: Support Uploading Multiple Files for HTML5 Browsers via #multiple attribute.
parent 8733925f
This diff is collapsed.
......@@ -4608,6 +4608,17 @@ function form_pre_render_file($element) {
return $element;
}
/**
* Processes a file upload element, make use of #multiple if present.
*/
function form_process_file($element) {
if ($element['#multiple']) {
$element['#attributes'] = array('multiple' => 'multiple');
$element['#name'] .= '[]';
}
return $element;
}
/**
* Returns HTML for a form element.
*
......
......@@ -188,7 +188,7 @@ function aggregator_form_opml_validate($form, &$form_state) {
function aggregator_form_opml_submit($form, &$form_state) {
$data = '';
$validators = array('file_validate_extensions' => array('opml xml'));
if ($file = file_save_upload('upload', $validators)) {
if ($file = file_save_upload('upload', $validators, FALSE, 0)) {
$data = file_get_contents($file->uri);
}
else {
......
......@@ -389,7 +389,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' => '',
);
......@@ -397,6 +397,47 @@ function file_field_widget_value($element, $input = FALSE, $form_state) {
return $return;
}
/**
* Validation callback for upload element on file widget. Checks if user has
* uploaded more files than allowed.
*
* This validator is used only when cardinality not set to 1 or unlimited.
*/
function file_field_widget_multiple_count_validate($element, &$form_state, $form) {
$parents = $element['#parents'];
$values = NestedArray::getValue($form_state['values'], $parents);
array_pop($parents);
$current = count(element_children(NestedArray::getValue($form, $parents))) - 1;
$field = field_info_field($element['#field_name']);
$uploaded = count($values['fids']);
$count = $uploaded + $current;
if ($count > $field['cardinality']) {
$keep = $uploaded - $count + $field['cardinality'];
$removed_files = array_slice($values['fids'], $keep);
$removed_names = array();
foreach ($removed_files as $fid) {
$file = file_load($fid);
$removed_names[] = $file->filename;
}
drupal_set_message(
t(
'Field %field can only hold @max values but there were @count uploaded. The following files have been omitted as a result: %list.',
array(
'%field' => $field['field_name'],
'@max' => $field['cardinality'],
'@count' => $keep,
'%list' => implode(', ', $removed_names),
)
),
'warning'
);
$values['fids'] = array_slice($values['fids'], 0, $keep);
NestedArray::setValue($form_state['values'], $element['#parents'], $values);
}
}
/**
* Render API callback: Processes a file_generic field element.
*
......@@ -406,7 +447,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);
......@@ -415,9 +456,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')),
......@@ -431,7 +472,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,18 +602,34 @@ function file_field_widget_submit($form, &$form_state) {
$langcode = $element['#language'];
$parents = $element['#field_parents'];
$submitted_values = NestedArray::getValue($form_state['values'], array_slice($button['#array_parents'], 0, -2));
$submitted_values = NestedArray::getValue($form_state['values'], array_slice($button['#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 the 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) {
if (is_array($submitted_value['fids'])) {
foreach ($submitted_value['fids'] as $fid) {
$new_value = $submitted_value;
$new_value['fids'] = array($fid);
$new_values[] = $new_value;
}
}
else {
$new_value = $submitted_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);
NestedArray::setValue($form_state['values'], array_slice($button['#parents'], 0, -2), $submitted_values);
// Update items.
$field_state = field_form_get_state($parents, $field_name, $langcode, $form_state);
......@@ -595,9 +652,10 @@ function theme_file_widget($variables) {
// The "form-managed-file" class is required for proper Ajax functionality.
$output .= '<div class="file-widget form-managed-file clearfix">';
if ($element['fid']['#value'] != 0) {
if (!empty($element['fids']['#value'])) {
// Add the file size after the file name.
$element['filename']['#markup'] .= ' <span class="file-size">(' . format_size($element['#file']->filesize) . ')</span> ';
$file = reset($element['#files']);
$element['file_' . $file->fid]['filename']['#markup'] .= ' <span class="file-size">(' . format_size($file->filesize) . ')</span> ';
}
$output .= drupal_render_children($element);
$output .= '</div>';
......@@ -644,7 +702,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;
......@@ -726,6 +784,7 @@ function theme_file_widget_multiple($variables) {
function theme_file_upload_help($variables) {
$description = $variables['description'];
$upload_validators = $variables['upload_validators'];
$cardinality = $variables['cardinality'];
$descriptions = array();
......@@ -738,6 +797,14 @@ function theme_file_upload_help($variables) {
if (isset($upload_validators['file_validate_extensions'])) {
$descriptions[] = t('Allowed file types: !extensions.', array('!extensions' => '<strong>' . check_plain($upload_validators['file_validate_extensions'][0]) . '</strong>'));
}
if (isset($cardinality)) {
if ($cardinality == -1) {
$descriptions[] = t('Unlimited number of files can be uploaded to this field.');
}
else {
$descriptions[] = format_plural($cardinality, 'This field can store only one file.', 'This field can store at most @count files.');
}
}
if (isset($upload_validators['file_validate_image_resolution'])) {
$max = $upload_validators['file_validate_image_resolution'][0];
$min = $upload_validators['file_validate_image_resolution'][1];
......
......@@ -246,7 +246,7 @@ function file_update_8000() {
));
}
/**
/*
* Convert the 'id' column in {file_usage} to accept UUIDs.
*/
function file_update_8001() {
......@@ -259,3 +259,32 @@ function file_update_8001() {
);
db_change_field('file_usage', 'id', 'id', $spec);
}
/**
* Convert image field's default image configuration to the new format.
*/
function file_update_8002() {
if (module_exists('field_sql_storage')) {
$fields = field_read_fields(array('type' => 'image'), array('include_deleted' => TRUE, 'include_inactive' => TRUE));
foreach ($fields as $field) {
if (!empty($field['settings']['default_image'])) {
$field['settings']['default_image'] = array($field['settings']['default_image']);
}
else {
$field['settings']['default_image'] = array();
}
field_update_field($field);
$instances = field_read_instances(array('field_name' => $field['field_name']));
foreach ($instances as $instance) {
if (!empty($instance['settings']['default_image'])) {
$instance['settings']['default_image'] = array($instance['settings']['default_image']);
}
else {
$instance['settings']['default_image'] = array();
}
field_update_instance($instance);
}
}
}
}
This diff is collapsed.
......@@ -156,7 +156,7 @@ protected function formMultipleElements(EntityInterface $entity, array $items, $
// field. These are added here so that they may be referenced easily
// through a hook_form_alter().
$elements['#file_upload_title'] = t('Add a new file');
$elements['#file_upload_description'] = theme('file_upload_help', array('description' => '', 'upload_validators' => $elements[0]['#upload_validators']));
$elements['#file_upload_description'] = theme('file_upload_help', array('description' => '', 'upload_validators' => $elements[0]['#upload_validators'], 'cardinality' => $this->field['cardinality']));
}
return $elements;
......@@ -167,7 +167,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' => '',
);
......@@ -187,13 +187,45 @@ public function formElement(array $items, $delta, array $element, $langcode, arr
);
$element['#weight'] = $delta;
// Field stores FID value in a single mode, so we need to transform it for
// form element to recognize it correctly.
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'])) {
$element['#description'] = theme('file_upload_help', array('description' => $element['#description'], 'upload_validators' => $element['#upload_validators']));
$default_fids = $element['#extended'] ? $element['#default_value']['fids'] : $element['#default_value'];
if (empty($default_fids)) {
$cardinality = isset($this->field['cardinality']) ? $this->field['cardinality'] : 1;
$element['#description'] = theme('file_upload_help', array('description' => $element['#description'], 'upload_validators' => $element['#upload_validators'], 'cardinality' => $cardinality));
$element['#multiple'] = $cardinality != 1 ? TRUE : FALSE;
if ($cardinality != 1 && $cardinality != -1) {
$element['#element_validate'] = array('file_field_widget_multiple_count_validate');
}
}
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 a
// time it always returns an 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;
}
}
......@@ -149,7 +149,12 @@ function uploadNodeFile($file, $field_name, $nid_or_type, $new_revision = TRUE,
}
// Attach a file to the node.
$edit['files[' . $field_name . '_' . $langcode . '_0]'] = drupal_realpath($file->uri);
$field = field_info_field($field_name);
$name = 'files[' . $field_name . '_' . $langcode . '_0]';
if ($field['cardinality'] != 1) {
$name .= '[]';
}
$edit[$name] = drupal_realpath($file->uri);
$this->drupalPost("node/$nid/edit", $edit, t('Save and keep published'));
return $nid;
......
......@@ -111,7 +111,7 @@ function testMultiValuedWidget() {
$this->drupalGet("node/add/$type_name");
foreach (array($field_name2, $field_name) as $each_field_name) {
for ($delta = 0; $delta < 3; $delta++) {
$edit = array('files[' . $each_field_name . '_' . LANGUAGE_NOT_SPECIFIED . '_' . $delta . ']' => drupal_realpath($test_file->uri));
$edit = array('files[' . $each_field_name . '_' . LANGUAGE_NOT_SPECIFIED . '_' . $delta . '][]' => drupal_realpath($test_file->uri));
// If the Upload button doesn't exist, drupalPost() will automatically
// fail with an assertion message.
$this->drupalPost(NULL, $edit, t('Upload'));
......
......@@ -30,73 +30,123 @@ function testManagedFile() {
$this->drupalGet('file/test');
$this->assertFieldByXpath('//input[@name="files[nested_file]" and @size="13"]', NULL, 'The custom #size attribute is passed to the child upload element.');
// Perform the tests with all permutations of $form['#tree'] and
// $element['#extended'].
// Perform the tests with all permutations of $form['#tree'],
// $element['#extended'], and $element['#multiple'].
$test_file = $this->getTestFile('text');
foreach (array(0, 1) as $tree) {
foreach (array(0, 1) as $extended) {
$test_file = $this->getTestFile('text');
$path = 'file/test/' . $tree . '/' . $extended;
$input_base_name = $tree ? 'nested_file' : 'file';
// Submit without a file.
$this->drupalPost($path, array(), t('Save'));
$this->assertRaw(t('The file id is %fid.', array('%fid' => 0)), t('Submitted without a file.'));
// Submit a new file, without using the Upload button.
$last_fid_prior = $this->getLastFileId();
$edit = array('files[' . $input_base_name . ']' => drupal_realpath($test_file->uri));
$this->drupalPost($path, $edit, t('Save'));
$last_fid = $this->getLastFileId();
$this->assertTrue($last_fid > $last_fid_prior, t('New file got saved.'));
$this->assertRaw(t('The file id is %fid.', array('%fid' => $last_fid)), t('Submit handler has correct file info.'));
// Submit no new input, but with a default file.
$this->drupalPost($path . '/' . $last_fid, array(), t('Save'));
$this->assertRaw(t('The file id is %fid.', array('%fid' => $last_fid)), t('Empty submission did not change an existing file.'));
// Now, test the Upload and Remove buttons, with and without Ajax.
foreach (array(FALSE, TRUE) as $ajax) {
// Upload, then Submit.
foreach (array(0, 1) as $multiple) {
$path = 'file/test/' . $tree . '/' . $extended . '/' . $multiple;
$input_base_name = $tree ? 'nested_file' : 'file';
$file_field_name = $multiple ? 'files[' . $input_base_name . '][]' : 'files[' . $input_base_name . ']';
// Submit without a file.
$this->drupalPost($path, array(), t('Save'));
$this->assertRaw(t('The file ids are %fids.', array('%fids' => implode(',', array()))), t('Submitted without a file.'));
// Submit a new file, without using the Upload button.
$last_fid_prior = $this->getLastFileId();
$this->drupalGet($path);
$edit = array('files[' . $input_base_name . ']' => drupal_realpath($test_file->uri));
if ($ajax) {
$this->drupalPostAJAX(NULL, $edit, $input_base_name . '_upload_button');
}
else {
$this->drupalPost(NULL, $edit, t('Upload'));
}
$edit = array($file_field_name => drupal_realpath($test_file->uri));
$this->drupalPost($path, $edit, t('Save'));
$last_fid = $this->getLastFileId();
$this->assertTrue($last_fid > $last_fid_prior, t('New file got uploaded.'));
$this->drupalPost(NULL, array(), t('Save'));
$this->assertRaw(t('The file id is %fid.', array('%fid' => $last_fid)), t('Submit handler has correct file info.'));
// Remove, then Submit.
$this->drupalGet($path . '/' . $last_fid);
if ($ajax) {
$this->drupalPostAJAX(NULL, array(), $input_base_name . '_remove_button');
}
else {
$this->drupalPost(NULL, array(), t('Remove'));
}
$this->drupalPost(NULL, array(), t('Save'));
$this->assertRaw(t('The file id is %fid.', array('%fid' => 0)), t('Submission after file removal was successful.'));
// Upload, then Remove, then Submit.
$this->drupalGet($path);
$edit = array('files[' . $input_base_name . ']' => drupal_realpath($test_file->uri));
if ($ajax) {
$this->drupalPostAJAX(NULL, $edit, $input_base_name . '_upload_button');
$this->drupalPostAJAX(NULL, array(), $input_base_name . '_remove_button');
}
else {
$this->drupalPost(NULL, $edit, t('Upload'));
$this->drupalPost(NULL, array(), t('Remove'));
$this->assertTrue($last_fid > $last_fid_prior, t('New file got saved.'));
$this->assertRaw(t('The file ids are %fids.', array('%fids' => implode(',', array($last_fid)))), t('Submit handler has correct file info.'));
// Submit no new input, but with a default file.
$this->drupalPost($path . '/' . $last_fid, array(), t('Save'));
$this->assertRaw(t('The file ids are %fids.', array('%fids' => implode(',', array($last_fid)))), t('Empty submission did not change an existing file.'));
// Now, test the Upload and Remove buttons, with and without Ajax.
foreach (array(FALSE, TRUE) as $ajax) {
// Upload, then Submit.
$last_fid_prior = $this->getLastFileId();
$this->drupalGet($path);
$edit = array($file_field_name => drupal_realpath($test_file->uri));
if ($ajax) {
$this->drupalPostAJAX(NULL, $edit, $input_base_name . '_upload_button');
}
else {
$this->drupalPost(NULL, $edit, t('Upload'));
}
$last_fid = $this->getLastFileId();
$this->assertTrue($last_fid > $last_fid_prior, t('New file got uploaded.'));
$this->drupalPost(NULL, array(), t('Save'));
$this->assertRaw(t('The file ids are %fids.', array('%fids' => implode(',', array($last_fid)))), t('Submit handler has correct file info.'));
// Remove, then Submit.
$remove_button_title = $multiple ? t('Remove selected') : t('Remove');
$remove_edit = array();
if ($multiple) {
$selected_checkbox = ($tree ? 'nested[file]' : 'file') . '[file_' . $last_fid . '][selected]';
$remove_edit = array($selected_checkbox => '1');
}
$this->drupalGet($path . '/' . $last_fid);
if ($ajax) {
$this->drupalPostAJAX(NULL, $remove_edit, $input_base_name . '_remove_button');
}
else {
$this->drupalPost(NULL, $remove_edit, $remove_button_title);
}
$this->drupalPost(NULL, array(), t('Save'));
$this->assertRaw(t('The file ids are %fids.', array('%fids' => '')), t('Submission after file removal was successful.'));
// Upload, then Remove, then Submit.
$this->drupalGet($path);
$edit = array($file_field_name => drupal_realpath($test_file->uri));
if ($ajax) {
$this->drupalPostAJAX(NULL, $edit, $input_base_name . '_upload_button');
}
else {
$this->drupalPost(NULL, $edit, t('Upload'));
}
$remove_edit = array();
if ($multiple) {
$selected_checkbox = ($tree ? 'nested[file]' : 'file') . '[file_' . $this->getLastFileId() . '][selected]';
$remove_edit = array($selected_checkbox => '1');
}
if ($ajax) {
$this->drupalPostAJAX(NULL, $remove_edit, $input_base_name . '_remove_button');
}
else {
$this->drupalPost(NULL, $remove_edit, $remove_button_title);
}
$this->drupalPost(NULL, array(), t('Save'));
$this->assertRaw(t('The file ids are %fids.', array('%fids' => '')), t('Submission after file upload and removal was successful.'));
}
$this->drupalPost(NULL, array(), t('Save'));
$this->assertRaw(t('The file id is %fid.', array('%fid' => 0)), t('Submission after file upload and removal was successful.'));
}
}
}
// The multiple file upload has additional conditions that need checking.
$path = 'file/test/1/1/1';
$edit = array('files[nested_file][]' => drupal_realpath($test_file->uri));
$fid_list = array();
$this->drupalGet($path);
// Add a single file to the upload field.
$this->drupalPost(NULL, $edit, t('Upload'));
$fid_list[] = $this->getLastFileId();
$this->assertFieldByXpath('//input[@name="nested[file][file_' . $fid_list[0] . '][selected]"]', NULL, 'First file successfully uploaded to multiple file element.');
// Add another file to the same upload field.
$this->drupalPost(NULL, $edit, t('Upload'));
$fid_list[] = $this->getLastFileId();
$this->assertFieldByXpath('//input[@name="nested[file][file_' . $fid_list[1] . '][selected]"]', NULL, 'Second file successfully uploaded to multiple file element.');
// Save the entire form.
$this->drupalPost(NULL, array(), t('Save'));
$this->assertRaw(t('The file ids are %fids.', array('%fids' => implode(',', $fid_list))), t('Two files saved into a single multiple file element.'));
// Delete only the first file.
$edit = array(
'nested[file][file_' . $fid_list[0] . '][selected]' => '1',
);
$this->drupalPost($path . '/' . implode(',', $fid_list), $edit, t('Remove selected'));
// Check that the first file has been deleted but not the second.
$this->assertNoFieldByXpath('//input[@name="nested[file][file_' . $fid_list[0] . '][selected]"]', NULL, 'An individual file can be deleted from a multiple file element.');
$this->assertFieldByXpath('//input[@name="nested[file][file_' . $fid_list[1] . '][selected]"]', NULL, 'Second individual file not deleted when the first file is deleted from a multiple file element.');
}
}
......@@ -31,7 +31,7 @@ function file_module_test_menu() {
* @see file_module_test_form_submit()
* @ingroup forms
*/
function file_module_test_form($form, &$form_state, $tree = TRUE, $extended = FALSE, $default_fid = NULL) {
function file_module_test_form($form, &$form_state, $tree = TRUE, $extended = TRUE, $multiple = FALSE, $default_fids = NULL) {
$form['#tree'] = (bool) $tree;
$form['nested']['file'] = array(
......@@ -41,9 +41,11 @@ function file_module_test_form($form, &$form_state, $tree = TRUE, $extended = FA
'#progress_message' => t('Please wait...'),
'#extended' => (bool) $extended,
'#size' => 13,
'#multiple' => (bool) $multiple,
);
if ($default_fid) {
$form['nested']['file']['#default_value'] = $extended ? array('fid' => $default_fid) : $default_fid;
if ($default_fids) {
$default_fids = explode(',', $default_fids);
$form['nested']['file']['#default_value'] = $extended ? array('fids' => $default_fids) : $default_fids;
}
$form['textfield'] = array(
......@@ -64,12 +66,22 @@ function file_module_test_form($form, &$form_state, $tree = TRUE, $extended = FA
*/
function file_module_test_form_submit($form, &$form_state) {
if ($form['#tree']) {
$fid = $form['nested']['file']['#extended'] ? $form_state['values']['nested']['file']['fid'] : $form_state['values']['nested']['file'];
$uploads = $form_state['values']['nested']['file'];
}
else {
$fid = $form['nested']['file']['#extended'] ? $form_state['values']['file']['fid'] : $form_state['values']['file'];
$uploads = $form_state['values']['file'];
}
drupal_set_message(t('The file id is %fid.', array('%fid' => $fid)));
if ($form['nested']['file']['#extended']) {
$uploads = $uploads['fids'];
}
$fids = array();
foreach ($uploads as $fid) {
$fids[] = $fid;
}
drupal_set_message(t('The file ids are %fids.', array('%fids' => implode(',', $fids))));
}
/**
......
......@@ -126,7 +126,7 @@ function _file_test_form_submit(&$form, &$form_state) {
$validators['file_validate_extensions'] = array($form_state['values']['extensions']);
}
$file = file_save_upload('file_test_upload', $validators, $destination, $form_state['values']['file_test_replace']);
$file = file_save_upload('file_test_upload', $validators, $destination, 0, $form_state['values']['file_test_replace']);
if ($file) {
$form_state['values']['file_test_upload'] = $file;
drupal_set_message(t('File @filepath was uploaded.', array('@filepath' => $file->uri)));
......
......@@ -18,7 +18,7 @@ function image_field_info() {
'description' => t('This field stores the ID of an image file as an integer value.'),
'settings' => array(
'uri_scheme' => file_default_scheme(),
'default_image' => 0,
'default_image' => array(),
'column_groups' => array(
'file' => array(
'label' => t('File'),
......@@ -44,7 +44,7 @@ function image_field_info() {
'title_field_required' => 0,
'max_resolution' => '',
'min_resolution' => '',
'default_image' => 0,
'default_image' => array(),
),
'default_widget' => 'image_image',
'default_formatter' => 'image',
......@@ -231,7 +231,7 @@ function image_field_prepare_view($entity_type, $entities, $field, $instances, $
// If there are no files specified at all, use the default.
foreach ($entities as $id => $entity) {
if (empty($items[$id])) {
$fid = 0;
$fid = array();
// Use the default for the instance if one is available.
if (!empty($instances[$id]['settings']['default_image'])) {
$fid = $instances[$id]['settings']['default_image'];
......@@ -242,7 +242,7 @@ function image_field_prepare_view($entity_type, $entities, $field, $instances, $
}
// Add the default image if one is found.
if ($fid && ($file = file_load($fid))) {
if ($fid && ($file = file_load($fid[0]))) {
$items[$id][0] = (array) $file + array(
'is_default' => TRUE,
'alt' => '',
......@@ -313,16 +313,17 @@ function image_field_is_empty($item, $field) {
*/
function image_field_widget_process($element, &$form_state, $form) {
$item = $element['#value'];
$item['fid'] = $element['fid']['#value'];
$item['fids'] = $element['fids']['#value'];
$element['#theme'] = 'image_widget';
$element['#attached']['css'][] = drupal_get_path('module', 'image') . '/image.theme.css';
// Add the image preview.
if ($element['#file'] && $element['#preview_image_style']) {
if (!empty($element['#files']) && $element['#preview_image_style']) {
$file = reset($element['#files']);
$variables = array(
'style_name' => $element['#preview_image_style'],
'uri' => $element['#file']->uri,
'uri' => $file->uri,
);
// Determine image dimensions.
......@@ -331,7 +332,7 @@ function image_field_widget_process($element, &$form_state, $form) {
$variables['height'] = $element['#value']['height'];
}
else {
$info = image_get_info($element['#file']->uri);
$info = image_get_info($file->uri);
if (is_array($info)) {
$variables['width'] = $info['width'];
......@@ -372,7 +373,7 @@ function image_field_widget_process($element, &$form_state, $form) {
// @see http://www.gawds.org/show.php?contentid=28
'#maxlength' => 512,
'#weight' => -2,
'#access' => (bool) $item['fid'] && $element['#alt_field'],
'#access' => (bool) $item['fids'] && $element['#alt_field'],
'#element_validate' => $settings['alt_field_required'] == 1 ? array('_image_field_required_fields_validate') : array(),
);
$element['title'] = array(
......@@ -382,7 +383,7 @@ function image_field_widget_process($element, &$form_state, $form) {
'#description' => t('The title is used as a tool tip when the user hovers the mouse over the image.'),
'#maxlength' => 1024,
'#weight' => -1,
'#access' => (bool) $item['fid'] && $element['#title_field'],
'#access' => (bool) $item['fids'] && $element['#title_field'],
'#element_validate' => $settings['alt_field_required'] == 1 ? array('_image_field_required_fields_validate') : array(),
);
......@@ -437,8 +438,9 @@ function theme_image_widget($variables) {
}
$output .= '<div class="image-widget-data">';
if ($element['fid']['#value'] != 0) {
$element['filename']['#markup'] .= ' <span class="file-size">(' . format_size($element['#file']->filesize) . ')</span> ';
if (!empty($element['fids']['#value'])) {
$file = reset($element['#files']);
$element['file_' . $file->fid]['filename']['#markup'] .= ' <span class="file-size">(' . format_size($file->filesize) . ')</span> ';
}
$output .= drupal_render_children($element);
$output .= '</div>';
......
......@@ -349,8 +349,8 @@ function image_field_delete_field($field) {
}
// The value of a managed_file element can be an array if #extended == TRUE.
$fid = (is_array($field['settings']['default_image']) ? $field['settings']['default_image']['fid'] : $field['settings']['default_image']);
if ($fid && ($file = file_load($fid))) {
$fid = (isset($field['settings']['default_image']['fids']) ? $field['settings']['default_image']['fids'] : $field['settings']['default_image']);
if ($fid && ($file = file_load($fid[0]))) {
file_usage()->delete($file, 'image', 'default_image', $field['id']);