GravityView  2.17
The best, easiest way to display Gravity Forms entries on your website.
class-api.php
Go to the documentation of this file.
1 <?php
2 /**
3  * GravityView template tags API
4  *
5  * @package GravityView
6  * @license GPL2+
7  * @author GravityView <[email protected]>
8  * @link http://gravityview.co
9  * @copyright Copyright 2014, Katz Web Services, Inc.
10  *
11  * @since 1.0.0
12  */
13 
15 
16  /**
17  * Fetch Field Label
18  *
19  * @deprecated Use \GV\Field::get_label()
20  *
21  * @static
22  * @param array $field GravityView field array
23  * @param array $entry Gravity Forms entry array
24  * @param boolean $force_show_label Whether to always show the label, regardless of field settings
25  * @return string
26  */
27  public static function field_label( $field, $entry = array(), $force_show_label = false ) {
28 
30 
31  $form = $gravityview_view->getForm();
32 
33  if ( defined( 'DOING_GRAVITYVIEW_TESTS' ) && ! empty( $GLOBALS['GravityView_API_field_label_override'] ) ) {
34  /** Allow to fall through for back compatibility testing purposes. */
35  } else {
37  }
38 
39  $label = '';
40 
41  if( !empty( $field['show_label'] ) || $force_show_label ) {
42 
43  $label = $field['label'];
44 
45  // Support Gravity Forms 1.9+
46  if( class_exists( 'GF_Field' ) ) {
47 
48  $field_object = RGFormsModel::get_field( $form, $field['id'] );
49 
50  if( $field_object ) {
51 
52  $input = GFFormsModel::get_input( $field_object, $field['id'] );
53 
54  // This is a complex field, with labels on a per-input basis
55  if( $input ) {
56 
57  // Does the input have a custom label on a per-input basis? Otherwise, default label.
58  $label = ! empty( $input['customLabel'] ) ? $input['customLabel'] : $input['label'];
59 
60  } else {
61 
62  // This is a field with one label
63  $label = $field_object->get_field_label( true, $field['label'] );
64 
65  }
66 
67  }
68 
69  }
70 
71  // Use Gravity Forms label by default, but if a custom label is defined in GV, use it.
72  if ( !empty( $field['custom_label'] ) ) {
73 
74  $label = self::replace_variables( $field['custom_label'], $form, $entry );
75 
76  }
77 
78  /**
79  * @filter `gravityview_render_after_label` Append content to a field label
80  * @param string $appended_content Content you can add after a label. Empty by default.
81  * @param array $field GravityView field array
82  */
83  $label .= apply_filters( 'gravityview_render_after_label', '', $field );
84 
85  } // End $field['show_label']
86 
87  /**
88  * @filter `gravityview/template/field_label` Modify field label output
89  * @since 1.7
90  * @param string $label Field label HTML
91  * @param array $field GravityView field array
92  * @param array $form Gravity Forms form array
93  * @param array $entry Gravity Forms entry array
94  *
95  * @deprecated Use the context-aware version `gravityview/template/field/label`
96  */
97  $label = apply_filters( 'gravityview/template/field_label', $label, $field, $form, $entry );
98 
99  return $label;
100  }
101 
102  /**
103  * Alias for GravityView_Merge_Tags::replace_variables()
104  *
105  * @see GravityView_Merge_Tags::replace_variables() Moved in 1.8.4
106  * @since 1.22.4 - Added $nl2br, $format, $aux_data args
107  *
108  * @param string $text Text to replace variables in
109  * @param array $form GF Form array
110  * @param array $entry GF Entry array
111  * @param bool $url_encode Pass return value through `url_encode()`
112  * @param bool $esc_html Pass return value through `esc_html()`
113  * @param bool $nl2br Convert newlines to <br> HTML tags
114  * @param string $format The format requested for the location the merge is being used. Possible values: html, text or url.
115  * @param array $aux_data Additional data to be used to replace merge tags {@see https://www.gravityhelp.com/documentation/article/gform_merge_tag_data/}
116  * @return string Text with variables maybe replaced
117  */
118  public static function replace_variables( $text, $form = array(), $entry = array(), $url_encode = false, $esc_html = true, $nl2br = true, $format = 'html', $aux_data = array() ) {
119  return GravityView_Merge_Tags::replace_variables( $text, $form, $entry, $url_encode, $esc_html, $nl2br, $format, $aux_data );
120  }
121 
122  /**
123  * Get column width from the field setting
124  *
125  * @since 1.9
126  *
127  * @param array $field Array of settings for the field
128  * @param string $format Format for width. "%" (default) will return
129  *
130  * @return string|null If not empty, string in $format format. Otherwise, null.
131  */
132  public static function field_width( $field, $format = '%d%%' ) {
133 
134  $width = NULL;
135 
136  if( !empty( $field['width'] ) ) {
137  $width = absint( $field['width'] );
138 
139  // If using percentages, limit to 100%
140  if( '%d%%' === $format && $width > 100 ) {
141  $width = 100;
142  }
143 
144  $width = sprintf( $format, $width );
145  }
146 
147  return $width;
148  }
149 
150  /**
151  * Fetch Field class
152  *
153  * @static
154  * @param mixed $field
155  * @return string
156  */
157  public static function field_class( $field, $form = NULL, $entry = NULL ) {
158  $classes = array();
159 
160  if( !empty( $field['custom_class'] ) ) {
161 
162  $custom_class = $field['custom_class'];
163 
164  if( !empty( $entry ) ) {
165 
166  // We want the merge tag to be formatted as a class. The merge tag may be
167  // replaced by a multiple-word value that should be output as a single class.
168  // "Office Manager" will be formatted as `.OfficeManager`, not `.Office` and `.Manager`
169  add_filter('gform_merge_tag_filter', 'sanitize_html_class');
170 
171  $custom_class = self::replace_variables( $custom_class, $form, $entry);
172 
173  // And then we want life to return to normal
174  remove_filter('gform_merge_tag_filter', 'sanitize_html_class');
175  }
176 
177  // And now we want the spaces to be handled nicely.
178  $classes[] = gravityview_sanitize_html_class( $custom_class );
179 
180  }
181 
182  if(!empty($field['id'])) {
183  if( !empty( $form ) && !empty( $form['id'] ) ) {
184  $form_id = '-'.$form['id'];
185  } else {
186  // @deprecated path. Form should always be given.
187  gravityview()->log->warning( 'GravityView_View::getInstance() legacy API called' );
189  $form_id = $gravityview_view->getFormId() ? '-'. $gravityview_view->getFormId() : '';
190  }
191 
192  $classes[] = 'gv-field'.$form_id.'-'.$field['id'];
193  }
194 
195  return esc_attr(implode(' ', $classes));
196  }
197 
198  /**
199  * Fetch Field HTML ID
200  *
201  * @since 1.11
202  *
203  * @static
204  * @param array $field GravityView field array passed to gravityview_field_output()
205  * @param array $form Gravity Forms form array, if set.
206  * @param array $entry Gravity Forms entry array
207  * @return string Sanitized unique HTML `id` attribute for the field
208  */
209  public static function field_html_attr_id( $field, $form = array(), $entry = array() ) {
210  $id = $field['id'];
211 
212  if ( ! empty( $id ) ) {
213  if ( ! empty( $form ) && ! empty( $form['id'] ) ) {
214  $form_id = '-' . $form['id'];
215  } else {
216  // @deprecated path. Form should always be given.
217  gravityview()->log->warning( 'GravityView_View::getInstance() legacy API called' );
219  $form_id = $gravityview_view->getFormId() ? '-' . $gravityview_view->getFormId() : '';
220  }
221 
222  $id = 'gv-field' . $form_id . '-' . $field['id'];
223  }
224 
225  return esc_attr( $id );
226  }
227 
228 
229  /**
230  * Given an entry and a form field id, calculate the entry value for that field.
231  *
232  * @deprecated Use \GV\Field_Template::render() or the more low-level \GV\Field::get_value()
233  *
234  * @param array $entry
235  * @param array $field
236  * @return null|string
237  */
238  public static function field_value( $entry, $field_settings, $format = 'html' ) {
239  gravityview()->log->notice( '\GravityView_API::field_value is deprecated. Use \GV\Field_Template::render() or \GV\Field::get_value()' );
241  }
242 
243  /**
244  * Generate an anchor tag that links to an entry.
245  *
246  * @since 1.6
247  * @see GVCommon::get_link_html()
248  *
249  * @param string $anchor_text The text or HTML inside the link
250  * @param array $entry Gravity Forms entry array
251  * @param array|string $passed_tag_atts Attributes to be added to the anchor tag, such as `title` or `rel`.
252  * @param array $field_settings Array of field settings. Optional, but passed to the `gravityview_field_entry_link` filter
253  *
254  * @since 2.0
255  * @param int $base_id The post or the view that this entry is linked from.
256  *
257  * @return string|null Returns HTML for an anchor link. Null if $entry isn't defined or is missing an ID.
258  */
259  public static function entry_link_html( $entry = array(), $anchor_text = '', $passed_tag_atts = array(), $field_settings = array(), $base_id = null ) {
260 
261  if ( empty( $entry ) || ! is_array( $entry ) || ! isset( $entry['id'] ) ) {
262  gravityview()->log->debug( 'Entry not defined; returning null', array( 'data' => $entry ) );
263  return NULL;
264  }
265 
266  $href = self::entry_link( $entry, $base_id );
267 
268  if( '' === $href ) {
269  return NULL;
270  }
271 
272  $link = gravityview_get_link( $href, $anchor_text, $passed_tag_atts );
273 
274  /**
275  * @filter `gravityview_field_entry_link` Modify the link HTML
276  * @param string $link HTML output of the link
277  * @param string $href URL of the link
278  * @param array $entry The GF entry array
279  * @param array $field_settings Settings for the particular GV field
280  */
281  $output = apply_filters( 'gravityview_field_entry_link', $link, $href, $entry, $field_settings );
282 
283  return $output;
284  }
285 
286  /**
287  * Get the "No Results" text depending on whether there were results.
288  *
289  * @since 2.0
290  *
291  * @param boolean $wpautop Apply wpautop() to the output?
292  * @param \GV\Template_Context|null $context The context
293  *
294  * @return string HTML of "no results" text
295  */
296  public static function no_results( $wpautop = true, $context = null ) {
297  $is_search = false;
298 
299  if ( $context instanceof \GV\Template_Context ) {
300  if ( $context->request->is_search() ) {
301  $is_search = true;
302  }
303  } else {
305 
306  if( $gravityview_view && ( $gravityview_view->curr_start || $gravityview_view->curr_end || $gravityview_view->curr_search ) ) {
307  $is_search = true;
308  }
309  }
310 
311  $setting = '';
312 
313  if ( $is_search ) {
314 
315  $output = esc_html__( 'This search returned no results.', 'gk-gravityview' );
316 
317  if( $context ) {
318  $setting = $context->view->settings->get( 'no_search_results_text', $output );
319  }
320 
321  } else {
322 
323  $output = esc_html__( 'No entries match your request.', 'gk-gravityview' );
324 
325  if( $context ) {
326  $setting = $context->view->settings->get( 'no_results_text', $output );
327  }
328  }
329 
330  if ( '' !== $setting ) {
331  $output = $setting;
332  }
333 
334  /**
335  * Added now that users are able to modify via View settings
336  * @since 2.8.2
337  */
338  $output = wp_kses(
339  $output,
340  array(
341  'p' => array( 'class' => array(), 'id' => array() ),
342  'h1' => array( 'class' => array(), 'id' => array() ),
343  'h2' => array( 'class' => array(), 'id' => array() ),
344  'h3' => array( 'class' => array(), 'id' => array() ),
345  'h4' => array( 'class' => array(), 'id' => array() ),
346  'h5' => array( 'class' => array(), 'id' => array() ),
347  'strong' => array( 'class' => array(), 'id' => array() ),
348  'span' => array( 'class' => array(), 'id' => array() ),
349  'b' => array( 'class' => array(), 'id' => array() ),
350  'em' => array( 'class' => array(), 'id' => array() ),
351  'a' => array( 'class' => array(), 'id' => array(), 'href' => array(), 'title' => array(), 'rel' => array(), 'target' => array() ),
352  'div' => array( 'class' => array(), 'id' => array() ),
353  'br' => array(),
354  )
355  );
356 
357  $unformatted_output = $output;
358 
359  $output = $wpautop ? wpautop( $output ) : $output;
360 
361  /**
362  * @filter `gravitview_no_entries_text` Modify the text displayed when there are no entries.
363  * Note: this filter is, and always has been, misspelled. This will not be fixed, since the filter is deprecated.
364  * @param string $output The existing "No Entries" text
365  * @param boolean $is_search Is the current page a search result, or just a multiple entries screen?
366  * @return string The modified text.
367  * @deprecated Use `gravityview/template/text/no_entries`
368  */
369  $output = apply_filters( 'gravitview_no_entries_text', $output, $is_search );
370 
371  /**
372  * @filter `gravityview/template/text/no_entries` Modify the text displayed when there are no entries.
373  * @since 2.0
374  * @since 2.17 Added $wpautop parameter.
375  * @param string $output The existing "No Entries" text.
376  * @param boolean $is_search Is the current page a search result, or just a multiple entries screen?
377  * @param \GV\Template_Context $context The context.
378  * @param string $unformatted_output Output without `wpautop()`.
379  * @return string The modified text.
380  */
381  $output = apply_filters( 'gravityview/template/text/no_entries', $output, $is_search, $context, $unformatted_output );
382 
383  return $output;
384  }
385 
386  /**
387  * Generate a URL to the Directory context
388  *
389  * 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!
390  *
391  * @param int $post_id Post ID
392  * @param boolean $add_query_args Add pagination and sorting arguments
393  *
394  * @since 2.0
395  * @param \GV\Template_Context $context The context this is being used in.
396  *
397  * @return string Permalink to multiple entries view
398  */
399  public static function directory_link( $post_id = NULL, $add_query_args = true, $context = null ) {
400  global $post;
401 
402  if ( empty( $post_id ) ) {
403  // DataTables passes the Post ID
404  if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
405  $post_id = \GV\Utils::_POST( 'post_id', false );
406  } else {
407  if ( $context instanceof \GV\Template_Context ) {
408  // Shortcodes, embeds
409  if ( is_a( $post, 'WP_Post' ) ) {
410  $post_id = $post->ID;
411 
412  // Actual views
413  } else {
414  $post_id = $context->view ? $context->view->ID : false;
415  }
416  } else {
417 
418  if ( ! class_exists( 'GravityView_View' ) ) {
419  gravityview()->plugin->include_legacy_frontend( true );
420  }
421 
422  /** @deprecated path of execution */
424 
425  // The Post ID has been passed via the shortcode
426  if ( ! empty( $gravityview_view ) && $gravityview_view->getPostId() ) {
427  $post_id = $gravityview_view->getPostId();
428  } else {
429  // This is a GravityView post type
430  if ( GravityView_frontend::getInstance()->isGravityviewPostType() ) {
431  $post_id = isset( $gravityview_view ) ? $gravityview_view->getViewId() : $post->ID;
432  } else {
433  // This is an embedded GravityView; use the embedded post's ID as the base.
434  if ( GravityView_frontend::getInstance()->isPostHasShortcode() && is_a( $post, 'WP_Post' ) ) {
435  $post_id = $post->ID;
436  } elseif ( $gravityview_view->getViewId() ) {
437  // The GravityView has been embedded in a widget or in a template, and
438  // is not in the current content. Thus, we defer to the View's own ID.
439  $post_id = $gravityview_view->getViewId();
440  }
441  }
442  }
443  }
444  }
445  }
446 
447  // No post ID, get outta here.
448  if ( empty( $post_id ) ) {
449  return null;
450  }
451 
452  static $directory_links = array();
453 
454  /**
455  * If we've saved the permalink, use it. Reduces time spent on `get_permalink()`, which is heavy.
456  * @since 1.3
457  * @since 2.17 Changed from using wp_cache_set() to using a static variable.
458  */
459  if ( isset( $directory_links[ 'gv_directory_link_' . $post_id ] ) ) {
460  $link = $directory_links[ 'gv_directory_link_' . $post_id ];
461  }
462 
463  if ( (int) $post_id === (int) get_option( 'page_on_front' ) ) {
464  $link = home_url();
465  }
466 
467  if ( empty( $link ) ) {
468  $link = get_permalink( $post_id );
469 
470  $directory_links[ 'gv_directory_link_' . $post_id ] = $link;
471  }
472 
473  // Deal with returning to proper pagination for embedded views
474  if ( $link && $add_query_args ) {
475 
476  $args = array();
477 
478  if( $pagenum = \GV\Utils::_GET( 'pagenum' ) ) {
479  $args['pagenum'] = intval( $pagenum );
480  }
481 
482  if( $sort = \GV\Utils::_GET( 'sort' ) ) {
483  $args['sort'] = $sort;
484  $args['dir'] = \GV\Utils::_GET( 'dir' );
485  }
486 
487  $link = add_query_arg( $args, $link );
488  }
489 
490  /**
491  * @filter `gravityview_directory_link` Modify the URL to the View "directory" context
492  * @since 1.19.4
493  * @param string $link URL to the View's "directory" context (Multiple Entries screen)
494  * @param int $post_id ID of the post to link to. If the View is embedded, it is the post or page ID
495  */
496  $link = apply_filters( 'gravityview_directory_link', $link, $post_id );
497 
498  /**
499  * @filter `gravityview/view/links/directory` Modify the URL to the View "directory" context
500  * @since 2.0
501  * @param string $link URL to the View's "directory" context (Multiple Entries screen)
502  * @param \GV\Template_Context $context
503  */
504  return apply_filters( 'gravityview/view/links/directory', $link, $context );
505  }
506 
507  /**
508  * Calculate an *unique* hash for an entry based on the entry ID
509  *
510  * 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.
511  *
512  * The hashed value MUST be unique, otherwise multiple entries will share the same URL, which leads to obvious problems.
513  *
514  * @param int|string $id Entry ID to generate the hash for.
515  * @param array $entry Entry data passed to provide additional information when generating the hash. Optional - don't rely on it being available.
516  * @return string Hashed unique value for entry
517  */
518  private static function get_custom_entry_slug( $id, $entry = array() ) {
519 
520  // Generate an unique hash to use as the default value
521  $slug = substr( wp_hash( $id, 'gravityview'.$id ), 0, 8 );
522 
523  /**
524  * @filter `gravityview_entry_slug` Modify the unique hash ID generated, if you want to improve usability or change the format. This will allow for custom URLs, such as `{entryid}-{first-name}` or even, if unique, `{first-name}-{last-name}`
525  * @param string $hash Existing hash generated by GravityView
526  * @param string $id The entry ID
527  * @param array $entry Entry data array. May be empty.
528  */
529  $slug = apply_filters( 'gravityview_entry_slug', $slug, $id, $entry );
530 
531  // Make sure we have something - use the original ID as backup.
532  if( empty( $slug ) ) {
533  $slug = $id;
534  }
535 
536  return sanitize_title( $slug );
537  }
538 
539  /**
540  * Get the entry slug for the entry. By default, it is the entry ID.
541  *
542  *
543  * @see gravityview_get_entry()
544  * @uses GravityView_API::get_custom_entry_slug() If using custom slug, gets the custom slug value
545  * @since 1.4
546  * @param int|string $id_or_string ID of the entry, or custom slug string
547  * @param array $entry Gravity Forms Entry array, optional. Used only to provide data to customize the `gravityview_entry_slug` filter
548  * @return string Unique slug ID, passed through `sanitize_title()`
549  */
550  public static function get_entry_slug( $id_or_string, $entry = array() ) {
551 
552  /**
553  * Default: use the entry ID as the unique identifier
554  */
555  $slug = $id_or_string;
556 
557  /**
558  * @filter `gravityview_custom_entry_slug` Whether to enable and use custom entry slugs.
559  * @param boolean True: Allow for slugs based on entry values. False: always use entry IDs (default)
560  */
561  $custom = apply_filters( 'gravityview_custom_entry_slug', false );
562 
563  // If we're using custom slug...
564  if ( $custom ) {
565 
566  // Get the entry hash
567  $hash = self::get_custom_entry_slug( $id_or_string, $entry );
568 
569  // Cache the slugs
570  static $cache = array();
571 
572  if ( ! isset( $cache[ $id_or_string ] ) ) {
573  global $wpdb;
574 
575  if ( version_compare( GFFormsModel::get_database_version(), '2.3-dev-1', '>=' ) ) {
576  $table = GFFormsModel::get_entry_meta_table_name();
577  $column = 'entry_id';
578  } else {
579  $table = RGFormsModel::get_lead_meta_table_name();
580  $column = 'lead_id';
581  }
582 
583  $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 ) );
584 
585  if ( $results ) {
586  $cache = array_replace( $cache, array_combine( wp_list_pluck( $results, $column ), wp_list_pluck( $results, 'meta_value' ) ) );
587  }
588 
589  if ( ! isset( $cache[ $id_or_string ] ) ) {
590  $cache[ $id_or_string ] = false;
591  }
592  }
593 
594  $value = $cache[ $id_or_string ];
595 
596  // If it does have a hash set, and the hash is expected, use it.
597  // This check allows users to change the hash structure using the
598  // gravityview_entry_hash filter and have the old hashes expire.
599  if ( empty( $value ) || $value !== $hash ) {
600  gravityview()->log->debug( 'Setting hash for entry {entry}: {hash}', array( 'entry' => $id_or_string, 'hash' => $hash ) );
601  gform_update_meta( $id_or_string, 'gravityview_unique_id', $hash, \GV\Utils::get( $entry, 'form_id' ) );
602  }
603 
604  $slug = $hash;
605 
606  unset( $value, $hash );
607  }
608 
609  return sanitize_title( $slug );
610  }
611 
612  /**
613  * If using the entry custom slug feature, make sure the new entries have the custom slug created and saved as meta
614  *
615  * Triggered by add_action( 'gform_entry_created', array( 'GravityView_API', 'entry_create_custom_slug' ), 10, 2 );
616  *
617  * @param $entry array Gravity Forms entry object
618  * @param $form array Gravity Forms form object
619  */
620  public static function entry_create_custom_slug( $entry, $form ) {
621  /**
622  * @filter `gravityview_custom_entry_slug` On entry creation, check if we are using the custom entry slug feature and update the meta
623  * @param boolean $custom Should we process the custom entry slug?
624  */
625  $custom = apply_filters( 'gravityview_custom_entry_slug', false );
626  if( $custom ) {
627  // create the gravityview_unique_id and save it
628 
629  // Get the entry hash
630  $hash = self::get_custom_entry_slug( $entry['id'], $entry );
631 
632  gravityview()->log->debug( 'Setting hash for entry {entry_id}: {hash}', array( 'entry_id' => $entry['id'], 'hash' => $hash ) );
633 
634  gform_update_meta( $entry['id'], 'gravityview_unique_id', $hash, \GV\Utils::get( $entry, 'form_id' ) );
635 
636  }
637  }
638 
639 
640 
641 
642  /**
643  * return href for single entry
644  *
645  * @since 1.7.3 Added $add_directory_args parameter
646  * @since 2.7.2 Added $view_id parameter
647  * @since 2.10 Added $_GET args to links by default. Use `gravityview/entry_link/add_query_args` filter to override.
648  *
649  * @param array|int $entry Entry array or entry ID.
650  * @param int|null $post_id If wanting to define the parent post, pass a post ID.
651  * @param boolean $add_directory_args True: Add args to help return to directory; False: only include args required to get to entry.
652  * @param int $view_id
653  *
654  * @return string Link to the entry with the directory parent slug, or empty string if embedded post or View doesn't exist
655  */
656  public static function entry_link( $entry, $post_id = NULL, $add_directory_args = true, $view_id = 0 ) {
657 
658  if ( ! empty( $entry ) && ! is_array( $entry ) ) {
660  } else if( empty( $entry ) ) {
661  // @deprecated path
663  }
664 
665  // Second parameter used to be passed as $field; this makes sure it's not an array
666  if ( ! is_numeric( $post_id ) ) {
667  $post_id = NULL;
668  }
669 
670  // Get the permalink to the View
671  $directory_link = self::directory_link( $post_id, false );
672 
673  // No post ID? Get outta here.
674  if ( empty( $directory_link ) ) {
675  return '';
676  }
677 
678  $query_arg_name = \GV\Entry::get_endpoint_name();
679 
680  if ( ! empty( $entry['_multi'] ) ) {
681  $entry_slugs = array();
682 
683  foreach ( $entry['_multi'] as $_multi ) {
684 
685  if( $gv_multi = \GV\GF_Entry::from_entry( $_multi ) ) {
686  $entry_slugs[] = $gv_multi->get_slug();
687  } else {
688  // TODO: This path isn't covered by unit tests
689  $entry_slugs[] = \GravityView_API::get_entry_slug( $_multi['id'], $_multi );
690  }
691 
692  unset( $gv_multi );
693 
694  $forms[] = $_multi['form_id'];
695  }
696 
697  $entry_slug = implode( ',', $entry_slugs );
698  } else {
699 
700  // Fallback when
701  if( $gv_entry = \GV\GF_Entry::from_entry( $entry ) ) {
702  $entry_slug = $gv_entry->get_slug();
703  } else {
704  // TODO: This path isn't covered by unit tests
706  }
707 
708  unset( $gv_entry );
709  }
710 
711  $args = array();
712 
713  /**
714  * @filter `gravityview/entry_link/add_query_args` Modify whether to include passed $_GET parameters to the end of the url
715  * @since 2.10
716  * @param bool $add_query_params Whether to include passed $_GET parameters to the end of the Entry Link URL. Default: true.
717  */
718  $add_query_args = apply_filters( 'gravityview/entry_link/add_query_args', true );
719 
720  if ( $add_query_args ) {
722  }
723 
724  if ( get_option('permalink_structure') && ! is_preview() ) {
725 
726  /**
727  * Make sure the $directory_link doesn't contain any query otherwise it will break when adding the entry slug.
728  * @since 1.16.5
729  */
730  $link_parts = explode( '?', $directory_link );
731 
732  $query = !empty( $link_parts[1] ) ? '?'.$link_parts[1] : '';
733 
734  $directory_link = trailingslashit( $link_parts[0] ) . $query_arg_name . '/'. $entry_slug .'/' . $query;
735 
736  } else {
737 
738  $args[] = array( $query_arg_name => $entry_slug );
739  }
740 
741  /**
742  * @since 1.7.3
743  */
744  if ( $add_directory_args ) {
745 
746  if ( ! empty( $_GET['pagenum'] ) ) {
747  $args['pagenum'] = intval( $_GET['pagenum'] );
748  }
749 
750  /**
751  * @since 1.7
752  */
753  if ( $sort = \GV\Utils::_GET( 'sort' ) ) {
754  $args['sort'] = $sort;
755  $args['dir'] = \GV\Utils::_GET( 'dir' );
756  }
757 
758  }
759 
760  if( $post_id ) {
761  $passed_post = get_post( $post_id );
762  $views = \GV\View_Collection::from_post( $passed_post );
763  $has_multiple_views = $views->count() > 1;
764  } else {
765  $has_multiple_views = class_exists( 'GravityView_View_Data' ) && GravityView_View_Data::getInstance()->has_multiple_views();
766  }
767 
768  if ( $has_multiple_views ) {
770  }
771 
772  return add_query_arg( $args, $directory_link );
773 
774  }
775 
776 
777 }
778 
779 /**
780  * Returns query parameters from $_GET with reserved internal GravityView keys removed
781  *
782  * @uses stripslashes_deep() $_GET is passed through stripslashes_deep().
783  * @uses urldecode_deep() $_GET is passed through urldecode_deep().
784  *
785  * Important: The return value of gv_get_query_args() is not escaped by default. Output should be
786  * late-escaped with esc_url() or similar to help prevent vulnerability to cross-site scripting
787  * (XSS) attacks.
788  *
789  * @since 2.10
790  *
791  * @return array
792  */
793 function gv_get_query_args() {
794 
795  $passed_get = isset( $_GET ) ? $_GET : array();
796 
797  $passed_get = stripslashes_deep( $passed_get );
798  $passed_get = urldecode_deep( $passed_get );
799 
800  if ( empty( $passed_get ) ) {
801  return array();
802  }
803 
804  $query_args = $passed_get;
805 
806  $reserved_args = array(
807  'entry',
808  'gvid',
809  'status',
810  'action',
811  'view_id',
812  'entry_id',
813  'pagenum',
814  );
815 
816  /**
817  * @filter `gravityview/api/reserved_query_args` Modify the URL arguments that should not be used because they are internal to GravityView
818  * @since 2.10
819  * @param array $reserved_args Array of URL query keys that should not be used except internally.
820  */
821  $reserved_args = apply_filters( 'gravityview/api/reserved_query_args', $reserved_args );
822 
823  foreach ( $reserved_args as $reserved_arg ) {
824  unset( $query_args[ $reserved_arg ] );
825  }
826 
827  return $query_args;
828 }
829 
830 
831 // inside loop functions
832 
833 /**
834  * @deprecated Use \GV\Field::get_label()
835  */
836 function gv_label( $field, $entry = NULL ) {
838 }
839 
840 function gv_class( $field, $form = NULL, $entry = array() ) {
842 }
843 
844 /**
845  * Generate a CSS class to be added to the wrapper <div> of a View
846  *
847  * @since 1.5.4
848  * @since 1.16 Added $echo parameter.
849  * @since 2.0 Added $context parameter.
850  *
851  * @param string $passed_css_class Default: `gv-container gv-container-{view id}`. If View is hidden until search, adds ` hidden`
852  * @param boolean $echo Whether to echo the output. Default: true
853  * @param \GV\Template_Context $context The template context.
854  *
855  * @return string CSS class, sanitized by gravityview_sanitize_html_class()
856  */
857 function gv_container_class( $passed_css_class = '', $echo = true, $context = null ) {
858  if ( $context instanceof \GV\Template_Context ) {
859  $hide_until_searched = false;
860  $total_entries = 0;
861  $view_id = 0;
862  if ( $context->view ) {
863  $view_id = $context->view->ID;
864  if( $context->view->settings->get( 'hide_until_searched' ) ) {
865  $hide_until_searched = ( empty( $context->entry ) && ! $context->request->is_search() );
866  }
867  }
868  if ( $context->entries ) {
869  $total_entries = $context->entries->total();
870  } else if ( $context->entry ) {
871  $total_entries = 1;
872  }
873  } else {
874  /** @deprecated legacy execution path */
875  $view_id = GravityView_View::getInstance()->getViewId();
876  $hide_until_searched = GravityView_View::getInstance()->isHideUntilSearched();
877  $total_entries = GravityView_View::getInstance()->getTotalEntries();
878  }
879 
880  $passed_css_class = trim( $passed_css_class );
881 
882  $default_css_class = ! empty( $view_id ) ? sprintf( 'gv-container gv-container-%d', $view_id ) : 'gv-container';
883 
884  if ( $hide_until_searched ) {
885  $default_css_class .= ' hidden';
886  }
887 
888  if ( 0 === $total_entries ) {
889  $default_css_class .= ' gv-container-no-results';
890  }
891 
892  if ( $context instanceof \GV\Template_Context && $context->view ) {
893  $default_css_class .= ' ' . $context->view->settings->get( 'class', '' );
894  }
895 
896  $css_class = trim( $passed_css_class . ' '. $default_css_class );
897 
898  /**
899  * @filter `gravityview/render/container/class` Modify the CSS class to be added to the wrapper <div> of a View
900  * @since 1.5.4
901  * @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`
902  * @since 2.0
903  * @param \GV\Template_Context $context The context.
904  */
905  $css_class = apply_filters( 'gravityview/render/container/class', $css_class, $context );
906 
907  $css_class = gravityview_sanitize_html_class( $css_class );
908 
909  if ( $echo ) {
910  echo $css_class;
911  }
912 
913  return $css_class;
914 }
915 
916 /**
917  * @deprecated Use \GV\Field_Template::render()
918  */
919 function gv_value( $entry, $field ) {
920 
922 
923  if( $value === '' ) {
924  /**
925  * @filter `gravityview_empty_value` What to display when a field is empty
926  * @param string $value (empty string)
927  */
928  $value = apply_filters( 'gravityview_empty_value', '' );
929  }
930 
931  return $value;
932 }
933 
934 function gv_directory_link( $post = NULL, $add_pagination = true, $context = null ) {
935  return GravityView_API::directory_link( $post, $add_pagination, $context );
936 }
937 
938 function gv_entry_link( $entry, $post_id = NULL ) {
939  return GravityView_API::entry_link( $entry, $post_id );
940 }
941 
942 function gv_no_results( $wpautop = true, $context = null ) {
943  return GravityView_API::no_results( $wpautop, $context );
944 }
945 
946 /**
947  * Generate HTML for the back link from single entry view
948  * @since 1.0.1
949  * @since 2.0
950  * @param \GV\Template_Context $context The context this link is being displayed from.
951  * @return string|null If no GV post exists, null. Otherwise, HTML string of back link.
952  */
953 function gravityview_back_link( $context = null ) {
954 
955  $href = gv_directory_link( null, true, $context );
956 
957  /**
958  * @filter `gravityview_go_back_url` Modify the back link URL
959  * @since 1.17.5
960  * @see gv_directory_link() Generated the original back link
961  * @param string $href Existing label URL
962  * @deprecated Use `gravityview/template/links/back/url`
963  */
964  $href = apply_filters( 'gravityview_go_back_url', $href );
965 
966  /**
967  * @filter `gravityview/template/links/back/url` Modify the back link URL
968  * @since 2.0
969  * @see gv_directory_link() Generated the original back link
970  * @param string $href Existing label URL
971  * @param \GV\Template_Context The context.
972  */
973  $href = apply_filters( 'gravityview/template/links/back/url', $href, $context );
974 
975  if ( empty( $href ) ) {
976  return NULL;
977  }
978 
979  if ( $context instanceof \GV\Template_Context ) {
980  $view_id = $context->view->ID;
981  $view_label = $context->template->get_back_label();
982  } else {
983  /** @deprecated legacy path */
985  $view_id = $gravityview_view->getViewId();
986  $view_label = $gravityview_view->getBackLinkLabel() ? $gravityview_view->getBackLinkLabel() : false;
987  }
988 
989  /** Default */
990  $label = $view_label ? $view_label : __( '&larr; Go back', 'gk-gravityview' );
991 
992  /**
993  * @filter `gravityview_go_back_label` Modify the back link text
994  * @since 1.0.9
995  * @param string $label Existing label text
996  * @deprecated Use `gravityview/template/links/back/label`
997  */
998  $label = apply_filters( 'gravityview_go_back_label', $label );
999 
1000  /**
1001  * @filter `gravityview/template/links/back/label` Modify the back link text
1002  * @since 2.0
1003  * @see gv_directory_link() Generated the original back link
1004  * @param string $label Existing label text
1005  * @param \GV\Template_Context The context.
1006  */
1007  $label = apply_filters( 'gravityview/template/links/back/label', $label, $context );
1008 
1009  /**
1010  * @filter `gravityview/template/links/back/atts` Modify the attributes used on the back link anchor tag
1011  * @since 2.1
1012  * @param array $atts Original attributes, default: [ data-viewid => $view_id ]
1013  * @param \GV\Template_Context The context.
1014  */
1015  $atts = apply_filters( 'gravityview/template/links/back/atts', array( 'data-viewid' => $view_id ), $context );
1016 
1017  $link = gravityview_get_link( $href, esc_html( $label ), $atts );
1018 
1019  return $link;
1020 }
1021 
1022 /**
1023  * Handle getting values for complex Gravity Forms fields
1024  *
1025  * If the field is complex, like a product, the field ID, for example, 11, won't exist. Instead,
1026  * it will be 11.1, 11.2, and 11.3. This handles being passed 11 and 11.2 with the same function.
1027  *
1028  * @since 1.0.4
1029  * @param array $entry GF entry array
1030  * @param string $field_id [description]
1031  * @param string $display_value The value generated by Gravity Forms
1032  * @return string Value
1033  */
1035 
1036  if( floatval( $field_id ) === floor( floatval( $field_id ) ) ) {
1037 
1038  // For the complete field value as generated by Gravity Forms
1039  return $display_value;
1040 
1041  } else {
1042 
1043  // For one part of the address (City, ZIP, etc.)
1044  return isset( $entry[ $field_id ] ) ? $entry[ $field_id ] : '';
1045 
1046  }
1047 
1048 }
1049 
1050 /**
1051  * Take a passed CSV of terms and generate a linked list of terms
1052  *
1053  * Gravity Forms passes categories as "Name:ID" so we handle that using the ID, which
1054  * is more accurate than checking the name, which is more likely to change.
1055  *
1056  * @param string $value Existing value
1057  * @param string $taxonomy Type of term (`post_tag` or `category`)
1058  * @return string CSV of linked terms
1059  */
1060 function gravityview_convert_value_to_term_list( $value, $taxonomy = 'post_tag' ) {
1061 
1062  $output = array();
1063 
1064  if ( is_array( $value ) ) {
1065  $terms = array_filter( array_values( $value ), 'strlen' );
1066  } else {
1067  $terms = explode( ', ', $value );
1068  }
1069 
1070  foreach ($terms as $term_name ) {
1071 
1072  // If we're processing a category,
1073  if( $taxonomy === 'category' ) {
1074 
1075  // Use rgexplode to prevent errors if : doesn't exist
1076  list( $term_name, $term_id ) = rgexplode( ':', $term_name, 2 );
1077 
1078  // The explode was succesful; we have the category ID
1079  if( !empty( $term_id )) {
1080  $term = get_term_by( 'id', $term_id, $taxonomy );
1081  } else {
1082  // We have to fall back to the name
1083  $term = get_term_by( 'name', $term_name, $taxonomy );
1084  }
1085 
1086  } else {
1087  // Use the name of the tag to get the full term information
1088  $term = get_term_by( 'name', $term_name, $taxonomy );
1089  }
1090 
1091  // There's still a tag/category here.
1092  if( $term ) {
1093 
1094  $term_link = get_term_link( $term, $taxonomy );
1095 
1096  // If there was an error, continue to the next term.
1097  if ( is_wp_error( $term_link ) ) {
1098  continue;
1099  }
1100 
1101  $output[] = gravityview_get_link( $term_link, esc_html( $term->name ) );
1102  }
1103  }
1104 
1105  return implode(', ', $output );
1106 }
1107 
1108 /**
1109  * Get the links for post_tags and post_category output based on post ID
1110  * @param int $post_id The ID of the post
1111  * @param boolean $link Add links or no?
1112  * @param string $taxonomy Taxonomy of term to fetch.
1113  * @return string String with terms
1114  */
1115 function gravityview_get_the_term_list( $post_id, $link = true, $taxonomy = 'post_tag' ) {
1116 
1117  $output = get_the_term_list( $post_id, $taxonomy, NULL, ', ' );
1118 
1119  if( empty( $link ) ) {
1120  return strip_tags( $output);
1121  }
1122 
1123  return $output;
1124 
1125 }
1126 
1127 
1128 /**
1129  * Get all views processed so far for the current page load
1130  *
1131  * @see GravityView_View_Data::add_view()
1132  * @return array Array of View data, each View data with `id`, `view_id`, `form_id`, `template_id`, `atts`, `fields`, `widgets`, `form` keys.
1133  */
1135 
1137 
1138  // Solve problem when loading content via admin-ajax.php
1139  if( ! $fe->getGvOutputData() ) {
1140 
1141  gravityview()->log->debug( 'gv_output_data not defined; parsing content.' );
1142 
1143  $fe->parse_content();
1144  }
1145 
1146  // Make 100% sure that we're dealing with a properly called situation
1147  if( !is_a( $fe->getGvOutputData(), 'GravityView_View_Data' ) ) {
1148 
1149  gravityview()->log->debug( 'gv_output_data not an object or get_view not callable.', array( 'data' => $fe->getGvOutputData() ) );
1150 
1151  return array();
1152  }
1153 
1154  return $fe->getGvOutputData()->get_views();
1155 }
1156 
1157 /**
1158  * Get data for a specific view
1159  *
1160  * @deprecated use \GV\View API instead
1161  * @since 2.5
1162  *
1163  * @see GravityView_View_Data::get_view()
1164  * @return array View data with `id`, `view_id`, `form_id`, `template_id`, `atts`, `fields`, `widgets`, `form` keys.
1165  */
1167  if ( $view_id ) {
1168  if ( $view = \GV\View::by_id( $view_id ) ) {
1169  return $view; // implements ArrayAccess
1170  }
1171  return array();
1172  }
1173 
1175 
1176  // If not set, grab the current view ID
1177  if ( empty( $view_id ) ) {
1178  $view_id = $fe->get_context_view_id();
1179  }
1180 
1181  if ( ! $fe->getGvOutputData() ) { return array(); }
1182 
1183  return $fe->getGvOutputData()->get_view( $view_id );
1184 }
1185 
1186 // Templates' hooks
1188  /**
1189  * @action `gravityview/template/before` Append content to the view.
1190  * @param object $gravityview The $gravityview object available in templates.
1191  */
1192  if ( count( $args = func_get_args() ) ) {
1193  $gravityview = reset( $args );
1194  if ( $gravityview instanceof \GV\Template_Context ) {
1195  /**
1196  * @action `gravityview/template/before` Prepend content to the view.
1197  * @param \GV\Template_Context $gravityview The $gravityview object available in templates.
1198  */
1199  do_action( 'gravityview/template/before', $gravityview );
1200 
1201  /**
1202  * @deprecated Use `gravityview/template/before`
1203  */
1204  return do_action( 'gravityview_before', $gravityview->view->ID );
1205  }
1206  }
1207 
1208  /**
1209  * @action `gravityview_before` Prepend content to the View container `<div>`
1210  * @deprecated Use `gravityview/template/before`.
1211  * @param int $view_id The ID of the View being displayed
1212  */
1213  do_action( 'gravityview_before', gravityview_get_view_id() );
1214 }
1215 
1217  /**
1218  * @action `gravityview/template/header` Append content to the view.
1219  * @param object $gravityview The $gravityview object available in templates.
1220  */
1221  if ( count( $args = func_get_args() ) ) {
1222  $gravityview = reset( $args );
1223  if ( $gravityview instanceof \GV\Template_Context ) {
1224  /**
1225  * @action `gravityview/template/header` Prepend content to the view container <div>.
1226  * @param \GV\Template_Context $gravityview The $gravityview object available in templates.
1227  */
1228  do_action( 'gravityview/template/header', $gravityview );
1229 
1230  /**
1231  * @deprecated Use `gravityview/template/header`
1232  */
1233  return do_action( 'gravityview_header', $gravityview->view->ID );
1234  }
1235  }
1236 
1237  /**
1238  * @action `gravityview_header` Prepend content to the View container `<div>`
1239  * @deprecated Use `gravityview/template/header`.
1240  * @param int $view_id The ID of the View being displayed
1241  */
1242  do_action( 'gravityview_header', gravityview_get_view_id() );
1243 }
1244 
1246  /**
1247  * @action `gravityview/template/footer` Append content to the view.
1248  * @param object $gravityview The $gravityview object available in templates.
1249  */
1250  if ( count( $args = func_get_args() ) ) {
1251  $gravityview = reset( $args );
1252  if ( $gravityview instanceof \GV\Template_Context ) {
1253  /**
1254  * @action `gravityview/template/footer` Prepend outside of the view container <div>.
1255  * @param \GV\Template_Context $gravityview The $gravityview object available in templates.
1256  */
1257  do_action( 'gravityview/template/footer', $gravityview );
1258 
1259  /**
1260  * @deprecated Use `gravityview/template/footer`
1261  */
1262  return do_action( 'gravityview_footer', $gravityview->view->ID );
1263  }
1264  }
1265 
1266  /**
1267  * @action `gravityview_after` Display content after a View. Used to render footer widget areas. Rendered outside the View container `<div>`
1268  * @deprecated Use `gravityview/template/footer`.
1269  * @param int $view_id The ID of the View being displayed
1270  */
1271  do_action( 'gravityview_footer', gravityview_get_view_id() );
1272 }
1273 
1274 function gravityview_after() {
1275  if ( count( $args = func_get_args() ) ) {
1276  $gravityview = reset( $args );
1277  if ( $gravityview instanceof \GV\Template_Context ) {
1278  /**
1279  * @action `gravityview/template/after` Append content to the view.
1280  * @param \GV\Template_Context $gravityview The $gravityview object available in templates.
1281  */
1282  do_action( 'gravityview/template/after', $gravityview );
1283 
1284  /**
1285  * @deprecated Use `gravityview/template/after`
1286  */
1287  do_action( 'gravityview_after', $gravityview->view->ID );
1288 
1289  return;
1290  }
1291  }
1292 
1293  /**
1294  * @action `gravityview_after` Append content to the View container `<div>`
1295  * @deprecated Use `gravityview/template/after`
1296  * @param int $view_id The ID of the View being displayed
1297  */
1298  do_action( 'gravityview_after', gravityview_get_view_id() );
1299 }
1300 
1301 /**
1302  * Get the current View ID being rendered
1303  *
1304  * @global GravityView_View $gravityview_view
1305  *
1306  * @return int View ID, if exists. `0` if `GravityView_View` doesn't exist, like in the admin, or no View is set.
1307  */
1309 
1310  if ( ! class_exists( 'GravityView_View' ) ) {
1311  return 0;
1312  }
1313 
1314  return GravityView_View::getInstance()->getViewId();
1315 }
1316 
1317 /**
1318  * Returns the current GravityView context, or empty string if not GravityView
1319  *
1320  * - Returns empty string on GravityView archive pages
1321  * - Returns empty string on archive pages containing embedded Views
1322  * - Returns empty string for embedded Views, not 'directory'
1323  * - Returns empty string for embedded entries (oEmbed or [gventry]), not 'single'
1324  * - Returns 'single' when viewing a [gravityview] shortcode-embedded single entry
1325  *
1326  * @global GravityView_View $gravityview_view
1327  * @deprecated since 2.0.6.2 Use `gravityview()->request`
1328  * @return string View context "directory", "single", "edit", or empty string if not GravityView
1329  */
1331  global $wp_query;
1332 
1333  if ( isset( $wp_query ) && $wp_query->post_count > 1 ) {
1334  return '';
1335  }
1336 
1337  /**
1338  * @filter `gravityview_is_edit_entry` Whether we're currently on the Edit Entry screen \n
1339  * The Edit Entry functionality overrides this value.
1340  * @param boolean $is_edit_entry
1341  */
1342  $is_edit_entry = apply_filters( 'gravityview_is_edit_entry', false );
1343 
1344  if ( $is_edit_entry ) {
1345  return 'edit';
1346  } else if ( gravityview()->request->is_entry() ) {
1347  return 'single';
1348  } else if ( gravityview()->request->is_view( false ) ) {
1349  return 'directory';
1350  }
1351 
1352  return '';
1353 }
1354 
1355 
1356 /**
1357  * Return an array of files prepared for output. Wrapper for GravityView_Field_FileUpload::get_files_array()
1358  *
1359  * Processes files by file type and generates unique output for each.
1360  *
1361  * Returns array for each file, with the following keys:
1362  *
1363  * `file_path` => The file path of the file, with a line break
1364  * `html` => The file output HTML formatted
1365  *
1366  * @see GravityView_Field_FileUpload::get_files_array()
1367  *
1368  * @since 1.2
1369  * @param string $value Field value passed by Gravity Forms. String of file URL, or serialized string of file URL array
1370  * @param string $gv_class Field class to add to the output HTML
1371  * @since 2.0
1372  * @param \GV\Template_Context $context The context
1373  * @return array Array of file output, with `file_path` and `html` keys (see comments above)
1374  */
1375 function gravityview_get_files_array( $value, $gv_class = '', $context = null ) {
1376  /** @define "GRAVITYVIEW_DIR" "../" */
1377 
1378  if( !class_exists( 'GravityView_Field' ) ) {
1379  include_once( GRAVITYVIEW_DIR .'includes/fields/class-gravityview-field.php' );
1380  }
1381 
1382  if( !class_exists( 'GravityView_Field_FileUpload' ) ) {
1383  include_once( GRAVITYVIEW_DIR .'includes/fields/class-gravityview-field-fileupload.php' );
1384  }
1385 
1386  if ( is_null( $context ) ) {
1387  _doing_it_wrong( __FUNCTION__, '2.0', 'Please pass an \GV\Template_Context object as the 3rd parameter' );
1388  }
1389 
1390  return GravityView_Field_FileUpload::get_files_array( $value, $gv_class, $context );
1391 }
1392 
1393 /**
1394  * Generate a mapping link from an address
1395  *
1396  * The address should be plain text with new line (`\n`) or `<br />` line breaks separating sections
1397  *
1398  * @since 2.14.1 Added $atts parameter
1399  *
1400  * @todo use GF's field get_export_value() instead
1401  *
1402  * @see https://docs.gravitykit.com/article/59-modify-the-map-it-address-link Read how to modify the link
1403  * @param string $address Address
1404  * @return string URL of link to map of address
1405  */
1406 function gravityview_get_map_link( $address, $atts = array() ) {
1407  $address_qs = str_replace( array( '<br />', "\n" ), ' ', $address ); // Replace \n with spaces
1408  $address_qs = urlencode( $address_qs );
1409 
1410  $url = "https://maps.google.com/maps?q={$address_qs}";
1411 
1412  $link_text = esc_html__( 'Map It', 'gk-gravityview' );
1413 
1414  $atts = array_merge(
1415  array(
1416  'class' => 'map-it-link'
1417  ),
1418  $atts
1419  );
1420 
1422 
1423  /**
1424  * @filter `gravityview_map_link` Modify the map link generated. You can use a different mapping service, for example.
1425  * @param string $link Map link
1426  * @param string $address Address to generate link for
1427  * @param string $url URL generated by the function
1428  */
1429  $link = apply_filters( 'gravityview_map_link', $link, $address, $url );
1430 
1431  return $link;
1432 }
1433 
1434 
1435 /**
1436  * Output field based on a certain html markup
1437  *
1438  * markup - string to be used on a sprintf statement.
1439  * Use:
1440  * {{label}} - field label
1441  * {{value}} - entry field value
1442  * {{class}} - field class
1443  *
1444  * wpautop - true will filter the value using wpautop function
1445  *
1446  * @since 1.1.5
1447  * @param array $passed_args Associative array with field data. `field` and `form` are required.
1448  * @since 2.0
1449  * @param \GV\Template_Context The template context.
1450  * @return string Field output. If empty value and hide empty is true, return empty.
1451  */
1452 function gravityview_field_output( $passed_args, $context = null ) {
1453  $defaults = array(
1454  'entry' => null,
1455  'field' => null,
1456  'form' => null,
1457  'hide_empty' => true,
1458  'markup' => '<div id="{{ field_id }}" class="{{ class }}">{{ label }}{{ value }}</div>',
1459  'label_markup' => '',
1460  'wpautop' => false,
1461  'zone_id' => null,
1462  );
1463 
1464  $args = wp_parse_args( $passed_args, $defaults );
1465 
1466  /**
1467  * @filter `gravityview/field_output/args` Modify the args before generation begins
1468  * @since 1.7
1469  * @param array $args Associative array; `field` and `form` is required.
1470  * @param array $passed_args Original associative array with field data. `field` and `form` are required.
1471  * @since 2.0
1472  * @param \GV\Template_Context $context The context.
1473  * @deprecated
1474  */
1475  $args = apply_filters( 'gravityview/field_output/args', $args, $passed_args, $context );
1476 
1477  /**
1478  * @filter `gravityview/template/field_output/context` Modify the context before generation begins.
1479  * @since 2.0
1480  * @param \GV\Template_Context $context The context.
1481  * @param array $args The sanitized arguments, these should not be trusted any longer.
1482  * @param array $passed_args The passed arguments, these should not be trusted any longer.
1483  */
1484  $context = apply_filters( 'gravityview/template/field_output/context', $context, $args, $passed_args );
1485 
1486  if ( $context instanceof \GV\Template_Context ) {
1487  if ( ! $context->field || ! $context->view || ! $context->view->form ) {
1488  gravityview()->log->error( 'Field or form are empty.', array( 'data' => array( $context->field, $context->view->form ) ) );
1489  return '';
1490  }
1491  } else {
1492  // @deprecated path
1493  // Required fields.
1494  if ( empty( $args['field'] ) || empty( $args['form'] ) ) {
1495  gravityview()->log->error( 'Field or form are empty.', array( 'data' => $args ) );
1496  return '';
1497  }
1498  }
1499 
1500  if ( $context instanceof \GV\Template_Context ) {
1501  $entry = $args['entry'] ? : ( $context->entry ? $context->entry->as_entry() : array() );
1502  $field = $args['field'] ? : ( $context->field ? $context->field->as_configuration() : array() );
1503  $form = $args['form'] ? : ( $context->view->form ? $context->view->form->form : array() );
1504  } else {
1505  // @deprecated path
1506  $entry = empty( $args['entry'] ) ? array() : $args['entry'];
1507  $field = $args['field'];
1508  $form = $args['form'];
1509  }
1510 
1511  /**
1512  * Create the content variables for replacing.
1513  * @since 1.11
1514  */
1515  $placeholders = array(
1516  'value' => '',
1517  'width' => '',
1518  'width:style' => '',
1519  'label' => '',
1520  'label_value' => '',
1521  'label_value:esc_attr' => '',
1522  'label_value:data-label' => '',
1523  'class' => '',
1524  'field_id' => '',
1525  );
1526 
1527  if ( $context instanceof \GV\Template_Context ) {
1528  $placeholders['value'] = \GV\Utils::get( $args, 'value', '' );
1529  } else {
1530  // @deprecated path
1531  $placeholders['value'] = gv_value( $entry, $field );
1532  }
1533 
1534  // If the value is empty and we're hiding empty, return empty.
1535  if ( $placeholders['value'] === '' && ! empty( $args['hide_empty'] ) ) {
1536  return '';
1537  }
1538 
1539  if ( $placeholders['value'] !== '' && ! empty( $args['wpautop'] ) ) {
1540  $placeholders['value'] = wpautop( $placeholders['value'] );
1541  }
1542 
1543  // Get width setting, if exists
1544  $placeholders['width'] = GravityView_API::field_width( $field );
1545 
1546  // If replacing with CSS inline formatting, let's do it.
1547  $placeholders['width:style'] = (string) GravityView_API::field_width( $field, 'width:' . $placeholders['width'] . '%;' );
1548 
1549  // Grab the Class using `gv_class`
1550  $placeholders['class'] = gv_class( $field, $form, $entry );
1551  $placeholders['field_id'] = GravityView_API::field_html_attr_id( $field, $form, $entry );
1552 
1553  if ( $context instanceof \GV\Template_Context ) {
1554  $placeholders['label_value'] = \GV\Utils::get( $args, 'label', '' );
1555  } else {
1556  // Default Label value
1557  $placeholders['label_value'] = gv_label( $field, $entry );
1558  }
1559 
1560  $placeholders['label_value:data-label'] = trim( esc_attr( strip_tags( str_replace( '>&nbsp;', '>', $placeholders['label_value'] ) ) ) );
1561  $placeholders['label_value:esc_attr'] = esc_attr( $placeholders['label_value'] );
1562 
1563  if ( empty( $placeholders['label'] ) && ! empty( $placeholders['label_value'] ) ){
1564  $placeholders['label'] = '<span class="gv-field-label">{{ label_value }}</span>';
1565  }
1566 
1567  /**
1568  * @filter `gravityview/field_output/pre_html` Allow Pre filtering of the HTML
1569  * @since 1.11
1570  * @param string $markup The HTML for the markup
1571  * @param array $args All args for the field output
1572  * @since 2.0
1573  * @param \GV\Template_Context $context The context.
1574  */
1575  $html = apply_filters( 'gravityview/field_output/pre_html', $args['markup'], $args, $context );
1576 
1577  /**
1578  * @filter `gravityview/field_output/open_tag` Modify the opening tags for the template content placeholders
1579  * @since 1.11
1580  * @param string $open_tag Open tag for template content placeholders. Default: `{{`
1581  * @since 2.0
1582  * @param \GV\Template_Context $context The context.
1583  */
1584  $open_tag = apply_filters( 'gravityview/field_output/open_tag', '{{', $args, $context );
1585 
1586  /**
1587  * @filter `gravityview/field_output/close_tag` Modify the closing tags for the template content placeholders
1588  * @since 1.11
1589  * @param string $close_tag Close tag for template content placeholders. Default: `}}`
1590  * @since 2.0
1591  * @param \GV\Template_Context $context The context.
1592  */
1593  $close_tag = apply_filters( 'gravityview/field_output/close_tag', '}}', $args, $context );
1594 
1595  /**
1596  * Loop through each of the tags to replace and replace both `{{tag}}` and `{{ tag }}` with the values
1597  * @since 1.11
1598  */
1599  foreach ( $placeholders as $tag => $value ) {
1600 
1601  // If the tag doesn't exist just skip it
1602  if ( false === strpos( $html, $open_tag . $tag . $close_tag ) && false === strpos( $html, $open_tag . ' ' . $tag . ' ' . $close_tag ) ){
1603  continue;
1604  }
1605 
1606  // Array to search
1607  $search = array(
1608  $open_tag . $tag . $close_tag,
1609  $open_tag . ' ' . $tag . ' ' . $close_tag,
1610  );
1611 
1612  /**
1613  * `gravityview/field_output/context/{$tag}` Allow users to filter content on context
1614  * @since 1.11
1615  * @param string $value The content to be shown instead of the {{tag}} placeholder
1616  * @param array $args Arguments passed to the function
1617  * @since 2.0
1618  * @param \GV\Template_Context $context The context.
1619  */
1620  $value = apply_filters( 'gravityview/field_output/context/' . $tag, $value, $args, $context );
1621 
1622  // Finally do the replace
1623  $html = str_replace( $search, (string) $value, $html );
1624  }
1625 
1626  /**
1627  * @filter `gravityview_field_output` Modify field HTML output
1628  * @param string $html Existing HTML output
1629  * @param array $args Arguments passed to the function
1630  * @since 2.0
1631  * @param \GV\Template_Context $context The context.
1632  */
1633  $html = apply_filters( 'gravityview_field_output', $html, $args, $context );
1634 
1635  /**
1636  * @filter `gravityview/field_output/html` Modify field HTML output
1637  * @param string $html Existing HTML output
1638  * @param array $args Arguments passed to the function
1639  * @since 2.0
1640  * @param \GV\Template_Context $context The context.
1641  */
1642  $html = apply_filters( 'gravityview/field_output/html', $html, $args, $context );
1643 
1644  /** @since 2.0.8 Remove unused atts */
1645  $html = str_replace( array( ' style=""', ' class=""', ' id=""' ), '', $html );
1646 
1647  return $html;
1648 }
gravityview_get_view_id()
Get the current View ID being rendered.
Definition: class-api.php:1308
const GRAVITYVIEW_DIR
"GRAVITYVIEW_DIR" "./" The absolute path to the plugin directory, with trailing slash ...
Definition: gravityview.php:49
$url
Definition: post_image.php:25
gv_value( $entry, $field)
Definition: class-api.php:919
gv_no_results( $wpautop=true, $context=null)
Definition: class-api.php:942
static no_results( $wpautop=true, $context=null)
Get the "No Results" text depending on whether there were results.
Definition: class-api.php:296
static _GET( $name, $default=null)
Grab a value from the _GET superglobal or default.
$forms
Definition: data-source.php:19
gravityview_get_field_value( $entry, $field_id, $display_value)
Handle getting values for complex Gravity Forms fields.
Definition: class-api.php:1034
static getInstance( $passed_post=NULL)
gravityview_get_files_array( $value, $gv_class='', $context=null)
Return an array of files prepared for output.
Definition: class-api.php:1375
gv_directory_link( $post=NULL, $add_pagination=true, $context=null)
Definition: class-api.php:934
gravityview_get_the_term_list( $post_id, $link=true, $taxonomy='post_tag')
Get the links for post_tags and post_category output based on post ID.
Definition: class-api.php:1115
gravityview_after()
Definition: class-api.php:1274
$add_query_args
static getInstance( $passed_post=NULL)
Definition: class-data.php:122
if(gv_empty( $field['value'], false, false)) $format
$display_value
gravityview_get_map_link( $address, $atts=array())
Generate a mapping link from an address.
Definition: class-api.php:1406
gravityview_footer()
Definition: class-api.php:1245
gravityview_get_current_view_data( $view_id=0)
Get data for a specific view.
Definition: class-api.php:1166
$field_settings['content']
Definition: custom.php:27
static replace_variables( $text, $form=array(), $entry=array(), $url_encode=false, $esc_html=true, $nl2br=true, $format='html', $aux_data=array())
Alias for GFCommon::replace_variables()
gravityview_get_link( $href='', $anchor_text='', $atts=array())
Generate an HTML anchor tag with a list of supported attributes.
if( $add_query_args) $link
static from_post(\WP_Post $post)
Get a list of objects inside the supplied .
global $post
Definition: delete-entry.php:7
GravityView_API_field_value( $entry, $field_settings, $format)
The old function does a bit too much, not only does it retrieve the value for a field, but it also renders some output.
Definition: _mocks.php:144
static get_custom_entry_slug( $id, $entry=array())
Calculate an unique hash for an entry based on the entry ID.
Definition: class-api.php:518
if(gravityview() ->plugin->is_GF_25()) $form
static entry_create_custom_slug( $entry, $form)
If using the entry custom slug feature, make sure the new entries have the custom slug created and sa...
Definition: class-api.php:620
gravityview_back_link( $context=null)
Generate HTML for the back link from single entry view.
Definition: class-api.php:953
static directory_link( $post_id=NULL, $add_query_args=true, $context=null)
Generate a URL to the Directory context.
Definition: class-api.php:399
gv_container_class( $passed_css_class='', $echo=true, $context=null)
Generate a CSS class to be added to the wrapper of a View.
Definition: class-api.php:857
static get_endpoint_name()
Return the endpoint name for a single Entry.
static get_files_array( $value, $gv_class, $context=null)
Return an array of files prepared for output.
static field_html_attr_id( $field, $form=array(), $entry=array())
Fetch Field HTML ID.
Definition: class-api.php:209
static entry_link_html( $entry=array(), $anchor_text='', $passed_tag_atts=array(), $field_settings=array(), $base_id=null)
Generate an anchor tag that links to an entry.
Definition: class-api.php:259
static field_value( $entry, $field_settings, $format='html')
Given an entry and a form field id, calculate the entry value for that field.
Definition: class-api.php:238
gravityview_header()
Definition: class-api.php:1216
gravityview_convert_value_to_term_list( $value, $taxonomy='post_tag')
Take a passed CSV of terms and generate a linked list of terms.
Definition: class-api.php:1060
static field_width( $field, $format='%d%%')
Get column width from the field setting.
Definition: class-api.php:132
gv_label( $field, $entry=NULL)
Definition: class-api.php:836
static replace_variables( $text, $form=array(), $entry=array(), $url_encode=false, $esc_html=true, $nl2br=true, $format='html', $aux_data=array())
Alias for GravityView_Merge_Tags::replace_variables()
Definition: class-api.php:118
gv_class( $field, $form=NULL, $entry=array())
Definition: class-api.php:840
if(empty( $created_by)) $form_id
GravityView_API_field_label( $form, $field_settings, $entry, $force_show_label=false)
Mock out the ::field_label method.
Definition: _mocks.php:214
static get_entry_slug( $id_or_string, $entry=array())
Get the entry slug for the entry.
Definition: class-api.php:550
static get( $array, $key, $default=null)
Grab a value from an array or an object or default.
gravityview()
The main GravityView wrapper function.
gv_entry_link( $entry, $post_id=NULL)
Definition: class-api.php:938
gv_get_query_args()
Returns query parameters from $_GET with reserved internal GravityView keys removed.
Definition: class-api.php:793
gravityview_get_context()
Returns the current GravityView context, or empty string if not GravityView.
Definition: class-api.php:1330
static field_class( $field, $form=NULL, $entry=NULL)
Fetch Field class.
Definition: class-api.php:157
$entry_slug
Definition: notes.php:30
static get_entry( $entry_slug, $force_allow_ids=false, $check_entry_display=true, $view=null)
Return a single entry object.
gravityview_field_output( $passed_args, $context=null)
Output field based on a certain html markup.
Definition: class-api.php:1452
$entry
Definition: notes.php:27
if(false !==strpos( $value, '00:00')) $field_id
string $field_id ID of the field being displayed
Definition: time.php:22
static entry_link( $entry, $post_id=NULL, $add_directory_args=true, $view_id=0)
return href for single entry
Definition: class-api.php:656
gravityview_before()
Definition: class-api.php:1187
static _POST( $name, $default=null)
Grab a value from the _POST superglobal or default.
static field_label( $field, $entry=array(), $force_show_label=false)
Fetch Field Label.
Definition: class-api.php:27
static getInstance()
Get the one true instantiated self.
gravityview_get_current_views()
Get all views processed so far for the current page load.
Definition: class-api.php:1134