|
/ Documentation /Developer Documentation/ SureForms Pro WordPress Plugin Integrations – Developer Guide (WordPress-Based)

SureForms Pro WordPress Plugin Integrations – Developer Guide (WordPress-Based)

Overview

SureForms Pro WordPress Plugin Integrations system allows you to create integrations with WordPress plugins using a hybrid approach: JSON configuration for metadata and PHP classes for action execution.

Key Features

Plugin Detection – Automatic detection of active WordPress plugins
JSON Configuration – Metadata and fields defined in JSON
PHP Action Classes – Business logic handled in PHP classes
Test Workflows – Real execution testing with cleanup capabilities
Dynamic Fields – WordPress filter-based field discovery
Action Hooks – WordPress hook system integration

Quick Start Tutorial

Unlike generic API integrations that use only JSON, WordPress plugin integrations require:

  1. JSON Configuration – Basic metadata and field definitions
  2. PHP Action Classes – Business logic and plugin interaction
  3. WordPress Hooks – Integration with plugin’s action system

Step-by-Step Integration Creation

Step 1: Create the Integration Metadata (JSON)

Create a config.json file in your integration directory:

PHP
{
  "id": "your-plugin",
  "integration": {
    "name": "Your Plugin",
    "icon": "your-plugin.svg",
    "website_url": "https://yourplugin.com",
    "docs_url": "https://docs.yourplugin.com",
    "category": "Your Category",
    "description": "Integration with Your Plugin"
  },
  "provider": "wordpress",
  "plugin_detection": {
    "class": "YourPluginMainClass"
  },
  "auth": {
    "type": "plugin_detection",
    "test_endpoint": {
      "method": "plugin_check",
      "success_criteria": {
        "plugin_active": true
      }
    }
  },
  "actions": [
    {
      "name": "Create Record",
      "description": "Create a new record in Your Plugin",
      "provider": "wordpress",
      "handler": {
        "type": "action",
        "action": "your_plugin_create_record"
      },
      "fields": [
        {
          "key": "name",
          "label": "Name",
          "type": "text",
          "required": true,
          "placeholder": "Enter name",
          "description": "Record name"
        },
        {
          "key": "email",
          "label": "Email",
          "type": "email",
          "required": true,
          "placeholder": "[email protected]",
          "description": "Email address"
        }
      ],
      "apis": {
        "custom_fields": {
          "filter": "your_plugin_get_custom_fields",
          "response_type": "dynamic_fields",
          "dependencies": []
        }
      }
    }
  ]
}

Key Configuration Elements:

  • provider: “wordpress” – Identifies this as a WordPress plugin integration
  • plugin_detection.class – WordPress class to check for plugin activation
  • handler.type: “action” – Use WordPress action hooks for execution
  • handler.action – WordPress action name (prefixed with srfm_ during execution)
  • apis.filter – WordPress filter for dynamic field discovery

**Important Note: All action names and filter names defined in your config.json will be automatically prefixed with “srfm_” when used in the WordPress hook system. For example:

  • Action “your_plugin_create_record” becomes WordPress action srfm_your_plugin_create_record

Filter “your_plugin_get_custom_fields” becomes WordPress filter srfm_your_plugin_get_custom_fields
You must use these prefixed names when registering your callbacks in PHP code.

Step 2: Create the PHP Action Class

Create your action class extending WordPress_Action:

PHP
<?php
namespace SRFM_Pro\Inc\Pro\Native_Integrations\Integrations\YourPlugin\Actions;

use SRFM_Pro\Inc\Pro\Native_Integrations\WordPress_Action;
use SRFM_Pro\Inc\Traits\Get_Instance;

if ( ! defined( 'ABSPATH' ) ) {
    exit; // Exit if accessed directly.
}

class Create_Record extends WordPress_Action {
    use Get_Instance;

    /**
     * Integration name
     */
    protected $integration = 'YourPlugin';

    /**
     * Action name
     */
    protected $action = 'create_record';

    /**
     * Check if plugin is active
     */
    protected function is_plugin_active() {
        return class_exists( 'YourPluginMainClass' );
    }

