Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save robertdevore/e7559769b22e00956664ee9c2de940c3 to your computer and use it in GitHub Desktop.
Save robertdevore/e7559769b22e00956664ee9c2de940c3 to your computer and use it in GitHub Desktop.
Adding Fluent Forms data to the DB Version Control plugin export

Fluent Forms Compatibility with DB Version Control

Fluent Forms uses its own custom database tables (like wp_fluentform_forms, wp_fluentform_submissions, etc.) which are completely separate from the standard WordPress posts/meta tables that our plugin currently handles.

DB Version Control would NOT work out of the box for Fluent Forms data because it only exports:

  • WordPress posts (wp_posts)
  • Post meta (wp_postmeta)
  • WordPress options (wp_options)
  • Navigation menus

Solution: Custom Filter Implementation

Here's how you can add Fluent Forms support using our plugin's extensible filter system:

// Add this to your theme's functions.php or a custom plugin

/**
 * Export Fluent Forms data after post export
 */
add_action( 'dbvc_after_export_options', 'export_fluent_forms_data' );

function export_fluent_forms_data( $file_path, $options_data ) {
    global $wpdb;
    
    // Get the sync path
    $sync_path = dbvc_get_sync_path();
    
    // Export Fluent Forms
    $forms_table = $wpdb->prefix . 'fluentform_forms';
    if ( $wpdb->get_var( "SHOW TABLES LIKE '$forms_table'" ) === $forms_table ) {
        $forms = $wpdb->get_results( "SELECT * FROM $forms_table", ARRAY_A );
        
        if ( ! empty( $forms ) ) {
            file_put_contents(
                $sync_path . 'fluent-forms.json',
                wp_json_encode( $forms, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES )
            );
        }
    }
    
    // Export Fluent Forms Submissions
    $submissions_table = $wpdb->prefix . 'fluentform_submissions';
    if ( $wpdb->get_var( "SHOW TABLES LIKE '$submissions_table'" ) === $submissions_table ) {
        $submissions = $wpdb->get_results( "SELECT * FROM $submissions_table", ARRAY_A );
        
        if ( ! empty( $submissions ) ) {
            file_put_contents(
                $sync_path . 'fluent-form-submissions.json',
                wp_json_encode( $submissions, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES )
            );
        }
    }
    
    // Export Fluent Forms Entry Details
    $entry_details_table = $wpdb->prefix . 'fluentform_entry_details';
    if ( $wpdb->get_var( "SHOW TABLES LIKE '$entry_details_table'" ) === $entry_details_table ) {
        $entry_details = $wpdb->get_results( "SELECT * FROM $entry_details_table", ARRAY_A );
        
        if ( ! empty( $entry_details ) ) {
            file_put_contents(
                $sync_path . 'fluent-form-entry-details.json',
                wp_json_encode( $entry_details, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES )
            );
        }
    }
}

/**
 * Import Fluent Forms data after options import
 */
add_action( 'wp_loaded', function() {
    if ( defined( 'WP_CLI' ) && WP_CLI ) {
        add_action( 'dbvc_after_import_options', 'import_fluent_forms_data' );
    }
});

function import_fluent_forms_data() {
    global $wpdb;
    
    $sync_path = dbvc_get_sync_path();
    
    // Import Fluent Forms
    $forms_file = $sync_path . 'fluent-forms.json';
    if ( file_exists( $forms_file ) ) {
        $forms = json_decode( file_get_contents( $forms_file ), true );
        
        if ( ! empty( $forms ) ) {
            $forms_table = $wpdb->prefix . 'fluentform_forms';
            
            foreach ( $forms as $form ) {
                $wpdb->replace( $forms_table, $form );
            }
        }
    }
    
    // Import Fluent Forms Submissions
    $submissions_file = $sync_path . 'fluent-form-submissions.json';
    if ( file_exists( $submissions_file ) ) {
        $submissions = json_decode( file_get_contents( $submissions_file ), true );
        
        if ( ! empty( $submissions ) ) {
            $submissions_table = $wpdb->prefix . 'fluentform_submissions';
            
            foreach ( $submissions as $submission ) {
                $wpdb->replace( $submissions_table, $submission );
            }
        }
    }
    
    // Import Fluent Forms Entry Details
    $entry_details_file = $sync_path . 'fluent-form-entry-details.json';
    if ( file_exists( $entry_details_file ) ) {
        $entry_details = json_decode( file_get_contents( $entry_details_file ), true );
        
        if ( ! empty( $entry_details ) ) {
            $entry_details_table = $wpdb->prefix . 'fluentform_entry_details';
            
            foreach ( $entry_details as $detail ) {
                $wpdb->replace( $entry_details_table, $detail );
            }
        }
    }
}

What This Code Does

  1. Export: Hooks into dbvc_after_export_options to export all Fluent Forms tables as separate JSON files
  2. Import: Hooks into a custom action to import the Fluent Forms data back
  3. Tables Covered: Forms definitions, submissions, and entry details
  4. Safety: Checks if tables exist before attempting to query them

Important Considerations

Limitations to Consider:

  • File uploads: Fluent Forms file uploads stored in /wp-content/uploads/ won't be synced
  • Large datasets: Form submissions could be massive - you might want to add date filters
  • Primary keys: Auto-increment IDs might cause conflicts between environments

File Structure After Export:

sync-folder/
├── options.json
├── menus.json
├── fluent-forms.json              # Form definitions
├── fluent-form-submissions.json   # Form submissions
├── fluent-form-entry-details.json # Entry details
└── post/
    └── ...

Why This Approach Works

This is exactly why our plugin's extensible architecture with filters and actions is so powerful - it can be extended to handle any WordPress data structure, not just the core WordPress tables.

The same pattern can be applied to:

  • Contact Form 7 data
  • Gravity Forms entries
  • WooCommerce order data
  • Custom plugin tables
  • Any database table your site uses

The plugin provides the foundation and workflow, while filters let you customize exactly what data gets synchronized for your specific use case.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment