field_table_name = $wpdb->prefix . 'visual_form_builder_fields';
$this->form_table_name = $wpdb->prefix . 'visual_form_builder_forms';
$this->entries_table_name = $wpdb->prefix . 'visual_form_builder_entries';
// Add suffix to load dev files
$this->load_dev_files = ( defined( 'VFB_SCRIPT_DEBUG' ) && VFB_SCRIPT_DEBUG ) ? '.dev' : '';
// Make sure we are in the admin before proceeding.
if ( is_admin() ) {
// Build options and settings pages.
add_action( 'admin_menu', array( &$this, 'add_admin' ) );
add_action( 'admin_menu', array( &$this, 'save' ) );
add_action( 'wp_ajax_visual_form_builder_process_sort', array( &$this, 'process_sort_callback' ) );
add_action( 'wp_ajax_visual_form_builder_create_field', array( &$this, 'create_field_callback' ) );
add_action( 'wp_ajax_visual_form_builder_delete_field', array( &$this, 'delete_field_callback' ) );
add_action( 'wp_ajax_visual_form_builder_form_settings', array( &$this, 'form_settings_callback' ) );
add_action( 'load-toplevel_page_visual-form-builder', array( &$this, 'help' ) );
// Adds additional media button to insert form shortcode
add_action( 'media_buttons_context', array( &$this, 'add_media_button' ) );
add_action( 'admin_footer', array( &$this, 'display_media_button' ) );
// Load the includes files
add_action( 'load-visual-form-builder_page_vfb-entries', array( &$this, 'includes' ) );
add_action( 'load-visual-form-builder_page_vfb-export', array( &$this, 'include_export' ) );
// Adds a Screen Options tab to the Entries screen
add_filter( 'set-screen-option', array( &$this, 'save_screen_options' ), 10, 3 );
add_filter( 'load-toplevel_page_visual-form-builder', array( &$this, 'screen_options' ) );
add_filter( 'load-visual-form-builder_page_vfb-entries', array( &$this, 'screen_options' ) );
// Add meta boxes to the form builder admin page
add_action( 'load-toplevel_page_visual-form-builder', array( &$this, 'add_meta_boxes' ) );
// Adds a Settings link to the Plugins page
add_filter( 'plugin_action_links', array( &$this, 'plugin_action_links' ), 10, 2 );
// Add a database version to help with upgrades and run SQL install
if ( !get_option( 'vfb_db_version' ) ) {
update_option( 'vfb_db_version', $this->vfb_db_version );
$this->install_db();
}
// If database version doesn't match, update and run SQL install
if ( version_compare( get_option( 'vfb_db_version' ), $this->vfb_db_version, '<' ) ) {
update_option( 'vfb_db_version', $this->vfb_db_version );
$this->install_db();
}
// Load the jQuery and CSS we need if we're on our plugin page
$current_pages = array( 'toplevel_page_visual-form-builder', 'visual-form-builder_page_vfb-add-new', 'visual-form-builder_page_vfb-entries', 'visual-form-builder_page_vfb-export' );
foreach ( $current_pages as $page ) {
add_action( "load-$page", array( &$this, 'admin_scripts' ) );
add_action( "load-$page", array( &$this, 'admin_css' ) );
}
// Display update messages
add_action('admin_notices', array( &$this, 'admin_notices' ) );
}
// Load i18n
load_plugin_textdomain( 'visual-form-builder', false , basename( dirname( __FILE__ ) ) . '/languages' );
add_shortcode( 'vfb', array( &$this, 'form_code' ) );
add_action( 'init', array( &$this, 'email' ), 10 );
add_action( 'init', array( &$this, 'confirmation' ), 12 );
// Add CSS to the front-end
add_action( 'wp_enqueue_scripts', array( &$this, 'css' ) );
}
/**
* Adds extra include files
*
* @since 1.2
*/
public function includes(){
global $entries_list, $entries_detail;
// Load the Entries List class
require_once( trailingslashit( plugin_dir_path( __FILE__ ) ) . 'includes/class-entries-list.php' );
$entries_list = new VisualFormBuilder_Entries_List();
// Load the Entries Details class
require_once( trailingslashit( plugin_dir_path( __FILE__ ) ) . 'includes/class-entries-detail.php' );
$entries_detail = new VisualFormBuilder_Entries_Detail();
}
/**
* Include the Import/Export files later because current_screen isn't available yet
*
* @since 1.4
*/
public function include_export(){
global $export;
// Load the Export class
require_once( trailingslashit( plugin_dir_path( __FILE__ ) ) . 'includes/class-export.php' );
$export = new VisualFormBuilder_Export();
}
/**
* Add Settings link to Plugins page
*
* @since 1.8
* @return $links array Links to add to plugin name
*/
public function plugin_action_links( $links, $file ) {
if ( $file == plugin_basename( __FILE__ ) )
$links[] = '' . __( 'Settings' , 'visual-form-builder') . ' ';
return $links;
}
/**
* Adds the media button image
*
* @since 2.3
*/
public function add_media_button( $context ){
if ( current_user_can( 'manage_options' ) )
$context .= ' ';
return $context;
}
/**
* Display the additional media button
*
* Used for inserting the form shortcode with desired form ID
*
* @since 2.3
*/
public function display_media_button(){
global $wpdb;
// Sanitize the sql orderby
$order = sanitize_sql_orderby( 'form_id ASC' );
// Build our forms as an object
$forms = $wpdb->get_results( $wpdb->prepare( "SELECT form_id, form_title FROM $this->form_table_name ORDER BY $order" ) );
?>
add_help_tab( array(
'id' => 'vfb-help-tab-getting-started',
'title' => 'Getting Started',
'content' => '
Click on the + tab, give your form a name and click Create Form.
Select form fields from the box on the left and click a field to add it to your form.
Edit the information for each form field by clicking on the down arrow.
Drag and drop the elements to put them in order.
Click Save Form to save your changes.
'
) );
$screen->add_help_tab( array(
'id' => 'vfb-help-tab-item-config',
'title' => 'Form Item Configuration',
'content' => "
Name will change the display name of your form input.
Description will be displayed below the associated input.
Validation allows you to select from several of jQuery's Form Validation methods for text inputs. For more about the types of validation, read the Validation section below.
Required is either Yes or No. Selecting 'Yes' will make the associated input a required field and the form will not submit until the user fills this field out correctly.
Options will only be active for Radio and Checkboxes. This field contols how many options are available for the associated input.
Size controls the width of Text, Textarea, Select, and Date Picker input fields. The default is set to Medium but if you need a longer text input, select Large.
CSS Classes allow you to add custom CSS to a field. This option allows you to fine tune the look of the form.
"
) );
$screen->add_help_tab( array(
'id' => 'vfb-help-tab-validation',
'title' => 'Validation',
'content' => "Visual Form Builder uses the jQuery Form Validation plugin to perform clientside form validation.
Email : makes the element require a valid email.
URL : makes the element require a valid url.
Date : makes the element require a date. Refer to documentation for various accepted formats .
Number : makes the element require a decimal number.
Digits : makes the element require digits only.
Phone : makes the element require a US or International phone number. Most formats are accepted.
Time : choose either 12- or 24-hour time format (NOTE: only available with the Time field).
"
) );
$screen->add_help_tab( array(
'id' => 'vfb-help-tab-confirmation',
'title' => 'Confirmation',
'content' => "Each form allows you to customize the confirmation by selecing either a Text Message, a WordPress Page, or to Redirect to a URL.
Text allows you to enter a custom formatted message that will be displayed on the page after your form is submitted. HTML is allowed here.
Page displays a dropdown of all WordPress Pages you have created. Select one to redirect the user to that page after your form is submitted.
Redirect will only accept URLs and can be used to send the user to a different site completely, if you choose.
"
) );
$screen->add_help_tab( array(
'id' => 'vfb-help-tab-notification',
'title' => 'Notification',
'content' => "Send a customized notification email to the user when the form has been successfully submitted.
Sender Name : the name that will be displayed on the email.
Sender Email : the email that will be used as the Reply To email.
Send To : the email where the notification will be sent. This must be a required text field with email validation.
Subject : the subject of the email.
Message : additional text that can be displayed in the body of the email. HTML tags are allowed.
Include a Copy of the User's Entry : appends a copy of the user's submitted entry to the notification email.
"
) );
$screen->add_help_tab( array(
'id' => 'vfb-help-tab-tips',
'title' => 'Tips',
'content' => "
Fieldsets, a way to group form fields, are an essential piece of this plugin's HTML. As such, at least one fieldset is required and must be first in the order. Subsequent fieldsets may be placed wherever you would like to start your next grouping of fields.
Security verification is automatically included on very form. It's a simple logic question and should keep out most, if not all, spam bots.
There is a hidden spam field, known as a honey pot, that should also help deter potential abusers of your form.
Nesting is allowed underneath fieldsets and sections. Sections can be nested underneath fieldsets. Nesting is not required, however, it does make reorganizing easier.
"
) );
}
/**
* Adds the Screen Options tab to the Entries screen
*
* @since 1.2
*/
public function entries_screen_options( $current ){
global $current_screen;
$options = get_option( 'visual-form-builder-screen-options' );
if ( $current_screen->id == 'settings_page_visual-form-builder' && isset( $_REQUEST['view'] ) && in_array( $_REQUEST['view'], array( 'entries' ) ) ){
$current = 'Show on screen
Entries
';
}
return $current;
}
/**
* Adds the Screen Options tab to the Entries screen
*
* @since 1.0
*/
public function screen_options(){
$screen = get_current_screen();
switch( $screen->id ) {
case 'visual-form-builder_page_vfb-entries' :
add_screen_option( 'per_page', array(
'label' => __( 'Entries per page', 'visual-form-builder' ),
'default' => 20,
'option' => 'vfb_entries_per_page'
) );
break;
case 'toplevel_page_visual-form-builder' :
if ( !isset( $_REQUEST['form'] ) )
break;
add_screen_option( 'layout_columns', array(
'max' => 2,
'default' => 2
) );
break;
}
}
/**
* Saves the Screen Options
*
* @since 1.0
*/
public function save_screen_options( $status, $option, $value ){
if ( $option == 'vfb_entries_per_page' )
return $value;
}
/**
* Add meta boxes to form builder screen
*
* @since 1.8
*/
public function add_meta_boxes() {
global $current_screen;
if ( $current_screen->id == 'toplevel_page_visual-form-builder' && isset( $_REQUEST['form'] ) ) {
add_meta_box( 'vfb_form_items_meta_box', __( 'Form Items', 'visual-form-builder' ), array( &$this, 'meta_box_form_items' ), 'toplevel_page_visual-form-builder', 'side', 'high' );
add_meta_box( 'vfb_form_media_button_tip', __( 'Display Forms', 'visual-form-builder' ), array( &$this, 'meta_box_display_forms' ), 'toplevel_page_visual-form-builder', 'side', 'low' );
}
}
/**
* Output for Form Items meta box
*
* @since 1.8
*/
public function meta_box_form_items() {
?>
prefix . 'visual_form_builder_fields';
$form_table_name = $wpdb->prefix . 'visual_form_builder_forms';
$entries_table_name = $wpdb->prefix . 'visual_form_builder_entries';
// Explicitly set the character set and collation when creating the tables
$charset = ( defined( 'DB_CHARSET' && '' !== DB_CHARSET ) ) ? DB_CHARSET : 'utf8';
$collate = ( defined( 'DB_COLLATE' && '' !== DB_COLLATE ) ) ? DB_COLLATE : 'utf8_general_ci';
require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
$field_sql = "CREATE TABLE $field_table_name (
field_id BIGINT(20) NOT NULL AUTO_INCREMENT,
form_id BIGINT(20) NOT NULL,
field_key VARCHAR(255) NOT NULL,
field_type VARCHAR(25) NOT NULL,
field_options TEXT,
field_description TEXT,
field_name TEXT NOT NULL,
field_sequence BIGINT(20) DEFAULT '0',
field_parent BIGINT(20) DEFAULT '0',
field_validation VARCHAR(25),
field_required VARCHAR(25),
field_size VARCHAR(25) DEFAULT 'medium',
field_css VARCHAR(255),
field_layout VARCHAR(255),
field_default TEXT,
PRIMARY KEY (field_id)
) DEFAULT CHARACTER SET $charset COLLATE $collate;";
$form_sql = "CREATE TABLE $form_table_name (
form_id BIGINT(20) NOT NULL AUTO_INCREMENT,
form_key TINYTEXT NOT NULL,
form_title TEXT NOT NULL,
form_email_subject TEXT,
form_email_to TEXT,
form_email_from VARCHAR(255),
form_email_from_name VARCHAR(255),
form_email_from_override VARCHAR(255),
form_email_from_name_override VARCHAR(255),
form_success_type VARCHAR(25) DEFAULT 'text',
form_success_message TEXT,
form_notification_setting VARCHAR(25),
form_notification_email_name VARCHAR(255),
form_notification_email_from VARCHAR(255),
form_notification_email VARCHAR(25),
form_notification_subject VARCHAR(255),
form_notification_message TEXT,
form_notification_entry VARCHAR(25),
form_label_alignment VARCHAR(25),
PRIMARY KEY (form_id)
) DEFAULT CHARACTER SET $charset COLLATE $collate;";
$entries_sql = "CREATE TABLE $entries_table_name (
entries_id BIGINT(20) NOT NULL AUTO_INCREMENT,
form_id BIGINT(20) NOT NULL,
data TEXT NOT NULL,
subject TEXT,
sender_name VARCHAR(255),
sender_email VARCHAR(255),
emails_to TEXT,
date_submitted DATETIME,
ip_address VARCHAR(25),
PRIMARY KEY (entries_id)
) DEFAULT CHARACTER SET $charset COLLATE $collate;";
// Create or Update database tables
dbDelta( $field_sql );
dbDelta( $form_sql );
dbDelta( $entries_sql );
}
/**
* Queue plugin CSS for admin styles
*
* @since 1.0
*/
public function admin_css() {
wp_enqueue_style( 'visual-form-builder-style', plugins_url( "visual-form-builder/css/visual-form-builder-admin$this->load_dev_files.css" ) );
}
/**
* Queue plugin scripts for sorting form fields
*
* @since 1.0
*/
public function admin_scripts() {
wp_enqueue_script( 'jquery-ui-sortable' );
wp_enqueue_script( 'postbox' );
wp_enqueue_script( 'jquery-form-validation', 'https://ajax.aspnetcdn.com/ajax/jquery.validate/1.9/jquery.validate.min.js', array( 'jquery' ), '', true );
wp_enqueue_script( 'form-elements-add', plugins_url( "visual-form-builder/js/visual-form-builder$this->load_dev_files.js" ) , array( 'jquery', 'jquery-form-validation' ), '', true );
wp_enqueue_script( 'nested-sortable', plugins_url( 'visual-form-builder/js/jquery.ui.nestedSortable.js' ) , array( 'jquery', 'jquery-ui-sortable' ), '', true );
}
/**
* Queue form validation scripts
*
* @since 1.0
*/
public function scripts() {
// Make sure scripts are only added once via shortcode
$this->add_scripts = true;
wp_enqueue_script( 'jquery-form-validation', 'https://ajax.aspnetcdn.com/ajax/jquery.validate/1.9/jquery.validate.min.js', array( 'jquery' ), '', true );
wp_enqueue_script( 'jquery-ui-datepicker' );
wp_enqueue_script( 'visual-form-builder-validation', plugins_url( "visual-form-builder/js/visual-form-builder-validate$this->load_dev_files.js" ) , array( 'jquery', 'jquery-form-validation' ), '', true );
wp_enqueue_script( 'visual-form-builder-metadata', plugins_url( 'visual-form-builder/js/jquery.metadata.js' ) , array( 'jquery', 'jquery-form-validation' ), '', true );
}
/**
* Add form CSS to wp_head
*
* @since 1.0
*/
public function css() {
wp_enqueue_style( 'visual-form-builder-css', apply_filters( 'visual-form-builder-css', plugins_url( 'visual-form-builder/css/visual-form-builder.css' ) ) );
wp_enqueue_style( 'vfb-date-picker-css', apply_filters( 'vfb-date-picker-css','https://ajax.aspnetcdn.com/ajax/jquery.ui/1.9.0/themes/base/jquery-ui.css' ) );
wp_enqueue_script( 'visual-form-builder-quicktags', plugins_url( 'visual-form-builder/js/js_quicktags.js' ) );
}
/**
* Actions to save, update, and delete forms/form fields
*
*
* @since 1.0
*/
public function save() {
global $wpdb;
if ( isset( $_REQUEST['page'] ) && in_array( $_REQUEST['page'], array( 'visual-form-builder', 'vfb-add-new' ) ) && isset( $_REQUEST['action'] ) ) {
switch ( $_REQUEST['action'] ) {
case 'create_form' :
$form_key = sanitize_title( $_REQUEST['form_title'] );
$form_title = esc_html( $_REQUEST['form_title'] );
$form_from_name = esc_html( $_REQUEST['form_email_from_name'] );
$form_subject = esc_html( $_REQUEST['form_email_subject'] );
$form_from = esc_html( $_REQUEST['form_email_from'] );
$form_to = serialize( array_map( 'esc_html', $_REQUEST['form_email_to'] ) );
check_admin_referer( 'create_form' );
$newdata = array(
'form_key' => $form_key,
'form_title' => $form_title,
'form_email_from_name' => $form_from_name,
'form_email_subject' => $form_subject,
'form_email_from' => $form_from,
'form_email_to' => $form_to
);
// Create the form
$wpdb->insert( $this->form_table_name, $newdata );
// Get form ID to add our first field
$new_form_selected = $wpdb->insert_id;
// Setup the initial fieldset
$initial_fieldset = array(
'form_id' => $wpdb->insert_id,
'field_key' => 'fieldset',
'field_type' => 'fieldset',
'field_name' => 'Fieldset',
'field_sequence' => 0
);
// Add the first fieldset to get things started
$wpdb->insert( $this->field_table_name, $initial_fieldset );
$verification_fieldset = array(
'form_id' => $new_form_selected,
'field_key' => 'verification',
'field_type' => 'verification',
'field_name' => 'Verification',
'field_description' => '(This is for preventing spam)',
'field_sequence' => 1
);
// Insert the submit field
$wpdb->insert( $this->field_table_name, $verification_fieldset );
$verify_fieldset_parent_id = $wpdb->insert_id;
$secret = array(
'form_id' => $new_form_selected,
'field_key' => 'secret',
'field_type' => 'secret',
'field_name' => 'Please enter any two digits with no spaces (Example: 12)',
'field_size' => 'medium',
'field_required' => 'yes',
'field_parent' => $verify_fieldset_parent_id,
'field_sequence' => 2
);
// Insert the submit field
$wpdb->insert( $this->field_table_name, $secret );
// Make the submit last in the sequence
$submit = array(
'form_id' => $new_form_selected,
'field_key' => 'submit',
'field_type' => 'submit',
'field_name' => 'Submit',
'field_parent' => $verify_fieldset_parent_id,
'field_sequence' => 3
);
// Insert the submit field
$wpdb->insert( $this->field_table_name, $submit );
// Redirect to keep the URL clean (use AJAX in the future?)
wp_redirect( 'admin.php?page=visual-form-builder&form=' . $new_form_selected );
exit();
break;
case 'update_form' :
$form_id = absint( $_REQUEST['form_id'] );
$form_key = sanitize_title( $_REQUEST['form_title'], $form_id );
$form_title = esc_html( $_REQUEST['form_title'] );
$form_subject = esc_html( $_REQUEST['form_email_subject'] );
$form_to = serialize( array_map( 'esc_html', $_REQUEST['form_email_to'] ) );
$form_from = esc_html( $_REQUEST['form_email_from'] );
$form_from_name = esc_html( $_REQUEST['form_email_from_name'] );
$form_from_override = esc_html( $_REQUEST['form_email_from_override'] );
$form_from_name_override = esc_html( $_REQUEST['form_email_from_name_override'] );
$form_success_type = esc_html( $_REQUEST['form_success_type'] );
$form_notification_setting = isset( $_REQUEST['form_notification_setting'] ) ? esc_html( $_REQUEST['form_notification_setting'] ) : '';
$form_notification_email_name = isset( $_REQUEST['form_notification_email_name'] ) ? esc_html( $_REQUEST['form_notification_email_name'] ) : '';
$form_notification_email_from = isset( $_REQUEST['form_notification_email_from'] ) ? sanitize_email( $_REQUEST['form_notification_email_from'] ) : '';
$form_notification_email = isset( $_REQUEST['form_notification_email'] ) ? esc_html( $_REQUEST['form_notification_email'] ) : '';
$form_notification_subject = isset( $_REQUEST['form_notification_subject'] ) ? esc_html( $_REQUEST['form_notification_subject'] ) : '';
$form_notification_message = isset( $_REQUEST['form_notification_message'] ) ? wp_richedit_pre( $_REQUEST['form_notification_message'] ) : '';
$form_notification_entry = isset( $_REQUEST['form_notification_entry'] ) ? esc_html( $_REQUEST['form_notification_entry'] ) : '';
$form_label_alignment = esc_html( $_REQUEST['form_label_alignment'] );
// Add confirmation based on which type was selected
switch ( $form_success_type ) {
case 'text' :
$form_success_message = wp_richedit_pre( $_REQUEST['form_success_message_text'] );
break;
case 'page' :
$form_success_message = esc_html( $_REQUEST['form_success_message_page'] );
break;
case 'redirect' :
$form_success_message = esc_html( $_REQUEST['form_success_message_redirect'] );
break;
}
check_admin_referer( 'update_form-' . $form_id );
$newdata = array(
'form_key' => $form_key,
'form_title' => $form_title,
'form_email_subject' => $form_subject,
'form_email_to' => $form_to,
'form_email_from' => $form_from,
'form_email_from_name' => $form_from_name,
'form_email_from_override' => $form_from_override,
'form_email_from_name_override' => $form_from_name_override,
'form_success_type' => $form_success_type,
'form_success_message' => $form_success_message,
'form_notification_setting' => $form_notification_setting,
'form_notification_email_name' => $form_notification_email_name,
'form_notification_email_from' => $form_notification_email_from,
'form_notification_email' => $form_notification_email,
'form_notification_subject' => $form_notification_subject,
'form_notification_message' => $form_notification_message,
'form_notification_entry' => $form_notification_entry,
'form_label_alignment' => $form_label_alignment
);
$where = array(
'form_id' => $form_id
);
// Update form details
$wpdb->update( $this->form_table_name, $newdata, $where );
// Initialize field sequence
$field_sequence = 0;
// Loop through each field and update all at once
if ( !empty( $_REQUEST['field_id'] ) ) {
foreach ( $_REQUEST['field_id'] as $id ) {
$field_name = ( isset( $_REQUEST['field_name-' . $id] ) ) ? esc_html( $_REQUEST['field_name-' . $id] ) : '';
$field_key = sanitize_title( $field_name, $id );
$field_desc = ( isset( $_REQUEST['field_description-' . $id] ) ) ? esc_html( $_REQUEST['field_description-' . $id] ) : '';
$field_options = ( isset( $_REQUEST['field_options-' . $id] ) ) ? serialize( array_map( 'esc_html', $_REQUEST['field_options-' . $id] ) ) : '';
$field_validation = ( isset( $_REQUEST['field_validation-' . $id] ) ) ? esc_html( $_REQUEST['field_validation-' . $id] ) : '';
$field_required = ( isset( $_REQUEST['field_required-' . $id] ) ) ? esc_html( $_REQUEST['field_required-' . $id] ) : '';
$field_size = ( isset( $_REQUEST['field_size-' . $id] ) ) ? esc_html( $_REQUEST['field_size-' . $id] ) : '';
$field_css = ( isset( $_REQUEST['field_css-' . $id] ) ) ? esc_html( $_REQUEST['field_css-' . $id] ) : '';
$field_layout = ( isset( $_REQUEST['field_layout-' . $id] ) ) ? esc_html( $_REQUEST['field_layout-' . $id] ) : '';
$field_default = ( isset( $_REQUEST['field_default-' . $id] ) ) ? esc_html( $_REQUEST['field_default-' . $id] ) : '';
$field_data = array(
'field_key' => $field_key,
'field_name' => $field_name,
'field_description' => $field_desc,
'field_options' => $field_options,
'field_validation' => $field_validation,
'field_required' => $field_required,
'field_size' => $field_size,
'field_css' => $field_css,
'field_layout' => $field_layout,
'field_sequence' => $field_sequence,
'field_default' => $field_default
);
$where = array(
'form_id' => $_REQUEST['form_id'],
'field_id' => $id
);
// Update all fields
$wpdb->update( $this->field_table_name, $field_data, $where );
$field_sequence++;
}
// Check if a submit field type exists for backwards compatibility upgrades
$is_verification = $wpdb->get_var( $wpdb->prepare( "SELECT field_id FROM $this->field_table_name WHERE field_type = 'verification' AND form_id = %d", $form_id ) );
$is_secret = $wpdb->get_var( $wpdb->prepare( "SELECT field_id FROM $this->field_table_name WHERE field_type = 'secret' AND form_id = %d", $form_id ) );
$is_submit = $wpdb->get_var( $wpdb->prepare( "SELECT field_id FROM $this->field_table_name WHERE field_type = 'submit' AND form_id = %d", $form_id ) );
// Decrement sequence
$field_sequence--;
$verification_id = '';
// If this form doesn't have a verification field, add one
if ( $is_verification == NULL ) {
// Adjust the sequence
$verification_fieldset = array(
'form_id' => $form_id,
'field_key' => 'verification',
'field_type' => 'verification',
'field_name' => 'Verification',
'field_sequence' => $field_sequence
);
// Insert the verification fieldset
$wpdb->insert( $this->field_table_name, $verification_fieldset );
$verification_id = $wpdb->insert_id;
}
// If the verification field was inserted, use that ID as a parent otherwise set no parent
$verify_fieldset_parent_id = ( $verification_id !== false ) ? $verification_id : 0;
// If this form doesn't have a secret field, add one
if ( $is_secret == NULL ) {
// Adjust the sequence
$secret = array(
'form_id' => $form_id,
'field_key' => 'secret',
'field_type' => 'secret',
'field_name' => 'Please enter any two digits with no spaces (Example: 12)',
'field_size' => 'medium',
'field_required' => 'yes',
'field_parent' => $verify_fieldset_parent_id,
'field_sequence' => ++$field_sequence
);
// Insert the submit field
$wpdb->insert( $this->field_table_name, $secret );
}
// If this form doesn't have a submit field, add one
if ( $is_submit == NULL ) {
// Make the submit last in the sequence
$submit = array(
'form_id' => $form_id,
'field_key' => 'submit',
'field_type' => 'submit',
'field_name' => 'Submit',
'field_parent' => $verify_fieldset_parent_id,
'field_sequence' => ++$field_sequence
);
// Insert the submit field
$wpdb->insert( $this->field_table_name, $submit );
}
else {
// Only update the Submit's parent ID if the Verification field is new
$data = ( $is_verification == NULL ) ? array( 'field_parent' => $verify_fieldset_parent_id, 'field_sequence' => ++$field_sequence ) : array( 'field_sequence' => $field_sequence );
$where = array(
'form_id' => $form_id,
'field_id' => $is_submit
);
// Update the submit field
$wpdb->update( $this->field_table_name, $data, $where );
}
}
break;
case 'delete_form' :
$id = absint( $_REQUEST['form'] );
check_admin_referer( 'delete-form-' . $id );
// Delete form and all fields
$wpdb->query( $wpdb->prepare( "DELETE FROM $this->form_table_name WHERE form_id = %d", $id ) );
$wpdb->query( $wpdb->prepare( "DELETE FROM $this->field_table_name WHERE form_id = %d", $id ) );
// Redirect to keep the URL clean (use AJAX in the future?)
wp_redirect( add_query_arg( 'action', 'deleted', 'admin.php?page=visual-form-builder' ) );
exit();
break;
case 'copy_form' :
$id = absint( $_REQUEST['form'] );
check_admin_referer( 'copy-form-' . $id );
// Get all fields and data for the request form
$fields = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $this->field_table_name WHERE form_id = %d", $id ) );
$forms = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $this->form_table_name WHERE form_id = %d", $id ) );
$override = $wpdb->get_var( $wpdb->prepare( "SELECT form_email_from_override, form_email_from_name_override, form_notification_email FROM $this->form_table_name WHERE form_id = %d", $id ) );
$from_name = $wpdb->get_var( null, 1 );
$notify = $wpdb->get_var( null, 2 );
// Copy this form and force the initial title to denote a copy
foreach ( $forms as $form ) {
$data = array(
'form_key' => sanitize_title( $form->form_key . ' copy' ),
'form_title' => $form->form_title . ' Copy',
'form_email_subject' => $form->form_email_subject,
'form_email_to' => $form->form_email_to,
'form_email_from' => $form->form_email_from,
'form_email_from_name' => $form->form_email_from_name,
'form_email_from_override' => $form->form_email_from_override,
'form_email_from_name_override' => $form->form_email_from_name_override,
'form_success_type' => $form->form_success_type,
'form_success_message' => $form->form_success_message,
'form_notification_setting' => $form->form_notification_setting,
'form_notification_email_name' => $form->form_notification_email_name,
'form_notification_email_from' => $form->form_notification_email_from,
'form_notification_email' => $form->form_notification_email,
'form_notification_subject' => $form->form_notification_subject,
'form_notification_message' => $form->form_notification_message,
'form_notification_entry' => $form->form_notification_entry,
'form_label_alignment' => $form->form_label_alignment
);
$wpdb->insert( $this->form_table_name, $data );
}
// Get form ID to add our first field
$new_form_selected = $wpdb->insert_id;
// Copy each field and data
foreach ( $fields as $field ) {
$data = array(
'form_id' => $new_form_selected,
'field_key' => $field->field_key,
'field_type' => $field->field_type,
'field_name' => $field->field_name,
'field_description' => $field->field_description,
'field_options' => $field->field_options,
'field_sequence' => $field->field_sequence,
'field_validation' => $field->field_validation,
'field_required' => $field->field_required,
'field_size' => $field->field_size,
'field_css' => $field->field_css,
'field_layout' => $field->field_layout,
'field_parent' => $field->field_parent
);
$wpdb->insert( $this->field_table_name, $data );
// If a parent field, save the old ID and the new ID to update new parent ID
if ( in_array( $field->field_type, array( 'fieldset', 'section', 'verification' ) ) )
$parents[ $field->field_id ] = $wpdb->insert_id;
if ( $override == $field->field_id )
$wpdb->update( $this->form_table_name, array( 'form_email_from_override' => $wpdb->insert_id ), array( 'form_id' => $new_form_selected ) );
if ( $from_name == $field->field_id )
$wpdb->update( $this->form_table_name, array( 'form_email_from_name_override' => $wpdb->insert_id ), array( 'form_id' => $new_form_selected ) );
if ( $notify == $field->field_id )
$wpdb->update( $this->form_table_name, array( 'form_notification_email' => $wpdb->insert_id ), array( 'form_id' => $new_form_selected ) );
}
// Loop through our parents and update them to their new IDs
foreach ( $parents as $k => $v ) {
$wpdb->update( $this->field_table_name, array( 'field_parent' => $v ), array( 'form_id' => $new_form_selected, 'field_parent' => $k ) );
}
break;
}
}
}
/**
* The jQuery field sorting callback
*
* @since 1.0
*/
public function process_sort_callback() {
global $wpdb;
$data = array();
foreach ( $_REQUEST['order'] as $k ) {
if ( 'root' !== $k['item_id'] ) {
$data[] = array(
'field_id' => $k['item_id'],
'parent' => $k['parent_id']
);
}
}
foreach ( $data as $k => $v ) {
// Update each field with it's new sequence and parent ID
$wpdb->update( $this->field_table_name, array( 'field_sequence' => $k, 'field_parent' => $v['parent'] ), array( 'field_id' => $v['field_id'] ) );
}
die(1);
}
/**
* The jQuery create field callback
*
* @since 1.9
*/
public function create_field_callback() {
global $wpdb;
$data = array();
$field_options = $field_validation = '';
foreach ( $_REQUEST['data'] as $k ) {
$data[ $k['name'] ] = $k['value'];
}
if ( isset( $_REQUEST['page'] ) && $_REQUEST['page'] == 'toplevel_page_visual-form-builder' && isset( $_REQUEST['action'] ) && $_REQUEST['action'] == 'visual_form_builder_create_field' ) {
$form_id = absint( $data['form_id'] );
$field_key = sanitize_title( $_REQUEST['field_type'] );
$field_name = esc_html( $_REQUEST['field_type'] );
$field_type = strtolower( sanitize_title( $_REQUEST['field_type'] ) );
// Set defaults for validation
switch ( $field_type ) {
case 'select' :
case 'radio' :
case 'checkbox' :
$field_options = serialize( array( 'Option 1', 'Option 2', 'Option 3' ) );
break;
case 'email' :
case 'url' :
case 'phone' :
$field_validation = $field_type;
break;
case 'currency' :
$field_validation = 'number';
break;
case 'number' :
$field_validation = 'digits';
break;
case 'time' :
$field_validation = 'time-12';
break;
case 'file-upload' :
$field_options = serialize( array( 'png|jpe?g|gif' ) );
break;
}
check_ajax_referer( 'create-field-' . $data['form_id'], 'nonce' );
// Get the last row's sequence that isn't a Verification
$sequence_last_row = $wpdb->get_var( $wpdb->prepare( "SELECT field_sequence FROM $this->field_table_name WHERE form_id = %d AND field_type = 'verification' ORDER BY field_sequence DESC LIMIT 1", $form_id ) );
// If it's not the first for this form, add 1
$field_sequence = ( !empty( $sequence_last_row ) ) ? $sequence_last_row : 0;
$newdata = array(
'form_id' => $form_id,
'field_key' => $field_key,
'field_name' => $field_name,
'field_type' => $field_type,
'field_options' => $field_options,
'field_sequence' => $field_sequence,
'field_validation' => $field_validation
);
// Create the field
$wpdb->insert( $this->field_table_name, $newdata );
$insert_id = $wpdb->insert_id;
$update_these = array( 'verification', 'secret', 'submit' );
foreach ( $update_these as $update ) {
$where = array(
'form_id' => absint( $data['form_id'] ),
'field_type' => $update
);
$wpdb->update( $this->field_table_name, array( 'field_sequence' => $field_sequence + 1 ), $where );
$field_sequence++;
}
echo $this->field_output( $data['form_id'], $insert_id );
}
die(1);
}
/**
* The jQuery delete field callback
*
* @since 1.9
*/
public function delete_field_callback() {
global $wpdb;
if ( isset( $_REQUEST['page'] ) && $_REQUEST['page'] == 'toplevel_page_visual-form-builder' && isset( $_REQUEST['action'] ) && $_REQUEST['action'] == 'visual_form_builder_delete_field' ) {
$form_id = absint( $_REQUEST['form'] );
$field_id = absint( $_REQUEST['field'] );
check_ajax_referer( 'delete-field-' . $form_id, 'nonce' );
if ( isset( $_REQUEST['child_ids'] ) ) {
foreach ( $_REQUEST['child_ids'] as $children ) {
$parent = absint( $_REQUEST['parent_id'] );
// Update each child item with the new parent ID
$wpdb->update( $this->field_table_name, array( 'field_parent' => $parent ), array( 'field_id' => $children ) );
}
}
// Delete the field
$wpdb->query( $wpdb->prepare( "DELETE FROM $this->field_table_name WHERE field_id = %d", $field_id ) );
}
die(1);
}
/**
* The jQuery form settings callback
*
* @since 2.2
*/
public function form_settings_callback() {
global $current_user;
get_currentuserinfo();
if ( isset( $_REQUEST['action'] ) && $_REQUEST['action'] == 'visual_form_builder_form_settings' ) {
$form_id = absint( $_REQUEST['form'] );
$status = isset( $_REQUEST['status'] ) ? $_REQUEST['status'] : 'opened';
$accordion = isset( $_REQUEST['accordion'] ) ? $_REQUEST['accordion'] : 'general-settings';
$user_id = $current_user->ID;
$form_settings = get_user_meta( $user_id, 'vfb-form-settings', true );
$array = array(
'form_setting_tab' => $status,
'setting_accordion' => $accordion
);
// Set defaults if meta key doesn't exist
if ( !$form_settings || $form_settings == '' ) {
$meta_value[ $form_id ] = $array;
update_user_meta( $user_id, 'vfb-form-settings', $meta_value );
}
else {
$form_settings[ $form_id ] = $array;
update_user_meta( $user_id, 'vfb-form-settings', $form_settings );
}
}
die(1);
}
/**
* All Forms output in admin
*
* @since 2.5
*/
public function all_forms() {
global $wpdb;
$order = sanitize_sql_orderby( 'form_title ASC' );
$where = apply_filters( 'vfb_pre_get_forms', '' );
$forms = $wpdb->get_results( "SELECT * FROM $this->form_table_name WHERE 1=1 $where ORDER BY $order" );
$a = array();
if ( $forms ) :
// Loop through each for and build the tabs
foreach ( $forms as $form ) {
$form_id = $form->form_id;
$form_title = stripslashes( $form->form_title );
$entries_count = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM $this->entries_table_name WHERE form_id = %d", $form_id ) );
$sort = substr( strtoupper( $form_title ), 0, 1 );
if ( preg_match( '/[0-9]/i', $sort ) )
$sort = '0-9';
$a[ $sort ][] = array(
'id' => $form_id,
'title' => $form_title,
'entries_count' => $entries_count
);
}
?>
get_results( $wpdb->prepare( "SELECT * FROM $this->field_table_name WHERE form_id = %d $field_where ORDER BY field_sequence ASC", $form_nav_selected_id ) );
$depth = 1;
$parent = $last = 0;
// Loop through each field and display
foreach ( $fields as $field ) :
// If we are at the root level
if ( !$field->field_parent && $depth > 1 ) {
// If we've been down a level, close out the list
while ( $depth > 1 ) {
echo '
';
$depth--;
}
// Close out the root item
echo '';
}
// first item of , so move down a level
elseif ( $field->field_parent && $field->field_parent == $last ) {
echo '';
$depth++;
}
// Close up a and move up a level
elseif ( $field->field_parent && $field->field_parent != $parent ) {
echo '
';
$depth--;
}
// Same level so close list item
elseif ( $field->field_parent && $field->field_parent == $parent )
echo '';
// Store item ID and parent ID to test for nesting
$last = $field->field_id;
$parent = $field->field_parent;
?>
and are closed
if ( $depth > 1 ) {
while( $depth > 1 ) {
echo '
';
$depth--;
}
}
// Close out last item
echo '';
}
/**
* Display admin notices
*
* @since 1.0
*/
public function admin_notices(){
if ( isset( $_REQUEST['action'] ) ) {
switch( $_REQUEST['action'] ) {
case 'create_form' :
echo __( 'The form has been successfully created.
' , 'visual-form-builder');
break;
case 'update_form' :
echo sprintf( __( 'The %s form has been updated.
' , 'visual-form-builder'), stripslashes( $_REQUEST['form_title'] ) );
break;
case 'deleted' :
echo __( 'The form has been successfully deleted.
' , 'visual-form-builder');
break;
case 'copy_form' :
echo __( 'The form has been successfully duplicated.
' , 'visual-form-builder');
break;
}
}
}
/**
* Add options page to Settings menu
*
*
* @since 1.0
* @uses add_options_page() Creates a menu item under the Settings menu.
*/
public function add_admin() {
add_menu_page( __( 'Visual Form Builder', 'visual-form-builder' ), __( 'Visual Form Builder', 'visual-form-builder' ), 'manage_options', 'visual-form-builder', array( &$this, 'admin' ), plugins_url( 'visual-form-builder/images/vfb_icon.png' ) );
add_submenu_page( 'visual-form-builder', __( 'Visual Form Builder', 'visual-form-builder' ), __( 'All Forms', 'visual-form-builder' ), 'manage_options', 'visual-form-builder', array( &$this, 'admin' ) );
add_submenu_page( 'visual-form-builder', __( 'Add New Form', 'visual-form-builder' ), __( 'Add New Form', 'visual-form-builder' ), 'manage_options', 'vfb-add-new', array( &$this, 'admin' ) );
add_submenu_page( 'visual-form-builder', __( 'Entries', 'visual-form-builder' ), __( 'Entries', 'visual-form-builder' ), 'manage_options', 'vfb-entries', array( &$this, 'admin' ) );
add_submenu_page( 'visual-form-builder', __( 'Export', 'visual-form-builder' ), __( 'Export', 'visual-form-builder' ), 'manage_options', 'vfb-export', array( &$this, 'admin' ) );
}
/**
* Builds the options settings page
*
* @since 1.0
*/
public function admin() {
global $wpdb, $current_user, $entries_list, $entries_detail, $export;
get_currentuserinfo();
// Save current user ID
$user_id = $current_user->ID;
// Set variables depending on which tab is selected
$form_nav_selected_id = ( isset( $_REQUEST['form'] ) ) ? $_REQUEST['form'] : '0';
?>
' . sprintf( __( 'Search results for "%s"' , 'visual-form-builder'), $_REQUEST['s'] ) : '';
?>
array( 'page' => __( 'Forms', 'visual-form-builder' ) ),
'vfb-entries' => array( 'page' => __( 'Entries', 'visual-form-builder' ) ),
'vfb-export' => array( 'page' => __( 'Export', 'visual-form-builder' ) )
);
foreach ( $pages as $page => $args ) {
$class = ( isset( $_REQUEST['page'] ) && in_array( $_REQUEST['page'], array( $page ) ) ) ? 'current' : '';
$views[ $args['page'] ] = "\t{$args['page']} ";
}
echo implode( ' | ', $views ) . '';
?>
entries_detail();
else :
$entries_list->prepare_items();
?>
display();
// Display the Forms
else:
if ( empty( $form_nav_selected_id ) ) :
?>
get_results( $wpdb->prepare( "SELECT * FROM $this->form_table_name WHERE form_id = %d ORDER BY $order", $form_id ) );
foreach ( $forms as $form ) {
// If text, return output and format the HTML for display
if ( 'text' == $form->form_success_type )
return stripslashes( html_entity_decode( wp_kses_stripslashes( $form->form_success_message ) ) );
// If page, redirect to the permalink
elseif ( 'page' == $form->form_success_type ) {
$page = get_permalink( $form->form_success_message );
wp_redirect( $page );
exit();
}
// If redirect, redirect to the URL
elseif ( 'redirect' == $form->form_success_type ) {
wp_redirect( $form->form_success_message );
exit();
}
}
}
}
/**
* Output form via shortcode
*
* @since 1.0
*/
public function form_code( $atts, $output = '' ) {
require( trailingslashit( plugin_dir_path( __FILE__ ) ) . 'includes/form-output.php' );
return $output;
}
/**
* Handle emailing the content
*
* @since 1.0
* @uses wp_mail() E-mails a message
*/
public function email() {
require( trailingslashit( plugin_dir_path( __FILE__ ) ) . 'includes/email.php' );
}
/**
* Validate the input
*
* @since 2.2
*/
public function validate_input( $data, $name, $type, $required ) {
if ( 'yes' == $required && strlen( $data ) == 0 )
wp_die( "$name " . __( 'This field is required and cannot be empty.', 'visual-form-builder' ), $name, array( 'back_link' => true ) );
if ( strlen( $data ) > 0 ) :
switch( $type ) {
case 'email' :
if ( !is_email( $data ) )
wp_die( "$name " . __( 'Not a valid email address', 'visual-form-builder' ), '', array( 'back_link' => true ) );
break;
case 'number' :
case 'currency' :
if ( !is_numeric( $data ) )
wp_die( "$name " . __( 'Not a valid number', 'visual-form-builder' ), '', array( 'back_link' => true ) );
break;
case 'phone' :
if ( strlen( $data ) > 9 && preg_match( '/^((\+)?[1-9]{1,2})?([-\s\.])?((\(\d{1,4}\))|\d{1,4})(([-\s\.])?[0-9]{1,12}){1,2}$/', $data ) )
return true;
else
wp_die( "$name " . __( 'Not a valid phone number. Most US/Canada and International formats accepted.', 'visual-form-builder' ), '', array( 'back_link' => true ) );
break;
case 'url' :
if ( !preg_match( '|^http(s)?://[a-z0-9-]+(.[a-z0-9-]+)*(:[0-9]+)?(/.*)?$|i', $data ) )
wp_die( "$name " . __( 'Not a valid URL.', 'visual-form-builder' ), '', array( 'back_link' => true ) );
break;
default :
return true;
break;
}
endif;
}
/**
* Sanitize the input
*
* @since 2.5
*/
public function sanitize_input( $data, $type ) {
if ( strlen( $data ) > 0 ) :
switch( $type ) {
case 'text' :
return sanitize_text_field( $data );
break;
case 'textarea' :
return wpautop( $data );
break;
case 'email' :
return sanitize_email( $data );
break;
case 'username' :
return sanitize_user( $data );
break;
default :
return $data;
break;
}
endif;
}
/**
* Make sure the User Agent string is not a SPAM bot
*
* @since 1.3
*/
public function isBot() {
$bots = apply_filters( 'vfb_blocked_spam_bots', array( 'archiver', 'binlar', 'casper', 'checkprivacy', 'clshttp', 'cmsworldmap', 'comodo', 'curl', 'diavol', 'dotbot', 'email', 'extract', 'feedfinder', 'flicky', 'grab', 'harvest', 'httrack', 'ia_archiver', 'jakarta', 'kmccrew', 'libwww', 'loader', 'miner', 'nikto', 'nutch', 'planetwork', 'purebot', 'pycurl', 'python', 'scan', 'skygrid', 'sucker', 'turnit', 'vikspider', 'wget', 'winhttp', 'youda', 'zmeu', 'zune' ) );
$isBot = false;
foreach ( $bots as $bot ) {
if ( stripos( $_SERVER['HTTP_USER_AGENT'], $bot ) !== false )
$isBot = true;
}
if ( empty($_SERVER['HTTP_USER_AGENT'] ) || $_SERVER['HTTP_USER_AGENT'] == ' ' )
$isBot = true;
return $isBot;
}
}
// On plugin activation, install the databases and add/update the DB version
register_activation_hook( __FILE__, array( 'Visual_Form_Builder', 'install_db' ) );
?>