Forked from spivurno/gp-limit-choices-field-groups.php
Last active
May 18, 2020 02:32
-
-
Save claygriffiths/d0a0e6119dc0dade9f40fb98157477bd to your computer and use it in GitHub Desktop.
Gravity Perks // GP Limit Choices // Field Groups
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Gravity Perks // GP Limit Choices // Field Group | |
* | |
* Specify a group of fields that should create a unique choice to limited. For example, a Date field and Radio Button field could be | |
* combined to sell x tickets per date where the ticket type is controlled by the Radio Button field and the date is | |
* selected in the Date field. | |
* | |
* @version 1.3 | |
* @author David Smith <[email protected]> | |
* @license GPL-2.0+ | |
* @link http://gravitywiz.com/documentation/gp-limit-choices/ | |
* | |
* Plugin Name: GP Limit Choices - Field Groups | |
* Plugin URI: http://gravitywiz.com/documentation/gp-limit-choices/ | |
* Description: Specify a group of fields that should create a unique choice to be limited. | |
* Author: Gravity Wiz | |
* Version: 1.2 | |
* Author URI: http://gravitywiz.com | |
*/ | |
class GP_Limit_Choices_Field_Group { | |
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, | |
'field_ids' => array(), | |
) ); | |
$this->_args['hash'] = hash_hmac( 'sha256', serialize( $this->_args ), 'gplc_field_group' ); | |
add_filter( 'gwlc_choice_counts_query', array( $this, 'limit_by_field_group' ), 10, 2 ); | |
add_action( 'wp_ajax_gplcfg_refresh_field', array( $this, 'ajax_refresh' ) ); | |
add_action( 'wp_ajax_nopriv_gplcfg_refresh_field', array( $this, 'ajax_refresh' ) ); | |
add_filter( 'gform_pre_render', array( $this, 'load_form_script' ), 10, 2 ); | |
add_filter( 'gform_register_init_scripts', array( $this, 'add_init_script' ), 10, 2 ); | |
if( rgpost( 'action' ) == 'gplcfg_refresh_field' ) { | |
remove_action( 'wp', array( 'GFForms', 'maybe_process_form' ), 9 ); | |
remove_action( 'admin_init', array( 'GFForms', 'maybe_process_form' ), 9 ); | |
} | |
} | |
public function limit_by_field_group( $query, $field ) { | |
global $wpdb; | |
$field_ids = $this->_args['field_ids']; | |
if( ! $this->is_applicable_form( $field->formId ) || ! in_array( $field->id, $field_ids ) ) { | |
return $query; | |
} | |
unset( $field_ids[ array_search( $field->id, $field_ids ) ] ); | |
$field_ids = array_values( $field_ids ); | |
$form = GFAPI::get_form( $field->formId ); | |
$join = $where = array(); | |
$select = $from = ''; | |
foreach( $field_ids as $index => $field_id ) { | |
$field = GFFormsModel::get_field( $form, $field_id ); | |
$alias = sprintf( 'fgem%d', $index + 1 ); | |
$_alias = null; | |
if( $index == 0 ) { | |
$_alias = $alias; | |
$select = "SELECT DISTINCT {$alias}.entry_id"; | |
$from = "FROM {$wpdb->prefix}gf_entry_meta {$alias}"; | |
$value = $field->get_value_save_entry( GFFormsModel::get_field_value( $field ), $form, null, null, null ); | |
$where[] = $wpdb->prepare( "( {$alias}.form_id = %d AND {$alias}.meta_key = %s AND {$alias}.meta_value = %s )", $field->formId, $field_id, $value ); | |
} else { | |
$join[] = "INNER JOIN {$wpdb->prefix}gf_entry_meta {$alias} ON {$_alias}.entry_id = {$alias}.entry_id"; | |
} | |
} | |
$field_group_query = array( | |
'select' => $select, | |
'from' => $from, | |
'join' => implode( ' ', $join ), | |
'where' => sprintf( 'WHERE %s', implode( "\nAND ", $where ) ) | |
); | |
$query['where'] .= sprintf( ' AND e.id IN( %s )', implode( "\n", $field_group_query ) ); | |
return $query; | |
} | |
public function is_applicable_form( $form ) { | |
$form_id = isset( $form['id'] ) ? $form['id'] : $form; | |
return empty( $this->_args['form_id'] ) || $form_id == $this->_args['form_id']; | |
} | |
public function load_form_script( $form, $is_ajax_enabled ) { | |
$func = array( 'GP_Limit_Choices_Field_Group', 'output_script' ); | |
if( $this->is_applicable_form( $form ) && ! has_action( 'wp_footer', $func ) ) { | |
add_action( 'wp_footer', $func ); | |
add_action( 'gform_preview_footer', $func ); | |
} | |
return $form; | |
} | |
public function add_init_script( $form ) { | |
if( ! $this->is_applicable_form( $form ) ) { | |
return; | |
} | |
$target_field_id = $this->get_target_field_id( $form, $this->_args['field_ids'] ); | |
$args = array( | |
'formId' => $this->_args['form_id'], | |
'targetFieldId' => $target_field_id, | |
'triggerFieldIds' => $this->get_trigger_field_ids( $form, $this->_args['field_ids'] ), | |
'ajaxUrl' => admin_url( 'admin-ajax.php' ), | |
'hash' => $this->_args['hash'], | |
); | |
$script = 'new GPLCFieldGroup( ' . json_encode( $args ) . ' );'; | |
$slug = implode( '_', array( 'gplc_field_group', $this->_args['form_id'], $target_field_id ) ); | |
GFFormDisplay::add_init_script( $this->_args['form_id'], $slug, GFFormDisplay::ON_PAGE_RENDER, $script ); | |
} | |
public function get_target_field_id( $form, $field_ids ) { | |
foreach( $field_ids as $field_id ) { | |
$field = GFAPI::get_field( $form, $field_id ); | |
if ( gp_limit_choices()->is_applicable_field( $field ) ) { | |
return $field_id; | |
} | |
} | |
return false; | |
} | |
public function get_trigger_field_ids( $form, $field_ids ) { | |
$target_field_id = $this->get_target_field_id( $form, $field_ids ); | |
return array_values( array_filter( $field_ids, function( $field_id ) use ( $target_field_id ) { | |
return $field_id != $target_field_id; | |
} ) ); | |
} | |
public function ajax_refresh() { | |
// Object can be instantiated multiple times. Only listen for this specific configuration's hash. | |
if ( rgpost( 'hash' ) !== $this->_args['hash'] ) { | |
/** | |
* Return out if the hash doesn't match. If we exit here, other ajax_refresh() calls in other instances | |
* won't have the chance to run. | |
*/ | |
return; | |
} | |
$entry = GFFormsModel::get_current_lead(); | |
if( ! $entry ) { | |
wp_send_json_error(); | |
} | |
$form = gf_apply_filters( array( 'gform_pre_render', $entry['form_id'] ), GFAPI::get_form( $entry['form_id'] ), false, array() ); | |
$field = GFFormsModel::get_field( $form, $this->get_target_field_id( $form, $this->_args['field_ids'] ) ); | |
if( $field->get_input_type() == 'html' ) { | |
$content = GWPreviewConfirmation::preview_replace_variables( $field->content, $form ); | |
} else { | |
$value = rgpost( 'input_' . $field->id ); | |
$content = $field->get_field_content( $value, true, $form ); | |
$content = str_replace( '{FIELD}', $field->get_field_input( $form, $value, $entry ), $content ); | |
} | |
wp_send_json_success( $content ); | |
} | |
public static function output_script() { | |
?> | |
<script type="text/javascript"> | |
( function( $ ) { | |
window.GPLCFieldGroup = 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.$form = $( '#gform_wrapper_{0}'.format( self.formId ) ); | |
self.$targetField = $( '#field_{0}_{1}'.format( self.formId, self.targetFieldId ) ); | |
self.$triggerFields = false; | |
for( var i = 0; i < self.triggerFieldIds.length; i++ ) { | |
var $field = $( '#field_{0}_{1}'.format( self.formId, self.triggerFieldIds[ i ] ) ); | |
if ( ! self.$triggerFields ) { | |
self.$triggerFields = $().add( $field ); | |
} | |
// @todo Test with multiple triggers. | |
else { | |
self.$triggerFields.add( $field ); | |
} | |
} | |
self.$triggerFields.on( 'change', function() { | |
self.refresh(); | |
} ); | |
self.refresh(); | |
}; | |
self.refresh = function() { | |
if( ! self.$targetField.is( ':visible' ) ) { | |
return; | |
} | |
var data = { | |
action: 'gplcfg_refresh_field', | |
hash: self.hash | |
}; | |
self.$form.find( 'input, select, textarea' ).each( function() { | |
data[ $( this ).attr( 'name' ) ] = $( this ).val(); | |
} ); | |
// Prevent AJAX-enabled forms from intercepting our AJAX request. | |
delete data['gform_ajax']; | |
$.post( self.ajaxUrl, data, function( response ) { | |
if( response.success ) { | |
self.$targetField.html( response.data ); | |
} | |
} ); | |
}; | |
self.init(); | |
} | |
} )( jQuery ); | |
</script> | |
<?php | |
} | |
} | |
# Configuration | |
new GP_Limit_Choices_Field_Group( array( | |
'form_id' => 1485, | |
'field_ids' => array( 1, 2 ) | |
) ); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment