Issue #625958 by slashrsm, quicksketch, eojthebrave, droplet, danlinn, czigor: Support Uploading Multiple Files for HTML5 Browsers via #multiple attribute.
parent
8733925ff7
commit
8fd2b4779e
|
|
@ -1020,14 +1020,14 @@ function file_unmanaged_delete_recursive($path, $callback = NULL) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Saves a file upload to a new location.
|
* Saves file uploads to a new location.
|
||||||
*
|
*
|
||||||
* The file will be added to the {file_managed} table as a temporary file.
|
* The files will be added to the {file_managed} table as temporary files.
|
||||||
* Temporary files are periodically cleaned. Use file_usage()->add() to register
|
* Temporary files are periodically cleaned. Use file_usage()->add() to register
|
||||||
* the usage of the file which will automatically mark it as permanent.
|
* the usage of the file which will automatically mark it as permanent.
|
||||||
*
|
*
|
||||||
* @param $source
|
* @param $source
|
||||||
* A string specifying the filepath or URI of the uploaded file to save.
|
* A string specifying the filepath or URI of the uploaded files to save.
|
||||||
* @param $validators
|
* @param $validators
|
||||||
* An optional, associative array of callback functions used to validate the
|
* An optional, associative array of callback functions used to validate the
|
||||||
* file. See file_validate() for a full discussion of the array format.
|
* file. See file_validate() for a full discussion of the array format.
|
||||||
|
|
@ -1041,6 +1041,8 @@ function file_unmanaged_delete_recursive($path, $callback = NULL) {
|
||||||
* A string containing the URI $source should be copied to.
|
* A string containing the URI $source should be copied to.
|
||||||
* This must be a stream wrapper URI. If this value is omitted, Drupal's
|
* This must be a stream wrapper URI. If this value is omitted, Drupal's
|
||||||
* temporary files scheme will be used ("temporary://").
|
* temporary files scheme will be used ("temporary://").
|
||||||
|
* @param $delta
|
||||||
|
* Delta of the file to save or NULL to save all files. Defaults to NULL.
|
||||||
* @param $replace
|
* @param $replace
|
||||||
* Replace behavior when the destination file already exists:
|
* Replace behavior when the destination file already exists:
|
||||||
* - FILE_EXISTS_REPLACE: Replace the existing file.
|
* - FILE_EXISTS_REPLACE: Replace the existing file.
|
||||||
|
|
@ -1049,181 +1051,209 @@ function file_unmanaged_delete_recursive($path, $callback = NULL) {
|
||||||
* - FILE_EXISTS_ERROR: Do nothing and return FALSE.
|
* - FILE_EXISTS_ERROR: Do nothing and return FALSE.
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
* An object containing the file information if the upload succeeded, FALSE
|
* Function returns array of files or a single file object if $delta
|
||||||
* in the event of an error, or NULL if no file was uploaded. The
|
* != NULL. Each file object contains the file information if the
|
||||||
* documentation for the "File interface" group, which you can find under
|
* upload succeeded or FALSE in the event of an error. Function
|
||||||
|
* returns NULL if no file was uploaded.
|
||||||
|
*
|
||||||
|
* The documentation for the "File interface" group, which you can find under
|
||||||
* Related topics, or the header at the top of this file, documents the
|
* Related topics, or the header at the top of this file, documents the
|
||||||
* components of a file entity. In addition to the standard components,
|
* components of a file entity. In addition to the standard components,
|
||||||
* this function adds:
|
* this function adds:
|
||||||
* - source: Path to the file before it is moved.
|
* - source: Path to the file before it is moved.
|
||||||
* - destination: Path to the file after it is moved (same as 'uri').
|
* - destination: Path to the file after it is moved (same as 'uri').
|
||||||
*/
|
*/
|
||||||
function file_save_upload($source, $validators = array(), $destination = FALSE, $replace = FILE_EXISTS_RENAME) {
|
function file_save_upload($source, $validators = array(), $destination = FALSE, $delta = NULL, $replace = FILE_EXISTS_RENAME) {
|
||||||
global $user;
|
global $user;
|
||||||
static $upload_cache;
|
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])) {
|
|
||||||
return $upload_cache[$source];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make sure there's an upload to process.
|
// Make sure there's an upload to process.
|
||||||
if (empty($_FILES['files']['name'][$source])) {
|
if (empty($_FILES['files']['name'][$source])) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for file upload errors and return FALSE if a lower level system
|
// Return cached objects without processing since the file will have
|
||||||
// error occurred. For a complete list of errors:
|
// already been processed and the paths in $_FILES will be invalid.
|
||||||
// See http://php.net/manual/features.file-upload.errors.php.
|
if (isset($upload_cache[$source])) {
|
||||||
switch ($_FILES['files']['error'][$source]) {
|
if (isset($delta)) {
|
||||||
case UPLOAD_ERR_INI_SIZE:
|
return $upload_cache[$source][$delta];
|
||||||
case UPLOAD_ERR_FORM_SIZE:
|
}
|
||||||
drupal_set_message(t('The file %file could not be saved because it exceeds %maxsize, the maximum allowed size for uploads.', array('%file' => $_FILES['files']['name'][$source], '%maxsize' => format_size(file_upload_max_size()))), 'error');
|
return $upload_cache[$source];
|
||||||
return FALSE;
|
}
|
||||||
|
|
||||||
case UPLOAD_ERR_PARTIAL:
|
// Prepare uploaded files info. Representation is slightly different
|
||||||
case UPLOAD_ERR_NO_FILE:
|
// for multiple uploads and we fix that here.
|
||||||
drupal_set_message(t('The file %file could not be saved because the upload did not complete.', array('%file' => $_FILES['files']['name'][$source])), 'error');
|
$uploaded_files = $_FILES;
|
||||||
return FALSE;
|
if (!is_array($uploaded_files['files']['name'][$source])) {
|
||||||
|
foreach (array('name', 'type', 'tmp_name', 'error', 'size') as $value)
|
||||||
|
$uploaded_files['files'][$value][$source] = array($uploaded_files['files'][$value][$source]);
|
||||||
|
}
|
||||||
|
|
||||||
case UPLOAD_ERR_OK:
|
$files = array();
|
||||||
// Final check that this is a valid upload, if it isn't, use the
|
foreach ($uploaded_files['files']['name'][$source] as $i => $name) {
|
||||||
// default error handler.
|
// Check for file upload errors and return FALSE for this file if a lower
|
||||||
if (is_uploaded_file($_FILES['files']['tmp_name'][$source])) {
|
// level system error occurred. For a complete list of errors:
|
||||||
break;
|
// See http://php.net/manual/features.file-upload.errors.php.
|
||||||
|
switch ($uploaded_files['files']['error'][$source][$i]) {
|
||||||
|
case UPLOAD_ERR_INI_SIZE:
|
||||||
|
case UPLOAD_ERR_FORM_SIZE:
|
||||||
|
drupal_set_message(t('The file %file could not be saved because it exceeds %maxsize, the maximum allowed size for uploads.', array('%file' => $name, '%maxsize' => format_size(file_upload_max_size()))), 'error');
|
||||||
|
$files[$i] = FALSE;
|
||||||
|
continue;
|
||||||
|
|
||||||
|
case UPLOAD_ERR_PARTIAL:
|
||||||
|
case UPLOAD_ERR_NO_FILE:
|
||||||
|
drupal_set_message(t('The file %file could not be saved because the upload did not complete.', array('%file' => $name)), 'error');
|
||||||
|
$files[$i] = FALSE;
|
||||||
|
continue;
|
||||||
|
|
||||||
|
case UPLOAD_ERR_OK:
|
||||||
|
// Final check that this is a valid upload, if it isn't, use the
|
||||||
|
// default error handler.
|
||||||
|
if (is_uploaded_file($uploaded_files['files']['tmp_name'][$source][$i])) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unknown error
|
||||||
|
default:
|
||||||
|
drupal_set_message(t('The file %file could not be saved. An unknown error has occurred.', array('%file' => $name)), 'error');
|
||||||
|
$files[$i] = FALSE;
|
||||||
|
continue;
|
||||||
|
|
||||||
|
}
|
||||||
|
// Begin building file entity.
|
||||||
|
$values = array(
|
||||||
|
'uid' => $user->uid,
|
||||||
|
'status' => 0,
|
||||||
|
'filename' => trim(drupal_basename($name, '.')),
|
||||||
|
'uri' => $uploaded_files['files']['tmp_name'][$source][$i],
|
||||||
|
'filesize' => $uploaded_files['files']['size'][$source][$i],
|
||||||
|
);
|
||||||
|
$values['filemime'] = file_get_mimetype($values['filename']);
|
||||||
|
$file = entity_create('file', $values);
|
||||||
|
|
||||||
|
$extensions = '';
|
||||||
|
if (isset($validators['file_validate_extensions'])) {
|
||||||
|
if (isset($validators['file_validate_extensions'][0])) {
|
||||||
|
// Build the list of non-munged extensions if the caller provided them.
|
||||||
|
$extensions = $validators['file_validate_extensions'][0];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// If 'file_validate_extensions' is set and the list is empty then the
|
||||||
|
// caller wants to allow any extension. In this case we have to remove the
|
||||||
|
// validator or else it will reject all extensions.
|
||||||
|
unset($validators['file_validate_extensions']);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unknown error
|
|
||||||
default:
|
|
||||||
drupal_set_message(t('The file %file could not be saved. An unknown error has occurred.', array('%file' => $_FILES['files']['name'][$source])), 'error');
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
// Begin building file entity.
|
|
||||||
$values = array(
|
|
||||||
'uid' => $user->uid,
|
|
||||||
'status' => 0,
|
|
||||||
'filename' => trim(drupal_basename($_FILES['files']['name'][$source]), '.'),
|
|
||||||
'uri' => $_FILES['files']['tmp_name'][$source],
|
|
||||||
'filesize' => $_FILES['files']['size'][$source],
|
|
||||||
);
|
|
||||||
$values['filemime'] = file_get_mimetype($values['filename']);
|
|
||||||
$file = entity_create('file', $values);
|
|
||||||
|
|
||||||
$extensions = '';
|
|
||||||
if (isset($validators['file_validate_extensions'])) {
|
|
||||||
if (isset($validators['file_validate_extensions'][0])) {
|
|
||||||
// Build the list of non-munged extensions if the caller provided them.
|
|
||||||
$extensions = $validators['file_validate_extensions'][0];
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// If 'file_validate_extensions' is set and the list is empty then the
|
// No validator was provided, so add one using the default list.
|
||||||
// caller wants to allow any extension. In this case we have to remove the
|
// Build a default non-munged safe list for file_munge_filename().
|
||||||
// validator or else it will reject all extensions.
|
$extensions = 'jpg jpeg gif png txt doc xls pdf ppt pps odt ods odp';
|
||||||
unset($validators['file_validate_extensions']);
|
$validators['file_validate_extensions'] = array();
|
||||||
|
$validators['file_validate_extensions'][0] = $extensions;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else {
|
|
||||||
// No validator was provided, so add one using the default list.
|
|
||||||
// Build a default non-munged safe list for file_munge_filename().
|
|
||||||
$extensions = 'jpg jpeg gif png txt doc xls pdf ppt pps odt ods odp';
|
|
||||||
$validators['file_validate_extensions'] = array();
|
|
||||||
$validators['file_validate_extensions'][0] = $extensions;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!empty($extensions)) {
|
|
||||||
// Munge the filename to protect against possible malicious extension hiding
|
|
||||||
// within an unknown file type (ie: filename.html.foo).
|
|
||||||
$file->filename = file_munge_filename($file->filename, $extensions);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Rename potentially executable files, to help prevent exploits (i.e. will
|
|
||||||
// rename filename.php.foo and filename.php to filename.php.foo.txt and
|
|
||||||
// filename.php.txt, respectively). Don't rename if 'allow_insecure_uploads'
|
|
||||||
// evaluates to TRUE.
|
|
||||||
if (!config('system.file')->get('allow_insecure_uploads') && preg_match('/\.(php|pl|py|cgi|asp|js)(\.|$)/i', $file->filename) && (substr($file->filename, -4) != '.txt')) {
|
|
||||||
$file->filemime = 'text/plain';
|
|
||||||
$file->uri .= '.txt';
|
|
||||||
$file->filename .= '.txt';
|
|
||||||
// The .txt extension may not be in the allowed list of extensions. We have
|
|
||||||
// to add it here or else the file upload will fail.
|
|
||||||
if (!empty($extensions)) {
|
if (!empty($extensions)) {
|
||||||
$validators['file_validate_extensions'][0] .= ' txt';
|
// Munge the filename to protect against possible malicious extension
|
||||||
drupal_set_message(t('For security reasons, your upload has been renamed to %filename.', array('%filename' => $file->filename)));
|
// hiding within an unknown file type (ie: filename.html.foo).
|
||||||
|
$file->filename = file_munge_filename($file->filename, $extensions);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// If the destination is not provided, use the temporary directory.
|
// Rename potentially executable files, to help prevent exploits (i.e. will
|
||||||
if (empty($destination)) {
|
// rename filename.php.foo and filename.php to filename.php.foo.txt and
|
||||||
$destination = 'temporary://';
|
// filename.php.txt, respectively). Don't rename if 'allow_insecure_uploads'
|
||||||
}
|
// evaluates to TRUE.
|
||||||
|
if (!config('system.file')->get('allow_insecure_uploads') && preg_match('/\.(php|pl|py|cgi|asp|js)(\.|$)/i', $file->filename) && (substr($file->filename, -4) != '.txt')) {
|
||||||
// Assert that the destination contains a valid stream.
|
$file->filemime = 'text/plain';
|
||||||
$destination_scheme = file_uri_scheme($destination);
|
$file->uri .= '.txt';
|
||||||
if (!file_stream_wrapper_valid_scheme($destination_scheme)) {
|
$file->filename .= '.txt';
|
||||||
drupal_set_message(t('The file could not be uploaded because the destination %destination is invalid.', array('%destination' => $destination)), 'error');
|
// The .txt extension may not be in the allowed list of extensions. We have
|
||||||
return FALSE;
|
// to add it here or else the file upload will fail.
|
||||||
}
|
if (!empty($extensions)) {
|
||||||
|
$validators['file_validate_extensions'][0] .= ' txt';
|
||||||
$file->source = $source;
|
drupal_set_message(t('For security reasons, your upload has been renamed to %filename.', array('%filename' => $file->filename)));
|
||||||
// A URI may already have a trailing slash or look like "public://".
|
}
|
||||||
if (substr($destination, -1) != '/') {
|
|
||||||
$destination .= '/';
|
|
||||||
}
|
|
||||||
$file->destination = file_destination($destination . $file->filename, $replace);
|
|
||||||
// If file_destination() returns FALSE then $replace == FILE_EXISTS_ERROR and
|
|
||||||
// there's an existing file so we need to bail.
|
|
||||||
if ($file->destination === FALSE) {
|
|
||||||
drupal_set_message(t('The file %source could not be uploaded because a file by that name already exists in the destination %directory.', array('%source' => $source, '%directory' => $destination)), 'error');
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add in our check of the the file name length.
|
|
||||||
$validators['file_validate_name_length'] = array();
|
|
||||||
|
|
||||||
// Call the validation functions specified by this function's caller.
|
|
||||||
$errors = file_validate($file, $validators);
|
|
||||||
|
|
||||||
// Check for errors.
|
|
||||||
if (!empty($errors)) {
|
|
||||||
$message = t('The specified file %name could not be uploaded.', array('%name' => $file->filename));
|
|
||||||
if (count($errors) > 1) {
|
|
||||||
$message .= theme('item_list', array('items' => $errors));
|
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
$message .= ' ' . array_pop($errors);
|
// If the destination is not provided, use the temporary directory.
|
||||||
|
if (empty($destination)) {
|
||||||
|
$destination = 'temporary://';
|
||||||
}
|
}
|
||||||
form_set_error($source, $message);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Move uploaded files from PHP's upload_tmp_dir to Drupal's temporary
|
// Assert that the destination contains a valid stream.
|
||||||
// directory. This overcomes open_basedir restrictions for future file
|
$destination_scheme = file_uri_scheme($destination);
|
||||||
// operations.
|
if (!file_stream_wrapper_valid_scheme($destination_scheme)) {
|
||||||
$file->uri = $file->destination;
|
drupal_set_message(t('The file could not be uploaded because the destination %destination is invalid.', array('%destination' => $destination)), 'error');
|
||||||
if (!drupal_move_uploaded_file($_FILES['files']['tmp_name'][$source], $file->uri)) {
|
$files[$i] = FALSE;
|
||||||
form_set_error($source, t('File upload error. Could not move uploaded file.'));
|
continue;
|
||||||
watchdog('file', 'Upload error. Could not move uploaded file %file to destination %destination.', array('%file' => $file->filename, '%destination' => $file->uri));
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set the permissions on the new file.
|
|
||||||
drupal_chmod($file->uri);
|
|
||||||
|
|
||||||
// If we are replacing an existing file re-use its database record.
|
|
||||||
if ($replace == FILE_EXISTS_REPLACE) {
|
|
||||||
$existing_files = entity_load_multiple_by_properties('file', array('uri' => $file->uri));
|
|
||||||
if (count($existing_files)) {
|
|
||||||
$existing = reset($existing_files);
|
|
||||||
$file->fid = $existing->fid;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$file->source = $source;
|
||||||
|
// A file URI may already have a trailing slash or look like "public://".
|
||||||
|
if (substr($destination, -1) != '/') {
|
||||||
|
$destination .= '/';
|
||||||
|
}
|
||||||
|
$file->destination = file_destination($destination . $file->filename, $replace);
|
||||||
|
// If file_destination() returns FALSE then $replace === FILE_EXISTS_ERROR and
|
||||||
|
// there's an existing file so we need to bail.
|
||||||
|
if ($file->destination === FALSE) {
|
||||||
|
drupal_set_message(t('The file %source could not be uploaded because a file by that name already exists in the destination %directory.', array('%source' => $source, '%directory' => $destination)), 'error');
|
||||||
|
$files[$i] = FALSE;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add in our check of the the file name length.
|
||||||
|
$validators['file_validate_name_length'] = array();
|
||||||
|
|
||||||
|
// Call the validation functions specified by this function's caller.
|
||||||
|
$errors = file_validate($file, $validators);
|
||||||
|
|
||||||
|
// Check for errors.
|
||||||
|
if (!empty($errors)) {
|
||||||
|
$message = t('The specified file %name could not be uploaded.', array('%name' => $file->filename));
|
||||||
|
if (count($errors) > 1) {
|
||||||
|
$message .= theme('item_list', array('items' => $errors));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$message .= ' ' . array_pop($errors);
|
||||||
|
}
|
||||||
|
form_set_error($source, $message);
|
||||||
|
$files[$i] = FALSE;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move uploaded files from PHP's upload_tmp_dir to Drupal's temporary
|
||||||
|
// directory. This overcomes open_basedir restrictions for future file
|
||||||
|
// operations.
|
||||||
|
$file->uri = $file->destination;
|
||||||
|
if (!drupal_move_uploaded_file($uploaded_files['files']['tmp_name'][$source][$i], $file->uri)) {
|
||||||
|
form_set_error($source, t('File upload error. Could not move uploaded file.'));
|
||||||
|
watchdog('file', 'Upload error. Could not move uploaded file %file to destination %destination.', array('%file' => $file->filename, '%destination' => $file->uri));
|
||||||
|
$files[$i] = FALSE;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the permissions on the new file.
|
||||||
|
drupal_chmod($file->uri);
|
||||||
|
|
||||||
|
// If we are replacing an existing file re-use its database record.
|
||||||
|
if ($replace == FILE_EXISTS_REPLACE) {
|
||||||
|
$existing_files = entity_load_multiple_by_properties('file', array('uri' => $file->uri));
|
||||||
|
if (count($existing_files)) {
|
||||||
|
$existing = reset($existing_files);
|
||||||
|
$file->fid = $existing->fid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we made it this far it's safe to record this file in the database.
|
||||||
|
$file->save();
|
||||||
|
$files[$i] = $file;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we made it this far it's safe to record this file in the database.
|
// Add files to the cache.
|
||||||
$file->save();
|
$upload_cache[$source] = $files;
|
||||||
// Add file to the cache.
|
|
||||||
$upload_cache[$source] = $file;
|
return isset($delta) ? $files[$delta] : $files;
|
||||||
return $file;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -1390,7 +1420,7 @@ function file_scan_directory($dir, $mask, $options = array(), $depth = 0) {
|
||||||
// Avoid warnings when opendir does not have the permissions to open a
|
// Avoid warnings when opendir does not have the permissions to open a
|
||||||
// directory.
|
// directory.
|
||||||
if (is_dir($dir)) {
|
if (is_dir($dir)) {
|
||||||
if($handle = @opendir($dir)) {
|
if ($handle = @opendir($dir)) {
|
||||||
while (FALSE !== ($filename = readdir($handle))) {
|
while (FALSE !== ($filename = readdir($handle))) {
|
||||||
// Skip this file if it matches the nomask or starts with a dot.
|
// Skip this file if it matches the nomask or starts with a dot.
|
||||||
if ($filename[0] != '.' && !preg_match($options['nomask'], $filename)) {
|
if ($filename[0] != '.' && !preg_match($options['nomask'], $filename)) {
|
||||||
|
|
|
||||||
|
|
@ -4608,6 +4608,17 @@ function form_pre_render_file($element) {
|
||||||
return $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.
|
* 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) {
|
function aggregator_form_opml_submit($form, &$form_state) {
|
||||||
$data = '';
|
$data = '';
|
||||||
$validators = array('file_validate_extensions' => array('opml xml'));
|
$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);
|
$data = file_get_contents($file->uri);
|
||||||
}
|
}
|
||||||
else {
|
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.
|
// Ensure that all the required properties are returned even if empty.
|
||||||
$return += array(
|
$return += array(
|
||||||
'fid' => 0,
|
'fids' => array(),
|
||||||
'display' => 1,
|
'display' => 1,
|
||||||
'description' => '',
|
'description' => '',
|
||||||
);
|
);
|
||||||
|
|
@ -397,6 +397,47 @@ function file_field_widget_value($element, $input = FALSE, $form_state) {
|
||||||
return $return;
|
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.
|
* 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) {
|
function file_field_widget_process($element, &$form_state, $form) {
|
||||||
$item = $element['#value'];
|
$item = $element['#value'];
|
||||||
$item['fid'] = $element['fid']['#value'];
|
$item['fids'] = $element['fids']['#value'];
|
||||||
|
|
||||||
$field = field_widget_field($element, $form_state);
|
$field = field_widget_field($element, $form_state);
|
||||||
$instance = field_widget_instance($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';
|
$element['#theme'] = 'file_widget';
|
||||||
|
|
||||||
// Add the display field if enabled.
|
// 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(
|
$element['display'] = array(
|
||||||
'#type' => empty($item['fid']) ? 'hidden' : 'checkbox',
|
'#type' => empty($item['fids']) ? 'hidden' : 'checkbox',
|
||||||
'#title' => t('Include file in display'),
|
'#title' => t('Include file in display'),
|
||||||
'#value' => isset($item['display']) ? $item['display'] : $field['settings']['display_default'],
|
'#value' => isset($item['display']) ? $item['display'] : $field['settings']['display_default'],
|
||||||
'#attributes' => array('class' => array('file-display')),
|
'#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.
|
// 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');
|
$config = config('file.settings');
|
||||||
$element['description'] = array(
|
$element['description'] = array(
|
||||||
'#type' => $config->get('description.type'),
|
'#type' => $config->get('description.type'),
|
||||||
|
|
@ -561,18 +602,34 @@ function file_field_widget_submit($form, &$form_state) {
|
||||||
$langcode = $element['#language'];
|
$langcode = $element['#language'];
|
||||||
$parents = $element['#field_parents'];
|
$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) {
|
foreach ($submitted_values as $delta => $submitted_value) {
|
||||||
if (!$submitted_value['fid']) {
|
if (empty($submitted_value['fids'])) {
|
||||||
unset($submitted_values[$delta]);
|
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.
|
// Re-index deltas after removing empty items.
|
||||||
$submitted_values = array_values($submitted_values);
|
$submitted_values = array_values($new_values);
|
||||||
|
|
||||||
// Update form_state 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.
|
// Update items.
|
||||||
$field_state = field_form_get_state($parents, $field_name, $langcode, $form_state);
|
$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.
|
// The "form-managed-file" class is required for proper Ajax functionality.
|
||||||
$output .= '<div class="file-widget form-managed-file clearfix">';
|
$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.
|
// 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 .= drupal_render_children($element);
|
||||||
$output .= '</div>';
|
$output .= '</div>';
|
||||||
|
|
@ -644,7 +702,7 @@ function theme_file_widget_multiple($variables) {
|
||||||
$rows = array();
|
$rows = array();
|
||||||
foreach ($widgets as $key => &$widget) {
|
foreach ($widgets as $key => &$widget) {
|
||||||
// Save the uploading row for last.
|
// Save the uploading row for last.
|
||||||
if ($widget['#file'] == FALSE) {
|
if (empty($widget['#files'])) {
|
||||||
$widget['#title'] = $element['#file_upload_title'];
|
$widget['#title'] = $element['#file_upload_title'];
|
||||||
$widget['#description'] = $element['#file_upload_description'];
|
$widget['#description'] = $element['#file_upload_description'];
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -726,6 +784,7 @@ function theme_file_widget_multiple($variables) {
|
||||||
function theme_file_upload_help($variables) {
|
function theme_file_upload_help($variables) {
|
||||||
$description = $variables['description'];
|
$description = $variables['description'];
|
||||||
$upload_validators = $variables['upload_validators'];
|
$upload_validators = $variables['upload_validators'];
|
||||||
|
$cardinality = $variables['cardinality'];
|
||||||
|
|
||||||
$descriptions = array();
|
$descriptions = array();
|
||||||
|
|
||||||
|
|
@ -738,6 +797,14 @@ function theme_file_upload_help($variables) {
|
||||||
if (isset($upload_validators['file_validate_extensions'])) {
|
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>'));
|
$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'])) {
|
if (isset($upload_validators['file_validate_image_resolution'])) {
|
||||||
$max = $upload_validators['file_validate_image_resolution'][0];
|
$max = $upload_validators['file_validate_image_resolution'][0];
|
||||||
$min = $upload_validators['file_validate_image_resolution'][1];
|
$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.
|
* Convert the 'id' column in {file_usage} to accept UUIDs.
|
||||||
*/
|
*/
|
||||||
function file_update_8001() {
|
function file_update_8001() {
|
||||||
|
|
@ -259,3 +259,32 @@ function file_update_8001() {
|
||||||
);
|
);
|
||||||
db_change_field('file_usage', 'id', 'id', $spec);
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -81,6 +81,7 @@ function file_element_info() {
|
||||||
'#upload_validators' => array(),
|
'#upload_validators' => array(),
|
||||||
'#upload_location' => NULL,
|
'#upload_location' => NULL,
|
||||||
'#size' => 22,
|
'#size' => 22,
|
||||||
|
'#multiple' => FALSE,
|
||||||
'#extended' => FALSE,
|
'#extended' => FALSE,
|
||||||
'#attached' => array(
|
'#attached' => array(
|
||||||
'library' => array(array('file','drupal.file')),
|
'library' => array(array('file','drupal.file')),
|
||||||
|
|
@ -610,7 +611,7 @@ function file_theme() {
|
||||||
'variables' => array('items' => NULL),
|
'variables' => array('items' => NULL),
|
||||||
),
|
),
|
||||||
'file_upload_help' => array(
|
'file_upload_help' => array(
|
||||||
'variables' => array('description' => NULL, 'upload_validators' => NULL),
|
'variables' => array('description' => NULL, 'upload_validators' => NULL, 'cardinality' => NULL),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -870,11 +871,15 @@ function file_managed_file_process($element, &$form_state, $form) {
|
||||||
// Append the '-upload' to the #id so the field label's 'for' attribute
|
// Append the '-upload' to the #id so the field label's 'for' attribute
|
||||||
// corresponds with the file element.
|
// corresponds with the file element.
|
||||||
$element['#id'] .= '-upload';
|
$element['#id'] .= '-upload';
|
||||||
$fid = isset($element['#value']['fid']) ? $element['#value']['fid'] : 0;
|
|
||||||
|
// This is used sometimes so let's implode it just once.
|
||||||
|
$parents_prefix = implode('_', $element['#parents']);
|
||||||
|
|
||||||
|
$fids = isset($element['#value']['fids']) ? $element['#value']['fids'] : array();
|
||||||
|
|
||||||
// Set some default element properties.
|
// Set some default element properties.
|
||||||
$element['#progress_indicator'] = empty($element['#progress_indicator']) ? 'none' : $element['#progress_indicator'];
|
$element['#progress_indicator'] = empty($element['#progress_indicator']) ? 'none' : $element['#progress_indicator'];
|
||||||
$element['#file'] = $fid ? file_load($fid) : FALSE;
|
$element['#files'] = !empty($fids) ? file_load_multiple($fids) : FALSE;
|
||||||
$element['#tree'] = TRUE;
|
$element['#tree'] = TRUE;
|
||||||
|
|
||||||
$ajax_settings = array(
|
$ajax_settings = array(
|
||||||
|
|
@ -889,7 +894,7 @@ function file_managed_file_process($element, &$form_state, $form) {
|
||||||
|
|
||||||
// Set up the buttons first since we need to check if they were clicked.
|
// Set up the buttons first since we need to check if they were clicked.
|
||||||
$element['upload_button'] = array(
|
$element['upload_button'] = array(
|
||||||
'#name' => implode('_', $element['#parents']) . '_upload_button',
|
'#name' => $parents_prefix . '_upload_button',
|
||||||
'#type' => 'submit',
|
'#type' => 'submit',
|
||||||
'#value' => t('Upload'),
|
'#value' => t('Upload'),
|
||||||
'#validate' => array(),
|
'#validate' => array(),
|
||||||
|
|
@ -905,19 +910,19 @@ function file_managed_file_process($element, &$form_state, $form) {
|
||||||
$ajax_settings['progress']['message'] = NULL;
|
$ajax_settings['progress']['message'] = NULL;
|
||||||
$ajax_settings['effect'] = 'none';
|
$ajax_settings['effect'] = 'none';
|
||||||
$element['remove_button'] = array(
|
$element['remove_button'] = array(
|
||||||
'#name' => implode('_', $element['#parents']) . '_remove_button',
|
'#name' => $parents_prefix . '_remove_button',
|
||||||
'#type' => 'submit',
|
'#type' => 'submit',
|
||||||
'#value' => t('Remove'),
|
'#value' => $element['#multiple'] ? t('Remove selected') : t('Remove'),
|
||||||
'#validate' => array(),
|
'#validate' => array(),
|
||||||
'#submit' => array('file_managed_file_submit'),
|
'#submit' => array('file_managed_file_submit'),
|
||||||
'#limit_validation_errors' => array($element['#parents']),
|
'#limit_validation_errors' => array($element['#parents']),
|
||||||
'#ajax' => $ajax_settings,
|
'#ajax' => $ajax_settings,
|
||||||
'#weight' => -5,
|
'#weight' => 1,
|
||||||
);
|
);
|
||||||
|
|
||||||
$element['fid'] = array(
|
$element['fids'] = array(
|
||||||
'#type' => 'hidden',
|
'#type' => 'hidden',
|
||||||
'#value' => $fid,
|
'#value' => $fids,
|
||||||
);
|
);
|
||||||
|
|
||||||
// Add progress bar support to the upload if possible.
|
// Add progress bar support to the upload if possible.
|
||||||
|
|
@ -951,21 +956,32 @@ function file_managed_file_process($element, &$form_state, $form) {
|
||||||
|
|
||||||
// The file upload field itself.
|
// The file upload field itself.
|
||||||
$element['upload'] = array(
|
$element['upload'] = array(
|
||||||
'#name' => 'files[' . implode('_', $element['#parents']) . ']',
|
'#name' => 'files[' . $parents_prefix . ']',
|
||||||
'#type' => 'file',
|
'#type' => 'file',
|
||||||
'#title' => t('Choose a file'),
|
'#title' => t('Choose a file'),
|
||||||
'#title_display' => 'invisible',
|
'#title_display' => 'invisible',
|
||||||
'#size' => $element['#size'],
|
'#size' => $element['#size'],
|
||||||
|
'#multiple' => $element['#multiple'],
|
||||||
'#theme_wrappers' => array(),
|
'#theme_wrappers' => array(),
|
||||||
'#weight' => -10,
|
'#weight' => -10,
|
||||||
);
|
);
|
||||||
|
|
||||||
if ($fid && $element['#file']) {
|
if (!empty($fids) && $element['#files']) {
|
||||||
$element['filename'] = array(
|
foreach ($element['#files'] as $delta => $file) {
|
||||||
'#type' => 'markup',
|
if ($element['#multiple']) {
|
||||||
'#markup' => theme('file_link', array('file' => $element['#file'])) . ' ',
|
$element['file_' . $delta]['selected'] = array(
|
||||||
'#weight' => -10,
|
'#type' => 'checkbox',
|
||||||
);
|
'#title' => theme('file_link', array('file' => $file)) . ' ',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$element['file_' . $delta]['filename'] = array(
|
||||||
|
'#type' => 'markup',
|
||||||
|
'#markup' => theme('file_link', array('file' => $file)) . ' ',
|
||||||
|
'#weight' => -10,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add the extension list to the page as JavaScript settings.
|
// Add the extension list to the page as JavaScript settings.
|
||||||
|
|
@ -992,28 +1008,25 @@ function file_managed_file_process($element, &$form_state, $form) {
|
||||||
* This function is assigned as a #value_callback in file_element_info().
|
* This function is assigned as a #value_callback in file_element_info().
|
||||||
*/
|
*/
|
||||||
function file_managed_file_value(&$element, $input = FALSE, $form_state = NULL) {
|
function file_managed_file_value(&$element, $input = FALSE, $form_state = NULL) {
|
||||||
$fid = 0;
|
// Find the current value of this field.
|
||||||
|
$fids = !empty($input['fids']) ? explode(' ', $input['fids']) : array();
|
||||||
// Find the current value of this field from the form state.
|
foreach ($fids as $key => $fid) {
|
||||||
$form_state_fid = $form_state['values'];
|
$fids[$key] = (int) $fid;
|
||||||
foreach ($element['#parents'] as $parent) {
|
|
||||||
$form_state_fid = isset($form_state_fid[$parent]) ? $form_state_fid[$parent] : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($element['#extended'] && isset($form_state_fid['fid'])) {
|
|
||||||
$fid = $form_state_fid['fid'];
|
|
||||||
}
|
|
||||||
elseif (is_numeric($form_state_fid)) {
|
|
||||||
$fid = $form_state_fid;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Process any input and save new uploads.
|
// Process any input and save new uploads.
|
||||||
if ($input !== FALSE) {
|
if ($input !== FALSE) {
|
||||||
|
$input['fids'] = $fids;
|
||||||
$return = $input;
|
$return = $input;
|
||||||
|
|
||||||
// Uploads take priority over all other values.
|
// Uploads take priority over all other values.
|
||||||
if ($file = file_managed_file_save_upload($element)) {
|
if ($files = file_managed_file_save_upload($element)) {
|
||||||
$fid = $file->fid;
|
if ($element['#multiple']) {
|
||||||
|
$fids = array_merge($fids, array_keys($files));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$fids = array_keys($files);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Check for #filefield_value_callback values.
|
// Check for #filefield_value_callback values.
|
||||||
|
|
@ -1025,9 +1038,15 @@ function file_managed_file_value(&$element, $input = FALSE, $form_state = NULL)
|
||||||
$callback($element, $input, $form_state);
|
$callback($element, $input, $form_state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Load file if the FID has changed to confirm it exists.
|
|
||||||
if (isset($input['fid']) && $file = file_load($input['fid'])) {
|
// Load files if the FIDs have changed to confirm they exist.
|
||||||
$fid = $file->fid;
|
if (!empty($input['fids'])) {
|
||||||
|
$fids = array();
|
||||||
|
foreach ($input['fids'] as $key => $fid) {
|
||||||
|
if ($file = file_load($fid)) {
|
||||||
|
$fids[] = $file->fid;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1035,22 +1054,26 @@ function file_managed_file_value(&$element, $input = FALSE, $form_state = NULL)
|
||||||
// If there is no input, set the default value.
|
// If there is no input, set the default value.
|
||||||
else {
|
else {
|
||||||
if ($element['#extended']) {
|
if ($element['#extended']) {
|
||||||
$default_fid = isset($element['#default_value']['fid']) ? $element['#default_value']['fid'] : 0;
|
$default_fids = isset($element['#default_value']['fids']) ? $element['#default_value']['fids'] : array();
|
||||||
$return = isset($element['#default_value']) ? $element['#default_value'] : array('fid' => 0);
|
$return = isset($element['#default_value']) ? $element['#default_value'] : array('fids' => array());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$default_fid = isset($element['#default_value']) ? $element['#default_value'] : 0;
|
$default_fids = isset($element['#default_value']) ? $element['#default_value'] : array();
|
||||||
$return = array('fid' => 0);
|
$return = array('fids' => array());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Confirm that the file exists when used as a default value.
|
// Confirm that the file exists when used as a default value.
|
||||||
if ($default_fid && $file = file_load($default_fid)) {
|
if (!empty($default_fids)) {
|
||||||
$fid = $file->fid;
|
$fids = array();
|
||||||
|
foreach ($default_fids as $key => $fid) {
|
||||||
|
if ($file = file_load($fid)) {
|
||||||
|
$fids[] = $file->fid;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$return['fid'] = $fid;
|
$return['fids'] = $fids;
|
||||||
|
|
||||||
return $return;
|
return $return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1065,28 +1088,31 @@ function file_managed_file_validate(&$element, &$form_state) {
|
||||||
// references. This prevents unmanaged files from being deleted if this
|
// references. This prevents unmanaged files from being deleted if this
|
||||||
// item were to be deleted.
|
// item were to be deleted.
|
||||||
$clicked_button = end($form_state['triggering_element']['#parents']);
|
$clicked_button = end($form_state['triggering_element']['#parents']);
|
||||||
if ($clicked_button != 'remove_button' && !empty($element['fid']['#value'])) {
|
if ($clicked_button != 'remove_button' && !empty($element['fids']['#value'])) {
|
||||||
if ($file = file_load($element['fid']['#value'])) {
|
$fids = $element['fids']['#value'];
|
||||||
if ($file->status == FILE_STATUS_PERMANENT) {
|
foreach ($fids as $fid) {
|
||||||
$references = file_usage()->listUsage($file);
|
if ($file = file_load($fid)) {
|
||||||
if (empty($references)) {
|
if ($file->status == FILE_STATUS_PERMANENT) {
|
||||||
form_error($element, t('The file used in the !name field may not be referenced.', array('!name' => $element['#title'])));
|
$references = file_usage()->listUsage($file);
|
||||||
|
if (empty($references)) {
|
||||||
|
form_error($element, t('The file used in the !name field may not be referenced.', array('!name' => $element['#title'])));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
else {
|
||||||
else {
|
form_error($element, t('The file referenced by the !name field does not exist.', array('!name' => $element['#title'])));
|
||||||
form_error($element, t('The file referenced by the !name field does not exist.', array('!name' => $element['#title'])));
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check required property based on the FID.
|
// Check required property based on the FID.
|
||||||
if ($element['#required'] && empty($element['fid']['#value']) && !in_array($clicked_button, array('upload_button', 'remove_button'))) {
|
if ($element['#required'] && empty($element['fids']['#value']) && !in_array($clicked_button, array('upload_button', 'remove_button'))) {
|
||||||
form_error($element['upload'], t('!name field is required.', array('!name' => $element['#title'])));
|
form_error($element['upload'], t('!name field is required.', array('!name' => $element['#title'])));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Consolidate the array value of this field to a single FID.
|
// Consolidate the array value of this field to array of FIDs.
|
||||||
if (!$element['#extended']) {
|
if (!$element['#extended']) {
|
||||||
form_set_value($element, $element['fid']['#value'], $form_state);
|
form_set_value($element, $element['fids']['#value'], $form_state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1107,11 +1133,28 @@ function file_managed_file_submit($form, &$form_state) {
|
||||||
// button was clicked. Action is needed here for the remove button, because we
|
// button was clicked. Action is needed here for the remove button, because we
|
||||||
// only remove a file in response to its remove button being clicked.
|
// only remove a file in response to its remove button being clicked.
|
||||||
if ($button_key == 'remove_button') {
|
if ($button_key == 'remove_button') {
|
||||||
// If it's a temporary file we can safely remove it immediately, otherwise
|
$fids = array_keys($element['#files']);
|
||||||
// it's up to the implementing module to remove usages of files to have them
|
// Get files that will be removed.
|
||||||
// removed.
|
if ($element['#multiple']) {
|
||||||
if ($element['#file'] && $element['#file']->status == 0) {
|
$remove_fids = array();
|
||||||
file_delete($element['#file']->fid);
|
foreach (element_children($element) as $name) {
|
||||||
|
if (strpos($name, 'file_') === 0 && $element[$name]['selected']['#value']) {
|
||||||
|
$remove_fids[] = (int) substr($name, 5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$fids = array_diff($fids, $remove_fids);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$remove_fids = $fids;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($remove_fids as $fid) {
|
||||||
|
// If it's a temporary file we can safely remove it immediately, otherwise
|
||||||
|
// it's up to the implementing module to remove usages of files to have them
|
||||||
|
// removed.
|
||||||
|
if ($element['#files'][$fid] && $element['#files'][$fid]->status == 0) {
|
||||||
|
file_delete($element['#files'][$fid]->fid);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Update both $form_state['values'] and $form_state['input'] to reflect
|
// Update both $form_state['values'] and $form_state['input'] to reflect
|
||||||
// that the file has been removed, so that the form is rebuilt correctly.
|
// that the file has been removed, so that the form is rebuilt correctly.
|
||||||
|
|
@ -1120,9 +1163,8 @@ function file_managed_file_submit($form, &$form_state) {
|
||||||
// when the managed_file element is part of a field widget.
|
// when the managed_file element is part of a field widget.
|
||||||
// $form_state['input'] must be updated so that file_managed_file_value()
|
// $form_state['input'] must be updated so that file_managed_file_value()
|
||||||
// has correct information during the rebuild.
|
// has correct information during the rebuild.
|
||||||
$values_element = $element['#extended'] ? $element['fid'] : $element;
|
form_set_value($element['fids'], implode(' ', $fids), $form_state);
|
||||||
form_set_value($values_element, NULL, $form_state);
|
NestedArray::setValue($form_state['input'], $element['fids']['#parents'], implode(' ', $fids));
|
||||||
NestedArray::setValue($form_state['input'], $values_element['#parents'], NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the form to rebuild so that $form is correctly updated in response to
|
// Set the form to rebuild so that $form is correctly updated in response to
|
||||||
|
|
@ -1141,8 +1183,8 @@ function file_managed_file_submit($form, &$form_state) {
|
||||||
* The FAPI element whose values are being saved.
|
* The FAPI element whose values are being saved.
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
* The file entity representing the file that was saved, or FALSE if no file
|
* An array of file entities for each file that was saved, keyed by its file
|
||||||
* was saved.
|
* ID, or FALSE if no files were saved.
|
||||||
*/
|
*/
|
||||||
function file_managed_file_save_upload($element) {
|
function file_managed_file_save_upload($element) {
|
||||||
$upload_name = implode('_', $element['#parents']);
|
$upload_name = implode('_', $element['#parents']);
|
||||||
|
|
@ -1157,13 +1199,24 @@ function file_managed_file_save_upload($element) {
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$file = file_save_upload($upload_name, $element['#upload_validators'], $destination)) {
|
// Save attached files to the database.
|
||||||
watchdog('file', 'The file upload failed. %upload', array('%upload' => $upload_name));
|
$files_uploaded = $element['#multiple'] && count(array_filter($_FILES['files']['name'][$upload_name])) > 0;
|
||||||
form_set_error($upload_name, t('The file in the !name field was unable to be uploaded.', array('!name' => $element['#title'])));
|
$files_uploaded |= !$element['#multiple'] && !empty($_FILES['files']['name'][$upload_name]);
|
||||||
return FALSE;
|
if ($files_uploaded) {
|
||||||
|
if (!$files = file_save_upload($upload_name, $element['#upload_validators'], $destination)) {
|
||||||
|
watchdog('file', 'The file upload failed. %upload', array('%upload' => $upload_name));
|
||||||
|
form_set_error($upload_name, t('Files in the !name field were unable to be uploaded.', array('!name' => $element['#title'])));
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Value callback expects FIDs to be keys.
|
||||||
|
$files = array_filter($files);
|
||||||
|
$fids = array_map(function($file) { return $file->fid; }, $files);
|
||||||
|
|
||||||
|
return empty($files) ? array() : array_combine($fids, $files);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $file;
|
return array();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -1218,9 +1271,11 @@ function theme_file_managed_file($variables) {
|
||||||
*/
|
*/
|
||||||
function file_managed_file_pre_render($element) {
|
function file_managed_file_pre_render($element) {
|
||||||
// If we already have a file, we don't want to show the upload controls.
|
// If we already have a file, we don't want to show the upload controls.
|
||||||
if (!empty($element['#value']['fid'])) {
|
if (!empty($element['#value']['fids'])) {
|
||||||
$element['upload']['#access'] = FALSE;
|
if (!$element['#multiple']) {
|
||||||
$element['upload_button']['#access'] = FALSE;
|
$element['upload']['#access'] = FALSE;
|
||||||
|
$element['upload_button']['#access'] = FALSE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// If we don't already have a file, there is nothing to remove.
|
// If we don't already have a file, there is nothing to remove.
|
||||||
else {
|
else {
|
||||||
|
|
|
||||||
|
|
@ -156,7 +156,7 @@ class FileWidget extends WidgetBase {
|
||||||
// field. These are added here so that they may be referenced easily
|
// field. These are added here so that they may be referenced easily
|
||||||
// through a hook_form_alter().
|
// through a hook_form_alter().
|
||||||
$elements['#file_upload_title'] = t('Add a new file');
|
$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;
|
return $elements;
|
||||||
|
|
@ -167,7 +167,7 @@ class FileWidget extends WidgetBase {
|
||||||
*/
|
*/
|
||||||
public function formElement(array $items, $delta, array $element, $langcode, array &$form, array &$form_state) {
|
public function formElement(array $items, $delta, array $element, $langcode, array &$form, array &$form_state) {
|
||||||
$defaults = array(
|
$defaults = array(
|
||||||
'fid' => 0,
|
'fids' => array(),
|
||||||
'display' => !empty($this->field['settings']['display_default']),
|
'display' => !empty($this->field['settings']['display_default']),
|
||||||
'description' => '',
|
'description' => '',
|
||||||
);
|
);
|
||||||
|
|
@ -187,13 +187,45 @@ class FileWidget extends WidgetBase {
|
||||||
);
|
);
|
||||||
|
|
||||||
$element['#weight'] = $delta;
|
$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;
|
$element['#default_value'] = !empty($items[$delta]) ? $items[$delta] : $defaults;
|
||||||
|
|
||||||
if (empty($element['#default_value']['fid'])) {
|
$default_fids = $element['#extended'] ? $element['#default_value']['fids'] : $element['#default_value'];
|
||||||
$element['#description'] = theme('file_upload_help', array('description' => $element['#description'], 'upload_validators' => $element['#upload_validators']));
|
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;
|
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 @@ abstract class FileFieldTestBase extends WebTestBase {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Attach a file to the node.
|
// 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'));
|
$this->drupalPost("node/$nid/edit", $edit, t('Save and keep published'));
|
||||||
|
|
||||||
return $nid;
|
return $nid;
|
||||||
|
|
|
||||||
|
|
@ -111,7 +111,7 @@ class FileFieldWidgetTest extends FileFieldTestBase {
|
||||||
$this->drupalGet("node/add/$type_name");
|
$this->drupalGet("node/add/$type_name");
|
||||||
foreach (array($field_name2, $field_name) as $each_field_name) {
|
foreach (array($field_name2, $field_name) as $each_field_name) {
|
||||||
for ($delta = 0; $delta < 3; $delta++) {
|
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
|
// If the Upload button doesn't exist, drupalPost() will automatically
|
||||||
// fail with an assertion message.
|
// fail with an assertion message.
|
||||||
$this->drupalPost(NULL, $edit, t('Upload'));
|
$this->drupalPost(NULL, $edit, t('Upload'));
|
||||||
|
|
|
||||||
|
|
@ -30,73 +30,123 @@ class FileManagedFileElementTest extends FileFieldTestBase {
|
||||||
$this->drupalGet('file/test');
|
$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.');
|
$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
|
// Perform the tests with all permutations of $form['#tree'],
|
||||||
// $element['#extended'].
|
// $element['#extended'], and $element['#multiple'].
|
||||||
|
$test_file = $this->getTestFile('text');
|
||||||
foreach (array(0, 1) as $tree) {
|
foreach (array(0, 1) as $tree) {
|
||||||
foreach (array(0, 1) as $extended) {
|
foreach (array(0, 1) as $extended) {
|
||||||
$test_file = $this->getTestFile('text');
|
foreach (array(0, 1) as $multiple) {
|
||||||
$path = 'file/test/' . $tree . '/' . $extended;
|
$path = 'file/test/' . $tree . '/' . $extended . '/' . $multiple;
|
||||||
$input_base_name = $tree ? 'nested_file' : 'file';
|
$input_base_name = $tree ? 'nested_file' : 'file';
|
||||||
|
$file_field_name = $multiple ? 'files[' . $input_base_name . '][]' : 'files[' . $input_base_name . ']';
|
||||||
|
|
||||||
// Submit without a file.
|
// Submit without a file.
|
||||||
$this->drupalPost($path, array(), t('Save'));
|
$this->drupalPost($path, array(), t('Save'));
|
||||||
$this->assertRaw(t('The file id is %fid.', array('%fid' => 0)), t('Submitted without a file.'));
|
$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.
|
// 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.
|
|
||||||
$last_fid_prior = $this->getLastFileId();
|
$last_fid_prior = $this->getLastFileId();
|
||||||
$this->drupalGet($path);
|
$edit = array($file_field_name => drupal_realpath($test_file->uri));
|
||||||
$edit = array('files[' . $input_base_name . ']' => drupal_realpath($test_file->uri));
|
$this->drupalPost($path, $edit, t('Save'));
|
||||||
if ($ajax) {
|
|
||||||
$this->drupalPostAJAX(NULL, $edit, $input_base_name . '_upload_button');
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$this->drupalPost(NULL, $edit, t('Upload'));
|
|
||||||
}
|
|
||||||
$last_fid = $this->getLastFileId();
|
$last_fid = $this->getLastFileId();
|
||||||
$this->assertTrue($last_fid > $last_fid_prior, t('New file got uploaded.'));
|
$this->assertTrue($last_fid > $last_fid_prior, t('New file got saved.'));
|
||||||
$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.'));
|
||||||
$this->assertRaw(t('The file id is %fid.', array('%fid' => $last_fid)), t('Submit handler has correct file info.'));
|
|
||||||
|
|
||||||
// Remove, then Submit.
|
// Submit no new input, but with a default file.
|
||||||
$this->drupalGet($path . '/' . $last_fid);
|
$this->drupalPost($path . '/' . $last_fid, array(), t('Save'));
|
||||||
if ($ajax) {
|
$this->assertRaw(t('The file ids are %fids.', array('%fids' => implode(',', array($last_fid)))), t('Empty submission did not change an existing file.'));
|
||||||
$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.
|
// Now, test the Upload and Remove buttons, with and without Ajax.
|
||||||
$this->drupalGet($path);
|
foreach (array(FALSE, TRUE) as $ajax) {
|
||||||
$edit = array('files[' . $input_base_name . ']' => drupal_realpath($test_file->uri));
|
// Upload, then Submit.
|
||||||
if ($ajax) {
|
$last_fid_prior = $this->getLastFileId();
|
||||||
$this->drupalPostAJAX(NULL, $edit, $input_base_name . '_upload_button');
|
$this->drupalGet($path);
|
||||||
$this->drupalPostAJAX(NULL, array(), $input_base_name . '_remove_button');
|
$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.'));
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
$this->drupalPost(NULL, $edit, t('Upload'));
|
|
||||||
$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 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()
|
* @see file_module_test_form_submit()
|
||||||
* @ingroup forms
|
* @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['#tree'] = (bool) $tree;
|
||||||
|
|
||||||
$form['nested']['file'] = array(
|
$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...'),
|
'#progress_message' => t('Please wait...'),
|
||||||
'#extended' => (bool) $extended,
|
'#extended' => (bool) $extended,
|
||||||
'#size' => 13,
|
'#size' => 13,
|
||||||
|
'#multiple' => (bool) $multiple,
|
||||||
);
|
);
|
||||||
if ($default_fid) {
|
if ($default_fids) {
|
||||||
$form['nested']['file']['#default_value'] = $extended ? array('fid' => $default_fid) : $default_fid;
|
$default_fids = explode(',', $default_fids);
|
||||||
|
$form['nested']['file']['#default_value'] = $extended ? array('fids' => $default_fids) : $default_fids;
|
||||||
}
|
}
|
||||||
|
|
||||||
$form['textfield'] = array(
|
$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) {
|
function file_module_test_form_submit($form, &$form_state) {
|
||||||
if ($form['#tree']) {
|
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 {
|
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']);
|
$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) {
|
if ($file) {
|
||||||
$form_state['values']['file_test_upload'] = $file;
|
$form_state['values']['file_test_upload'] = $file;
|
||||||
drupal_set_message(t('File @filepath was uploaded.', array('@filepath' => $file->uri)));
|
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.'),
|
'description' => t('This field stores the ID of an image file as an integer value.'),
|
||||||
'settings' => array(
|
'settings' => array(
|
||||||
'uri_scheme' => file_default_scheme(),
|
'uri_scheme' => file_default_scheme(),
|
||||||
'default_image' => 0,
|
'default_image' => array(),
|
||||||
'column_groups' => array(
|
'column_groups' => array(
|
||||||
'file' => array(
|
'file' => array(
|
||||||
'label' => t('File'),
|
'label' => t('File'),
|
||||||
|
|
@ -44,7 +44,7 @@ function image_field_info() {
|
||||||
'title_field_required' => 0,
|
'title_field_required' => 0,
|
||||||
'max_resolution' => '',
|
'max_resolution' => '',
|
||||||
'min_resolution' => '',
|
'min_resolution' => '',
|
||||||
'default_image' => 0,
|
'default_image' => array(),
|
||||||
),
|
),
|
||||||
'default_widget' => 'image_image',
|
'default_widget' => 'image_image',
|
||||||
'default_formatter' => '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.
|
// If there are no files specified at all, use the default.
|
||||||
foreach ($entities as $id => $entity) {
|
foreach ($entities as $id => $entity) {
|
||||||
if (empty($items[$id])) {
|
if (empty($items[$id])) {
|
||||||
$fid = 0;
|
$fid = array();
|
||||||
// Use the default for the instance if one is available.
|
// Use the default for the instance if one is available.
|
||||||
if (!empty($instances[$id]['settings']['default_image'])) {
|
if (!empty($instances[$id]['settings']['default_image'])) {
|
||||||
$fid = $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.
|
// 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(
|
$items[$id][0] = (array) $file + array(
|
||||||
'is_default' => TRUE,
|
'is_default' => TRUE,
|
||||||
'alt' => '',
|
'alt' => '',
|
||||||
|
|
@ -313,16 +313,17 @@ function image_field_is_empty($item, $field) {
|
||||||
*/
|
*/
|
||||||
function image_field_widget_process($element, &$form_state, $form) {
|
function image_field_widget_process($element, &$form_state, $form) {
|
||||||
$item = $element['#value'];
|
$item = $element['#value'];
|
||||||
$item['fid'] = $element['fid']['#value'];
|
$item['fids'] = $element['fids']['#value'];
|
||||||
|
|
||||||
$element['#theme'] = 'image_widget';
|
$element['#theme'] = 'image_widget';
|
||||||
$element['#attached']['css'][] = drupal_get_path('module', 'image') . '/image.theme.css';
|
$element['#attached']['css'][] = drupal_get_path('module', 'image') . '/image.theme.css';
|
||||||
|
|
||||||
// Add the image preview.
|
// 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(
|
$variables = array(
|
||||||
'style_name' => $element['#preview_image_style'],
|
'style_name' => $element['#preview_image_style'],
|
||||||
'uri' => $element['#file']->uri,
|
'uri' => $file->uri,
|
||||||
);
|
);
|
||||||
|
|
||||||
// Determine image dimensions.
|
// Determine image dimensions.
|
||||||
|
|
@ -331,7 +332,7 @@ function image_field_widget_process($element, &$form_state, $form) {
|
||||||
$variables['height'] = $element['#value']['height'];
|
$variables['height'] = $element['#value']['height'];
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$info = image_get_info($element['#file']->uri);
|
$info = image_get_info($file->uri);
|
||||||
|
|
||||||
if (is_array($info)) {
|
if (is_array($info)) {
|
||||||
$variables['width'] = $info['width'];
|
$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
|
// @see http://www.gawds.org/show.php?contentid=28
|
||||||
'#maxlength' => 512,
|
'#maxlength' => 512,
|
||||||
'#weight' => -2,
|
'#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_validate' => $settings['alt_field_required'] == 1 ? array('_image_field_required_fields_validate') : array(),
|
||||||
);
|
);
|
||||||
$element['title'] = 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.'),
|
'#description' => t('The title is used as a tool tip when the user hovers the mouse over the image.'),
|
||||||
'#maxlength' => 1024,
|
'#maxlength' => 1024,
|
||||||
'#weight' => -1,
|
'#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(),
|
'#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">';
|
$output .= '<div class="image-widget-data">';
|
||||||
if ($element['fid']['#value'] != 0) {
|
if (!empty($element['fids']['#value'])) {
|
||||||
$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 .= drupal_render_children($element);
|
||||||
$output .= '</div>';
|
$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.
|
// 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']);
|
$fid = (isset($field['settings']['default_image']['fids']) ? $field['settings']['default_image']['fids'] : $field['settings']['default_image']);
|
||||||
if ($fid && ($file = file_load($fid))) {
|
if ($fid && ($file = file_load($fid[0]))) {
|
||||||
file_usage()->delete($file, 'image', 'default_image', $field['id']);
|
file_usage()->delete($file, 'image', 'default_image', $field['id']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -364,10 +364,10 @@ function image_field_update_field($field, $prior_field, $has_data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// The value of a managed_file element can be an array if #extended == TRUE.
|
// The value of a managed_file element can be an array if #extended == TRUE.
|
||||||
$fid_new = (is_array($field['settings']['default_image']) ? $field['settings']['default_image']['fid'] : $field['settings']['default_image']);
|
$fid_new = (isset($field['settings']['default_image']['fids']) ? $field['settings']['default_image']['fids'] : $field['settings']['default_image']);
|
||||||
$fid_old = (is_array($prior_field['settings']['default_image']) ? $prior_field['settings']['default_image']['fid'] : $prior_field['settings']['default_image']);
|
$fid_old = (isset($prior_field['settings']['default_image']['fids']) ? $prior_field['settings']['default_image']['fids'] : $prior_field['settings']['default_image']);
|
||||||
|
|
||||||
$file_new = $fid_new ? file_load($fid_new) : FALSE;
|
$file_new = $fid_new ? file_load($fid_new[0]) : FALSE;
|
||||||
|
|
||||||
if ($fid_new != $fid_old) {
|
if ($fid_new != $fid_old) {
|
||||||
|
|
||||||
|
|
@ -379,7 +379,7 @@ function image_field_update_field($field, $prior_field, $has_data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Is there an old file?
|
// Is there an old file?
|
||||||
if ($fid_old && ($file_old = file_load($fid_old))) {
|
if ($fid_old && ($file_old = file_load($fid_old[0]))) {
|
||||||
file_usage()->delete($file_old, 'image', 'default_image', $field['uuid']);
|
file_usage()->delete($file_old, 'image', 'default_image', $field['uuid']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -428,16 +428,16 @@ function image_field_update_instance($instance, $prior_instance) {
|
||||||
// The value of a managed_file element can be an array if the #extended
|
// The value of a managed_file element can be an array if the #extended
|
||||||
// property is set to TRUE.
|
// property is set to TRUE.
|
||||||
$fid_new = $instance['settings']['default_image'];
|
$fid_new = $instance['settings']['default_image'];
|
||||||
if (is_array($fid_new)) {
|
if (isset($fid_new['fids'])) {
|
||||||
$fid_new = $fid_new['fid'];
|
$fid_new = $fid_new['fids'];
|
||||||
}
|
}
|
||||||
$fid_old = $prior_instance['settings']['default_image'];
|
$fid_old = $prior_instance['settings']['default_image'];
|
||||||
if (is_array($fid_old)) {
|
if (isset($fid_old['fids'])) {
|
||||||
$fid_old = $fid_old['fid'];
|
$fid_old = $fid_old['fids'];
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the old and new files do not match, update the default accordingly.
|
// If the old and new files do not match, update the default accordingly.
|
||||||
$file_new = $fid_new ? file_load($fid_new) : FALSE;
|
$file_new = $fid_new ? file_load($fid_new[0]) : FALSE;
|
||||||
if ($fid_new != $fid_old) {
|
if ($fid_new != $fid_old) {
|
||||||
// Save the new file, if present.
|
// Save the new file, if present.
|
||||||
if ($file_new) {
|
if ($file_new) {
|
||||||
|
|
@ -446,7 +446,7 @@ function image_field_update_instance($instance, $prior_instance) {
|
||||||
file_usage()->add($file_new, 'image', 'default_image', $instance['uuid']);
|
file_usage()->add($file_new, 'image', 'default_image', $instance['uuid']);
|
||||||
}
|
}
|
||||||
// Delete the old file, if present.
|
// Delete the old file, if present.
|
||||||
if ($fid_old && ($file_old = file_load($fid_old))) {
|
if ($fid_old && ($file_old = file_load($fid_old[0]))) {
|
||||||
file_usage()->delete($file_old, 'image', 'default_image', $instance['uuid']);
|
file_usage()->delete($file_old, 'image', 'default_image', $instance['uuid']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1029,4 +1029,3 @@ function image_filter_keyword($value, $current_pixels, $new_pixels) {
|
||||||
function _image_effect_definitions_sort($a, $b) {
|
function _image_effect_definitions_sort($a, $b) {
|
||||||
return strcasecmp($a['name'], $b['name']);
|
return strcasecmp($a['name'], $b['name']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -61,12 +61,12 @@ class ImageWidget extends FileWidget {
|
||||||
|
|
||||||
if ($this->field['cardinality'] == 1) {
|
if ($this->field['cardinality'] == 1) {
|
||||||
// If there's only one field, return it as delta 0.
|
// If there's only one field, return it as delta 0.
|
||||||
if (empty($elements[0]['#default_value']['fid'])) {
|
if (empty($elements[0]['#default_value']['fids'])) {
|
||||||
$elements[0]['#description'] = theme('file_upload_help', array('description' => $this->instance['description'], 'upload_validators' => $elements[0]['#upload_validators']));
|
$elements[0]['#description'] = theme('file_upload_help', array('description' => $this->instance['description'], 'upload_validators' => $elements[0]['#upload_validators'], 'cardinality' => $this->field['cardinality']));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$elements['#file_upload_description'] = theme('file_upload_help', array('upload_validators' => $elements[0]['#upload_validators']));
|
$elements['#file_upload_description'] = theme('file_upload_help', array('upload_validators' => $elements[0]['#upload_validators'], 'cardinality' => $this->field['cardinality']));
|
||||||
}
|
}
|
||||||
|
|
||||||
return $elements;
|
return $elements;
|
||||||
|
|
|
||||||
|
|
@ -43,10 +43,10 @@ class ImageFieldDefaultImagesTest extends ImageFieldTestBase {
|
||||||
// Create an image field and add an instance to the article content type.
|
// Create an image field and add an instance to the article content type.
|
||||||
$field_name = strtolower($this->randomName());
|
$field_name = strtolower($this->randomName());
|
||||||
$field_settings = array(
|
$field_settings = array(
|
||||||
'default_image' => $default_images['field']->fid,
|
'default_image' => array($default_images['field']->fid),
|
||||||
);
|
);
|
||||||
$instance_settings = array(
|
$instance_settings = array(
|
||||||
'default_image' => $default_images['instance']->fid,
|
'default_image' => array($default_images['instance']->fid),
|
||||||
);
|
);
|
||||||
$widget_settings = array(
|
$widget_settings = array(
|
||||||
'preview_image_style' => 'medium',
|
'preview_image_style' => 'medium',
|
||||||
|
|
@ -63,7 +63,7 @@ class ImageFieldDefaultImagesTest extends ImageFieldTestBase {
|
||||||
'label' => $instance['label'],
|
'label' => $instance['label'],
|
||||||
'required' => $instance['required'],
|
'required' => $instance['required'],
|
||||||
'settings' => array(
|
'settings' => array(
|
||||||
'default_image' => $default_images['instance2']->fid,
|
'default_image' => array($default_images['instance2']->fid),
|
||||||
),
|
),
|
||||||
'widget' => $instance['widget'],
|
'widget' => $instance['widget'],
|
||||||
);
|
);
|
||||||
|
|
@ -76,7 +76,7 @@ class ImageFieldDefaultImagesTest extends ImageFieldTestBase {
|
||||||
// Confirm the defaults are present on the article field settings form.
|
// Confirm the defaults are present on the article field settings form.
|
||||||
$this->drupalGet("admin/structure/types/manage/article/fields/$field_name/field-settings");
|
$this->drupalGet("admin/structure/types/manage/article/fields/$field_name/field-settings");
|
||||||
$this->assertFieldByXpath(
|
$this->assertFieldByXpath(
|
||||||
'//input[@name="field[settings][default_image][fid]"]',
|
'//input[@name="field[settings][default_image][fids]"]',
|
||||||
$default_images['field']->fid,
|
$default_images['field']->fid,
|
||||||
format_string(
|
format_string(
|
||||||
'Article image field default equals expected file ID of @fid.',
|
'Article image field default equals expected file ID of @fid.',
|
||||||
|
|
@ -86,7 +86,7 @@ class ImageFieldDefaultImagesTest extends ImageFieldTestBase {
|
||||||
// Confirm the defaults are present on the article field edit form.
|
// Confirm the defaults are present on the article field edit form.
|
||||||
$this->drupalGet("admin/structure/types/manage/article/fields/$field_name");
|
$this->drupalGet("admin/structure/types/manage/article/fields/$field_name");
|
||||||
$this->assertFieldByXpath(
|
$this->assertFieldByXpath(
|
||||||
'//input[@name="instance[settings][default_image][fid]"]',
|
'//input[@name="instance[settings][default_image][fids]"]',
|
||||||
$default_images['instance']->fid,
|
$default_images['instance']->fid,
|
||||||
format_string(
|
format_string(
|
||||||
'Article image field instance default equals expected file ID of @fid.',
|
'Article image field instance default equals expected file ID of @fid.',
|
||||||
|
|
@ -97,7 +97,7 @@ class ImageFieldDefaultImagesTest extends ImageFieldTestBase {
|
||||||
// Confirm the defaults are present on the page field settings form.
|
// Confirm the defaults are present on the page field settings form.
|
||||||
$this->drupalGet("admin/structure/types/manage/page/fields/$field_name/field-settings");
|
$this->drupalGet("admin/structure/types/manage/page/fields/$field_name/field-settings");
|
||||||
$this->assertFieldByXpath(
|
$this->assertFieldByXpath(
|
||||||
'//input[@name="field[settings][default_image][fid]"]',
|
'//input[@name="field[settings][default_image][fids]"]',
|
||||||
$default_images['field']->fid,
|
$default_images['field']->fid,
|
||||||
format_string(
|
format_string(
|
||||||
'Page image field default equals expected file ID of @fid.',
|
'Page image field default equals expected file ID of @fid.',
|
||||||
|
|
@ -107,7 +107,7 @@ class ImageFieldDefaultImagesTest extends ImageFieldTestBase {
|
||||||
// Confirm the defaults are present on the page field edit form.
|
// Confirm the defaults are present on the page field edit form.
|
||||||
$this->drupalGet("admin/structure/types/manage/page/fields/$field_name");
|
$this->drupalGet("admin/structure/types/manage/page/fields/$field_name");
|
||||||
$this->assertFieldByXpath(
|
$this->assertFieldByXpath(
|
||||||
'//input[@name="instance[settings][default_image][fid]"]',
|
'//input[@name="instance[settings][default_image][fids]"]',
|
||||||
$default_images['instance2']->fid,
|
$default_images['instance2']->fid,
|
||||||
format_string(
|
format_string(
|
||||||
'Page image field instance default equals expected file ID of @fid.',
|
'Page image field instance default equals expected file ID of @fid.',
|
||||||
|
|
@ -140,13 +140,13 @@ class ImageFieldDefaultImagesTest extends ImageFieldTestBase {
|
||||||
);
|
);
|
||||||
|
|
||||||
// Upload a new default for the field.
|
// Upload a new default for the field.
|
||||||
$field['settings']['default_image'] = $default_images['field_new']->fid;
|
$field['settings']['default_image'] = array($default_images['field_new']->fid);
|
||||||
field_update_field($field);
|
field_update_field($field);
|
||||||
|
|
||||||
// Confirm that the new default is used on the article field settings form.
|
// Confirm that the new default is used on the article field settings form.
|
||||||
$this->drupalGet("admin/structure/types/manage/article/fields/$field_name/field-settings");
|
$this->drupalGet("admin/structure/types/manage/article/fields/$field_name/field-settings");
|
||||||
$this->assertFieldByXpath(
|
$this->assertFieldByXpath(
|
||||||
'//input[@name="field[settings][default_image][fid]"]',
|
'//input[@name="field[settings][default_image][fids]"]',
|
||||||
$default_images['field_new']->fid,
|
$default_images['field_new']->fid,
|
||||||
format_string(
|
format_string(
|
||||||
'Updated image field default equals expected file ID of @fid.',
|
'Updated image field default equals expected file ID of @fid.',
|
||||||
|
|
@ -175,14 +175,14 @@ class ImageFieldDefaultImagesTest extends ImageFieldTestBase {
|
||||||
);
|
);
|
||||||
|
|
||||||
// Upload a new default for the article's field instance.
|
// Upload a new default for the article's field instance.
|
||||||
$instance['settings']['default_image'] = $default_images['instance_new']->fid;
|
$instance['settings']['default_image'] = array($default_images['instance_new']->fid);
|
||||||
field_update_instance($instance);
|
field_update_instance($instance);
|
||||||
|
|
||||||
// Confirm the new field instance default is used on the article field
|
// Confirm the new field instance default is used on the article field
|
||||||
// admin form.
|
// admin form.
|
||||||
$this->drupalGet("admin/structure/types/manage/article/fields/$field_name");
|
$this->drupalGet("admin/structure/types/manage/article/fields/$field_name");
|
||||||
$this->assertFieldByXpath(
|
$this->assertFieldByXpath(
|
||||||
'//input[@name="instance[settings][default_image][fid]"]',
|
'//input[@name="instance[settings][default_image][fids]"]',
|
||||||
$default_images['instance_new']->fid,
|
$default_images['instance_new']->fid,
|
||||||
format_string(
|
format_string(
|
||||||
'Updated article image field instance default equals expected file ID of @fid.',
|
'Updated article image field instance default equals expected file ID of @fid.',
|
||||||
|
|
@ -220,7 +220,7 @@ class ImageFieldDefaultImagesTest extends ImageFieldTestBase {
|
||||||
// Confirm the article field instance default has been removed.
|
// Confirm the article field instance default has been removed.
|
||||||
$this->drupalGet("admin/structure/types/manage/article/fields/$field_name");
|
$this->drupalGet("admin/structure/types/manage/article/fields/$field_name");
|
||||||
$this->assertFieldByXpath(
|
$this->assertFieldByXpath(
|
||||||
'//input[@name="instance[settings][default_image][fid]"]',
|
'//input[@name="instance[settings][default_image][fids]"]',
|
||||||
'',
|
'',
|
||||||
'Updated article image field instance default has been successfully removed.'
|
'Updated article image field instance default has been successfully removed.'
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -233,7 +233,7 @@ class ImageFieldDisplayTest extends ImageFieldTestBase {
|
||||||
// Clear field info cache so the new default image is detected.
|
// Clear field info cache so the new default image is detected.
|
||||||
field_info_cache_clear();
|
field_info_cache_clear();
|
||||||
$field = field_info_field($field_name);
|
$field = field_info_field($field_name);
|
||||||
$image = file_load($field['settings']['default_image']);
|
$image = file_load($field['settings']['default_image'][0]);
|
||||||
$this->assertTrue($image->status == FILE_STATUS_PERMANENT, 'The default image status is permanent.');
|
$this->assertTrue($image->status == FILE_STATUS_PERMANENT, 'The default image status is permanent.');
|
||||||
$default_output = theme('image', array('uri' => $image->uri));
|
$default_output = theme('image', array('uri' => $image->uri));
|
||||||
$this->drupalGet('node/' . $node->nid);
|
$this->drupalGet('node/' . $node->nid);
|
||||||
|
|
@ -255,7 +255,7 @@ class ImageFieldDisplayTest extends ImageFieldTestBase {
|
||||||
|
|
||||||
// Remove default image from the field and make sure it is no longer used.
|
// Remove default image from the field and make sure it is no longer used.
|
||||||
$edit = array(
|
$edit = array(
|
||||||
'field[settings][default_image][fid]' => 0,
|
'field[settings][default_image][fids]' => 0,
|
||||||
);
|
);
|
||||||
$this->drupalPost("admin/structure/types/manage/article/fields/$field_name/field-settings", $edit, t('Save field settings'));
|
$this->drupalPost("admin/structure/types/manage/article/fields/$field_name/field-settings", $edit, t('Save field settings'));
|
||||||
// Clear field info cache so the new default image is detected.
|
// Clear field info cache so the new default image is detected.
|
||||||
|
|
@ -275,7 +275,7 @@ class ImageFieldDisplayTest extends ImageFieldTestBase {
|
||||||
field_info_cache_clear();
|
field_info_cache_clear();
|
||||||
|
|
||||||
$private_field = field_info_field($private_field_name);
|
$private_field = field_info_field($private_field_name);
|
||||||
$image = file_load($private_field['settings']['default_image']);
|
$image = file_load($private_field['settings']['default_image'][0]);
|
||||||
$this->assertEqual('private', file_uri_scheme($image->uri), 'Default image uses private:// scheme.');
|
$this->assertEqual('private', file_uri_scheme($image->uri), 'Default image uses private:// scheme.');
|
||||||
$this->assertTrue($image->status == FILE_STATUS_PERMANENT, 'The default image status is permanent.');
|
$this->assertTrue($image->status == FILE_STATUS_PERMANENT, 'The default image status is permanent.');
|
||||||
// Create a new node with no image attached and ensure that default private
|
// Create a new node with no image attached and ensure that default private
|
||||||
|
|
|
||||||
|
|
@ -108,7 +108,7 @@ function locale_translate_import_form($form, &$form_state) {
|
||||||
*/
|
*/
|
||||||
function locale_translate_import_form_submit($form, &$form_state) {
|
function locale_translate_import_form_submit($form, &$form_state) {
|
||||||
// Ensure we have the file uploaded.
|
// Ensure we have the file uploaded.
|
||||||
if ($file = file_save_upload('file', $form['file']['#upload_validators'], 'translations://')) {
|
if ($file = file_save_upload('file', $form['file']['#upload_validators'], 'translations://', 0)) {
|
||||||
|
|
||||||
// Add language, if not yet supported.
|
// Add language, if not yet supported.
|
||||||
$language = language_load($form_state['values']['langcode']);
|
$language = language_load($form_state['values']['langcode']);
|
||||||
|
|
|
||||||
|
|
@ -1123,7 +1123,7 @@ function hook_delete(\Drupal\Core\Entity\EntityInterface $node) {
|
||||||
*/
|
*/
|
||||||
function hook_prepare(\Drupal\Core\Entity\EntityInterface $node) {
|
function hook_prepare(\Drupal\Core\Entity\EntityInterface $node) {
|
||||||
if ($file = file_check_upload($field_name)) {
|
if ($file = file_check_upload($field_name)) {
|
||||||
$file = file_save_upload($field_name, _image_filename($file->filename, NULL, TRUE));
|
$file = file_save_upload($field_name, _image_filename($file->filename, NULL, TRUE), FALSE, 0);
|
||||||
if ($file) {
|
if ($file) {
|
||||||
if (!image_get_info($file->uri)) {
|
if (!image_get_info($file->uri)) {
|
||||||
form_set_error($field_name, t('Uploaded file is not a valid image'));
|
form_set_error($field_name, t('Uploaded file is not a valid image'));
|
||||||
|
|
|
||||||
|
|
@ -40,8 +40,8 @@ class UserPictureUpgradePathTest extends UpgradePathTestBase {
|
||||||
|
|
||||||
// Retrieve the field instance and check for migrated settings.
|
// Retrieve the field instance and check for migrated settings.
|
||||||
$instance = field_info_instance('user', 'user_picture', 'user');
|
$instance = field_info_instance('user', 'user_picture', 'user');
|
||||||
$file = entity_load('file', $instance['settings']['default_image']);
|
$file = entity_load('file', $instance['settings']['default_image'][0]);
|
||||||
$this->assertIdentical($instance['settings']['default_image'], $file->id(), 'Default user picture has been migrated.');
|
$this->assertIdentical($instance['settings']['default_image'][0], $file->id(), 'Default user picture has been migrated.');
|
||||||
$this->assertEqual($file->uri, 'public://user_pictures_dir/druplicon.png', 'File id matches the uri expected.');
|
$this->assertEqual($file->uri, 'public://user_pictures_dir/druplicon.png', 'File id matches the uri expected.');
|
||||||
$this->assertEqual($file->filename, 'druplicon.png');
|
$this->assertEqual($file->filename, 'druplicon.png');
|
||||||
$this->assertEqual($file->langcode, LANGUAGE_NOT_SPECIFIED);
|
$this->assertEqual($file->langcode, LANGUAGE_NOT_SPECIFIED);
|
||||||
|
|
|
||||||
|
|
@ -619,7 +619,7 @@ function system_theme_settings_validate($form, &$form_state) {
|
||||||
$validators = array('file_validate_is_image' => array());
|
$validators = array('file_validate_is_image' => array());
|
||||||
|
|
||||||
// Check for a new uploaded logo.
|
// Check for a new uploaded logo.
|
||||||
$file = file_save_upload('logo_upload', $validators);
|
$file = file_save_upload('logo_upload', $validators, FALSE, 0);
|
||||||
if (isset($file)) {
|
if (isset($file)) {
|
||||||
// File upload was attempted.
|
// File upload was attempted.
|
||||||
if ($file) {
|
if ($file) {
|
||||||
|
|
@ -635,7 +635,7 @@ function system_theme_settings_validate($form, &$form_state) {
|
||||||
$validators = array('file_validate_extensions' => array('ico png gif jpg jpeg apng svg'));
|
$validators = array('file_validate_extensions' => array('ico png gif jpg jpeg apng svg'));
|
||||||
|
|
||||||
// Check for a new uploaded favicon.
|
// Check for a new uploaded favicon.
|
||||||
$file = file_save_upload('favicon_upload', $validators);
|
$file = file_save_upload('favicon_upload', $validators, FALSE, 0);
|
||||||
if (isset($file)) {
|
if (isset($file)) {
|
||||||
// File upload was attempted.
|
// File upload was attempted.
|
||||||
if ($file) {
|
if ($file) {
|
||||||
|
|
|
||||||
|
|
@ -499,6 +499,8 @@ function system_element_info() {
|
||||||
);
|
);
|
||||||
$types['file'] = array(
|
$types['file'] = array(
|
||||||
'#input' => TRUE,
|
'#input' => TRUE,
|
||||||
|
'#multiple' => FALSE,
|
||||||
|
'#process' => array('form_process_file'),
|
||||||
'#size' => 60,
|
'#size' => 60,
|
||||||
'#pre_render' => array('form_pre_render_file'),
|
'#pre_render' => array('form_pre_render_file'),
|
||||||
'#theme' => 'input__file',
|
'#theme' => 'input__file',
|
||||||
|
|
|
||||||
|
|
@ -645,7 +645,7 @@ function update_manager_install_form_submit($form, &$form_state) {
|
||||||
elseif ($_FILES['files']['name']['project_upload']) {
|
elseif ($_FILES['files']['name']['project_upload']) {
|
||||||
$validators = array('file_validate_extensions' => array(archiver_get_extensions()));
|
$validators = array('file_validate_extensions' => array(archiver_get_extensions()));
|
||||||
$field = 'project_upload';
|
$field = 'project_upload';
|
||||||
if (!($finfo = file_save_upload($field, $validators, NULL, FILE_EXISTS_REPLACE))) {
|
if (!($finfo = file_save_upload($field, $validators, NULL, 0, FILE_EXISTS_REPLACE))) {
|
||||||
// Failed to upload the file. file_save_upload() calls form_set_error() on
|
// Failed to upload the file. file_save_upload() calls form_set_error() on
|
||||||
// failure.
|
// failure.
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue