Skip Navigation

[Resolved] Media Fields & Uploads

This is the technical support forum for Toolset - a suite of plugins for developing WordPress sites without writing PHP.

Everyone can read this forum, but only Toolset clients can post in it. Toolset support works 6 days per week, 19 hours per day.

Tagged: 

This topic contains 16 replies, has 2 voices.

Last updated by julieP 1 year, 4 months ago.

Assigned support staff: Shane.

Author
Posts
#1654009

I started a chat today but had no response in 3 hours. Here's my question:-

I understand the AJAX upload mechanism for media fields in CRED forms has changed (https://toolset.com/errata/a-note-on-using-the-cred_form_ajax_upload_validate-hook/). So I can take this discussion in the right direction, could you start by clarifying for me please what the advantages & disadvantages are of uploading using AJAX and the advantages & disadvantages of disabling AJAX upload.

Thank you!

#1654397

Shane
Supporter

Languages: English (English )

Timezone: America/Jamaica (GMT-05:00)

Hi Julie,

Thank you for getting in touch.

With AJAX Advantages & Disadvantages

Advantages:
1. Upload multiple image at the same time. Useful for repeatable fields.
2. Allows for dynamic validation of the images before they get uploaded or the form gets submitted.
3. Access to your previously uploaded images through the media library.

Disadvantages.
1. If Javascript is disabled in your browser then the upload won't work.
2. If there are any Javascript error in the console then your upload may not work.

Without AJAX

Advantages.
1. Uses PHP to upload so its independent of Javascript.
2. Javascript errors doesn't affect the upload.

Disadvantages.
1. With repeatable fields you will need to upload the images one by one.
2. Any validation hook will need to fire when the form is submitted.

Essentially these are just a few advantages and disadvantages based on my experience and uses of the AJAX upload. Please let me know if this was able to help.

Thanks,
Shane

#1654909

Hi Shane

Many thanks for this.

I believe media uploads are now handled using WP's Media Uploader; forgive my ignorance but after reading numerous posts in this forum and other articles on the web, I'm not 100% clear as to whether this mechanism uses AJAX or not. Can you confirm for me please?

I also have some questions about Forms and the Media Library. When creating a CRED form, I see there's a checkbox for the Media Library. If that box is checked, I believe the User completing the form is given access to their uploaded images using the Media Library. Is that right?

Does checking or unchecking the Media Library box do anything else?

#1655721

Shane
Supporter

Languages: English (English )

Timezone: America/Jamaica (GMT-05:00)

Hi Julie,

I'm not 100% clear as to whether this mechanism uses AJAX or not. Can you confirm for me please?

Yes it is using the default AJAX functions that wordpress uses for its media library.

When creating a CRED form, I see there's a checkbox for the Media Library. If that box is checked, I believe the User completing the form is given access to their uploaded images using the Media Library. Is that right?

Yes that is correct, checking this option will give the users access to the media library which will contain the images they upload as well as allowing them to upload any other images.

Does checking or unchecking the Media Library box do anything else?

No it doesn't checking it gives them media library access for uploads.

Unchecking uses the default php upload.

Please let me know if this helps.
Thanks,
Shane

#1656675

Hi again

Many thanks for bearing with me; I'm just building a picture so I can ask the right questions next!

So, if I want to validate image uploads (without disabling AJAX), I believe I now need to use $fields not $_FILES in my hook meaning it would look like this. Is this code correct please?

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 ) {
    
    	$form_ids = array( 281 => true );
	list($fields,$errors)=$error_fields;
    
    if ( isset( $form_ids[ $form_data['id'] ] ) ) {

         $field_key = 'wpcf-logo';

         if ( array_key_exists( $field_key, $fields ) ) { 

            $file_uploading_data = $fields[ $field_key ];            
            $file_uploading_type = $file_uploading_data['field_data']['type'];
            $file_uploading_size = $file_uploading_data['field_data']['size'];            
            
            if ( ( $file_uploading_type != 'image/jpeg' ) || ( $file_uploading_size > 10240 ) ) {
                $errors['logo'] = 'Please check your image is a JPG/JPEG and smaller than 10KB in size';
            }
        }
    }
    return array( $fields, $errors );
}

