Skip to content

Instantly share code, notes, and snippets.

@claygriffiths
Last active November 2, 2020 02:37
Show Gist options
  • Save claygriffiths/f87b83b2b8d83035ddf95dadad95d591 to your computer and use it in GitHub Desktop.
Save claygriffiths/f87b83b2b8d83035ddf95dadad95d591 to your computer and use it in GitHub Desktop.
GP Nested Forms: Limit Entries Based on Another Field's Numeric Value
<?php
class GP_Nested_Forms_Dynamic_Entry_Min_Max {
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(
'parent_form_id' => false,
'nested_form_field_id' => false,
'default_max' => 0, // Max to fallback to if the dependent field isn't populated
'default_min' => 0, // Min to fallback to if the dependent field isn't populated
'max_field_id' => null,
'min_field_id' => null, // (Optional)
) );
// 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' ) );
}
public 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' ), 10, 2 );
add_filter( 'gform_register_init_scripts', array( $this, 'add_init_script' ), 5, 2 );
add_action( 'gform_validation', array( $this, 'validate' ) );
}
public function load_form_script( $form, $is_ajax_enabled ) {
if ( $this->is_applicable_form( $form ) && ! has_action( 'wp_footer', array( $this, 'output_script' ) ) ) {
add_action( 'wp_footer', array( $this, 'output_script' ) );
add_action( 'gform_preview_footer', array( $this, 'output_script' ) );
}
return $form;
}
public function validate( $validation_result ) {
if ( $validation_result['form']['id'] != $this->_args['parent_form_id'] ) {
return $validation_result;
}
if ( ! $this->_args['max_field_id'] && ! $this->_args['min_field_id'] ) {
return $validation_result;
}
$form = $validation_result['form'];
$nested_form_field_id = $this->_args['nested_form_field_id'];
$nested_form_field_value = rgpost( "input_{$nested_form_field_id}" );
$nested_form_field = GFAPI::get_field( $form, $nested_form_field_id );
$entry_ids = explode( ',', $nested_form_field_value );
$entry_count = empty( $nested_form_field_value ) ? 0 : count( $entry_ids );
$raw_min = rgpost( "input_{$this->_args['min_field_id']}" );
$raw_max = rgpost( "input_{$this->_args['max_field_id']}" );
if ( empty( $raw_min ) ) {
$raw_min = $this->_args['default_min'];
}
if ( empty( $raw_max ) ) {
$raw_max = $this->_args['default_max'];
}
$min = apply_filters( 'gpnf_entry_limit_min', $raw_min, $entry_count, $entry_ids, null, $form );
$max = apply_filters( 'gpnf_entry_limit_max', $raw_max, $entry_count, $entry_ids, null, $form );
$has_validation_error = false;
foreach ( $validation_result['form']['fields'] as &$field ) {
if ( $field['failed_validation'] ) {
$has_validation_error = true;
}
if ( $field['id'] !== $nested_form_field_id ) {
continue;
}
if ( $min !== null && $min !== '' && $entry_count < $min ) {
$field['failed_validation'] = true;
$field['validation_message'] = sprintf( __( 'Please enter a minimum of %d %s', 'gp-nested-forms' ), $min, $min > 1 ? $nested_form_field->get_items_label() : $nested_form_field->get_item_label() );
$has_validation_error = true;
}
if ( $max !== null && $max !== '' && $entry_count > $max ) {
$field['failed_validation'] = true;
$field['validation_message'] = sprintf( __( 'Please enter a maximum of %d %s', 'gp-nested-forms' ), $max, $max > 1 ? $nested_form_field->get_items_label() : $nested_form_field->get_item_label() );
$has_validation_error = true;
}
}
$validation_result['is_valid'] = ! $has_validation_error;
return $validation_result;
}
public function output_script() {
?>
<script type="text/javascript">
(function ($) {
window.GPNFDynamicEntryMax = 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 () {
var $maxField = $('#input_' + self.parentFormId + '_' + self.maxFieldId);
gform.addFilter('gpnf_entry_limit_max', function (max, currentFormId, currentFieldId) {
if (self.parentFormId != currentFormId || self.nestedFormFieldId != currentFieldId) {
return max;
}
var value = parseInt($maxField.val());
return value ? value : self.defaultMax;
});
$maxField.on('change', function () {
// Force Knockout to recalculate the max when the number has changed
window['GPNestedForms_' + self.parentFormId + '_' + self.nestedFormFieldId].viewModel.entries.valueHasMutated();
});
};
self.init();
}
})(jQuery);
</script>
<?php
}
public function add_init_script( $form ) {
if ( ! $this->is_applicable_form( $form ) ) {
return;
}
$args = array(
'parentFormId' => $this->_args['parent_form_id'],
'nestedFormFieldId' => $this->_args['nested_form_field_id'],
'defaultMax' => $this->_args['default_max'],
'maxFieldId' => $this->_args['max_field_id'],
);
$script = 'new GPNFDynamicEntryMax( ' . json_encode( $args ) . ' );';
$slug = implode( '_', array(
'gpnf_dynamic_entry_max_template',
$this->_args['parent_form_id'],
$this->_args['nested_form_field_id']
) );
GFFormDisplay::add_init_script( $this->_args['parent_form_id'], $slug, GFFormDisplay::ON_PAGE_RENDER, $script );
}
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'];
}
}
new GP_Nested_Forms_Dynamic_Entry_Min_Max( array(
'parent_form_id' => 4,
'nested_form_field_id' => 3,
'max_field_id' => 1,
'min_field_id' => 2, // (Optional)
) );
@jkyllonen
Copy link

I'm trying to get this to work on a paged form, but am having trouble. The "max field" is on the first page, and the nested form is on the second page. Any thoughts? (it works when they're on the same page, just not when on different ones)

@claygriffiths
Copy link
Author

Hi @jkyllonen,

Please send us an e-mail via https://gravitywiz.com/support and we'd be happy to help out with the snippet. 😃

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