Visual Form Builder Pro: Customize the upload directory

Are you annoyed that Visual Form Builder Pro places your file uploads mixed in with the uploads for your Posts and Pages?  If so, this bit of code is for you.

Visual Form Builder Pro uses a WordPress function called wp_handle_upload to handle uploading and moving the file to the appropriate content directory.  The upside (or downside, depending on how you look at it) is that is handles everything you need in a single function.  You just need to pass it the $_FILES reference.  With this simplification comes a price and the reason for this tutorial: customizing where the files goes is handled outside this function.

upload_dir filter

The upload_dir filter takes an array of all the path and URL info it needs to upload a file.  For our purposes, though, we only want to affect uploads that happen through Visual Form Builder Pro and not every upload. This is done by checking to see if our file upload field is set and, if so, change the upload directory. Otherwise, leave as is and continue as normal.

add_filter( 'upload_dir', 'vfb_upload_dir' );

function vfb_upload_dir( $upload ){

    /* If our File Upload field is detected.
       To change all forms, use $_POST['vfb-submit']
    */
    if ( isset( $_FILES['vfb-611'] ) ) {
        /* Customize this to fit your needs */
        $dir = WP_CONTENT_DIR . '/vfb-uploads';
        $url = WP_CONTENT_URL . '/vfb-uploads';

        $bdir = $dir;
        $burl = $url;

        $subdir = '';

        /* Append year/month folders if that option is set */
        if ( get_option( 'uploads_use_yearmonth_folders' ) ) {
            if ( !$time )
                $time = current_time( 'mysql' );

            $y = substr( $time, 0, 4 );
            $m = substr( $time, 5, 2 );

            $subdir = "/$y/$m";    
        }

        $dir .= $subdir;
        $url .= $subdir;

        /* Set the $uploads array with our new paths */
        $upload['path'] = $dir;
        $upload['url'] = $url;
        $upload['subdir'] = $subdir;
        $upload['basedir'] = $bdir;
        $upload['baseurl'] = $burl;
        $upload['error'] = false;
    }

	return $upload;
}

This function can be customized to fit your needs as you see fit.  This particular function will only run for the form that has the ‘vfb-611′ field, but you can expand it to include or exclude more forms.  You can even change it to pick up on all VFB forms if that’s what you want to do.

IMPORTANT NOTE!

Changing the upload directory in this way will affect how these uploads work in the Media Library.  In other words, you won’t see the thumbnail and the links in the Media Library will be pointing to the wrong file location.  WordPress stores the file location attachment metadata as a relative path, so it’s always going to be in reference to your default upload directory.

If customizing the upload path is more important than seeing thumbnails in the Media Library, then this detail can be overlooked.

Visual Form Builder Pro 1.5 released

Visual Form Builder Pro 1.5 is now available for download.  This version includes a ton of advanced features, which I will get to shortly, but there’s one very big addition included: the SPAM verification section is now optional.

Disable the SPAM verification by going to the Form Settings

Removing the automatic SPAM verification is perhaps the most asked for feature request I get.  The message was clear.  You wanted this.  And I want Visual Form Builder to be a product that serves your needs.  Your forms will still be protected using the other security measures built into the plugin, but there is always a risk so please keep an eye on how your forms are being used.

Version 1.5 includes more than just being able to turn off the SPAM verification!  I have added a ton of hooks and filters throughout the code to allow for some advanced modifications and controls.  Also, there are new custom capabilities to allow for even more control over who can see what.  I will have more posts talking about the filters in the future, so keep an eye out for those.

Release Notes

  • Add ability to turn off the spam Verification section
  • Add custom capabilities for user roles
  • Add various filters
  • Add nag message if free version of Visual Form Builder is detected and still active
  • Fix bug in Analytics and Email Design where the initial form might not display
  • Fix bug where certain rows in the email would not use the alt row color
  • Fix bug for plain text email formatting
  • Fix bug where notification email would send as HTML even if plain text was selected
  • Update subnav to accommodate new custom capabilities
  • Update list of spam bots
  • Update spam bot check to only execute when form is submitted

Adding custom jQuery validation to your form

In most cases, the standard validation options that ship with Visual Form Builder will cover most of your needs.  However, there are those occasions where you need something customized and the standard options just don’t cut it.  Today, we’re going to look at how you can add your own jQuery validation rules.

Before we begin, you might want to head over to the jQuery Form Validation plugin page and read through some of the documentation to get a better idea of what we’ll be talking about.

Create a JS file and add to your theme via functions.php file

Go into your theme’s folder and create a new file called vfb-js.js in a folder called js.  Create that folder if it doesn’t exist.