    /**
     * Execute the action
     *
     * @param array $data Form submission data.
     * @return array|WP_Error Result of the action execution.
     */
    protected function execute( $data ) {
        // Check if this is test mode execution
        is_test_mode = isset( $data['_test_mode'] ) && true === data['_test_mode'];

        // Remove test mode flags from data for processing
        if ( $is_test_mode ) {
            unset( $data['_test_mode'] );
            // Add test identifier if needed
            data['notes'] = ( data['notes'] ?? '' ) . "\n\n[TEST RECORD - Created by SureForms workflow test]";
        }

        // Validate required data
        $required_fields = [ 'name', 'email' ];
        validation = $this->validate_required_fields( $data, required_fields );

        if ( is_wp_error( $validation ) ) {
            return $validation;
        }

        try {
            // Your plugin's business logic here
            $record = new \YourPluginRecordModel();
            $record->set_data([
                'name'  => $data['name'],
                'email' => $data['email'],
                'notes' => $data['notes'] ?? '',
            ]);

            if ( ! $record->save() ) {
                throw new \Exception( 'Failed to save record.' );
            }

            // Fire plugin's native hooks if available
            do_action( 'your_plugin_record_created', $record );

            return [
                'success'   => true,
                'message'   => __( 'Record created successfully!', 'sureforms-pro' ),
                'record_id' => $record->id,
            ];

        } catch ( \Exception $e ) {
            return new \WP_Error(
                'record_creation_failed',
                sprintf(
                    __( 'Record creation failed: %s', 'sureforms-pro' ),
                    $e->getMessage()
                )
            );
        }
    }
}

// Initialize the action when this file is loaded
Create_Record::get_instance();

Step 3: Create the Integration Handler

Create an integration handler to manage filters and load action files:

PHP
<?php
namespace SRFM_Pro\Inc\Pro\Native_Integrations\Integrations\YourPlugin;

use SRFM_Pro\Inc\Traits\Get_Instance;

if ( ! defined( 'ABSPATH' ) ) {
    exit; // Exit if accessed directly.
}

class YourPlugin_Integration {
    use Get_Instance;

    public function __construct() {
        $this->register_filters();
    }

    /**
     * Get custom fields from your plugin
     */
    public function get_custom_fields( $fields = [] ) {
        if ( ! $this->is_plugin_active() ) {
            return $fields;
        }

        try {
            // Your plugin's custom field discovery logic
            $custom_fields = \YourPluginCustomFields::get_all_fields();
            
            $formatted_fields = [];
            foreach ( custom_fields as field ) {
                $formatted_fields[] = [
                    'key'         => $field['id'],
                    'label'       => $field['label'],
                    'type'        => $field['type'],
                    'required'    => $field['required'] ?? false,
                    'description' => $field['description'] ?? '',
                ];
            }

            return $formatted_fields;

        } catch ( \Exception $e ) {
            return $fields;
        }
    }

    /**
     * Check if plugin is active
     */
    private function is_plugin_active() {
        return class_exists( 'YourPluginMainClass' );
    }

    /**
     * Register WordPress filters
     */
    private function register_filters() {
        if ( ! $this->is_plugin_active() ) {
            return;
        }

        // Register filter for dynamic fields
        add_filter( 'srfm_your_plugin_get_custom_fields', [ $this, 'get_custom_fields' ] );

        // Load action files
        $this->load_action_files();
    }

    /**
     * Load action files
     */
    private function load_action_files() {
        $action_files = [
            __DIR__ . '/actions/create-record.php',
        ];

        foreach ( action_files as file ) {
            if ( file_exists( $file ) ) {
                require_once $file;
            }
        }
    }
}

// Initialize the integration
YourPlugin_Integration::get_instance();

Step 4: Register Your Integration

WordPress plugin integrations require two separate filter registrations. Add both to your plugin’s initialization file:

4.1: Register JSON Configuration

PHP
// Register the JSON configuration
add_filter( 'srfm_pro_native_integrations_json_configs', 'add_your_plugin_integration_config' );

