spivurno
7/19/2015 - 7:35 PM

Gravity Wiz // Gravity Forms // All Fields Template

Gravity Wiz // Gravity Forms // All Fields Template

<?php
/**
 * Gravity Wiz // Gravity Forms // All Fields Template
 *
 * Modify the {all_fields} merge tag output via a template file.
 *
 * @version   0.9.6
 * @author    David Smith <david@gravitywiz.com>
 * @license   GPL-2.0+
 * @link      https://gravitywiz.com/gravity-forms-all-fields-template/
 *
 * Plugin Name:  Gravity Forms All Fields Template
 * Plugin URI:   https://gravitywiz.com/gravity-forms-all-fields-template/
 * Description:  Modify the {all_fields} merge tag output via a template file.
 * Author:       Gravity Wiz
 * Version:      0.9.6
 * Author URI:   http://gravitywiz.com
 *
 * Usage:
 *
 * {all_fields}
 *
 *     By default, enabling this plugin will look for this template:
 *     <theme>/gravity-forms/all-fields.php
 *
 *     Override the {all_fields} template for a specific form by specifying the form ID:
 *     <theme>/gravity-forms/all-fields-<formId>.php
 *
 * {all_fields:template[custom]}
 *
 *     Specify a custom template suffix. This is useful for allowing specific forms to use the same template.
 *     <theme>/gravity-forms/all-fields-custom.php
 *
 * {all_fields:notemplate}
 *
 *     Will always load the default Gravity Forms {all_fields} markup.
 *
 * {all_fields:nopricingfields}
 *
 * 	   Hide all pricing fields (i.e. order summary).
 *
 * Filtering Usage:
 *
 * :filter
 *
 *     Filtering will only include the specified fields and exclude all others. It cannot be combined with the include
 *     exclude filters.
 *
 *     {all_fields:filter[1]}
 *     {all_fields:filter[1,2]}
 *
 * :include
 *
 *     Including will include fields with types that are typically not supported by the {all_fields} merge tag
 *     (e.g., HTML fields).
 *
 *     {all_fields:include[3]}
 *     {all_fields:include[3,4]}
 *     {all_fields:include[3,4],exclude[5]}
 *
 * :exclude
 *
 *     Excluding will exclude specific fields from being included in the {all_fields} output.
 *
 *     {all_fields:exclude[5]}
 *     {all_fields:exclude[5,6]}
 *     {all_fields:exclude[5],include[3,4]}
 *
 */
class GW_All_Fields_Template {

	private static $instance = null;

	public static function get_instance() {
		if( self::$instance == null ) {
			self::$instance = new self;
		}
		return self::$instance;
	}

	private function __construct() {

		add_action( 'init', array( $this, 'init' ) );

	}

	public function init() {

		add_filter( 'gform_pre_replace_merge_tags', array( $this, 'replace_merge_tags' ), 9, 7 );
		add_filter( 'gform_merge_tag_filter',       array( $this, 'all_fields_extra_options' ), 11, 5 );

	}