Now, go to your theme’s functions.php file and add the following code:

function my_scripts_method() {
   wp_register_script( 'vfb-js-file',
       get_template_directory_uri() . '/js/vfb-js.js',
       array( 'jquery-form-validation' ),
       '1.0',
       false );

   wp_enqueue_script( 'vfb-js-file' );
}

add_action( 'wp_enqueue_scripts', 'my_scripts_method' );

You are now ready to configure your JavaScript file.

Prepping our validation class

All custom rules that you want applied to a form will need to be placed inside the validation class.  But first you will need to find the ID of the form you want to configure.  Here, I am using Firebug to find that out, but View Source works just as well.

Getting the form ID using Firebug

Open your vfb-js.js file and add the following code:

jQuery(document).ready(function($) {
    $('#contact-us').validate({
        rules: {

        }
    });
});

Example #1: Require multiple checkboxes to be selected

For this example, let’s say that we have a form with a Checkbox field called Topics of Interest with several different topics to choose from.  This is a required field, but we also want to make sure they select at least two topics.

In the same way that we grabbed the ID of the form, we’ll need to do the same here to get the name property of the checkbox field.

Getting the name property of the checkbox field using Firebug

Open your vfb-js.js file and add the following code:

jQuery(document).ready(function($) {
    $('#contact-us').validate({
        rules:{
            'vfb-topics-of-interest-26[]':{
                required: true,
                minlength: 2
            }
        }
    });
});

But that’s not all. We can also customize the error messages for that field!

jQuery(document).ready(function($) {
    $('#contact-us').validate({
        rules:{
            'vfb-topics-of-interest-26[]':{
                required: true,
                minlength: 2
            }
        },
        messages:{
            'vfb-topics-of-interest-26[]':{
                minlength: 'Please select at least two topics.'
            }
        },
        errorPlacement: function(error, element) {
	    if ( element.is( ':radio' ) || element.is( ':checkbox' ) )
	        error.appendTo( element.parent().parent() );
	    else if ( element.is( ':password' ) )
		error.hide();
	    else
		error.insertAfter( element );
	} 
    });
});

Example #2: Require one field to be equal to another field

In this example, we have a Test Answer field but we need to be able to confirm that the user has entered the data correctly.  To do this, we’ll add a second Text field and call it Confirm Test Answer.  Now, we just need to make our first text field equal to our second one in our jQuery and throw an error message that lets them know if they don’t match.

Requiring one field to be equal to another

jQuery(document).ready(function($) {
    $('#contact-us').validate({
        rules:{
            'vfb-topics-of-interest-26[]':{
                required: true,
                minlength: 2
            },
            'vfb-confirm-test-answer-621':{
                equalTo: '#vfb-test-answer-620'
            }
        },
        messages:{
            'vfb-topics-of-interest-26[]':{
                minlength: 'Please select at least two topics.'
            },
            'vfb-confirm-test-answer-621':{
                equalTo: 'Your answers do not match'
            }
        },
        errorPlacement: function(error, element) {
	    if ( element.is( ':radio' ) || element.is( ':checkbox' ) )
		error.appendTo( element.parent().parent() );
	    else if ( element.is( ':password' ) )
		error.hide();
	    else
		error.insertAfter( element );
	}
    });
});

Example #3: Make a field required, depending on the value of another field

Let’s say that you have a form where you have a Start Date and an End Date.  If the user fills out the Start Date, the End Date needs to be required.  The End Date, in this case, is dependent on the Start Date not being left empty.

jQuery(document).ready(function($) {
    $('#contact-us').validate({
        rules:{
            'vfb-topics-of-interest-26':{
                required: true,
                minlength: 2
            },
            'vfb-confirm-test-answer-621':{
                equalTo: '#vfb-test-answer-620'
            },
            'vfb-end-date-85':{
                required: function(e){
                    return $('#vfb-start-date-80').val() !== '';
                }
            }
        },
        messages:{
            'vfb-topics-of-interest-26':{
                minlength: 'Please select at least two topics.'
            },
            'vfb-confirm-test-answer-621':{
                equalTo: 'Your answers do not match.'
            }
        },
        errorPlacement: function(error, element) {
	    if ( element.is( ':radio' ) || element.is( ':checkbox' ) )
		error.appendTo( element.parent().parent() );
	    else if ( element.is( ':password' ) )
		error.hide();
	    else
		error.insertAfter( element );
	}
    });
});

You can customize this to your needs so if you need the Start Date to have a certain value before the End Date is required, you can do that too.

As you can see, there are plenty of ways to extend your form with jQuery to accomplish some custom and complex things.