function add_your_plugin_integration_config( $json_configs ) {
    // Your JSON configuration from Step 1
    $your_plugin_config = [
        'integrations' => [
            [
                'id' => 'your-plugin',
                'integration' => [
                    'name' => 'Your Plugin',
                    'icon' => 'your-plugin.svg',
                    'website_url' => 'https://yourplugin.com',
                    'docs_url' => 'https://docs.yourplugin.com',
                    'category' => 'Your Category',
                    'description' => 'Integration with Your Plugin'
                ],
                'provider' => 'wordpress',
                'plugin_detection' => [
                    'class' => 'YourPluginMainClass'
                ],
                'auth' => [
                    'type' => 'plugin_detection',
                    'test_endpoint' => [
                        'method' => 'plugin_check',
                        'success_criteria' => [
                            'plugin_active' => true
                        ]
                    ]
                ],
                'actions' => [
                    // Your actions from JSON config
                ]
            ]
        ]
    ];

    json_configs[] = wp_json_encode( your_plugin_config );
    return $json_configs;
}

4.2: Register PHP Handler Files

PHP
// Register the PHP integration handler
add_filter( 'srfm_pro_wordpress_plugin_integrations', 'register_your_plugin_integration_handler' );

function register_your_plugin_integration_handler( $plugin_integrations ) {
    $plugin_integrations['yourplugin'] = [
        'file'      => plugin_dir_path( __FILE__ ) . 'integrations/sureforms/actions.php',
        'detection' => 'YourPluginMainClass', // Your plugin's main class
    ];

    return $plugin_integrations;
}
Registration Details:

JSON Configuration Filter (srfm_pro_native_integrations_json_configs):

  • Provides the integration metadata, fields, and action definitions
  • Must be JSON-encoded string added to the configs array
  • Contains the complete JSON structure from Step 1

PHP Handler Filter (srfm_pro_wordpress_plugin_integrations):

  • Registers the PHP files that contain action classes
  • file: Path to your integration handler file (actions.php)
  • detection: Main class name used to detect if your plugin is active

This dual-filter approach allows your plugin to register its SureForms integration without requiring modifications to the SureForms Pro codebase.

WordPress Action Classes

Base Class: WordPress_Action

All WordPress plugin actions must extend the WordPress_Action base class:

PHP
abstract class WordPress_Action {
    /**
     * Integration name - must be set in child class
     */
    protected $integration = '';

    /**
     * Action name - must be set in child class  
     */
    protected $action = '';

    /**
     * Check if target plugin is active - must be implemented
     */
    abstract protected function is_plugin_active();

    /**
     * Execute the action - must be implemented
     */
    abstract protected function execute( $data );

    /**
     * Validate required fields - utility method
     */
    protected function validate_required_fields( data, required_fields ) {
        // Built-in validation logic
    }

    /**
     * Store result for retrieval by provider - utility method
     */
    protected function store_result( $result ) {
        // Built-in result storage
    }
}

Action Registration

Actions are automatically registered when their files are loaded. The base class handles:

  • WordPress Hook Registration – Registers action hook using srfm_{integration}_{action} pattern
  • Error Handling – Catches exceptions and converts to WP_Error
  • Result Storage – Stores results for provider retrieval
  • Plugin Detection – Validates the plugin is active before execution

Test Mode Handling

WordPress actions support test mode execution:

PHP
protected function execute( $data ) {
    // Check if this is test mode execution
    is_test_mode = isset( $data['_test_mode'] ) && true === data['_test_mode'];

    // Remove test mode flags from data
    if ( $is_test_mode ) {
        unset( $data['_test_mode'] );
        // Add test identifiers if needed
        data['notes'] = ( data['notes'] ?? '' ) . "\n\n[TEST RECORD]";
    }

    // Same execution logic for both test and real mode
    // Test mode executes real operations - no simulation
}

Field Types Reference

Static Fields (JSON Configuration)

PHP
{
  "key": "field_name",
  "label": "Field Label",
  "type": "text|email|password|number|textarea|dropdown",
  "required": true|false,
  "placeholder": "Placeholder text",
  "description": "Field description",
  "options": [
    {"label": "Option 1", "value": "value1"},
    {"label": "Option 2", "value": "value2"}
  ]
}

Dynamic Fields (WordPress Filters)