	/**
	 * to exclude field from notification add 'exclude[ID]' option to {all_fields} tag
	 * 'include[ID]' option includes HTML field / Section Break field description / Signature image in notification
	 * see http://www.gravityhelp.com/documentation/page/Merge_Tags for a list of standard options
	 *
	 * include: Include a field that is not included by default (i.e. HTML fields).
	 * exclude: Exclude a field that is included by default.
	 * filter:  Only include the specified field IDs. This takes precedence over both the 'include' and 'exclude' modifiers.
	 *
	 * example: {all_fields:exclude[2,3]}
	 * example: {all_fields:include[6]}
	 * example: {all_fields:include[6],exclude[2,3]}
	 */
	public function all_fields_extra_options( $value, $merge_tag, $modifiers, $field, $raw_value ) {

		if( ! is_a( $field, 'GF_Field' ) ) {
			$field = new GF_Field();
			$field->type = $field;
		}

		if( $merge_tag != 'all_fields' && $field->type == 'form' ) {
			return $value;
		}

		$modifiers = $this->parse_modifiers( $modifiers );
		$whitelist = array( 'filter', 'include', 'exclude', 'nopricingfields' );
		$context   = rgar( $modifiers, 'context', false );

		foreach( $modifiers as $modifier => $mod_value ) {

			if( ! in_array( $modifier, $whitelist ) ) {
				continue;
			}

			if( ! is_array( $mod_value ) ) {
				$mod_value = array( $mod_value );
			}

			if( $modifier === 'nopricingfields' ) {
				$func = function() use ( &$func ) {
					remove_filter( 'gform_order_summary', $func );
					return '';
				};
				add_filter( 'gform_order_summary', $func );
			}

			/**
			 * Integrate w/ GP Nested Forms to allow filtering which fields are displayed for nested entries in the
			 * Nested Form field's value. GPNF will pass custom modifiers (e.g., context[nested],parent[fieldId]).
			 */
			if( $context == 'nested' ) {

				$nested_form_field_id = rgar( $modifiers, 'parent', false );
				if( ! $nested_form_field_id ) {
					break;
				}

				$field_ids = array();
				foreach( $mod_value as $field_id ) {
					if( intval( $field_id ) == $nested_form_field_id && $field_id !== intval( $field_id ) ) {
						$field_id_bits = explode( '.', $field_id );
						$field_ids[] = array_pop( $field_id_bits );
					}
				}

			} else {

				$field_ids = array_map( 'intval', $mod_value );

			}

			switch( $modifier ) {
				case 'filter':
					if( in_array( $field->id, $field_ids ) ) {
						$value = $this->get_all_fields_field_value( $field, $value );
					} else {
						$value = false;
					}
					break;
				case 'include':
					if( in_array( $field->id, $field_ids ) ) {
						$value = $this->get_all_fields_field_value( $field, $value );
					}
					break;
				case 'exclude':
					if( in_array( $field->id, $field_ids ) ) {
						$value = false;
					}
					break;
			}
		}		

		// echo '<pre>';
		// $field_id = $field->id;
		// print_r( compact( 'modifiers', 'field_ids', 'field_id', 'value' ) );
		// echo '<pre>';

		return $value;
	}

	public function replace_merge_tags( $text, $form, $entry, $url_encode, $esc_html, $nl2br, $format ) {

		$matches = array();

		preg_match_all( '/{all_fields(?::(.*?))?}/i', $text, $matches, PREG_SET_ORDER );

		foreach ( $matches as $match ) {

			// Replace each unique merge tag only once.
			if( strpos( $text, $match[0] ) === false ) {
				continue;
			}

			$modifiers = rgar( $match, 1 );
			$options   = compact( 'url_encode', 'esc_html', 'nl2br', 'format' );
			$content   = $this->parse_template( 'all-fields', $modifiers, $form, $entry, $options );

			if( $content !== false ) {
				$text = str_replace( $match[0], $content, $text );
			}

		}

		return $text;
	}

	public function parse_template( $template, $modifiers, $form, $entry, $options = array() ) {

		$_modifiers = $modifiers;
		$modifiers  = $this->parse_modifiers( $modifiers );

		if( in_array( 'notemplate', $modifiers ) ) {
			return false;
		}

		$use_value       = in_array( 'value', $modifiers );
		$display_empty   = in_array( 'empty', $modifiers );
		$use_admin_label = in_array( 'admin', $modifiers );

		$suffixes = array( $form['id'] );
		if( array_key_exists( 'template', $modifiers ) ) {
			array_unshift( $suffixes, $modifiers['template'] );
		}

		$items = rgar( $options, 'items' );
		if( empty( $items ) ) {
			$items = $this->get_items( $form, $entry, $display_empty, ! $use_value, $options['format'], $use_admin_label, 'all_fields', $_modifiers );
		}

		$output = $this->load_template( $template, null, array(
			'form'  => $form,
			'entry' => $entry,
			'items' => $items
		), $suffixes );

		if( $output === false && rgar( $options, 'fallback' ) ) {
			if( is_callable( $options['fallback'] ) ) {
				$output = call_user_func( $options['fallback'], $items );
			}
		}

		return $output;
	}

	public function replace_nested_forms_all_fields( $value, $field, $nested_form, $entry, $modifiers ) {

		$output = $this->parse_template( $modifiers, $nested_form, $entry, array( 'format' => 'html' ) );
		if( $output ) {
			$value = $output;
		}

		return $value;
	}

