Resolved
Reported for: Toolset Forms 2.4
Resolved in: Toolset Forms 2.4
In Forms 2.4 we switched the AJAX upload mechanism for media fields, from a jQuery upload plugin, to the native media library provided by WordPress.
One side effect of that change is that, when the file is being uploaded, the $_FILES
global holds data in a slightly different structure:
async-upload
instead.This should not be a problem, since the cred_form_ajax_upload_validate
provides all the information you would need to validate a file being uploaded. However, we detected some support tickets that included some custom code that was accessing directly the $_FILES
global instead.
Please never trust any external data when working with a hook (an action or a filter). The only data that will keep its structure on a hook callback is the one passed to the hook itself.
The correct way of accessing the data for the file being uploaded when using AJAX on a media field in Forms is as follows (and this is working before, on, and after Forms 2.4):
add_filter( 'cred_form_ajax_upload_validate', 'prefix_get_data_for_uploading_files', 10, 2 );
function prefix_get_data_for_uploading_files( $error_fields, $form_data ) {
// You can apply this to a given relevant form checking against $form_data['id']
// Get the list of uploading fields and errors
list( $fields, $errors ) = $error_fields;
// Put here the key of the field that you want to validate
$field_key = 'my-field-key';
// You can get data from the uploading field as follows:
if ( array_key_exists( $field_key, $fields ) ) {
$file_uploading_data = $fields[ $field_key ];
// Get the filename for the file being uploaded
$file_uploading_name = $file_uploading_data['field_data']['name'];
// Get the mime type of the file being uploaded
$file_uploading_type = $file_uploading_data['field_data']['type'];
// Get the size of the file being uploaded
$file_uploading_size = $file_uploading_data['field_data']['size'];
// Get the temporary name of the file being uploaded
$file_uploading_tmp_name = $file_uploading_data['field_data']['tmp_name'];
}
return array( $fields, $errors );
}
In case you have some old custom code that is hard to review, and that is getting data from the global $_FILES
inside a callback for this cred_form_ajax_upload_validate
filter, here it is a workaround that should set the global data to what it was before Forms 2.4, and then reset it back to what the media library requires.
add_filter( 'cred_form_ajax_upload_validate', 'prefix_cred_form_ajax_upload_validate_set_legacy_global_files', 1 );
add_filter( 'cred_form_ajax_upload_validate', 'prefix_cred_form_ajax_upload_validate_reset_global_files', 9999 );
function prefix_cred_form_ajax_upload_validate_set_legacy_global_files( $error_fields ) {
if ( array_key_exists( 'async-upload', $_FILES ) ) {
$files_global = array();
list( $fields, $errors ) = $error_fields;
foreach ( $fields as $field_key => $field_data ) {
$files_global[ $field_key ] = $field_data['field_data'];
}
$_FILES = $files_global;
}
return $error_fields;
}
function prefix_cred_form_ajax_upload_validate_reset_global_files( $error_fields ) {
$files_global = $_FILES;
$files_global_restored = array();
foreach ( $files_global as $key => $value ) {
$files_global_restored['async-upload'] = $value;
}
$_FILES = $files_global_restored;
return $error_fields;
}