September 5, 2019: Fixed notices generated in PHP7.3 by
continue
statements inside a foreach/switch.April 11, 2019: Updated priority of template replacement to avoid conflict with other merge tags replacement plugins.
<?php | |
/** | |
* Gravity Wiz // Gravity Forms // All Fields Template | |
* | |
* Modify the {all_fields} merge tag output via a template file. | |
* | |
* @version 0.9.5 | |
* @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.5 | |
* 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. | |
* | |
* 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:filter[3]} | |
* {all_fields:filter[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' ); | |
$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 ); | |
} | |
/** | |
* 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[ $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"> </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 ? ' ' : $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"> </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(); |
The Gravity Forms {all_fields}
merge tag provides a super simple way to output all of the submitted form data but it’s notoriously difficult to customize.
This plugin provides templating support for the {all_fields}
merge tag. Huh? It means you can replace the markup generated by the merge tag with the contents of a file. This tutorial offers a solid starter template file too!
Getting Started
This tutorial assumes you’re running a recent version of Gravity Forms, that you already have the {all_fields}
merge tag implemented wherever you want, and that you ♥ Gravity Wiz.
![]() | Download, install, and activate the plugin. |
![]() | Download the sample template directory/file. Add the folder to your active theme’s root directory: /wp-content/themes/{your-theme}/ |
![]() | Customize the template as desired. |
Template and Merge Tag Options
This plugin provides a few handy modifiers for controlling which template will be used to render the {all_fields}
merge tag.
Note: All template paths are relative to your theme’s root directory.
Default Templates
Merge Tag | Template |
---|---|
{all_fields} | /gravity-forms/all-fields.php |
Form-specific Template
Providing a form-specific template requires not changes to the merge tag. Simply append the targeted form ID to your template’s name. This template will now only be used with the merge tag is used in the context of the specified form.
Merge Tag | Template |
---|---|
{all_fields} | /gravity-forms/all-fields.php /gravity-forms/all-fields-1.php |
Custom Template
You may want to create a custom template that should only be applied to specific instances of the merge tag. The “template” modifier allows you to specify a custom template suffix.
Merge Tag | Template |
---|---|
{all_fields:template[custom]} | /gravity-forms/all-fields-{template}.php /gravity-forms/all-fields-custom.php |
No Template
You may want to create a generic template that applies to all instances of the merge tag by default and then disable that template to use the default Gravity Forms merge tag output in a few specific instances.
Merge Tag | Template |
---|---|
{all_fields:notemplate} | No template |
Field Filtering Modifier
These modifiers allow you to control which fields are output in the {all_fields}
merge tag without having to touch any code.
Please note: you only need the plugin installed to use these modifiers. You do not need to install the template files in your theme.
Merge Tag | Description |
---|---|
{all_fields:include[1,2]} | Include a field that is not included by default (i.e. HTML fields). |
{all_fields:exclude[3,4]} | Exclude a field that is included by default. |
{all_fields:filter[1,2]} | Only include the specified field IDs. This takes precedence over both the ‘include’ and ‘exclude’ modifiers. |
{all_fields:include[1,2],exclude[3]} | The :include and :exclude modifiers can be combined. |
GF Nested Forms Support
To filter which fields from a child form display in your {all_fields}
merge tag you can use the :filter modifier and the [Nested Form Field ID].[Child Field ID] format (e.g., 4.3; where 4 is the Nested Form field ID and 3 is the child field ID from the child form.
You can use the :include, :exclude, and :filter modifiers on the Nested Form field to filter which child fields should be displayed.
Merge Tag | Description |
---|---|
{all_fields:filter[1,2,3.4,3.5]} | In this example, 1 and 2 are field IDs on the parent form. 3 is the Nested Form Field ID and 4 and 5 are field IDs on the child form. |
{Nested Form:1:filter[4,5]} | Show fields 4 and 5 from the child form for this Nested Form field. |
Customizing the Template
Ok, don’t let this section intimidate you. Here’s the TLDR; Loop through $items
, use $item['label']
for the field label, and $item['value']
for the field value. Here’s the simplest template you could have:
<ul> | |
<?php foreach( $items as $item ): ?> | |
<li> | |
<strong><?php echo $item['label']; ?><strong><br> | |
<?php echo $item['value']; ?> | |
</li> | |
<?php endforeach; ?> | |
</ul> |
You’ll most likely want to use the sample template above as a starting point though as it takes care of a requirements to better align the template with Gravity Forms default All Fields functionality.
Digging Deeper
The {all_fields}
template works like any other WordPress template with one exception. There is a special $items
array available to you.
Each $item
contains a label, value, and field property. The label and value are the exact label and value that the default {all_fields}
merge tag would output. The field is the input-type-specific GF_Field object for the current field. This is useful when you want to alter the way a field is displayed depending on the field you’re working with.
Lastly, you have access to the current entry via the $entry
variable and the current form via the $form
variable. For more details on these variables, see the parameters section below.
Parameters
$items array
An array of items, each item containing the Gravity-Forms-formatted field label, field value and field object for the given field. The field label and field value are the same values that Gravity Forms outputs in the default
{all_fields}
merge tag.$entry Entry Object
The current Gravity Forms Entry object.
$form Form Object
The current Gravity Forms Form object.
Questions? Feedback?
What questions do you have? What features are missing? We’d like to make this into a more robust plugin and your feedback will be a big part of shaping the final product.
Did this resource help you do something awesome with Gravity Forms? Then you'll absolutely love Gravity Perks; a suite of 31+ essential add-ons for Gravity Forms with support you can count on.
I’ve created a form using the products field but I only want to display quantities not unit price, price or total. Is this possible using this plugin and if so what would be the best way to go about it?
Hi Karl, this plugin does not offer a way to customize the order summary. Something we’re considering for a future release.
I downloaded this plugin in hopes that I can change the background colors. I want the I think I am missing a step somewhere. I want only certain fields to be in color. The rest to stay white.
Thanks
Kristen – are you referring to having certain fields have different background OR text colors?
example: Name field has black text, and white background. While Email field has blue text, and green background.
If so – then you just want CSS changes. Example: (look in the CSS section of my code) https://codepen.io/rockykev/pen/xxKpQpK?editors=1100
You’ll have to learn a bit of CSS (each form item has a unique ID), and a way to put it on your page (I use a WordPress plugin for at.)
Section fields set to Administrative for visibility do not appear on the {all_fields} even if included using the {all_fields:include[#]}.
If I enter a description, it does show up so but the label is still not present.
Thanks for the note, Mike. This is something we’ll take a look at for the next version.
Hi I am a web developer and upgrading a clients WordPress theme and starting fresh by moving it to a new host. The previous web developer created a quote generator using gravity forms and had the “Gravity Forms All Fields Template” plugin installed and an all-fields-php file in the theme folder. I imported the gravity form, I copied the all-fields.php file to the theme folder under /your-theme/gravity-forms/all-fields.php and still I cannot see the table.
Instead I just see a shortcode {modified_order_summary} where the table should be. You can test the working form here https://weddingspartiesentertainment.com.au/packages/ and the one at the new theme here. http://weddingparty.wpengine.com/packages/
What am I doing wrong? Had 3 or 4 coders look at it and not able to work it out.
Hi Paul, I believe there is some other code that is handling the
{modified_order_summary}
merge tag. This is not part of the All Fields template.Ahh thank you very much for the quick response. I will look into it.