	public function parse_modifiers( $modifiers_str ) {

		preg_match_all( '/([a-z]+)(?:(?:\[(.+?)\])|,?)/i', $modifiers_str, $modifiers, PREG_SET_ORDER );
		$parsed  = array();

		foreach( $modifiers as $modifier ) {

			list( $match, $modifier, $value ) = array_pad( $modifier, 3, null );
			if( $value === null ) {
				$value = $modifier;
			}

			// Split '1,2,3' into array( 1, 2, 3 ).
			if( strpos( $value, ',' ) !== false ) {
				$value = array_map( 'trim', explode( ',', $value ) );
			}

			$parsed[ strtolower( $modifier ) ] = $value;

		}

		return $parsed;
	}

	public function get_items( $form, $lead, $display_empty = false, $use_text = false, $format = 'html', $use_admin_label = false, $merge_tag = '', $modifiers = '' ) {
		return $this->get_submitted_fields( $form, $lead, $display_empty, $use_text, $format, $use_admin_label, $merge_tag, $modifiers );
	}

	public function get_submitted_fields( $form, $lead, $display_empty = false, $use_text = false, $format = 'html', $use_admin_label = false, $merge_tag = '', $modifiers = '' ) {

		$items = array();

		//$field_data = '';

		$modifiers_array         = explode( ',', $modifiers );
		$no_admin                = in_array( 'noadmin', $modifiers_array );
		$no_hidden               = in_array( 'nohidden', $modifiers_array );
		$display_product_summary = false;

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

			$field_value = '';
			$field_label = $use_admin_label && ! empty( $field->adminLabel ) ? $field->adminLabel : esc_html( GFCommon::get_label( $field, 0, false, $use_admin_label ) );

			switch ( $field->type ) {
				case 'captcha' :
					break;
				case 'section' :

					$field_value = false;

					if ( GFFormsModel::is_field_hidden( $form, $field, array(), $lead ) ){
						break;
					}

					if ( ( ! GFCommon::is_section_empty( $field, $form, $lead ) || $display_empty ) && ! $field->adminOnly ) {

						switch ( $format ) {
							case 'text' :
								$field_value = "--------------------------------\n{$field_label}\n\n";
								break;

							default:
								$field_value = '';
								break;
						}
					}

					$field_value = apply_filters( 'gform_merge_tag_filter', $field_value, $merge_tag, $modifiers, $field, $field_label );

					//$field_data .= $field_value;

					if( $field_value !== false ) {
						$item = array(
							'label' => $field_label,
							'value' => $field_value,
							'field' => $field
						);
					}

					break;
				case 'password' :
					//ignore password fields
					break;

				default :

					if ( GFCommon::is_product_field( $field->type ) ) {

						// ignore product fields as they will be grouped together at the end of the grid
						$display_product_summary = apply_filters( 'gform_display_product_summary', true, $field, $form, $lead );
						if ( $display_product_summary ) {
							break;
						}
					} else if ( GFFormsModel::is_field_hidden( $form, $field, array(), $lead ) ) {
						// ignore fields hidden by conditional logic
						break;
					}

					$raw_field_value = RGFormsModel::get_lead_field_value( $lead, $field );
					$field_value     = GFCommon::get_lead_field_display( $field, $raw_field_value, rgar( $lead, 'currency' ), $use_text, $format, 'email' );

					$display_field = true;
					//depending on parameters, don't display adminOnly or hidden fields
					if ( $no_admin && $field->adminOnly ) {
						$display_field = false;
					} else if ( $no_hidden && RGFormsModel::get_input_type( $field ) == 'hidden' ) {
						$display_field = false;
					}

					//if field is not supposed to be displayed, pass false to filter. otherwise, pass field's value
					if ( ! $display_field ) {
						$field_value = false;
					}

					$field_value = apply_filters( 'gform_merge_tag_filter', $field_value, $merge_tag, $modifiers, $field, $raw_field_value );

					if ( $field_value === false ) {
						break;
					}

					if ( ! empty( $field_value ) || strlen( $field_value ) > 0 || $display_empty ) {

						switch ( $format ) {
							case 'text' :
								//$field_data .= "{$field_label}: {$field_value}\n\n";
								break;

							default:

//								$field_data .= sprintf(
//									'<tr bgcolor="%3$s">
//                                                            <td colspan="2">
//                                                                <font style="font-family: sans-serif; font-size:12px;"><strong>%1$s</strong></font>
//                                                            </td>
//                                                       </tr>
//                                                       <tr bgcolor="%4$s">
//                                                            <td width="20">&nbsp;</td>
//                                                            <td>
//                                                                <font style="font-family: sans-serif; font-size:12px;">%2$s</font>
//                                                            </td>
//                                                       </tr>
//                                                       ', $field_label, empty( $field_value ) && strlen( $field_value ) == 0 ? '&nbsp;' : $field_value, apply_filters( 'gform_email_background_color_label', '#EAF2FA', $field, $lead ), apply_filters( 'gform_email_background_color_data', '#FFFFFF', $field, $lead )
//								);
								break;
						}

						$item = array(
							'label' => $field_label,
							'value' => $field_value,
							'field' => $field
						);

					}
			}

			if( isset( $item ) ) {
				$items[] = $item;
				unset( $item );
			}

		}

