Last active
November 14, 2022 21:16
-
-
Save spivurno/8ca209fbb5068e62655ddf91678830a3 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.4 | |
* @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.4 | |
* 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( isset( $_POST['action'] ) && $_POST['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() { | |
if ( this.type === 'radio' ) { | |
if ( this.checked ) { | |
data[ $( this ).attr( 'name' ) ] = $( this ).val(); | |
} | |
} else { | |
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 ) | |
) ); |
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 | |
new GP_Limit_Choices_Field_Group( array( | |
'form_id' => 12, | |
'field_ids' => array( 3, 4 ) | |
) ); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@spivurno
Thank you for the quick response and fix! It is greatly appreciated.