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