		if ( $display_product_summary ) {
			$value = $this->all_fields_extra_options( GFCommon::get_submitted_pricing_fields( $form, $lead, $format, $use_text, $use_admin_label ), $merge_tag, $modifiers, 'order_summary', null );
			if( $value !== false ) {
				$items[] = array(
					'label' => 'Order Summary',
					'value' => $value,
				);
			}
		}

		return $items;
	}

	public function get_all_fields_field_value( $field, $value ) {

		switch ( $field->type ) {
			case 'html' :
				$value = $field->content;
				break;
			// Sections are included by default; including them manually will append their description.
			case 'section' :
				$value .= sprintf( '<tr bgcolor="#FFFFFF">
	                                                        <td width="20">&nbsp;</td>
	                                                        <td>
	                                                            <font style="font-family: sans-serif; font-size:12px;">%s</font>
	                                                        </td>
	                                                   </tr>
	                                                   ', $field->description );
				break;
			case 'signature' :
				$url   = is_callable( 'gf_signature' ) ? gf_signature()->get_signature_url( $value ) : $value;
				$value = "<img alt='signature' src='{$url}' />";
				break;
		}

		return $value;
	}

	public function log( $message ) {
		GFCommon::log_debug( $message );
	}

	// ### TEMPLATE SYSTEM (compliments of EDD) ###

	public function load_template( $slug, $name = null, $data = array(), $suffixes = array() ) {
		ob_start();
		extract( $data );
		$template = $this->get_template_part( $slug, $name, false, $suffixes );
		if( ! empty( $template ) ) {
			include( $template );
		}
		$content = ob_get_clean();
		return ! $template ? false : $content;
	}

	public function get_template_part( $slug, $name = null, $load = true, $suffixes = array() ) {

		// Execute code for this part
		do_action( 'get_template_part_' . $slug, $slug, $name, $suffixes );

		// Setup possible parts
		$templates = array();

		if( isset( $name ) ) {
			$suffixes[] = $name;
		}

		foreach( $suffixes as $suffix ) {
			$templates[] = $slug . '-' . $suffix . '.php';
		}

		$templates[] = $slug . '.php';

		// Return the part that is found
		return $this->locate_template( $templates, $load, false );
	}

	public function locate_template( $template_names, $load = false, $require_once = true ) {

		// No file found yet
		$located = false;

		// Try to find a template file
		foreach ( (array) $template_names as $template_name ) {

			// Continue if template is empty
			if ( empty( $template_name ) )
				continue;

			// Trim off any slashes from the template name
			$template_name = ltrim( $template_name, '/' );

			// try locating this template file by looping through the template paths
			foreach( $this->get_theme_template_paths() as $template_path ) {

				if( file_exists( $template_path . $template_name ) ) {
					$located = $template_path . $template_name;
					break;
				}
			}

			if( $located ) {
				break;
			}
		}

		if ( ( true == $load ) && ! empty( $located ) )
			load_template( $located, $require_once );

		return $located;
	}

	public function get_theme_template_paths() {

		$template_dir = $this->get_theme_template_dir_name();

		$file_paths = array(
			1 => trailingslashit( get_stylesheet_directory() ) . $template_dir,
			10 => trailingslashit( get_template_directory() ) . $template_dir
		);

		// sort the file paths based on priority
		ksort( $file_paths, SORT_NUMERIC );

		return array_map( 'trailingslashit', $file_paths );
	}

	public function get_theme_template_dir_name() {
		return trailingslashit( 'gravity-forms' );
	}

}

function gw_all_fields_template() {
	return GW_All_Fields_Template::get_instance();
}

gw_all_fields_template();
<ul>

	<?php foreach( $items as $item ): ?>

	<li>
		<strong><?php echo $item['label']; ?><strong><br>
		<?php echo $item['value']; ?>
	</li>

	<?php endforeach; ?>

</ul>