If, however, I wanted to disable AJAX for uploads, do I continue using this filter and/or has it changed?

add_filter( 'cred_file_upload_disable_progress_bar', '__return_true' );

And do I continue to use $_FILES in my (non AJAX) hook like this or does the content need to be the same as in the one above even though AJAX isn't being used?

add_filter('cred_form_validate', 'ts_validate_data_281',10,2);
function ts_validate_data_281($field_data, $form_data){
    
    $form_ids = array( 281 => true );
    list($fields,$errors)=$field_data;
    
    if ( isset( $form_ids[ $form_data['id'] ] ) ) {
        if ( ( !empty( $fields['wpcf-logo']['value'] )) && ( !empty($_FILES['wpcf-logo']['type'] )) && ( !empty($_FILES['wpcf-logo']['size'] )) )  {            
            $file_type_uploaded=$_FILES['wpcf-logo']['type'];
            $file_size_uploaded=$_FILES['wpcf-logo']['size'];
            
            if ( ( $file_type_uploaded != 'image/jpeg' ) || ( $file_size_uploaded > 10240 ) ) {
                $errors['logo'] = 'Please check your image is a JPG/JPEG and smaller than 10KB in size';
            }
        }
    }
    return array($fields,$errors);
}
#1657105

Shane
Supporter

Languages: English (English )

Timezone: America/Jamaica (GMT-05:00)

Hi Julie,

Based on our documentation yes this is correct.

However the "add_filter( 'cred_file_upload_disable_progress_bar', '__return_true' );" is no longer needed given that we do not use the previous AJAX upload method that had the progress bar.

The AJAX upload now uses the media library.

Please let me know if this is clearer.

Thanks,
Shane

#1658353

OK so how DO I disable AJAX upload now then?

#1658695

Shane
Supporter

Languages: English (English )

Timezone: America/Jamaica (GMT-05:00)

Hi Julie,

You will need to uncheck the box in the Form that enables the use of the Media Uploader.

Unfortunately there isn't a way to disable the AJAX upload for the media library because the entire media library uploader is based on AJAX.

Thanks,
Shane

#1658995

I specifically asked you if checking/unchecking the box on the Form did anything else, you said not. Now you're telling me it enables/disables AJAX upload ............. in the first line anyway. In the second line you're saying the opposite.

None of this makes any sense; I've seen other tickets that say the correct hook to use if AJAX uploads are enabled is 'cred_form_ajax_upload_validate' or 'cred_form_validate' if AJAX is disabled so there must be a way of enabling/disabling AJAX submission. I've spent days trawling threads trying to make sense of this new method so I know what to do with my setup and hooks and I've spent even more days repeatedly testing upload validation with a form and endless different hook formats based on documentation, other tickets and hooks I've used successfully before'til I'm blue in the face. Every single time, images that exceed the size limit are uploaded whether I check the box on the form or not. When I leave the box on the form unchecked and use this validation hook, a 23KB JPEG image uploads and I get an undefined index notice for 'size'in my debug file:-

add_filter('cred_form_validate', 'tsbmp1_validate_data_281_303',10,2);
function tsbmp1_validate_data_281_303($error_fields, $form_data){
    
     $form_ids = array( 281 => true, 303 => true );
	
	// field data are field values and errors
     list($fields,$errors)=$error_fields;
    
     if ( isset( $form_ids[ $form_data['id'] ] ) ) {
        
        
        if ( ( !empty( $fields[ 'wpcf-logo' ]['value'] ) ) && ( !empty( $_FILES['wpcf-logo']['type'] ) ) && ( !empty( $_FILES['wpcf-logo']['size'] ) ) ) {
            
            $file_type = $fields['wpcf-logo']['type'];
            $file_size = $fields['wpcf-logo']['size'];
            
            if ( ( $file_type != 'image/jpeg' ) || ( $file_size > 10240 ) ) {
                $errors['logo'] = 'Please check your image is a JPG/JPEG and smaller than 10KB in size';
            }
        }
    }
    return array($fields,$errors);
}