Dynamic fields are discovered through WordPress filters:

    PHP
    {
      "apis": {
        "custom_fields": {
          "filter": "your_plugin_get_custom_fields",
          "response_type": "dynamic_fields",
          "dependencies": []
        }
      }
    }

    The corresponding PHP filter:

    PHP
    add_filter( 'srfm_your_plugin_get_custom_fields', function( $fields ) {
        return [
            [
                'key'         => 'custom_field_1',
                'label'       => 'Custom Field 1',
                'type'        => 'text',
                'required'    => false,
                'description' => 'A custom field',
            ]
        ];
    });
    

    Advanced Features

    Field Dependencies

    Create dependent dropdowns using WordPress filters:

    PHP
    {
      "fields": [
        {
          "key": "category_id",
          "label": "Select Category",
          "type": "select-async",
          "exclude_from_payload": true
        },
        {
          "key": "item_id",
          "label": "Select Item",
          "type": "select-async",
          "dependent_on": "category_id"
        }
      ],
      "apis": {
        "categories": {
          "filter": "your_plugin_get_categories",
          "response_type": "select_options",
          "target_fields": ["category_id"],
          "dependencies": []
        },
        "items": {
          "filter": "your_plugin_get_items",
          "response_type": "select_options", 
          "target_fields": ["item_id"],
          "dependencies": ["category_id"]
        }
      }
    }

    PHP filter implementation:

    PHP
    add_filter( 'srfm_your_plugin_get_items', function( options, parameters ) {
        category_id = parameters['category_id'] ?? '';
        
        if ( empty( $category_id ) ) {
            return [];
        }
    
        items = YourPlugin::get_items_by_category( category_id );
        
        $formatted_options = [];
        foreach ( items as item ) {
            $formatted_options[] = [
                'label' => $item->name,
                'value' => $item->id,
            ];
        }
    
        return $formatted_options;
    }, 10, 2 );
    

    Multiple Actions

    Add multiple actions to a single integration:

    PHP
    {
      "actions": [
        {
          "name": "Create Customer",
          "handler": {
            "type": "action",
            "action": "your_plugin_create_customer"
          }
        },
        {
          "name": "Create Order", 
          "handler": {
            "type": "action",
            "action": "your_plugin_create_order"
          }
        }
      ]
    }
    

    Each action requires its own PHP class:

    • actions/create-order.php
    • actions/create-customer.php

    Error Handling

    WordPress actions should return standardized results:

    PHP
    // Success result
    return [
        'success' => true,
        'message' => __( 'Operation completed successfully!', 'sureforms-pro' ),
        'data'    => $additional_data, // Optional
    ];
    
    // Error result using WP_Error
    return new \WP_Error(
        'operation_failed',
        __( 'Operation failed: Error details', 'sureforms-pro' )
    );
    

    WordPress Hook Integration

    Actions can trigger WordPress hooks for ecosystem integration:

    PHP
    protected function execute( $data ) {
        // Execute business logic
        result = $this->create_record( data );
    
        // Fire WordPress hooks for other plugins
        do_action( 'your_plugin_record_created', result, data );
        do_action( 'your_plugin_sureforms_integration_executed', this->action, result );
    
        return $result;
    }
    

    Complete Example

    Directory Structure

    Plaintext
    inc/pro/native-integrations/integrations/latepoint/
    ├── config.json
    ├── actions.php
    └── actions/
        └── create-customer.php
    

    config.json

    PHP
    {
      "id": "latepoint",
      "integration": {
        "name": "LatePoint",
        "icon": "latepoint.svg",
        "website_url": "https://latepoint.com",
        "docs_url": "https://latepoint.com/documentation/",
        "category": "Booking & Appointments",
        "description": "Create bookings and manage appointments in LatePoint booking system"
      },
      "provider": "wordpress",
      "plugin_detection": {
        "class": "OsBookingModel"
      },
      "auth": {
        "type": "plugin_detection",
        "test_endpoint": {
          "method": "plugin_check",
          "success_criteria": {
            "plugin_active": true
          }
        }
      },
      "actions": [
        {
          "name": "Create Customer",
          "description": "Create a new customer in LatePoint",
          "provider": "wordpress",
          "handler": {
            "type": "action",
            "action": "latepoint_create_customer"
          },
          "fields": [
            {
              "key": "first_name",
              "label": "First Name",
              "type": "text",
              "required": true,
              "placeholder": "John",
              "description": "Customer's first name"
            },
            {
              "key": "last_name",
              "label": "Last Name", 
              "type": "text",
              "required": true,
              "placeholder": "Doe",
              "description": "Customer's last name"
            },
            {
              "key": "email",
              "label": "Email",
              "type": "email",
              "required": true,
              "placeholder": "[email protected]",
              "description": "Customer's email address"
            }
          ],
          "apis": {
            "customer_fields": {
              "filter": "latepoint_get_customer_fields",
              "response_type": "dynamic_fields",
              "dependencies": []
            }
          }
        }
      ]
    }
    

    actions.php

    PHP
    <?php
    namespace SRFM_Pro\Inc\Pro\Native_Integrations\Integrations\LatePoint;
    
    use SRFM_Pro\Inc\Traits\Get_Instance;
    
    class LatePoint_Integration {
        use Get_Instance;
    
        public function __construct() {
            $this->register_filters();
        }
    
        public function get_customer_custom_fields( $fields = [] ) {
            if ( ! $this->is_plugin_active() ) {
                return $fields;
            }
    
            // Get LatePoint custom fields from database
            global $wpdb;
            customer_fields = wpdb->get_row(
                $wpdb->prepare(
                    "SELECT * FROM {$wpdb->prefix}latepoint_settings WHERE name = %s",
                    'custom_fields_for_customer'
                )
            );
    
            // Format fields for SureForms
            $formatted_fields = [];
            if ( ! empty( customer_fields ) && ! empty( customer_fields->value ) ) {
                custom_fields_data = json_decode( customer_fields->value, true );
                
                if ( is_array( $custom_fields_data ) ) {
                    foreach ( custom_fields_data as field ) {
                        $formatted_fields[] = [
                            'key'         => $field['id'],
                            'label'       => field['label'] ?? ucwords( str_replace( '_', ' ', field['id'] ) ),
                            'type'        => $field['type'] ?? 'text',
                            'required'    => ! empty( $field['required'] ),
                            'description' => $field['placeholder'] ?? '',
                        ];
                    }
                }
            }
    
            return $formatted_fields;
        }
    
        private function is_plugin_active() {
            return class_exists( 'OsCustomerModel' );
        }
    
        private function register_filters() {
            if ( ! $this->is_plugin_active() ) {
                return;
            }
    
            add_filter( 'srfm_latepoint_get_customer_fields', [ $this, 'get_customer_custom_fields' ] );
            $this->load_action_files();
        }
    
        private function load_action_files() {
            require_once __DIR__ . '/actions/create-customer.php';
        }
    }
    
    LatePoint_Integration::get_instance();

    actions/create-customer.php

    PHP
    <?php
    namespace SRFM_Pro\Inc\Pro\Native_Integrations\Integrations\LatePoint\Actions;
    
    use SRFM_Pro\Inc\Pro\Native_Integrations\WordPress_Action;
    use SRFM_Pro\Inc\Traits\Get_Instance;
    
    class Create_Customer extends WordPress_Action {
        use Get_Instance;
    
        protected $integration = 'LatePoint';
        protected $action = 'create_customer';
    
        protected function is_plugin_active() {
            return class_exists( 'OsCustomerModel' );
        }
    
        protected function execute( $data ) {
            // Handle test mode
            is_test_mode = isset( $data['_test_mode'] ) && true === data['_test_mode'];
            if ( $is_test_mode ) {
                unset( $data['_test_mode'] );
                data['admin_notes'] = ( data['admin_notes'] ?? '' ) . "\n\n[TEST CUSTOMER - Created by SureForms workflow test]";
            }
    
            // Validate required fields
            $required_fields = [ 'first_name', 'last_name', 'email' ];
            validation = $this->validate_required_fields( $data, required_fields );
    
            if ( is_wp_error( $validation ) ) {
                return $validation;
            }
    
            try {
                // Check if customer exists
                $customer_model = new \OsCustomerModel();
                existing_customer = $customer_model->where( [ 'email' => data['email'] ] )->set_limit( 1 )->get_results_as_models();
    
                if ( ! empty( $existing_customer ) ) {
                    // Update existing customer
                    $existing_customer->set_data([
                        'first_name'  => $data['first_name'],
                        'last_name'   => $data['last_name'],
                        'phone'       => data['phone'] ?? existing_customer->phone,
                        'admin_notes' => data['admin_notes'] ?? existing_customer->admin_notes ?? '',
                    ]);
    
                    if ( ! $existing_customer->save() ) {
                        throw new \Exception( 'Failed to update customer.' );
                    }
    
                    do_action( 'latepoint_customer_updated', $existing_customer );
    
                    return [
                        'success'     => true,
                        'message'     => __( 'Customer updated successfully!', 'sureforms-pro' ),
                        'customer_id' => $existing_customer->id,
                        'is_new'      => false,
                    ];
                }
    
                // Create new customer
                $customer = new \OsCustomerModel();
                $customer->set_data([
                    'first_name'  => $data['first_name'],
                    'last_name'   => $data['last_name'],
                    'email'       => $data['email'],
                    'phone'       => $data['phone'] ?? '',
                    'admin_notes' => $data['admin_notes'] ?? '',
                    'status'      => 'active',
                ]);
    
                if ( ! $customer->save() ) {
                    throw new \Exception( 'Failed to create customer.' );
                }
    
                do_action( 'latepoint_customer_created', $customer );
    
                return [
                    'success'     => true,
                    'message'     => __( 'Customer created successfully!', 'sureforms-pro' ),
                    'customer_id' => $customer->id,
                    'is_new'      => true,
                ];
    
            } catch ( \Exception $e ) {
                return new \WP_Error(
                    'customer_creation_failed',
                    sprintf(
                        __( 'Customer creation failed: %s', 'sureforms-pro' ),
                        $e->getMessage()
                    )
                );
            }
        }
    }
    
    Create_Customer::get_instance();

    Common Integration Patterns

    Plugin Detection

    Always use the main plugin class for detection:

    PHP
    {
      "plugin_detection": {
        "class": "MainPluginClass"
      }
    }
    

    Filter Naming Convention

    Use consistent filter naming:

    PHP
    // Pattern: srfm_{plugin_name}_{action_type}_{object_type}
    add_filter( 'srfm_latepoint_get_customer_fields', $callback );
    add_filter( 'srfm_woocommerce_get_product_categories', $callback );
    add_filter( 'srfm_gravity_get_form_fields', $callback );

    Action Naming Convention

    Use consistent action naming:

    PHP
    {
      "handler": {
        "type": "action",
        "action": "plugin_name_action_name"
      }
    }

    This creates WordPress action: srfm_plugin_name_action_name

    Test Mode Implementation

    Always support test mode in your actions:

    PHP
    protected function execute( $data ) {
        is_test_mode = isset( $data['_test_mode'] ) && true === data['_test_mode'];
        
        if ( $is_test_mode ) {
            unset( $data['_test_mode'] );
            // Add test identifiers as needed
        }
        
        // Execute real operations - no simulation
        // Test mode creates real data for verification
    }

    Troubleshooting

    Common Issues

    • Plugin Not Detected
      • Verify plugin_detection.class exists
      • Check plugin activation status
      • Ensure class name is correct
    • Actions Not Executing
      • Verify action file is loaded
      • Check WordPress action hook registration
      • Confirm get_instance() is called
    • Dynamic Fields Not Loading
      • Verify filter name matches JSON configuration
      • Check filter callback registration
      • Ensure plugin is active when filter runs
    • Test Workflow Fails
      • Check required field validation
      • Verify plugin classes are available
      • Review error messages in developer tools

    Debugging Tips

    PHP
    // Add debug logging to your actions
    protected function execute( $data ) {
        error_log( 'SureForms Action: ' . this->integration . '_' . this->action );
        error_log( 'Data: ' . print_r( $data, true ) );
        
        // Your execution logic
    }
    
    // Add debug logging to filters
    add_filter( 'srfm_your_plugin_get_fields', function( $fields ) {
        error_log( 'SureForms Filter: fields requested' );
        error_log( 'Fields: ' . print_r( $fields, true ) );
        return $fields;
    });
    

    This guide provides a comprehensive foundation for creating WordPress plugin integrations with SureForms Pro. The system is designed to be flexible while maintaining consistency and reliability across different plugin ecosystems.

    Was this doc helpful?
    What went wrong?

    We don't respond to the article feedback, we use it to improve our support content.

    Need help? Contact Support
    On this page
    Scroll to Top