spivurno
9/17/2014 - 3:15 PM

Gravity Wiz // Gravity Forms // Auto Populate

Gravity Wiz // Gravity Forms // Auto Populate

<?php
/**
 * Gravity Wiz // Gravity Forms // Auto Populate
 *
 * Automatically populate a form with data based on an entry ID or an array of custom data.
 *
 * @version	  1.0
 * @author    David Smith <david@gravitywiz.com>
 * @license   GPL-2.0+
 * @link      http://gravitywiz.com/...
 */
class GW_Auto_Populate {

    protected static $is_script_output = false;

    public function __construct( $args = array() ) {

        // set our default arguments, parse against the provided arguments, and store for use throughout the class
        $this->_args = wp_parse_args( $args, array(
            'form_id'               => false,
            'source_field_id'       => false,
            'source_type'           => 'entry_id', // or 'field_value'
            'populate_button_label' => __( 'Populate' )
        ) );

        // do version check in the init to make sure if GF is going to be loaded, it is already loaded
        add_action( 'init', array( $this, 'init' ) );

    }

    function init() {

        // make sure we're running the required minimum version of Gravity Forms
        if( ! property_exists( 'GFCommon', 'version' ) || ! version_compare( GFCommon::$version, '1.8', '>=' ) ) {
            return;
        }

        // time for hooks
        add_filter( 'gform_pre_render', array( $this, 'load_form_script' ) );
        add_filter( 'gform_register_init_scripts', array( $this, 'add_init_script' ) );

        add_filter( 'wp', array( $this, 'auto_populate_form' ), 8 );
        add_filter( 'gform_validation', array( $this, 'override_validation' ) );

    }

    function load_form_script( $form ) {

        if( $this->is_applicable_form( $form ) && ! self::$is_script_output ) {
            $this->output_script();
        }

        return $form;
    }

    function output_script() {
        ?>

        <script type="text/javascript">

            ( function( $ ) {

                window.GWAutoPopulate = function( args ) {

                    var self = this;

                    // copy all args to current object: (list expected props)
                    for( prop in args ) {
                        if( args.hasOwnProperty( prop ) )
                            self[prop] = args[prop];
                    }

                    self.init = function() {

                        self.$sourceInput    = $( '#input_' + self.formId + '_' + self.sourceFieldId );
                        self.$populateButton = $(
                            '<input id="input_' + self.formId + '_' + self.sourceFieldId + '_populate" \
                                type="submit" \
                                value="' + self.buttonLabel + '" \
                                tabindex="' + self.$sourceInput.attr( 'tabindex' ) + '" \
                                onclick="GWAutoPopulate.addMetaInputs( ' + self.formId + ', ' + self.sourceFieldId + ' )" />'
                            ).hide().insertAfter( self.$sourceInput );

                        self.$sourceInput.keyup( function() {

                            if( $.trim( $( this ).val() ) == '' ) {
                                self.$populateButton.hide();
                            } else {
                                self.$populateButton.show();
                            }

                        } );

                    }

                    GWAutoPopulate.addMetaInputs = function( formId, fieldId ) {

                        var $form    = $( '#gform_' + formId ),
                            $fieldId = $( '<input type="hidden" name="gwap_source_field_id" value="' + fieldId + '" />' ),
                            $formId  = $( '<input type="hidden" name="gwap_source_form_id" value="' + formId + '" />' );

                        $form.append( $fieldId );
                        $form.append( $formId );

                    }

                    self.init();

                }

            } )( jQuery );

        </script>

        <?php

        self::$is_script_output = true;

    }

    function add_init_script( $form ) {

        if( ! $this->is_applicable_form( $form ) ) {
            return;
        }

        $args = array(
            'formId'        => $this->_args['form_id'],
            'sourceFieldId' => $this->_args['source_field_id'],
            'buttonLabel'   => $this->_args['populate_button_label']
        );

        $script = 'new GWAutoPopulate( ' . json_encode( $args ) . ' );';
        $slug   = implode( '_', array( 'gw_js_snippet_template', $this->_args['form_id'], $this->_args['source_field_id'] ) );

        GFFormDisplay::add_init_script( $this->_args['form_id'], $slug, GFFormDisplay::ON_PAGE_RENDER, $script );

    }

    function auto_populate_form( $form ) {

        if( ! $this->is_auto_populate_submission() ) {
            return;
        }

        $source_form_id  = rgpost( 'gwap_source_form_id' );
        $source_field_id = rgpost( 'gwap_source_field_id' );
        $source_value    = rgpost( "input_{$source_field_id}" );
        $source          = false;

        switch( $this->_args['source_type'] ) {
            case 'entry_id':
                $source = GFAPI::get_entry( $source_value );
            break;
            case 'field_value':
                $entries = GFAPI::get_entries( $source_form_id, array( 'field_filters' => array( array( 'key' => $source_field_id, 'value' => $source_value ) ) ) );
                $source = rgar( $entries, 0 );
            break;
        }

        if( $source ) {
            foreach( $source as $input_id => $value ) {

                $input_key = sprintf( 'input_%s', str_replace( '.', '_', $input_id ) );
                $submitted_value = rgpost( $input_key );

                if( ! $submitted_value ) {
                    $_POST[$input_key] = $value;
                }

            }
        }

        $_POST[ "gform_target_page_number_{$source_form_id}" ] = rgpost( "gform_source_page_number_{$source_form_id}" );

    }

    /**
     * If this is an auto populate submission, override all the validation errors to give the appearance that the form has not been submitted at all.
     *
     * @param $validation_result
     *
     * @return mixed
     */
    function override_validation( $validation_result ) {

        if( ! $this->is_auto_populate_submission() ) {
            return $validation_result;
        }

        foreach( $validation_result['form']['fields'] as &$field ) {
            $field['failed_validation'] = false;
        }

        $validation_result['is_valid'] = true;

        return $validation_result;
    }

    function is_applicable_form( $form ) {

        $form_id = isset( $form['id'] ) ? $form['id'] : $form;

        return $form_id == $this->_args['form_id'];
    }

    function is_auto_populate_submission() {

        $submitted_form_id = rgpost( 'gform_submit' );
        $source_form_id    = rgpost( 'gwap_source_form_id' );
        $source_field_id   = rgpost( 'gwap_source_field_id' );

        return $submitted_form_id == $source_form_id && $source_field_id;
    }

}

# Configuration

new GW_Auto_Populate( array(
    'form_id' => 600,
    'source_field_id' => 8,
    'source_type' => 'field_value', // or 'field_value'
    'populate_button_label' => __( 'Populate' )
) );