I don't (currently) want to give my users access to the Media Library and I don't (currently) want to use AJAX to upload files/images but I do want to validate the images for file type and size (a fundamental requirement for security reasons). I just need a clear answer as to how I achieve this and what's wrong with my code, if anything.

#1659027

Shane
Supporter

Languages: English (English )

Timezone: America/Jamaica (GMT-05:00)

Hi Julie,

I specifically asked you if checking/unchecking the box on the Form did anything else, you said not. Now you're telling me it enables/disables AJAX upload ............. in the first line anyway.

In response to this I did mention that it reverts to the default php upload, which doesn't use AJAX in my response here
https://toolset.com/forums/topic/media-fields-uploads/#post-1655721

I wasn't clear with your entire requirement.

Here you say

I don't (currently) want to give my users access to the Media Library and I don't (currently) want to use AJAX to upload files/images to wp-content/uploads/ but I do want to validate the images for file type and size (a fundamental requirement for security reasons). I just need a clear answer as to how I achieve this and what's wrong with my code, if anything.

If that is the case then you will leave the media library button unchecked. I was under the impression that you wanted to use the media library but have the AJAX upload disabled. It should also be noted that even if the user uploads using the Media Library they will only have access to their previously uploaded images, so if another user uploads another image, the previous use won't see that image.

Is there a particular reason why you want to not use the AJAX upload ?

For your code would it be possible to get admin access to the site that you are using to test this ?

This way I can debug the code. I will need to run through the code and particularly the "$fields['wpcf-logo']" array variable to see what exactly it stores in order to find out what are the correct attribute to be used.

I will enable the private fields for your next response. Also please let me know the page that the for is on that you are using to test out this code.

I must apologize for the confusion as I wasn't getting the full scope of your query until now.

Thanks,
Shane

#1659545

Access isn't possible; it's a test site that's completely locked down to the outside world.

So to make sure I've understood this correctly, please confirm if these two statements are correct:-

box is unchecked on form = AJAX upload is disabled & image validation hook to use is 'cred_form_validate'
box is checked on form = AJAX upload is enabled & image validation hook to use is ''cred_form_ajax_upload_validate'

How do I display the image info on the frontend to check what info is available once an image has been selected but before the form is submitted?

#1660269

Shane
Supporter

Languages: English (English )

Timezone: America/Jamaica (GMT-05:00)

Hi Julie,

box is unchecked on form = AJAX upload is disabled & image validation hook to use is 'cred_form_validate'
Correct

box is checked on form = AJAX upload is enabled & image validation hook to use is ''cred_form_ajax_upload_validate'
Correct

How do I display the image info on the frontend to check what info is available once an image has been selected but before the form is submitted?

Not possible to do because AJAX is disabled and the image isn't uploaded as yet, so the page isn't able to pull the image data. The image is only uploaded when the form is submitted.

Thanks,
Shane

#1660953
type & size data_2.JPG
type & size data.JPG

Not possible to do because AJAX is disabled and the image isn't uploaded as yet, so the page isn't able to pull the image data. The image is only uploaded when the form is submitted.

That's exactly what I expected so why then did you say earlier you wanted to run through my code to see what is stored? You can see why I'm finding this frustrating! In any case, I've given you my code here https://toolset.com/forums/topic/media-fields-uploads/#post-1658995; I really don't understand why you're not testing this on your own test installation to see if you get the same results. This is a normal approach for support staff.

After even more testing (box unchecked), I modified my validation hook to this. Please note the additional code at lines 14 & 15 :-

add_filter('cred_form_validate', 'ts_validate_data_281',10,2);
function ts_validate_data_281($field_data, $form_data){
     
    $form_ids = array( 281 => true );
    list($fields,$errors)=$field_data;
     
    if ( isset( $form_ids[ $form_data['id'] ] ) ) {
        
        if ( ( !empty( $fields['wpcf-logo']['value'] )) && ( !empty($_FILES['wpcf-logo']['type'] )) && ( !empty($_FILES['wpcf-logo']['size'] )) )  {
            
            $file_type=$_FILES['wpcf-logo']['type'];
            $file_size=$_FILES['wpcf-logo']['size'];
            
            add_post_meta(999, '_the_file_type', $file_type);
            add_post_meta(999, '_the_file_size', $file_size);
             
            if ( ( $file_type != 'image/jpeg' ) || ( $file_size > 10240 ) ) {
                $errors['logo'] = 'Please check your image is a JPG/JPEG and smaller than 10KB in size';
            }
        }
    }
    return array($fields,$errors);
}

