XylotrechusZ
<?php
/**
* GravityView template tags API
*
* @package GravityView
* @license GPL2+
* @author GravityKit <[email protected]>
* @link http://www.gravitykit.com
* @copyright Copyright 2014, Katz Web Services, Inc.
*
* @since 1.0.0
*/
class GravityView_API {
/**
* Fetch Field Label
*
* @deprecated Use \GV\Field::get_label()
*
* @static
* @param array $field GravityView field array
* @param array $entry Gravity Forms entry array
* @param boolean $force_show_label Whether to always show the label, regardless of field settings
* @return string
*/
public static function field_label( $field, $entry = array(), $force_show_label = false ) {
$gravityview_view = GravityView_View::getInstance();
$form = $gravityview_view->getForm();
if ( defined( 'DOING_GRAVITYVIEW_TESTS' ) && ! empty( $GLOBALS['GravityView_API_field_label_override'] ) ) {
/** Allow to fall through for back compatibility testing purposes. */
} else {
return \GV\Mocks\GravityView_API_field_label( $form, $field, $entry, $force_show_label );
}
$label = '';
if ( ! empty( $field['show_label'] ) || $force_show_label ) {
$label = $field['label'];
// Support Gravity Forms 1.9+
if ( class_exists( 'GF_Field' ) ) {
$field_object = RGFormsModel::get_field( $form, $field['id'] );
if ( $field_object ) {
$input = GFFormsModel::get_input( $field_object, $field['id'] );
// This is a complex field, with labels on a per-input basis
if ( $input ) {
// Does the input have a custom label on a per-input basis? Otherwise, default label.
$label = ! empty( $input['customLabel'] ) ? $input['customLabel'] : $input['label'];
} else {
// This is a field with one label
$label = $field_object->get_field_label( true, $field['label'] );
}
}
}
// Use Gravity Forms label by default, but if a custom label is defined in GV, use it.
if ( ! empty( $field['custom_label'] ) ) {
$label = self::replace_variables( $field['custom_label'], $form, $entry );
}
/**
* Append content to a field label.
*
* @param string $appended_content Content you can add after a label. Empty by default.
* @param array $field GravityView field array
*/
$label .= apply_filters( 'gravityview_render_after_label', '', $field );
} // End $field['show_label']
/**
* Modify field label output.
*
* @since 1.7
* @param string $label Field label HTML
* @param array $field GravityView field array
* @param array $form Gravity Forms form array
* @param array $entry Gravity Forms entry array
*
* @deprecated Use the context-aware version `gravityview/template/field/label`
*/
$label = apply_filters( 'gravityview/template/field_label', $label, $field, $form, $entry );
return $label;
}
/**
* Alias for GravityView_Merge_Tags::replace_variables()
*
* @see GravityView_Merge_Tags::replace_variables() Moved in 1.8.4
* @since 1.22.4 - Added $nl2br, $format, $aux_data args
*
* @param string $text Text to replace variables in
* @param array $form GF Form array
* @param array $entry GF Entry array
* @param bool $url_encode Pass return value through `url_encode()`
* @param bool $esc_html Pass return value through `esc_html()`
* @param bool $nl2br Convert newlines to <br> HTML tags
* @param string $format The format requested for the location the merge is being used. Possible values: html, text or url.
* @param array $aux_data Additional data to be used to replace merge tags {@see https://www.gravityhelp.com/documentation/article/gform_merge_tag_data/}
* @return string Text with variables maybe replaced
*/
public static function replace_variables( $text, $form = array(), $entry = array(), $url_encode = false, $esc_html = true, $nl2br = true, $format = 'html', $aux_data = array() ) {
return GravityView_Merge_Tags::replace_variables( $text, $form, $entry, $url_encode, $esc_html, $nl2br, $format, $aux_data );
}
/**
* Get column width from the field setting
*
* @since 1.9
*
* @param array $field Array of settings for the field
* @param string $format Format for width. "%" (default) will return
*
* @return string|null If not empty, string in $format format. Otherwise, null.
*/
public static function field_width( $field, $format = '%d%%' ) {
$width = null;
if ( ! empty( $field['width'] ) ) {
$width = absint( $field['width'] );
// If using percentages, limit to 100%
if ( '%d%%' === $format && $width > 100 ) {
$width = 100;
}
$width = sprintf( $format, $width );
}
return $width;
}
/**
* Fetch Field class
*
* @static
* @param mixed $field
* @return string
*/
public static function field_class( $field, $form = null, $entry = null ) {
$classes = array();
if ( ! empty( $field['custom_class'] ) ) {
$custom_class = $field['custom_class'];
if ( ! empty( $entry ) ) {
// We want the merge tag to be formatted as a class. The merge tag may be
// replaced by a multiple-word value that should be output as a single class.
// "Office Manager" will be formatted as `.OfficeManager`, not `.Office` and `.Manager`
add_filter( 'gform_merge_tag_filter', 'sanitize_html_class' );
$custom_class = self::replace_variables( $custom_class, $form, $entry );
// And then we want life to return to normal
remove_filter( 'gform_merge_tag_filter', 'sanitize_html_class' );
}
// And now we want the spaces to be handled nicely.
$classes[] = gravityview_sanitize_html_class( $custom_class );
}
if ( ! empty( $field['id'] ) ) {
if ( ! empty( $form ) && ! empty( $form['id'] ) ) {
$form_id = '-' . $form['id'];
} else {
// @deprecated path. Form should always be given.
gravityview()->log->warning( 'GravityView_View::getInstance() legacy API called' );
$gravityview_view = GravityView_View::getInstance();
$form_id = $gravityview_view->getFormId() ? '-' . $gravityview_view->getFormId() : '';
}
$classes[] = 'gv-field' . $form_id . '-' . $field['id'];
}
return esc_attr( implode( ' ', $classes ) );
}
/**
* Fetch Field HTML ID
*
* @since 1.11
*
* @static
* @param array $field GravityView field array passed to gravityview_field_output()
* @param array $form Gravity Forms form array, if set.
* @param array $entry Gravity Forms entry array
* @return string Sanitized unique HTML `id` attribute for the field
*/
public static function field_html_attr_id( $field, $form = array(), $entry = array() ) {
$id = $field['id'];
if ( ! empty( $id ) ) {
if ( ! empty( $form ) && ! empty( $form['id'] ) ) {
$form_id = '-' . $form['id'];
} else {
// @deprecated path. Form should always be given.
gravityview()->log->warning( 'GravityView_View::getInstance() legacy API called' );
$gravityview_view = GravityView_View::getInstance();
$form_id = $gravityview_view->getFormId() ? '-' . $gravityview_view->getFormId() : '';
}
$id = 'gv-field' . $form_id . '-' . $field['id'];
}
return esc_attr( $id );
}
/**
* Given an entry and a form field id, calculate the entry value for that field.
*
* @deprecated Use \GV\Field_Template::render() or the more low-level \GV\Field::get_value()
*
* @param array $entry
* @param array $field
* @return null|string
*/
public static function field_value( $entry, $field_settings, $format = 'html' ) {
gravityview()->log->notice( '\GravityView_API::field_value is deprecated. Use \GV\Field_Template::render() or \GV\Field::get_value()' );
return \GV\Mocks\GravityView_API_field_value( $entry, $field_settings, $format );
}
/**
* Generate an anchor tag that links to an entry.
*
* @since 1.6
* @see GVCommon::get_link_html()
*
* @param string $anchor_text The text or HTML inside the link
* @param array $entry Gravity Forms entry array
* @param array|string $passed_tag_atts Attributes to be added to the anchor tag, such as `title` or `rel`.
* @param array $field_settings Array of field settings. Optional, but passed to the `gravityview_field_entry_link` filter
*
* @since 2.0
* @param int $base_id The post or the view that this entry is linked from.
*
* @return string|null Returns HTML for an anchor link. Null if $entry isn't defined or is missing an ID.
*/
public static function entry_link_html( $entry = array(), $anchor_text = '', $passed_tag_atts = array(), $field_settings = array(), $base_id = null ) {
if ( empty( $entry ) || ! is_array( $entry ) || ! isset( $entry['id'] ) ) {
gravityview()->log->debug( 'Entry not defined; returning null', array( 'data' => $entry ) );
return null;
}
$href = self::entry_link( $entry, $base_id );
if ( '' === $href ) {
return null;
}
$link = gravityview_get_link( $href, $anchor_text, $passed_tag_atts );
/**
* Modify the link HTML.
*
* @param string $link HTML output of the link
* @param string $href URL of the link
* @param array $entry The GF entry array
* @param array $field_settings Settings for the particular GV field
*/
$output = apply_filters( 'gravityview_field_entry_link', $link, $href, $entry, $field_settings );
return $output;
}
/**
* Get the "No Results" text depending on whether there were results.
*
* @since 2.0
*
* @param boolean $wpautop Apply wpautop() to the output?
* @param \GV\Template_Context|null $context The context
*
* @return string HTML of "no results" text
*/
public static function no_results( $wpautop = true, $context = null ) {
$is_search = false;
if ( $context instanceof \GV\Template_Context ) {
if ( $context->request->is_search() ) {
$is_search = true;
}
} else {
$gravityview_view = GravityView_View::getInstance();
if ( $gravityview_view && ( $gravityview_view->curr_start || $gravityview_view->curr_end || $gravityview_view->curr_search ) ) {
$is_search = true;
}
}
$setting = '';
if ( $is_search ) {
$output = esc_html__( 'This search returned no results.', 'gk-gravityview' );
if ( $context ) {
$setting = $context->view->settings->get( 'no_search_results_text', $output );
}
} else {
$output = esc_html__( 'No entries match your request.', 'gk-gravityview' );
if ( $context ) {
$setting = $context->view->settings->get( 'no_results_text', $output );
}
}
if ( '' !== $setting ) {
$output = $setting;
}
/**
* Added now that users are able to modify via View settings
*
* @since 2.8.2
*/
$output = wp_kses(
$output,
array(
'p' => array(
'class' => array(),
'id' => array(),
),
'h1' => array(
'class' => array(),
'id' => array(),
),
'h2' => array(
'class' => array(),
'id' => array(),
),
'h3' => array(
'class' => array(),
'id' => array(),
),
'h4' => array(
'class' => array(),
'id' => array(),
),
'h5' => array(
'class' => array(),
'id' => array(),
),
'strong' => array(
'class' => array(),
'id' => array(),
),
'span' => array(
'class' => array(),
'id' => array(),
),
'b' => array(
'class' => array(),
'id' => array(),
),
'em' => array(
'class' => array(),
'id' => array(),
),
'a' => array(
'class' => array(),
'id' => array(),
'href' => array(),
'title' => array(),
'rel' => array(),
'target' => array(),
),
'div' => array(
'class' => array(),
'id' => array(),
),
'br' => array(),
)
);
$unformatted_output = $output;
$output = $wpautop ? wpautop( $output ) : $output;
/**
* Modify the text displayed when there are no entries.
* Note: this filter is, and always has been, misspelled. This will not be fixed, since the filter is deprecated.
*
* @param string $output The existing "No Entries" text
* @param boolean $is_search Is the current page a search result, or just a multiple entries screen?
* @return string The modified text.
* @deprecated Use `gravityview/template/text/no_entries`
*/
$output = apply_filters( 'gravitview_no_entries_text', $output, $is_search );
/**
* Modify the text displayed when there are no entries.
*
* @since 2.0
* @since 2.17 Added $wpautop parameter.
* @param string $output The existing "No Entries" text.
* @param boolean $is_search Is the current page a search result, or just a multiple entries screen?
* @param \GV\Template_Context $context The context.
* @param string $unformatted_output Output without `wpautop()`.
* @return string The modified text.
*/
$output = apply_filters( 'gravityview/template/text/no_entries', $output, $is_search, $context, $unformatted_output );
return $output;
}
/**
* Generate a URL to the Directory context
*
* Uses local static variable to speed up repeated requests to get permalink, which improves load time. Since we may be doing this hundreds of times per request, it adds up!
*
* @used-by GravityView_API::entry_link()
* @used-by GravityView_Widget_Page_Links::render_frontend()
*
* @param int $post_id Post ID
* @param boolean $add_query_args Add pagination and sorting arguments
*
* @since 2.0
* @param \GV\Template_Context $context The context this is being used in.
*
* @return string Permalink to multiple entries view
*/
public static function directory_link( $post_id = null, $add_query_args = true, $context = null ) {
global $post;
if ( empty( $post_id ) ) {
// DataTables passes the Post ID
if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
$post_id = \GV\Utils::_POST( 'post_id', false );
} elseif ( $context instanceof \GV\Template_Context ) {
// Shortcodes, embeds
if ( is_a( $post, 'WP_Post' ) ) {
$post_id = $post->ID;
// Actual views
} else {
$post_id = $context->view ? $context->view->ID : false;
}
} else {
if ( ! class_exists( 'GravityView_View' ) ) {
gravityview()->plugin->include_legacy_frontend( true );
}
/** @deprecated path of execution */
$gravityview_view = GravityView_View::getInstance();
// The Post ID has been passed via the shortcode
if ( ! empty( $gravityview_view ) && $gravityview_view->getPostId() ) {
$post_id = $gravityview_view->getPostId();
} else {
// This is a GravityView post type
if ( GravityView_frontend::getInstance()->isGravityviewPostType() ) {
$post_id = isset( $gravityview_view ) ? $gravityview_view->getViewId() : $post->ID;
} else {
// This is an embedded GravityView; use the embedded post's ID as the base.
if ( GravityView_frontend::getInstance()->isPostHasShortcode() && is_a( $post, 'WP_Post' ) ) {
$post_id = $post->ID;
} elseif ( $gravityview_view->getViewId() ) {
// The GravityView has been embedded in a widget or in a template, and
// is not in the current content. Thus, we defer to the View's own ID.
$post_id = $gravityview_view->getViewId();
}
}
}
}
}
// No post ID, get outta here.
if ( empty( $post_id ) ) {
return null;
}
static $directory_links = array();
/**
* If we've saved the permalink, use it. Reduces time spent on `get_permalink()`, which is heavy.
*
* @since 1.3
* @since 2.17 Changed from using wp_cache_set() to using a static variable.
*/
if ( isset( $directory_links[ 'gv_directory_link_' . $post_id ] ) ) {
$link = $directory_links[ 'gv_directory_link_' . $post_id ];
}
if ( (int) $post_id === (int) get_option( 'page_on_front' ) ) {
$link = home_url();
}
if ( empty( $link ) ) {
$link = get_permalink( $post_id );
$directory_links[ 'gv_directory_link_' . $post_id ] = $link;
}
// Deal with returning to proper pagination for embedded views
if ( $link && $add_query_args ) {
$args = array();
if ( $pagenum = \GV\Utils::_GET( 'pagenum' ) ) {
$args['pagenum'] = intval( $pagenum );
}
if ( $sort = \GV\Utils::_GET( 'sort' ) ) {
$args['sort'] = $sort;
$args['dir'] = \GV\Utils::_GET( 'dir' );
}
$link = add_query_arg( $args, $link );
}
/**
* Modify the URL to the View "directory" context.
*
* @since 1.19.4
* @param string $link URL to the View's "directory" context (Multiple Entries screen)
* @param int $post_id ID of the post to link to. If the View is embedded, it is the post or page ID
*/
$link = apply_filters( 'gravityview_directory_link', $link, $post_id );
/**
* Modify the URL to the View "directory" context.
*
* @since 2.0
* @param string $link URL to the View's "directory" context (Multiple Entries screen)
* @param \GV\Template_Context $context
*/
return apply_filters( 'gravityview/view/links/directory', $link, $context );
}
/**
* Calculate an *unique* hash for an entry based on the entry ID
*
* This allows you to be more discrete as to the number of the entry - if you don't want users to know that you have made a certain number of sales, for example, or that their entry in the giveaway is entry #3.
*
* The hashed value MUST be unique, otherwise multiple entries will share the same URL, which leads to obvious problems.
*
* @param int|string $id Entry ID to generate the hash for.
* @param array $entry Entry data passed to provide additional information when generating the hash. Optional - don't rely on it being available.
* @return string Hashed unique value for entry
*/
private static function get_custom_entry_slug( $id, $entry = array() ) {
// Generate an unique hash to use as the default value
$slug = substr( wp_hash( $id, 'gravityview' . $id ), 0, 8 );
/**
* or even, if unique, `{first-name}-{last-name}`.
*
* @param string $hash Existing hash generated by GravityView
* @param string $id The entry ID
* @param array $entry Entry data array. May be empty.
*/
$slug = apply_filters( 'gravityview_entry_slug', $slug, $id, $entry );
// Make sure we have something - use the original ID as backup.
if ( empty( $slug ) ) {
$slug = $id;
}
return sanitize_title( $slug );
}
/**
* Get the entry slug for the entry. By default, it is the entry ID.
*
* @see gravityview_get_entry()
* @uses GravityView_API::get_custom_entry_slug() If using custom slug, gets the custom slug value
* @since 1.4
* @param int|string $id_or_string ID of the entry, or custom slug string
* @param array $entry Gravity Forms Entry array, optional. Used only to provide data to customize the `gravityview_entry_slug` filter
* @return string Unique slug ID, passed through `sanitize_title()`
*/
public static function get_entry_slug( $id_or_string, $entry = array() ) {
/**
* Default: use the entry ID as the unique identifier
*/
$slug = $id_or_string;
/**
* Whether to enable and use custom entry slugs.
*
* @param boolean True: Allow for slugs based on entry values. False: always use entry IDs (default)
*/
$custom = apply_filters( 'gravityview_custom_entry_slug', false );
// If we're using custom slug...
if ( $custom ) {
// Get the entry hash
$hash = self::get_custom_entry_slug( $id_or_string, $entry );
// Cache the slugs
static $cache = array();
if ( ! isset( $cache[ $id_or_string ] ) ) {
global $wpdb;
if ( version_compare( GFFormsModel::get_database_version(), '2.3-dev-1', '>=' ) ) {
$table = GFFormsModel::get_entry_meta_table_name();
$column = 'entry_id';
} else {
$table = RGFormsModel::get_lead_meta_table_name();
$column = 'lead_id';
}
$results = $wpdb->get_results( $wpdb->prepare( "SELECT $column, meta_value FROM $table WHERE form_id = (SELECT form_id FROM $table WHERE $column = %d LIMIT 1) AND meta_key = 'gravityview_unique_id'", $id_or_string ) );
if ( $results ) {
$cache = array_replace( $cache, array_combine( wp_list_pluck( $results, $column ), wp_list_pluck( $results, 'meta_value' ) ) );
}
if ( ! isset( $cache[ $id_or_string ] ) ) {
$cache[ $id_or_string ] = false;
}
}
$value = $cache[ $id_or_string ];
// If it does have a hash set, and the hash is expected, use it.
// This check allows users to change the hash structure using the
// gravityview_entry_hash filter and have the old hashes expire.
if ( empty( $value ) || $value !== $hash ) {
gravityview()->log->debug(
'Setting hash for entry {entry}: {hash}',
array(
'entry' => $id_or_string,
'hash' => $hash,
)
);
gform_update_meta( $id_or_string, 'gravityview_unique_id', $hash, \GV\Utils::get( $entry, 'form_id' ) );
}
$slug = $hash;
unset( $value, $hash );
}
return sanitize_title( $slug );
}
/**
* If using the entry custom slug feature, make sure the new entries have the custom slug created and saved as meta
*
* Triggered by add_action( 'gform_entry_created', array( 'GravityView_API', 'entry_create_custom_slug' ), 10, 2 );
*
* @param $entry array Gravity Forms entry object
* @param $form array Gravity Forms form object
*/
public static function entry_create_custom_slug( $entry, $form ) {
/**
* On entry creation, check if we are using the custom entry slug feature and update the meta.
*
* @param boolean $custom Should we process the custom entry slug?
*/
$custom = apply_filters( 'gravityview_custom_entry_slug', false );
if ( $custom ) {
// create the gravityview_unique_id and save it
// Get the entry hash
$hash = self::get_custom_entry_slug( $entry['id'], $entry );
gravityview()->log->debug(
'Setting hash for entry {entry_id}: {hash}',
array(
'entry_id' => $entry['id'],
'hash' => $hash,
)
);
gform_update_meta( $entry['id'], 'gravityview_unique_id', $hash, \GV\Utils::get( $entry, 'form_id' ) );
}
}
/**
* return href for single entry
*
* @since 1.7.3 Added $add_directory_args parameter
* @since 2.7.2 Added $view_id parameter
* @since 2.10 Added $_GET args to links by default. Use `gravityview/entry_link/add_query_args` filter to override.
*
* @used-by GravityView_Entry_List::get_output()
* @used-by GravityView_Delete_Entry::get_delete_link()
* @used-by GravityView_Edit_Entry::get_edit_link()
* @used-by GravityView_Entry_Link_Shortcode::shortcode()
*
* @param array|int $entry Entry array or entry ID.
* @param int|null $post_id If wanting to define the parent post, pass a post ID.
* @param boolean $add_directory_args True: Add args to help return to directory; False: only include args required to get to entry.
* @param int $view_id
*
* @return string Link to the entry with the directory parent slug, or empty string if embedded post or View doesn't exist
*/
public static function entry_link( $entry, $post_id = null, $add_directory_args = true, $view_id = 0 ) {
if ( ! empty( $entry ) && ! is_array( $entry ) ) {
$entry = GVCommon::get_entry( $entry );
} elseif ( empty( $entry ) ) {
// @deprecated path
$entry = GravityView_frontend::getInstance()->getEntry();
}
// Second parameter used to be passed as $field; this makes sure it's not an array
if ( ! is_numeric( $post_id ) ) {
$post_id = null;
}
// Get the permalink to the View
$directory_link = self::directory_link( $post_id, false );
// No post ID? Get outta here.
if ( empty( $directory_link ) ) {
return '';
}
$query_arg_name = \GV\Entry::get_endpoint_name();
if ( ! empty( $entry['_multi'] ) ) {
$entry_slugs = array();
foreach ( $entry['_multi'] as $_multi ) {
if ( $gv_multi = \GV\GF_Entry::from_entry( $_multi ) ) {
$entry_slugs[] = $gv_multi->get_slug();
} else {
// TODO: This path isn't covered by unit tests
$entry_slugs[] = self::get_entry_slug( $_multi['id'], $_multi );
}
unset( $gv_multi );
$forms[] = $_multi['form_id'];
}
$entry_slug = implode( ',', $entry_slugs );
} else {
// Fallback when
if ( $gv_entry = \GV\GF_Entry::from_entry( $entry ) ) {
$entry_slug = $gv_entry->get_slug();
} else {
// TODO: This path isn't covered by unit tests
$entry_slug = self::get_entry_slug( $entry['id'], $entry );
}
unset( $gv_entry );
}
$args = array();
/**
* Modify whether to include passed $_GET parameters to the end of the url.
*
* @since 2.10
* @param bool $add_query_params Whether to include passed $_GET parameters to the end of the Entry Link URL. Default: true.
*/
$add_query_args = apply_filters( 'gravityview/entry_link/add_query_args', true );
if ( $add_query_args ) {
$args = gv_get_query_args();
}
if ( get_option( 'permalink_structure' ) && ! is_preview() ) {
/**
* Make sure the $directory_link doesn't contain any query otherwise it will break when adding the entry slug.
*
* @since 1.16.5
*/
$link_parts = explode( '?', $directory_link );
$query = ! empty( $link_parts[1] ) ? '?' . $link_parts[1] : '';
$directory_link = trailingslashit( $link_parts[0] ) . $query_arg_name . '/' . $entry_slug . '/' . $query;
} else {
$args[] = array( $query_arg_name => $entry_slug );
}
/**
* @since 1.7.3
*/
if ( $add_directory_args ) {
if ( ! empty( $_GET['pagenum'] ) ) {
$args['pagenum'] = intval( $_GET['pagenum'] );
}
/**
* @since 1.7
*/
if ( $sort = \GV\Utils::_GET( 'sort' ) ) {
$args['sort'] = $sort;
$args['dir'] = \GV\Utils::_GET( 'dir' );
}
}
if ( $post_id ) {
$passed_post = get_post( $post_id );
$views = \GV\View_Collection::from_post( $passed_post );
$has_multiple_views = $views->count() > 1;
} else {
$has_multiple_views = class_exists( 'GravityView_View_Data' ) && GravityView_View_Data::getInstance()->has_multiple_views();
}
if ( $has_multiple_views ) {
$args['gvid'] = $view_id ? $view_id : gravityview_get_view_id();
}
return add_query_arg( $args, $directory_link );
}
}
/**
* Returns query parameters from $_GET with reserved internal GravityView keys removed
*
* @uses stripslashes_deep() $_GET is passed through stripslashes_deep().
* @uses urldecode_deep() $_GET is passed through urldecode_deep().
*
* Important: The return value of gv_get_query_args() is not escaped by default. Output should be
* late-escaped with esc_url() or similar to help prevent vulnerability to cross-site scripting
* (XSS) attacks.
*
* @since 2.10
*
* @return array
*/
function gv_get_query_args() {
$passed_get = isset( $_GET ) ? $_GET : array();
$passed_get = stripslashes_deep( $passed_get );
$passed_get = urldecode_deep( $passed_get );
if ( empty( $passed_get ) ) {
return array();
}
$query_args = $passed_get;
$reserved_args = array(
'entry',
'gvid',
'status',
'action',
'view_id',
'entry_id',
'pagenum',
);
/**
* Modify the URL arguments that should not be used because they are internal to GravityView.
*
* @since 2.10
* @param array $reserved_args Array of URL query keys that should not be used except internally.
*/
$reserved_args = apply_filters( 'gravityview/api/reserved_query_args', $reserved_args );
foreach ( $reserved_args as $reserved_arg ) {
unset( $query_args[ $reserved_arg ] );
}
return $query_args;
}
// inside loop functions
/**
* @deprecated Use \GV\Field::get_label()
*/
function gv_label( $field, $entry = null ) {
return GravityView_API::field_label( $field, $entry );
}
function gv_class( $field, $form = null, $entry = array() ) {
return GravityView_API::field_class( $field, $form, $entry );
}
/**
* Generate a CSS class to be added to the wrapper <div> of a View
*
* @since 1.5.4
* @since 1.16 Added $echo parameter.
* @since 2.0 Added $context parameter.
*
* @param string $passed_css_class Default: `gv-container gv-container-{view id}`. If View is hidden until search, adds ` hidden`
* @param boolean $echo Whether to echo the output. Default: true
* @param \GV\Template_Context $context The template context.
*
* @return string CSS class, sanitized by gravityview_sanitize_html_class()
*/
function gv_container_class( $passed_css_class = '', $echo = true, $context = null ) {
if ( $context instanceof \GV\Template_Context ) {
$hide = false;
$total_entries = 0;
$view_id = 0;
if ( $context->view ) {
$view_id = $context->view->ID;
if ( $context->view->settings->get( 'hide_until_searched' ) ) {
$hide = ( empty( $context->entry ) && ! $context->request->is_search() );
}
}
if ( $context->entries ) {
$total_entries = $context->entries->total();
} elseif ( $context->entry ) {
$total_entries = 1;
}
} else {
/** @deprecated legacy execution path */
$view_id = GravityView_View::getInstance()->getViewId();
$hide = GravityView_View::getInstance()->isHideUntilSearched();
$total_entries = GravityView_View::getInstance()->getTotalEntries();
}
$passed_css_class = trim( $passed_css_class );
$default_css_class = ! empty( $view_id ) ? sprintf( 'gv-container gv-container-%d', $view_id ) : 'gv-container';
if ( 0 === $total_entries ) {
$default_css_class .= ' gv-container-no-results';
if (
! gravityview()->request->is_search()
&& $context instanceof \GV\Template_Context
&& 3 === (int) $context->view->settings->get( 'no_entries_options', '0' )
) {
$hide = true;
}
}
if ( $hide ) {
$default_css_class .= ' gv-hidden';
}
if ( $context instanceof \GV\Template_Context && $context->view ) {
$default_css_class .= ' ' . $context->view->settings->get( 'class', '' );
}
$css_class = trim( $passed_css_class . ' ' . $default_css_class );
/**
* Modify the CSS class to be added to the wrapper <div> of a View.
*
* @since 1.5.4
* @param string $css_class Default: `gv-container gv-container-{view id}`. If View is hidden until search, adds ` hidden`. If the View has no results, adds `gv-container-no-results`
* @since 2.0
* @param \GV\Template_Context $context The context.
*/
$css_class = apply_filters( 'gravityview/render/container/class', $css_class, $context );
$css_class = gravityview_sanitize_html_class( $css_class );
if ( $echo ) {
echo $css_class;
}
return $css_class;
}
/**
* @deprecated Use \GV\Field_Template::render()
*/
function gv_value( $entry, $field ) {
$value = GravityView_API::field_value( $entry, $field );
if ( '' === $value ) {
/**
* What to display when a field is empty.
*
* @param string $value (empty string)
*/
$value = apply_filters( 'gravityview_empty_value', '' );
}
return $value;
}
function gv_directory_link( $post = null, $add_pagination = true, $context = null ) {
return GravityView_API::directory_link( $post, $add_pagination, $context );
}
function gv_entry_link( $entry, $post_id = null ) {
return GravityView_API::entry_link( $entry, $post_id );
}
function gv_no_results( $wpautop = true, $context = null ) {
return GravityView_API::no_results( $wpautop, $context );
}
/**
* Generate HTML for the back link from single entry view
*
* @since 1.0.1
* @since 2.0
* @param \GV\Template_Context $context The context this link is being displayed from.
* @return string|null If no GV post exists, null. Otherwise, HTML string of back link.
*/
function gravityview_back_link( $context = null ) {
$href = gv_directory_link( null, true, $context );
/**
* Modify the back link URL.
*
* @since 1.17.5
* @see gv_directory_link() Generated the original back link
* @param string $href Existing label URL
* @deprecated Use `gravityview/template/links/back/url`
*/
$href = apply_filters( 'gravityview_go_back_url', $href );
/**
* Modify the back link URL.
*
* @since 2.0
* @see gv_directory_link() Generated the original back link
* @param string $href Existing label URL
* @param \GV\Template_Context The context.
*/
$href = apply_filters( 'gravityview/template/links/back/url', $href, $context );
if ( empty( $href ) ) {
return null;
}
if ( $context instanceof \GV\Template_Context ) {
$view_id = $context->view->ID;
$view_label = $context->template->get_back_label();
} else {
/** @deprecated legacy path */
$gravityview_view = GravityView_View::getInstance();
$view_id = $gravityview_view->getViewId();
$view_label = $gravityview_view->getBackLinkLabel() ? $gravityview_view->getBackLinkLabel() : false;
}
/** Default */
$label = $view_label ? $view_label : __( '← Go back', 'gk-gravityview' );
/**
* Modify the back link text.
*
* @since 1.0.9
* @param string $label Existing label text
* @deprecated Use `gravityview/template/links/back/label`
*/
$label = apply_filters( 'gravityview_go_back_label', $label );
/**
* Modify the back link text.
*
* @since 2.0
* @see gv_directory_link() Generated the original back link
* @param string $label Existing label text
* @param \GV\Template_Context The context.
*/
$label = apply_filters( 'gravityview/template/links/back/label', $label, $context );
/**
* Modify the attributes used on the back link anchor tag.
*
* @since 2.1
* @param array $atts Original attributes, default: [ data-viewid => $view_id ]
* @param \GV\Template_Context The context.
*/
$atts = apply_filters( 'gravityview/template/links/back/atts', array( 'data-viewid' => $view_id ), $context );
$link = gravityview_get_link( $href, esc_html( $label ), $atts );
return $link;
}
/**
* Handle getting values for complex Gravity Forms fields
*
* If the field is complex, like a product, the field ID, for example, 11, won't exist. Instead,
* it will be 11.1, 11.2, and 11.3. This handles being passed 11 and 11.2 with the same function.
*
* @since 1.0.4
* @param array $entry GF entry array
* @param string $field_id [description]
* @param string $display_value The value generated by Gravity Forms
* @return string Value
*/
function gravityview_get_field_value( $entry, $field_id, $display_value ) {
if ( floatval( $field_id ) === floor( floatval( $field_id ) ) ) {
// For the complete field value as generated by Gravity Forms
return $display_value;
} else {
// For one part of the address (City, ZIP, etc.)
return isset( $entry[ $field_id ] ) ? $entry[ $field_id ] : '';
}
}
/**
* Take a passed CSV of terms and generate a linked list of terms
*
* Gravity Forms passes categories as "Name:ID" so we handle that using the ID, which
* is more accurate than checking the name, which is more likely to change.
*
* @param string $value Existing value
* @param string $taxonomy Type of term (`post_tag` or `category`)
* @return string CSV of linked terms
*/
function gravityview_convert_value_to_term_list( $value, $taxonomy = 'post_tag' ) {
$output = array();
if ( is_array( $value ) ) {
$terms = array_filter( array_values( $value ), 'strlen' );
} else {
$terms = explode( ', ', $value );
}
foreach ( $terms as $term_name ) {
// If we're processing a category,
if ( 'category' === $taxonomy ) {
// Use rgexplode to prevent errors if : doesn't exist
list( $term_name, $term_id ) = rgexplode( ':', $term_name, 2 );
// The explode was succesful; we have the category ID
if ( ! empty( $term_id ) ) {
$term = get_term_by( 'id', $term_id, $taxonomy );
} else {
// We have to fall back to the name
$term = get_term_by( 'name', $term_name, $taxonomy );
}
} else {
// Use the name of the tag to get the full term information
$term = get_term_by( 'name', $term_name, $taxonomy );
}
// There's still a tag/category here.
if ( $term ) {
$term_link = get_term_link( $term, $taxonomy );
// If there was an error, continue to the next term.
if ( is_wp_error( $term_link ) ) {
continue;
}
$output[] = gravityview_get_link( $term_link, esc_html( $term->name ) );
}
}
return implode( ', ', $output );
}
/**
* Get the links for post_tags and post_category output based on post ID
*
* @param int $post_id The ID of the post
* @param boolean $link Add links or no?
* @param string $taxonomy Taxonomy of term to fetch.
* @return string String with terms
*/
function gravityview_get_the_term_list( $post_id, $link = true, $taxonomy = 'post_tag' ) {
$output = get_the_term_list( $post_id, $taxonomy, null, ', ' );
if ( empty( $link ) ) {
return wp_strip_all_tags( $output );
}
return $output;
}
/**
* Get all views processed so far for the current page load
*
* @see GravityView_View_Data::add_view()
* @return array Array of View data, each View data with `id`, `view_id`, `form_id`, `template_id`, `atts`, `fields`, `widgets`, `form` keys.
*/
function gravityview_get_current_views() {
$fe = GravityView_frontend::getInstance();
// Solve problem when loading content via admin-ajax.php
if ( ! $fe->getGvOutputData() ) {
gravityview()->log->debug( 'gv_output_data not defined; parsing content.' );
$fe->parse_content();
}
// Make 100% sure that we're dealing with a properly called situation
if ( ! is_a( $fe->getGvOutputData(), 'GravityView_View_Data' ) ) {
gravityview()->log->debug( 'gv_output_data not an object or get_view not callable.', array( 'data' => $fe->getGvOutputData() ) );
return array();
}
return $fe->getGvOutputData()->get_views();
}
/**
* Get data for a specific view
*
* @deprecated use \GV\View API instead
* @since 2.5
*
* @see GravityView_View_Data::get_view()
* @return array View data with `id`, `view_id`, `form_id`, `template_id`, `atts`, `fields`, `widgets`, `form` keys.
*/
function gravityview_get_current_view_data( $view_id = 0 ) {
if ( $view_id ) {
if ( $view = \GV\View::by_id( $view_id ) ) {
return $view; // implements ArrayAccess
}
return array();
}
$fe = GravityView_frontend::getInstance();
// If not set, grab the current view ID
if ( empty( $view_id ) ) {
$view_id = $fe->get_context_view_id();
}
if ( ! $fe->getGvOutputData() ) {
return array(); }
return $fe->getGvOutputData()->get_view( $view_id );
}
// Templates' hooks
function gravityview_before() {
/**
* Append content to the view.
*
* @param object $gravityview The $gravityview object available in templates.
*/
if ( count( $args = func_get_args() ) ) {
$gravityview = reset( $args );
if ( $gravityview instanceof \GV\Template_Context ) {
/**
* Prepend content to the View.
*
* @param \GV\Template_Context $gravityview The $gravityview object available in templates.
*/
do_action( 'gravityview/template/before', $gravityview );
/**
* @deprecated Use `gravityview/template/before`
*/
return do_action( 'gravityview_before', $gravityview->view->ID );
}
}
/**
* Prepend content to the View container `<div>`.
*
* @deprecated Use `gravityview/template/before`.
* @param int $view_id The ID of the View being displayed
*/
do_action( 'gravityview_before', gravityview_get_view_id() );
}
function gravityview_header() {
/**
* Append content to the view.
*
* @param object $gravityview The $gravityview object available in templates.
*/
if ( count( $args = func_get_args() ) ) {
$gravityview = reset( $args );
if ( $gravityview instanceof \GV\Template_Context ) {
/**
* Prepend content to the View container <div>.
*
* @param \GV\Template_Context $gravityview The $gravityview object available in templates.
*/
do_action( 'gravityview/template/header', $gravityview );
/**
* @deprecated Use `gravityview/template/header`
*/
return do_action( 'gravityview_header', $gravityview->view->ID );
}
}
/**
* Prepend content to the View container `<div>`.
*
* @deprecated Use `gravityview/template/header`.
* @param int $view_id The ID of the View being displayed
*/
do_action( 'gravityview_header', gravityview_get_view_id() );
}
function gravityview_footer() {
/**
* Append content to the view.
*
* @param object $gravityview The $gravityview object available in templates.
*/
if ( count( $args = func_get_args() ) ) {
$gravityview = reset( $args );
if ( $gravityview instanceof \GV\Template_Context ) {
/**
* Prepend outside the View container <div>.
*
* @param \GV\Template_Context $gravityview The $gravityview object available in templates.
*/
do_action( 'gravityview/template/footer', $gravityview );
/**
* @deprecated Use `gravityview/template/footer`
*/
return do_action( 'gravityview_footer', $gravityview->view->ID );
}
}
/**
* Display content after a View. Used to render footer widget areas. Rendered outside the View container `<div>`.
*
* @deprecated Use `gravityview/template/footer`.
* @param int $view_id The ID of the View being displayed
*/
do_action( 'gravityview_footer', gravityview_get_view_id() );
}
function gravityview_after() {
if ( count( $args = func_get_args() ) ) {
$gravityview = reset( $args );
if ( $gravityview instanceof \GV\Template_Context ) {
/**
* Append content to the View.
*
* @param \GV\Template_Context $gravityview The $gravityview object available in templates.
* @since 2.0
*/
do_action( 'gravityview/template/after', $gravityview );
/**
* @deprecated Use `gravityview/template/after`
*/
do_action( 'gravityview_after', $gravityview->view->ID );
return;
}
}
/**
* Append content to the View container `<div>`.
*
* @deprecated Use `gravityview/template/after`
* @param int $view_id The ID of the View being displayed
*/
do_action( 'gravityview_after', gravityview_get_view_id() );
}
/**
* Get the current View ID being rendered
*
* @global GravityView_View $gravityview_view
*
* @return int View ID, if exists. `0` if `GravityView_View` doesn't exist, like in the admin, or no View is set.
*/
function gravityview_get_view_id() {
if ( ! class_exists( 'GravityView_View' ) ) {
return 0;
}
return GravityView_View::getInstance()->getViewId();
}
/**
* Returns the current GravityView context, or empty string if not GravityView
*
* - Returns empty string on GravityView archive pages
* - Returns empty string on archive pages containing embedded Views
* - Returns empty string for embedded Views, not 'directory'
* - Returns empty string for embedded entries (oEmbed or [gventry]), not 'single'
* - Returns 'single' when viewing a [gravityview] shortcode-embedded single entry
*
* @global GravityView_View $gravityview_view
* @deprecated since 2.0.6.2 Use `gravityview()->request`
* @return string View context "directory", "single", "edit", or empty string if not GravityView
*/
function gravityview_get_context() {
global $wp_query;
if ( isset( $wp_query ) && $wp_query->post_count > 1 ) {
return '';
}
if ( gravityview()->request->is_edit_entry() ) {
return 'edit';
} elseif ( gravityview()->request->is_entry() ) {
return 'single';
} elseif ( gravityview()->request->is_view( false ) ) {
return 'directory';
} elseif ( gravityview()->views->get() ) {
return 'directory';
}
return '';
}
/**
* Return an array of files prepared for output. Wrapper for GravityView_Field_FileUpload::get_files_array()
*
* Processes files by file type and generates unique output for each.
*
* Returns array for each file, with the following keys:
*
* `file_path` => The file path of the file, with a line break
* `html` => The file output HTML formatted
*
* @see GravityView_Field_FileUpload::get_files_array()
*
* @since 1.2
* @param string $value Field value passed by Gravity Forms. String of file URL, or serialized string of file URL array
* @param string $gv_class Field class to add to the output HTML
* @since 2.0
* @param \GV\Template_Context $context The context
* @return array Array of file output, with `file_path` and `html` keys (see comments above)
*/
function gravityview_get_files_array( $value, $gv_class = '', $context = null ) {
/** @define "GRAVITYVIEW_DIR" "../" */
if ( ! class_exists( 'GravityView_Field' ) ) {
include_once GRAVITYVIEW_DIR . 'includes/fields/class-gravityview-field.php';
}
if ( ! class_exists( 'GravityView_Field_FileUpload' ) ) {
include_once GRAVITYVIEW_DIR . 'includes/fields/class-gravityview-field-fileupload.php';
}
if ( is_null( $context ) ) {
_doing_it_wrong( __FUNCTION__, '2.0', 'Please pass an \GV\Template_Context object as the 3rd parameter' );
}
return GravityView_Field_FileUpload::get_files_array( $value, $gv_class, $context );
}
/**
* Generate a mapping link from an address
*
* The address should be plain text with new line (`\n`) or `<br />` line breaks separating sections
*
* @since 2.14.1 Added $atts parameter
*
* @todo use GF's field get_export_value() instead
*
* @see https://docs.gravitykit.com/article/59-modify-the-map-it-address-link Read how to modify the link
* @param string $address Address
* @return string URL of link to map of address
*/
function gravityview_get_map_link( $address, $atts = array() ) {
$address_qs = str_replace( array( '<br />', "\n" ), ' ', $address ); // Replace \n with spaces
$address_qs = urlencode( $address_qs );
$url = "https://maps.google.com/maps?q={$address_qs}";
$link_text = esc_html__( 'Map It', 'gk-gravityview' );
$atts = array_merge(
array(
'class' => 'map-it-link',
),
$atts
);
$link = gravityview_get_link( $url, $link_text, $atts );
/**
* Modify the map link generated. You can use a different mapping service, for example.
*
* @param string $link Map link
* @param string $address Address to generate link for
* @param string $url URL generated by the function
*/
$link = apply_filters( 'gravityview_map_link', $link, $address, $url );
return $link;
}
/**
* Output field based on a certain html markup
*
* markup - string to be used on a sprintf statement.
* Use:
* {{label}} - field label
* {{value}} - entry field value
* {{class}} - field class
*
* wpautop - true will filter the value using wpautop function
*
* @since 1.1.5
* @param array $passed_args Associative array with field data. `field` and `form` are required.
* @since 2.0
* @param \GV\Template_Context The template context.
* @return string Field output. If empty value and hide empty is true, return empty.
*/
function gravityview_field_output( $passed_args, $context = null ) {
$defaults = array(
'entry' => null,
'field' => null,
'form' => null,
'hide_empty' => true,
'markup' => '<div id="{{ field_id }}" class="{{ class }}">{{ label }}{{ value }}</div>',
'label_markup' => '',
'wpautop' => false,
'zone_id' => null,
);
$args = wp_parse_args( $passed_args, $defaults );
/**
* Modify the args before generation begins.
*
* @since 1.7
* @param array $args Associative array; `field` and `form` is required.
* @param array $passed_args Original associative array with field data. `field` and `form` are required.
* @since 2.0
* @param \GV\Template_Context $context The context.
* @deprecated
*/
$args = apply_filters( 'gravityview/field_output/args', $args, $passed_args, $context );
/**
* Modify the context before generation begins.
*
* @since 2.0
* @param \GV\Template_Context $context The context.
* @param array $args The sanitized arguments, these should not be trusted any longer.
* @param array $passed_args The passed arguments, these should not be trusted any longer.
*/
$context = apply_filters( 'gravityview/template/field_output/context', $context, $args, $passed_args );
if ( $context instanceof \GV\Template_Context ) {
if ( ! $context->field || ! $context->view || ! $context->view->form ) {
gravityview()->log->error( 'Field or form are empty.', array( 'data' => array( $context->field, $context->view->form ) ) );
return '';
}
} else {
// @deprecated path
// Required fields.
if ( empty( $args['field'] ) || empty( $args['form'] ) ) {
gravityview()->log->error( 'Field or form are empty.', array( 'data' => $args ) );
return '';
}
}
if ( $context instanceof \GV\Template_Context ) {
$entry = $args['entry'] ? : ( $context->entry ? $context->entry->as_entry() : array() );
$field = $args['field'] ? : ( $context->field ? $context->field->as_configuration() : array() );
$form = $args['form'] ? : ( $context->view->form ? $context->view->form->form : array() );
} else {
// @deprecated path
$entry = empty( $args['entry'] ) ? array() : $args['entry'];
$field = $args['field'];
$form = $args['form'];
}
/**
* Create the content variables for replacing.
*
* @since 1.11
*/
$placeholders = array(
'value' => '',
'width' => '',
'width:style' => '',
'label' => '',
'label_value' => '',
'label_value:esc_attr' => '',
'label_value:data-label' => '',
'class' => '',
'field_id' => '',
);
if ( $context instanceof \GV\Template_Context ) {
$placeholders['value'] = \GV\Utils::get( $args, 'value', '' );
} else {
// @deprecated path
$placeholders['value'] = gv_value( $entry, $field );
}
// If the value is empty and we're hiding empty, return empty.
if ( '' === $placeholders['value'] && ! empty( $args['hide_empty'] ) ) {
return '';
}
if ( '' !== $placeholders['value'] && ! empty( $args['wpautop'] ) && 'gravityview_view' !== ( $field['id'] ?? '' ) ) {
$placeholders['value'] = wpautop( $placeholders['value'] );
}
// Get width setting, if exists
$placeholders['width'] = GravityView_API::field_width( $field );
// If replacing with CSS inline formatting, let's do it.
$placeholders['width:style'] = (string) GravityView_API::field_width( $field, 'width:' . $placeholders['width'] . '%;' );
// Grab the Class using `gv_class`
$placeholders['class'] = gv_class( $field, $form, $entry );
$placeholders['field_id'] = GravityView_API::field_html_attr_id( $field, $form, $entry );
if ( $context instanceof \GV\Template_Context ) {
$placeholders['label_value'] = \GV\Utils::get( $args, 'label', '' );
} else {
// Default Label value
$placeholders['label_value'] = gv_label( $field, $entry );
}
$placeholders['label_value:data-label'] = trim( esc_attr( strip_tags( str_replace( '> ', '>', $placeholders['label_value'] ) ) ) );
$placeholders['label_value:esc_attr'] = esc_attr( $placeholders['label_value'] );
if ( empty( $placeholders['label'] ) && ! empty( $placeholders['label_value'] ) ) {
$placeholders['label'] = '<span class="gv-field-label">{{ label_value }}</span>';
}
/**
* Allow Pre filtering of the HTML.
*
* @since 1.11
* @param string $markup The HTML for the markup
* @param array $args All args for the field output
* @since 2.0
* @param \GV\Template_Context $context The context.
*/
$html = apply_filters( 'gravityview/field_output/pre_html', $args['markup'], $args, $context );
/**
* Modify the opening tags for the template content placeholders.
*
* @since 1.11
* @param string $open_tag Open tag for template content placeholders. Default: `{{`
* @since 2.0
* @param \GV\Template_Context $context The context.
*/
$open_tag = apply_filters( 'gravityview/field_output/open_tag', '{{', $args, $context );
/**
* Modify the closing tags for the template content placeholders.
*
* @since 1.11
* @param string $close_tag Close tag for template content placeholders. Default: `}}`
* @since 2.0
* @param \GV\Template_Context $context The context.
*/
$close_tag = apply_filters( 'gravityview/field_output/close_tag', '}}', $args, $context );
/**
* Loop through each of the tags to replace and replace both `{{tag}}` and `{{ tag }}` with the values
*
* @since 1.11
*/
foreach ( $placeholders as $tag => $value ) {
// If the tag doesn't exist just skip it
if ( false === strpos( $html, $open_tag . $tag . $close_tag ) && false === strpos( $html, $open_tag . ' ' . $tag . ' ' . $close_tag ) ) {
continue;
}
// Array to search
$search = array(
$open_tag . $tag . $close_tag,
$open_tag . ' ' . $tag . ' ' . $close_tag,
);
/**
* `gravityview/field_output/context/{$tag}` Allow users to filter content on context
*
* @since 1.11
* @param string $value The content to be shown instead of the {{tag}} placeholder
* @param array $args Arguments passed to the function
* @since 2.0
* @param \GV\Template_Context $context The context.
*/
$value = apply_filters( 'gravityview/field_output/context/' . $tag, $value, $args, $context );
// Finally do the replace
$html = str_replace( $search, (string) $value, $html );
}
/**
* Modify field HTML output.
*
* @param string $html Existing HTML output
* @param array $args Arguments passed to the function
* @since 2.0
* @param \GV\Template_Context $context The context.
*/
$html = apply_filters( 'gravityview_field_output', $html, $args, $context );
/**
* Modify field HTML output.
*
* @param string $html Existing HTML output
* @param array $args Arguments passed to the function
* @since 2.0
* @param \GV\Template_Context $context The context.
*/
$html = apply_filters( 'gravityview/field_output/html', $html, $args, $context );
/** @since 2.0.8 Remove unused atts */
$html = str_replace( array( ' style=""', ' class=""', ' id=""' ), '', $html );
return $html;
}