Use List Field as Choices for Gravity Forms

Adds support for populating choice-based fields with values entered in a List field.

Read the Walkthrough

Code

Filename: gw-list-field-as-choices.php

<?php
/**
* Gravity Wiz // Gravity Forms // Use List Field as Choices for Gravity Forms
* https://gravitywiz.com/use-list-field-choices-gravity-forms/
*
* Adds support for populating choice-based fields (i.e. checkboxes, selects, radio buttons) with values entered in a
* List field. This functionality requires that the form has multiple pages and that the List field must be placed on
* a page prior to the choice-based field that it will populate.
*
* Plugin Name:  Gravity Forms - Use List Field as Choices
* Plugin URI:   https://gravitywiz.com/use-list-field-choices-gravity-forms/
* Description:  Adds support for populating choice-based fields with values entered in a List field.
* Author:       Gravity Wiz
* Version:      1.0
* Author URI:   https://gravitywiz.com/
*/
class GW_List_Field_As_Choices {

	function __construct( $args ) {

		$this->_args = wp_parse_args( $args, array(
			'form_id'          => false,
			'list_field_id'    => false,
			'choice_field_ids' => false,
			'label_template'   => '{0}',
			'sort'             => false,
		) );

		if ( ! is_array( $this->_args['choice_field_ids'] ) ) {
			$this->_args['choice_field_ids'] = array( $this->_args['choice_field_ids'] );
		}

		// phpcs:ignore WordPress.PHP.DontExtract.extract_extract
		extract( $this->_args ); // gives us $form_id, $list_field_id, $choices_field_id

		add_filter( 'gform_pre_render', array( $this, 'populate_choice_fields' ), 9 );
		add_filter( 'gform_pre_validation', array( $this, 'populate_choice_fields' ), 9 );
		add_filter( 'gform_pre_submission_filter_' . $form_id, array( $this, 'populate_choice_fields' ) );

	}

	function populate_choice_fields( $form ) {

		if ( $form['id'] != $this->_args['form_id'] ) {
			return $form;
		}

		$list_field = GFFormsModel::get_field( $form, $this->_args['list_field_id'] );
		$values     = GFFormsModel::get_field_value( $list_field );

		/**
		 * Filter the values from the List field that will be used to populate field choices.
		 *
		 * @param array|mixed|string $values The List field values that will be used to populate field choices.
		 * @param array              $form   The current form.
		 * @param array              $args   The arguments used to initialize this instance of GW_List_Field_As_Choices.
		 */
		$values = apply_filters( 'gwlfac_list_field_values', $values, $form, $this->_args );

		// if list field doesn't have any values, let's ditch this party
		if ( ! is_array( $values ) ) {
			return $form;
		}

		$choices = $this->get_list_choices( $values );

		foreach ( $form['fields'] as &$field ) {

			if ( ! $this->is_applicable_field( $field ) ) {
				continue;
			}

			// set 'choices' for choice fields
			$field['choices'] = $choices;

			// only set inputs for 'checkbox' choice fields
			if ( GFFormsModel::get_input_type( $field ) == 'checkbox' ) {
				$inputs = array();
				foreach ( $choices as $index => $choice ) {
					$inputs[] = array(
						'label' => $choice['text'],
						'id'    => $field['id'] . '.' . ( $index + 1 ),
					);
				}
				$field['inputs'] = $inputs;
			}
		}

		return $form;
	}

	function get_list_choices( $values ) {

		$choices = array();

		foreach ( $values as $row ) {

			$label = $this->replace_template( $this->_args['label_template'], $row );
			$value = isset( $this->_args['value_template'] ) ? $this->replace_template( $this->_args['value_template'], $row ) : $label;

			$choices[] = array(
				'text'  => $label,
				'value' => $value,
			);

		}

		if ( $this->_args['sort'] == true ) {
			usort( $choices, function( $a, $b ) {
				return strnatcasecmp( $a['text'], $b['text'] );
			} );
		}

		return $choices;
	}

	function replace_template( $template, $row ) {

		// combine our templates so we can find all matches at once
		preg_match_all( '/{(\w+)}/', $template, $matches, PREG_SET_ORDER );

		if ( is_array( $row ) ) {

			$mega_row = array_merge( $row, array_values( $row ) );

			foreach ( $matches as $match ) {
				$template = str_replace( $match[0], rgar( $mega_row, $match[1] ), $template );
			}
		} else {

			foreach ( $matches as $match ) {
				$template = str_replace( $match[0], $row, $template );
			}
		}

		return $template;
	}

	function is_applicable_field( $field ) {

		$is_choice_field     = is_array( rgar( $field, 'choices' ) );
		$is_registered_field = in_array( $field['id'], $this->_args['choice_field_ids'] );

		return $is_choice_field && $is_registered_field;
	}

}

/**
* Uncomment the code below by removing the pound symbols (#) in front of each line. See @link in the comment section
* at the top for additional usage instructions.
*/

# Basic Usage
# new GW_List_Field_As_Choices( array(
#    'form_id' => 1,
#    'list_field_id' => 2,
#    'choice_field_ids' => 3
# ) );

Leave a Reply

Your email address will not be published. Required fields are marked *

  • Trouble installing this snippet? See our troubleshooting tips.
  • Need to include code? Create a gist and link to it in your comment.
  • Reporting a bug? Provide a URL where this issue can be recreated.

By commenting, I understand that I may receive emails related to Gravity Wiz and can unsubscribe at any time.