Please then check the attached screenshot of the database entries created which shows the file type and size have been successfully recorded and that the validation should have returned an error message and stopped the form submission.

I then took the hook one stage further and revised it to this (I'm sure you can work out what's new):-

add_filter('cred_form_validate', 'ts_validate_data_281',10,2);
function ts_validate_data_281$field_data, $form_data){
     
    $form_ids = array( 281 => true);
    list($fields,$errors)=$field_data;
     
    if ( isset( $form_ids[ $form_data['id'] ] ) ) {
        
        if ( ( !empty( $fields['wpcf-logo']['value'] )) && ( !empty($_FILES['wpcf-logo']['type'] )) && ( !empty($_FILES['wpcf-logo']['size'] )) )  {
            
            $file_type=$_FILES['wpcf-logo']['type'];
            $file_size=$_FILES['wpcf-logo']['size'];
            
            add_post_meta(999, '_the_file_type', $file_type);
            add_post_meta(999, '_the_file_size', $file_size);
             
            if ( $file_type != 'image/jpeg' ) {                
                add_post_meta(999, '_wrong_type', 'Yes');
            } else {                
                add_post_meta(999, '_wrong_type', 'No');
            }
            
            if ( $file_size > 10240 ) {            
                add_post_meta(999, '_wrong_size', 'Yes');
            } else {                
                add_post_meta(999, '_wrong_size', 'No');
            }
        }
    }
    return array($fields,$errors);
}

Please refer to the second attachment showing the values saved to the database which confirms there's nothing wrong with my conditional statements. The only possible conclusion left is that the cred validation hook itself isn't working properly. Please investigate.

#1663623

Shane
Supporter

Languages: English (English )

Timezone: America/Jamaica (GMT-05:00)

Hi Julie,

I must apologise for the frustration but initially there was some confusion and we are trying to get on the right track to resolve this one for you.

That's exactly what I expected so why then did you say earlier you wanted to run through my code to see what is stored?

For clarity on this, when you submit the form, the image gets uploaded. This upload data is contained in an array that we can pick up when the image is being uploaded. In order to ensure that you are picking off the right values in your if statement we will need to check that array.

However I did some checks and a test on this locally and found that you are missing a few things. Try using this code below.

add_filter('cred_form_validate', 'ts_validate_data_281',10,2);
function ts_validate_data_281($field_data, $form_data){
      
    $form_ids = array( 281 );
    list($fields,$errors)=$field_data;
      
    if ( in_array($form_data['id'],$form_ids)) {
        if ( ( !empty( $fields['wpcf-logo']['value'] )) )  {
             
            $file_type=$fields['wpcf-logo']['file_data']['type'];
            $file_size=$fields['wpcf-logo']['file_data']['size'];    

            if ( ( $file_type != 'image/jpeg' ) || ( $file_size > 10240 ) ) {
                $errors['logo'] = 'Please check your image is a JPG/JPEG and smaller than 10KB in size';
            }
        }
    }
    return array($fields,$errors);
}

Note the modifications that i've made to $fields['wpcf-logo'] where i've added the ['file_data'] selector for the array. The type and size information is stored in a nested array. Here is an example of it exploded.

$fields['wpcf-my_file']['file_data'] = array(
    'size' => uploaded file size,
    'name' => name of uploaded file,
    'type' => type of uploaded file,
    'error' => what error occurred during upload,
    'tmp_name' => location of temporary uploaded file
);

Also i've removed a few of your conditional checks in the second if statement because it is safe to assume that once the empty check for $fields['wpcf-logo']['value'] passes then there will be a type and a size attribute.

The above code is the hook in its simplest form so you can start your tests from there.

Please try this and let me know if it helps. If there are any issues please let me know.

Thanks,
Shane

#1665993

Thanks for this - I'll run some tests and get back to you (might take me a couple of days)