Completed
Push — develop ( 846913...22c9fc )
by Zack
17s queued 12s
created

class-api.php ➔ gv_get_query_args()   A

Complexity

Conditions 4
Paths 6

Size

Total Lines 35

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 21
CRAP Score 4

Importance

Changes 0
Metric Value
cc 4
nc 6
nop 0
dl 0
loc 35
ccs 21
cts 21
cp 1
crap 4
rs 9.36
c 0
b 0
f 0
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
14
class GravityView_API {
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 3
	public static function field_label( $field, $entry = array(), $force_show_label = false ) {
28
29 3
		$gravityview_view = GravityView_View::getInstance();
30
31 3
		$form = $gravityview_view->getForm();
32
33 3
		if ( defined( 'DOING_GRAVITYVIEW_TESTS' ) && ! empty( $GLOBALS['GravityView_API_field_label_override'] ) ) {
34
			/** Allow to fall through for back compatibility testing purposes. */
35
		} else {
36 3
			return \GV\Mocks\GravityView_API_field_label( $form, $field, $entry, $force_show_label );
37
		}
38
39 1
		$label = '';
40
41 1
		if( !empty( $field['show_label'] ) || $force_show_label ) {
42
43 1
			$label = $field['label'];
44
45
			// Support Gravity Forms 1.9+
46 1
			if( class_exists( 'GF_Field' ) ) {
47
48 1
				$field_object = RGFormsModel::get_field( $form, $field['id'] );
49
50 1
				if( $field_object ) {
51
52 1
					$input = GFFormsModel::get_input( $field_object, $field['id'] );
53
54
					// This is a complex field, with labels on a per-input basis
55 1
					if( $input ) {
56
57
						// Does the input have a custom label on a per-input basis? Otherwise, default label.
58 1
						$label = ! empty( $input['customLabel'] ) ? $input['customLabel'] : $input['label'];
59
60
					} else {
61
62
						// This is a field with one label
63 1
						$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 1
			if ( !empty( $field['custom_label'] ) ) {
73
74 1
				$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 1
			$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 1
		$label = apply_filters( 'gravityview/template/field_label', $label, $field, $form, $entry );
98
99 1
		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 50
	public static function replace_variables( $text, $form = array(), $entry = array(), $url_encode = false, $esc_html = true, $nl2br = true, $format = 'html', $aux_data = array() ) {
119 50
		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 35
	public static function field_width( $field, $format = '%d%%' ) {
133
134 35
		$width = NULL;
135
136 35
		if( !empty( $field['width'] ) ) {
137 1
			$width = absint( $field['width'] );
138
139
			// If using percentages, limit to 100%
140 1
			if( '%d%%' === $format && $width > 100 ) {
141 1
				$width = 100;
142
			}
143
144 1
			$width = sprintf( $format, $width );
145
		}
146
147 35
		return $width;
148
	}
149
150
	/**
151
	 * Fetch Field class
152
	 *
153
	 * @static
154
	 * @param mixed $field
155
	 * @return string
156
	 */
157 38
	public static function field_class( $field, $form = NULL, $entry = NULL ) {
158 38
		$classes = array();
159
160 38
		if( !empty( $field['custom_class'] ) ) {
161
162 2
            $custom_class = $field['custom_class'];
163
164 2
            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 2
                add_filter('gform_merge_tag_filter', 'sanitize_html_class');
170
171 2
                $custom_class = self::replace_variables( $custom_class, $form, $entry);
172
173
                // And then we want life to return to normal
174 2
                remove_filter('gform_merge_tag_filter', 'sanitize_html_class');
175
            }
176
177
			// And now we want the spaces to be handled nicely.
178 2
			$classes[] = gravityview_sanitize_html_class( $custom_class );
179
180
		}
181
182 38
		if(!empty($field['id'])) {
183 38
			if( !empty( $form ) && !empty( $form['id'] ) ) {
184 38
				$form_id = '-'.$form['id'];
185
			} else {
186
				// @deprecated path. Form should always be given.
187
				gravityview()->log->warning( 'GravityView_View::getInstance() legacy API called' );
188
				$gravityview_view = GravityView_View::getInstance();
189
				$form_id = $gravityview_view->getFormId() ? '-'. $gravityview_view->getFormId() : '';
190
			}
191
192 38
			$classes[] = 'gv-field'.$form_id.'-'.$field['id'];
193
		}
194
195 38
		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 34
	public static function field_html_attr_id( $field, $form = array(), $entry = array() ) {
0 ignored issues
show
Unused Code introduced by
The parameter $entry is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
210 34
		$id = $field['id'];
211
212 34
		if ( ! empty( $id ) ) {
213 34
			if ( ! empty( $form ) && ! empty( $form['id'] ) ) {
214 34
				$form_id = '-' . $form['id'];
215
			} else {
216
				// @deprecated path. Form should always be given.
217
				gravityview()->log->warning( 'GravityView_View::getInstance() legacy API called' );
218
				$gravityview_view = GravityView_View::getInstance();
219
				$form_id = $gravityview_view->getFormId() ? '-' . $gravityview_view->getFormId() : '';
220
			}
221
222 34
			$id = 'gv-field' . $form_id . '-' . $field['id'];
223
		}
224
225 34
		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
0 ignored issues
show
Bug introduced by
There is no parameter named $field. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
236
	 * @return null|string
237
	 */
238 3
	public static function field_value( $entry, $field_settings, $format = 'html' ) {
239 3
		gravityview()->log->notice( '\GravityView_API::field_value is deprecated. Use \GV\Field_Template::render() or \GV\Field::get_value()' );
240 3
		return \GV\Mocks\GravityView_API_field_value( $entry, $field_settings, $format );
0 ignored issues
show
Deprecated Code introduced by
The function GV\Mocks\GravityView_API_field_value() has been deprecated with message: Use \GV\Field_Template::render()

This function has been deprecated. The supplier of the file has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed from the class and what other function to use instead.

Loading history...
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 2
	public static function entry_link_html( $entry = array(), $anchor_text = '', $passed_tag_atts = array(), $field_settings = array(), $base_id = null ) {
260
261 2
		if ( empty( $entry ) || ! is_array( $entry ) || ! isset( $entry['id'] ) ) {
262 1
			gravityview()->log->debug( 'Entry not defined; returning null', array( 'data' => $entry ) );
263 1
			return NULL;
264
		}
265
266 2
		$href = self::entry_link( $entry, $base_id );
267
268 2
		if( '' === $href ) {
269
			return NULL;
270
		}
271
272 2
		$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 2
		$output = apply_filters( 'gravityview_field_entry_link', $link, $href, $entry, $field_settings );
282
283 2
		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 10
	public static function no_results( $wpautop = true, $context = null ) {
296 10
		$is_search = false;
297
298 10
		if ( $context instanceof \GV\Template_Context ) {
299 9
			if ( $context->request->is_search() ) {
300 9
				$is_search = true;
301
			}
302
		} else {
303 2
			$gravityview_view = GravityView_View::getInstance();
304
305 2
			if( $gravityview_view && ( $gravityview_view->curr_start || $gravityview_view->curr_end || $gravityview_view->curr_search ) ) {
0 ignored issues
show
Documentation introduced by
The property curr_start does not exist on object<GravityView_View>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
Documentation introduced by
The property curr_end does not exist on object<GravityView_View>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
Documentation introduced by
The property curr_search does not exist on object<GravityView_View>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
306 1
				$is_search = true;
307
			}
308
		}
309
310 10
		$setting = '';
311
312 10
		if ( $is_search ) {
313
314 1
			$output = esc_html__( 'This search returned no results.', 'gravityview' );
315
316 1
			if( $context ) {
317 1
				$setting = $context->view->settings->get( 'no_search_results_text', $output );
318
			}
319
320
		} else {
321
322 10
			$output = esc_html__( 'No entries match your request.', 'gravityview' );
323
324 10
			if( $context ) {
325 9
				$setting = $context->view->settings->get( 'no_results_text', $output );
326
			}
327
		}
328
329 10
		if ( '' !== $setting ) {
330 1
			$output = $setting;
331
		}
332
333
		/**
334
		 * Added now that users are able to modify via View settings
335
		 * @since 2.8.2
336
		 */
337 10
		$output = wp_kses(
338 10
			$output,
339
			array(
340 10
				'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 10
		$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 10
		$output = apply_filters( 'gravityview/template/text/no_entries', $output, $is_search, $context );
375
376 10
		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 46
	public static function directory_link( $post_id = NULL, $add_query_args = true, $context = null ) {
393 46
		global $post;
394
395 46
		if ( empty( $post_id ) ) {
396
			// DataTables passes the Post ID
397 21
			if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
398
				$post_id = \GV\Utils::_POST( 'post_id', false );
399
			} else {
400 21
				if ( $context instanceof \GV\Template_Context ) {
401
					// Shortcodes, embeds
402 17
					if ( is_a( $post, 'WP_Post' ) ) {
403 5
						$post_id = $post->ID;
404
405
					// Actual views
406
					} else {
407 17
						$post_id = $context->view ? $context->view->ID : false;
408
					}
409
				} else {
410
					/** @deprecated path of execution */
411 4
					$gravityview_view = GravityView_View::getInstance();
412
413
					// The Post ID has been passed via the shortcode
414 4
					if ( ! empty( $gravityview_view ) && $gravityview_view->getPostId() ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $gravityview_view->getPostId() of type integer|null is loosely compared to true; this is ambiguous if the integer can be zero. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
415 2
						$post_id = $gravityview_view->getPostId();
416
					} else {
417
						// This is a GravityView post type
418 2
						if ( GravityView_frontend::getInstance()->isGravityviewPostType() ) {
419
							$post_id = isset( $gravityview_view ) ? $gravityview_view->getViewId() : $post->ID;
420
						} else {
421
							// This is an embedded GravityView; use the embedded post's ID as the base.
422 2
							if ( GravityView_frontend::getInstance()->isPostHasShortcode() && is_a( $post, 'WP_Post' ) ) {
423
								$post_id = $post->ID;
424 2
							} elseif ( $gravityview_view->getViewId() ) {
425
								// The GravityView has been embedded in a widget or in a template, and
426
								// is not in the current content. Thus, we defer to the View's own ID.
427 1
								$post_id = $gravityview_view->getViewId();
428
							}
429
						}
430
					}
431
				}
432
			}
433
		}
434
435
		// No post ID, get outta here.
436 46
		if ( empty( $post_id ) ) {
437 1
			return null;
438
		}
439
440
		// If we've saved the permalink in memory, use it
441
		// @since 1.3
442 45
		$link = wp_cache_get( 'gv_directory_link_'.$post_id );
443
444 45
		if ( (int) $post_id === (int) get_option( 'page_on_front' ) ) {
445
			$link = home_url();
446
		}
447
448 45
		if ( empty( $link ) ) {
449 45
			$link = get_permalink( $post_id );
450
451
			// If not yet saved, cache the permalink.
452
			// @since 1.3
453 45
			wp_cache_set( 'gv_directory_link_'.$post_id, $link );
454
		}
455
456
		// Deal with returning to proper pagination for embedded views
457 45
		if ( $link && $add_query_args ) {
458
459 41
			$args = array();
460
461 41
			if( $pagenum = \GV\Utils::_GET( 'pagenum' ) ) {
462 2
				$args['pagenum'] = intval( $pagenum );
463
			}
464
465 41
			if( $sort = \GV\Utils::_GET( 'sort' ) ) {
466
				$args['sort'] = $sort;
467
				$args['dir'] = \GV\Utils::_GET( 'dir' );
468
			}
469
470 41
			$link = add_query_arg( $args, $link );
471
		}
472
473
		/**
474
		 * @filter `gravityview_directory_link` Modify the URL to the View "directory" context
475
		 * @since 1.19.4
476
		 * @param string $link URL to the View's "directory" context (Multiple Entries screen)
477
		 * @param int $post_id ID of the post to link to. If the View is embedded, it is the post or page ID
478
		 */
479 45
		$link = apply_filters( 'gravityview_directory_link', $link, $post_id );
480
481
		/**
482
		 * @filter `gravityview/view/links/directory` Modify the URL to the View "directory" context
483
		 * @since 2.0
484
		 * @param string $link URL to the View's "directory" context (Multiple Entries screen)
485
		 * @param \GV\Template_Context $context
486
		 */
487 45
		return apply_filters( 'gravityview/view/links/directory', $link, $context );
488
	}
489
490
	/**
491
	 * Calculate an *unique* hash for an entry based on the entry ID
492
	 *
493
	 * 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.
494
	 *
495
	 * The hashed value MUST be unique, otherwise multiple entries will share the same URL, which leads to obvious problems.
496
	 *
497
	 * @param  int|string $id Entry ID to generate the hash for.
498
	 * @param  array  $entry        Entry data passed to provide additional information when generating the hash. Optional - don't rely on it being available.
499
	 * @return string               Hashed unique value for entry
500
	 */
501 3
	private static function get_custom_entry_slug( $id, $entry = array() ) {
502
503
		// Generate an unique hash to use as the default value
504 3
		$slug = substr( wp_hash( $id, 'gravityview'.$id ), 0, 8 );
505
506
		/**
507
		 * @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}`
508
		 * @param string $hash Existing hash generated by GravityView
509
		 * @param  string $id The entry ID
510
		 * @param  array $entry Entry data array. May be empty.
511
		 */
512 3
		$slug = apply_filters( 'gravityview_entry_slug', $slug, $id, $entry );
513
514
		// Make sure we have something - use the original ID as backup.
515 3
		if( empty( $slug ) ) {
516
			$slug = $id;
517
		}
518
519 3
		return sanitize_title( $slug );
520
	}
521
522
	/**
523
	 * Get the entry slug for the entry. By default, it is the entry ID.
524
	 *
525
	 *
526
	 * @see gravityview_get_entry()
527
	 * @uses GravityView_API::get_custom_entry_slug() If using custom slug, gets the custom slug value
528
	 * @since 1.4
529
	 * @param  int|string $id_or_string ID of the entry, or custom slug string
530
	 * @param  array  $entry        Gravity Forms Entry array, optional. Used only to provide data to customize the `gravityview_entry_slug` filter
531
	 * @return string               Unique slug ID, passed through `sanitize_title()`
532
	 */
533 157
	public static function get_entry_slug( $id_or_string, $entry = array() ) {
534
535
		/**
536
		 * Default: use the entry ID as the unique identifier
537
		 */
538 157
		$slug = $id_or_string;
539
540
		/**
541
		 * @filter `gravityview_custom_entry_slug` Whether to enable and use custom entry slugs.
542
		 * @param boolean True: Allow for slugs based on entry values. False: always use entry IDs (default)
543
		 */
544 157
		$custom = apply_filters( 'gravityview_custom_entry_slug', false );
545
546
		// If we're using custom slug...
547 157
		if ( $custom ) {
548
549
			// Get the entry hash
550 3
			$hash = self::get_custom_entry_slug( $id_or_string, $entry );
551
552
			// Cache the slugs
553 3
			static $cache = array();
554
555 3
			if ( ! isset( $cache[ $id_or_string ] ) ) {
556 3
				global $wpdb;
557
558 3
				if ( version_compare( GFFormsModel::get_database_version(), '2.3-dev-1', '>=' ) ) {
559 3
					$table = GFFormsModel::get_entry_meta_table_name();
560 3
					$column = 'entry_id';
561
				} else {
562
					$table = RGFormsModel::get_lead_meta_table_name();
563
					$column = 'lead_id';
564
				}
565
566 3
				$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 ) );
567
568 3
				if ( $results ) {
569
					$cache = array_replace( $cache, array_combine( wp_list_pluck( $results, $column ), wp_list_pluck( $results, 'meta_value' ) ) );
570
				}
571
572 3
				if ( ! isset( $cache[ $id_or_string ] ) ) {
573 3
					$cache[ $id_or_string ] = false;
574
				}
575
			}
576
577 3
			$value = $cache[ $id_or_string ];
578
579
			// If it does have a hash set, and the hash is expected, use it.
580
			// This check allows users to change the hash structure using the
581
			// gravityview_entry_hash filter and have the old hashes expire.
582 3
			if ( empty( $value ) || $value !== $hash ) {
583 3
				gravityview()->log->debug( 'Setting hash for entry {entry}: {hash}', array( 'entry' => $id_or_string, 'hash' => $hash ) );
584 3
				gform_update_meta( $id_or_string, 'gravityview_unique_id', $hash, \GV\Utils::get( $entry, 'form_id' ) );
585
			}
586
587 3
			$slug = $hash;
588
589 3
			unset( $value, $hash );
590
		}
591
592 157
		return sanitize_title( $slug );
593
	}
594
595
    /**
596
     * If using the entry custom slug feature, make sure the new entries have the custom slug created and saved as meta
597
     *
598
     * Triggered by add_action( 'gform_entry_created', array( 'GravityView_API', 'entry_create_custom_slug' ), 10, 2 );
599
     *
600
     * @param $entry array Gravity Forms entry object
601
     * @param $form array Gravity Forms form object
602
     */
603
    public static function entry_create_custom_slug( $entry, $form ) {
0 ignored issues
show
Unused Code introduced by
The parameter $form is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
604
        /**
605
         * @filter `gravityview_custom_entry_slug` On entry creation, check if we are using the custom entry slug feature and update the meta
606
         * @param boolean $custom Should we process the custom entry slug?
607
         */
608
        $custom = apply_filters( 'gravityview_custom_entry_slug', false );
609
        if( $custom ) {
610
            // create the gravityview_unique_id and save it
611
612
            // Get the entry hash
613
            $hash = self::get_custom_entry_slug( $entry['id'], $entry );
614
615
	        gravityview()->log->debug( 'Setting hash for entry {entry_id}: {hash}', array( 'entry_id' => $entry['id'], 'hash' => $hash ) );
616
617
            gform_update_meta( $entry['id'], 'gravityview_unique_id', $hash, \GV\Utils::get( $entry, 'form_id' ) );
618
619
        }
620
    }
621
622
623
624
625
	/**
626
	 * return href for single entry
627
	 *
628
	 * @since 1.7.3 Added $add_directory_args parameter
629
	 * @since 2.7.2 Added $view_id parameter
630
	 * @since 2.10  Added $_GET args to links by default. Use `gravityview/entry_link/add_query_args` filter to override.
631
	 *
632
	 * @param  array|int $entry   Entry array or entry ID.
633
	 * @param  int|null $post_id If wanting to define the parent post, pass a post ID.
634
	 * @param boolean $add_directory_args True: Add args to help return to directory; False: only include args required to get to entry.
635
	 * @param int $view_id
636
	 *
637
	 * @return string Link to the entry with the directory parent slug, or empty string if embedded post or View doesn't exist
638 6
	 */
639
	public static function entry_link( $entry, $post_id = NULL, $add_directory_args = true, $view_id = 0 ) {
640 6
641
		if ( ! empty( $entry ) && ! is_array( $entry ) ) {
642 6
			$entry = GVCommon::get_entry( $entry );
643
		} else if( empty( $entry ) ) {
644
			// @deprecated path
645
			$entry = GravityView_frontend::getInstance()->getEntry();
646
		}
647
648 6
		// Second parameter used to be passed as $field; this makes sure it's not an array
649 1
		if ( ! is_numeric( $post_id ) ) {
650
			$post_id = NULL;
651
		}
652
653 6
		// Get the permalink to the View
654
		$directory_link = self::directory_link( $post_id, false );
655
656 6
		// No post ID? Get outta here.
657 1
		if ( empty( $directory_link ) ) {
658
			return '';
659
		}
660 5
661
		$query_arg_name = \GV\Entry::get_endpoint_name();
662 5
663 1
		if ( ! empty( $entry['_multi'] ) ) {
664
			$entry_slugs = array();
665 1
666
			foreach ( $entry['_multi'] as $_multi ) {
667 1
668 1
				if( $gv_multi = \GV\GF_Entry::from_entry( $_multi ) ) {
669
					$entry_slugs[] = $gv_multi->get_slug();
670
				} else {
671
					// TODO: This path isn't covered by unit tests
672
					$entry_slugs[] = \GravityView_API::get_entry_slug( $_multi['id'], $_multi );
673
				}
674 1
675
				unset( $gv_multi );
676 1
677
				$forms[] = $_multi['form_id'];
0 ignored issues
show
Coding Style Comprehensibility introduced by
$forms was never initialized. Although not strictly required by PHP, it is generally a good practice to add $forms = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
678
			}
679 1
680
			$entry_slug = implode( ',', $entry_slugs );
681
		} else {
682
683 5
			// Fallback when
684 5
			if( $gv_entry = \GV\GF_Entry::from_entry( $entry ) ) {
685
				$entry_slug = $gv_entry->get_slug();
686
			} else {
687
				// TODO: This path isn't covered by unit tests
688
				$entry_slug = \GravityView_API::get_entry_slug( $entry['id'], $entry );
689
			}
690 5
691
			unset( $gv_entry );
692
		}
693 5
694
		$args = array();
695
696
		/**
697
		 * @filter `gravityview/entry_link/add_query_args` Modify whether to include passed $_GET parameters to the end of the url
698
		 * @since 2.10
699
		 * @param bool $add_query_params Whether to include passed $_GET parameters to the end of the Entry Link URL. Default: true.
700
		 */
701
		$add_query_args = apply_filters( 'gravityview/entry_link/add_query_args', true );
702
703
		if ( $add_query_args ) {
704
			$args = gv_get_query_args();
705
		}
706
707
		if ( get_option('permalink_structure') && ! is_preview() ) {
708
709 5
			/**
710
			 * Make sure the $directory_link doesn't contain any query otherwise it will break when adding the entry slug.
711
			 * @since 1.16.5
712
			 */
713
			$link_parts = explode( '?', $directory_link );
714
715 5
			$query = !empty( $link_parts[1] ) ? '?'.$link_parts[1] : '';
716
717 5
			$directory_link = trailingslashit( $link_parts[0] ) . $query_arg_name . '/'. $entry_slug .'/' . $query;
718
719
		} else {
720
721
			$args[] = array( $query_arg_name => $entry_slug );
722
		}
723
724 5
		/**
725
		 * @since 1.7.3
726
		 */
727
		if ( $add_directory_args ) {
728
729
			if ( ! empty( $_GET['pagenum'] ) ) {
730
				$args['pagenum'] = intval( $_GET['pagenum'] );
731 5
			}
732 5
733 5
			/**
734 5
			 * @since 1.7
735
			 */
736
			if ( $sort = \GV\Utils::_GET( 'sort' ) ) {
737
				$args['sort'] = $sort;
738
				$args['dir'] = \GV\Utils::_GET( 'dir' );
739 5
			}
740 1
741
		}
742
743 5
		if( $post_id ) {
744
			$passed_post = get_post( $post_id );
745
			$views       = \GV\View_Collection::from_post( $passed_post );
746
			$has_multiple_views = $views->count() > 1;
747
		} else {
748
			$has_multiple_views = class_exists( 'GravityView_View_Data' ) && GravityView_View_Data::getInstance()->has_multiple_views();
0 ignored issues
show
Deprecated Code introduced by
The method GravityView_View_Data::has_multiple_views() has been deprecated.

This method has been deprecated.

Loading history...
749
		}
750
751
		if ( $has_multiple_views ) {
752
			$args['gvid'] = $view_id ? $view_id : gravityview_get_view_id();
753
		}
754
755
		return add_query_arg( $args, $directory_link );
756
757 2
	}
758
759
760
}
761 37
762
/**
763
 * Returns query parameters from $_GET with reserved internal GravityView keys removed
764
 *
765
 * @uses stripslashes_deep() $_GET is passed through stripslashes_deep().
766
 * @uses urldecode_deep() $_GET is passed through urldecode_deep().
767
 *
768
 * Important: The return value of gv_get_query_args() is not escaped by default. Output should be
769
 * late-escaped with esc_url() or similar to help prevent vulnerability to cross-site scripting
770
 * (XSS) attacks.
771
 *
772
 * @since 2.10
773
 *
774
 * @return array
775
 */
776
function gv_get_query_args() {
777
778 38
	$passed_get = isset( $_GET ) ? $_GET : array();
779 36
780 36
	$passed_get = stripslashes_deep( $passed_get );
781 36
	$passed_get = urldecode_deep( $passed_get );
782 36
783 36
	if ( empty( $passed_get ) ) {
784 36
		return array();
785 4
	}
786
787
	$query_args = $passed_get;
788 36
789 23
	$reserved_args = array(
790 17
		'entry',
791 36
		'gvid',
792
		'status',
793
		'action',
794
		'view_id',
795 3
		'entry_id',
796 3
	);
797 3
798
	/**
799
	 * @filter `gravityview/api/reserved_query_args` Modify the URL arguments that should not be used because they are internal to GravityView
800 38
	 * @since 2.10
801
	 * @param array $reserved_args Array of URL query keys that should not be used except internally.
802 38
	 */
803
	$reserved_args = apply_filters( 'gravityview/api/reserved_query_args', $reserved_args );
804 38
805 4
	foreach ( $reserved_args as $reserved_arg ) {
806
		unset( $query_args[ $reserved_arg ] );
807
	}
808 38
809 8
	return $query_args;
810
}
811
812 38
813 36
// inside loop functions
814
815
/**
816 38
 * @deprecated Use \GV\Field::get_label()
817
 */
818
function gv_label( $field, $entry = NULL ) {
819
	return GravityView_API::field_label( $field, $entry );
0 ignored issues
show
Deprecated Code introduced by
The method GravityView_API::field_label() has been deprecated with message: Use \GV\Field::get_label()

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
820
}
821
822
function gv_class( $field, $form = NULL, $entry = array() ) {
823
	return GravityView_API::field_class( $field, $form, $entry  );
824
}
825 38
826
/**
827 38
 * Generate a CSS class to be added to the wrapper <div> of a View
828
 *
829 38
 * @since 1.5.4
830 38
 * @since 1.16 Added $echo parameter.
831
 * @since 2.0 Added $context parameter.
832
 *
833 38
 * @param string $passed_css_class Default: `gv-container gv-container-{view id}`. If View is hidden until search, adds ` hidden`
834
 * @param boolean $echo Whether to echo the output. Default: true
835
 * @param \GV\Template_Context $context The template context.
836
 *
837
 * @return string CSS class, sanitized by gravityview_sanitize_html_class()
838
 */
839
function gv_container_class( $passed_css_class = '', $echo = true, $context = null ) {
840
	if ( $context instanceof \GV\Template_Context ) {
841 2
		$hide_until_searched = false;
842
		$total_entries = 0;
843 2
		$view_id = 0;
844
		if ( $context->view ) {
845
			$view_id = $context->view->ID;
846
			if( $context->view->settings->get( 'hide_until_searched' ) ) {
847
				$hide_until_searched = ( empty( $context->entry ) && ! $context->request->is_search() );
848 1
			}
849
		}
850
		if ( $context->entries ) {
851 2
			$total_entries = $context->entries->total();
852
		} else if ( $context->entry ) {
853
			$total_entries = 1;
854
		}
855 18
	} else {
856
		/** @deprecated legacy execution path */
857
		$view_id = GravityView_View::getInstance()->getViewId();
858
		$hide_until_searched = GravityView_View::getInstance()->isHideUntilSearched();
859 2
		$total_entries = GravityView_View::getInstance()->getTotalEntries();
860
	}
861
862
	$passed_css_class = trim( $passed_css_class );
863 9
864
	$default_css_class = ! empty( $view_id ) ? sprintf( 'gv-container gv-container-%d', $view_id ) : 'gv-container';
865
866
	if ( $hide_until_searched ) {
867
		$default_css_class .= ' hidden';
868
	}
869
870
	if ( 0 === $total_entries ) {
871
		$default_css_class .= ' gv-container-no-results';
872
	}
873
874
	if ( $context instanceof \GV\Template_Context && $context->view ) {
875 17
		$default_css_class .= ' ' . $context->view->settings->get( 'class', '' );
876
	}
877
878
	$css_class = trim( $passed_css_class . ' '. $default_css_class );
879
880
	/**
881
	 * @filter `gravityview/render/container/class` Modify the CSS class to be added to the wrapper <div> of a View
882
	 * @since 1.5.4
883
	 * @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`
884 17
	 * @since 2.0
885
	 * @param \GV\Template_Context $context The context.
886
	 */
887
	$css_class = apply_filters( 'gravityview/render/container/class', $css_class, $context );
888
889
	$css_class = gravityview_sanitize_html_class( $css_class );
890
891
	if ( $echo ) {
892
		echo $css_class;
893 17
	}
894
895 17
	return $css_class;
896 4
}
897
898
/**
899 14
 * @deprecated Use \GV\Field_Template::render()
900 14
 */
901 14
function gv_value( $entry, $field ) {
902
903
	$value = GravityView_API::field_value( $entry, $field );
0 ignored issues
show
Deprecated Code introduced by
The method GravityView_API::field_value() has been deprecated with message: Use \GV\Field_Template::render() or the more low-level \GV\Field::get_value()

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
904
905
	if( $value === '' ) {
906
		/**
907
		 * @filter `gravityview_empty_value` What to display when a field is empty
908
		 * @param string $value (empty string)
909
		 */
910 14
		$value = apply_filters( 'gravityview_empty_value', '' );
911
	}
912
913
	return $value;
914
}
915
916
function gv_directory_link( $post = NULL, $add_pagination = true, $context = null ) {
917
	return GravityView_API::directory_link( $post, $add_pagination, $context );
918 14
}
919
920
function gv_entry_link( $entry, $post_id = NULL ) {
921
	return GravityView_API::entry_link( $entry, $post_id );
922
}
923
924
function gv_no_results( $wpautop = true, $context = null ) {
925
	return GravityView_API::no_results( $wpautop, $context );
926
}
927 14
928
/**
929
 * Generate HTML for the back link from single entry view
930
 * @since 1.0.1
931
 * @since 2.0
932
 * @param \GV\Template_Context $context The context this link is being displayed from.
933
 * @return string|null      If no GV post exists, null. Otherwise, HTML string of back link.
934
 */
935 14
function gravityview_back_link( $context = null ) {
936
937 14
	$href = gv_directory_link( null, true, $context );
938
939 14
	/**
940
	 * @filter `gravityview_go_back_url` Modify the back link URL
941
	 * @since 1.17.5
942
	 * @see gv_directory_link() Generated the original back link
943
	 * @param string $href Existing label URL
944
	 * @deprecated Use `gravityview/template/links/back/url`
945
	 */
946
	$href = apply_filters( 'gravityview_go_back_url', $href );
947
948
	/**
949
	 * @filter `gravityview/template/links/back/url` Modify the back link URL
950
	 * @since 2.0
951
	 * @see gv_directory_link() Generated the original back link
952
	 * @param string $href Existing label URL
953
	 * @param \GV\Template_Context The context.
954
	 */
955
	$href = apply_filters( 'gravityview/template/links/back/url', $href, $context );
956 15
957
	if ( empty( $href ) ) {
958
		return NULL;
959 12
	}
960
961
	if ( $context instanceof \GV\Template_Context ) {
962
		$view_id = $context->view->ID;
963
		$view_label = $context->template->get_back_label();
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class GV\Template as the method get_back_label() does only exist in the following sub-classes of GV\Template: GV\Entry_Legacy_Template, GV\Entry_List_Template, GV\Entry_Table_Template, GV\Entry_Template. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
964 7
	} else {
965
		/** @deprecated legacy path */
966
		$gravityview_view = GravityView_View::getInstance();
967
		$view_id = $gravityview_view->getViewId();
968
		$view_label = $gravityview_view->getBackLinkLabel() ? $gravityview_view->getBackLinkLabel() : false;
0 ignored issues
show
Deprecated Code introduced by
The method GravityView_View::getBackLinkLabel() has been deprecated with message: Use $template->get_back_label();

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
969
	}
970
971
	/** Default */
972
	$label = $view_label ? $view_label : __( '&larr; Go back', 'gravityview' );
973
974
	/**
975
	 * @filter `gravityview_go_back_label` Modify the back link text
976
	 * @since 1.0.9
977
	 * @param string $label Existing label text
978
	 * @deprecated Use `gravityview/template/links/back/label`
979
	 */
980
	$label = apply_filters( 'gravityview_go_back_label', $label );
981
982 1
	/**
983
	 * @filter `gravityview/template/links/back/label` Modify the back link text
984 1
	 * @since 2.0
985 1
	 * @see gv_directory_link() Generated the original back link
986
	 * @param string $label Existing label text
987 1
	 * @param \GV\Template_Context The context.
988
	 */
989
	$label = apply_filters( 'gravityview/template/links/back/label', $label, $context );
990 1
991
	/**
992
	 * @filter `gravityview/template/links/back/atts` Modify the attributes used on the back link anchor tag
993 1
	 * @since 2.1
994
	 * @param array $atts Original attributes, default: [ data-viewid => $view_id ]
995
	 * @param \GV\Template_Context The context.
996 1
	 */
997
	$atts = apply_filters( 'gravityview/template/links/back/atts', array( 'data-viewid' => $view_id ), $context );
998
999 1
	$link = gravityview_get_link( $href, esc_html( $label ), $atts );
1000 1
1001
	return $link;
1002
}
1003 1
1004
/**
1005
 * Handle getting values for complex Gravity Forms fields
1006
 *
1007
 * If the field is complex, like a product, the field ID, for example, 11, won't exist. Instead,
1008 1
 * it will be 11.1, 11.2, and 11.3. This handles being passed 11 and 11.2 with the same function.
1009
 *
1010
 * @since 1.0.4
1011
 * @param  array      $entry    GF entry array
1012 1
 * @param  string      $field_id [description]
1013
 * @param  string 	$display_value The value generated by Gravity Forms
1014 1
 * @return string                Value
1015
 */
1016
function gravityview_get_field_value( $entry, $field_id, $display_value ) {
1017 1
1018
	if( floatval( $field_id ) === floor( floatval( $field_id ) ) ) {
1019
1020
		// For the complete field value as generated by Gravity Forms
1021 1
		return $display_value;
1022
1023
	} else {
1024
1025 1
		// For one part of the address (City, ZIP, etc.)
1026
		return isset( $entry[ $field_id ] ) ? $entry[ $field_id ] : '';
1027
1028
	}
1029
1030
}
1031
1032
/**
1033
 * Take a passed CSV of terms and generate a linked list of terms
1034
 *
1035
 * Gravity Forms passes categories as "Name:ID" so we handle that using the ID, which
1036
 * is more accurate than checking the name, which is more likely to change.
1037 1
 *
1038
 * @param  string      $value    Existing value
1039 1
 * @param  string      $taxonomy Type of term (`post_tag` or `category`)
1040 1
 * @return string                CSV of linked terms
1041
 */
1042
function gravityview_convert_value_to_term_list( $value, $taxonomy = 'post_tag' ) {
1043 1
1044
	$output = array();
1045
1046
	if ( is_array( $value ) ) {
1047
		$terms = array_filter( array_values( $value ), 'strlen' );
1048
	} else {
1049
		$terms = explode( ', ', $value );
1050
	}
1051
1052
	foreach ($terms as $term_name ) {
1053
1054
		// If we're processing a category,
1055
		if( $taxonomy === 'category' ) {
1056 1
1057
			// Use rgexplode to prevent errors if : doesn't exist
1058
			list( $term_name, $term_id ) = rgexplode( ':', $term_name, 2 );
1059 1
1060
			// The explode was succesful; we have the category ID
1061 1
			if( !empty( $term_id )) {
1062
				$term = get_term_by( 'id', $term_id, $taxonomy );
1063 1
			} else {
1064
			// We have to fall back to the name
1065
				$term = get_term_by( 'name', $term_name, $taxonomy );
1066
			}
1067 1
1068
		} else {
1069
			// Use the name of the tag to get the full term information
1070
			$term = get_term_by( 'name', $term_name, $taxonomy );
1071
		}
1072
1073
		// There's still a tag/category here.
1074 1
		if( $term ) {
1075
1076
			$term_link = get_term_link( $term, $taxonomy );
1077
1078
			// If there was an error, continue to the next term.
1079
			if ( is_wp_error( $term_link ) ) {
1080
			    continue;
1081
			}
1082
1083
			$output[] = gravityview_get_link( $term_link, esc_html( $term->name ) );
1084
		}
1085
	}
1086
1087
	return implode(', ', $output );
1088
}
1089
1090
/**
1091
 * Get the links for post_tags and post_category output based on post ID
1092
 * @param  int      $post_id  The ID of the post
1093
 * @param  boolean     $link     Add links or no?
1094
 * @param  string      $taxonomy Taxonomy of term to fetch.
1095
 * @return string                String with terms
1096
 */
1097
function gravityview_get_the_term_list( $post_id, $link = true, $taxonomy = 'post_tag' ) {
1098
1099
	$output = get_the_term_list( $post_id, $taxonomy, NULL, ', ' );
1100
1101
	if( empty( $link ) ) {
1102
		return strip_tags( $output);
1103
	}
1104
1105
	return $output;
1106
1107
}
1108
1109
1110
/**
1111
 * Get all views processed so far for the current page load
1112 37
 *
1113 35
 * @see  GravityView_View_Data::add_view()
1114 35
 * @return array Array of View data, each View data with `id`, `view_id`, `form_id`, `template_id`, `atts`, `fields`, `widgets`, `form` keys.
1115
 */
1116
function gravityview_get_current_views() {
1117
1118
	$fe = GravityView_frontend::getInstance();
1119 35
1120
	// Solve problem when loading content via admin-ajax.php
1121
	if( ! $fe->getGvOutputData() ) {
1122
1123
		gravityview()->log->debug( 'gv_output_data not defined; parsing content.' );
1124 35
1125
		$fe->parse_content();
1126
	}
1127
1128
	// Make 100% sure that we're dealing with a properly called situation
1129
	if( !is_a( $fe->getGvOutputData(), 'GravityView_View_Data' ) ) {
1130
1131
		gravityview()->log->debug( 'gv_output_data not an object or get_view not callable.', array( 'data' => $fe->getGvOutputData() ) );
1132
1133 2
		return array();
1134 2
	}
1135
1136
	return $fe->getGvOutputData()->get_views();
0 ignored issues
show
Deprecated Code introduced by
The method GravityView_View_Data::get_views() has been deprecated.

This method has been deprecated.

Loading history...
1137
}
1138
1139
/**
1140
 * Get data for a specific view
1141 33
 *
1142 31
 * @deprecated use \GV\View API instead
1143 31
 * @since 2.5
1144
 *
1145
 * @see  GravityView_View_Data::get_view()
1146
 * @return array View data with `id`, `view_id`, `form_id`, `template_id`, `atts`, `fields`, `widgets`, `form` keys.
1147
 */
1148 31
function gravityview_get_current_view_data( $view_id = 0 ) {
1149
	if ( $view_id ) {
1150
		if ( $view = \GV\View::by_id( $view_id ) ) {
1151
			return $view; // implements ArrayAccess
1152
		}
1153 31
		return array();
1154
	}
1155
1156
	$fe = GravityView_frontend::getInstance();
1157
1158
	// If not set, grab the current view ID
1159
	if ( empty( $view_id ) ) {
1160
		$view_id = $fe->get_context_view_id();
1161
	}
1162 2
1163 2
	if ( ! $fe->getGvOutputData() ) { return array(); }
1164
1165
	return $fe->getGvOutputData()->get_view( $view_id );
0 ignored issues
show
Deprecated Code introduced by
The method GravityView_View_Data::get_view() has been deprecated.

This method has been deprecated.

Loading history...
1166
}
1167
1168
// Templates' hooks
1169
function gravityview_before() {
1170 33
	/**
1171 31
	 * @action `gravityview/template/before` Append content to the view.
1172 31
	 * @param object $gravityview The $gravityview object available in templates.
1173
	 */
1174
	if ( count( $args = func_get_args() ) ) {
1175
		$gravityview = reset( $args );
1176
		if ( $gravityview instanceof \GV\Template_Context ) {
1177 31
			/**
1178
			 * @action `gravityview/template/before` Prepend content to the view.
1179
			 * @param \GV\Template_Context $gravityview The $gravityview object available in templates.
1180
			 */
1181
			do_action( 'gravityview/template/before', $gravityview );
1182 31
1183
			/**
1184
			 * @deprecated Use `gravityview/template/before`
1185
			 */
1186
			return do_action( 'gravityview_before', $gravityview->view->ID );
1187
		}
1188
	}
1189
1190
	/**
1191 2
	 * @action `gravityview_before` Prepend content to the View container `<div>`
1192 2
	 * @deprecated Use `gravityview/template/before`.
1193
	 * @param int $view_id The ID of the View being displayed
1194
	 */
1195 37
	do_action( 'gravityview_before', gravityview_get_view_id() );
1196 35
}
1197 35
1198
function gravityview_header() {
1199
	/**
1200
	 * @action `gravityview/template/header` Append content to the view.
1201
	 * @param object $gravityview The $gravityview object available in templates.
1202 35
	 */
1203
	if ( count( $args = func_get_args() ) ) {
1204
		$gravityview = reset( $args );
1205
		if ( $gravityview instanceof \GV\Template_Context ) {
1206
			/**
1207 35
			 * @action `gravityview/template/header` Prepend content to the view container <div>.
1208
			 * @param \GV\Template_Context $gravityview The $gravityview object available in templates.
1209 35
			 */
1210
			do_action( 'gravityview/template/header', $gravityview );
1211
1212
			/**
1213
			 * @deprecated Use `gravityview/template/header`
1214
			 */
1215
			return do_action( 'gravityview_header', $gravityview->view->ID );
1216
		}
1217
	}
1218 2
1219 2
	/**
1220
	 * @action `gravityview_header` Prepend content to the View container `<div>`
1221
	 * @deprecated Use `gravityview/template/header`.
1222
	 * @param int $view_id The ID of the View being displayed
1223
	 */
1224
	do_action( 'gravityview_header', gravityview_get_view_id() );
1225
}
1226
1227
function gravityview_footer() {
1228
	/**
1229
	 * @action `gravityview/template/footer` Append content to the view.
1230 2
	 * @param object $gravityview The $gravityview object available in templates.
1231
	 */
1232
	if ( count( $args = func_get_args() ) ) {
1233
		$gravityview = reset( $args );
1234 2
		if ( $gravityview instanceof \GV\Template_Context ) {
1235
			/**
1236
			 * @action `gravityview/template/footer` Prepend outside of the view container <div>.
1237
			 * @param \GV\Template_Context $gravityview The $gravityview object available in templates.
1238
			 */
1239
			do_action( 'gravityview/template/footer', $gravityview );
1240
1241
			/**
1242
			 * @deprecated Use `gravityview/template/footer`
1243
			 */
1244
			return do_action( 'gravityview_footer', $gravityview->view->ID );
1245
		}
1246
	}
1247
1248
	/**
1249
	 * @action `gravityview_after` Display content after a View. Used to render footer widget areas. Rendered outside the View container `<div>`
1250
	 * @deprecated Use `gravityview/template/footer`.
1251 4
	 * @param int $view_id The ID of the View being displayed
1252
	 */
1253 4
	do_action( 'gravityview_footer', gravityview_get_view_id() );
1254
}
1255
1256
function gravityview_after() {
1257
	if ( count( $args = func_get_args() ) ) {
1258
		$gravityview = reset( $args );
1259
		if ( $gravityview instanceof \GV\Template_Context ) {
1260
			/**
1261
			 * @action `gravityview/template/after` Append content to the view.
1262 4
			 * @param \GV\Template_Context $gravityview The $gravityview object available in templates.
1263
			 */
1264 4
			do_action( 'gravityview/template/after', $gravityview );
1265
1266 4
			/**
1267 1
			 * @deprecated Use `gravityview/template/after`
1268 4
			 */
1269 4
			do_action( 'gravityview_after', $gravityview->view->ID );
1270
1271
			return;
1272
		}
1273
	}
1274
1275
	/**
1276
	 * @action `gravityview_after` Append content to the View container `<div>`
1277
	 * @deprecated Use `gravityview/template/after`
1278
	 * @param int $view_id The ID of the View being displayed
1279
	 */
1280
	do_action( 'gravityview_after', gravityview_get_view_id() );
1281
}
1282
1283
/**
1284
 * Get the current View ID being rendered
1285
 *
1286
 * @global GravityView_View $gravityview_view
1287
 *
1288
 * @return int View ID, if exists. `0` if `GravityView_View` doesn't exist, like in the admin, or no View is set.
1289
 */
1290
function gravityview_get_view_id() {
1291
1292
	if ( ! class_exists( 'GravityView_View' ) ) {
1293
		return 0;
1294
	}
1295
1296
	return GravityView_View::getInstance()->getViewId();
1297
}
1298 5
1299
/**
1300
 * Returns the current GravityView context, or empty string if not GravityView
1301
 *
1302 5
 * - Returns empty string on GravityView archive pages
1303
 * - Returns empty string on archive pages containing embedded Views
1304
 * - Returns empty string for embedded Views, not 'directory'
1305
 * - Returns empty string for embedded entries (oEmbed or [gventry]), not 'single'
1306 5
 * - Returns 'single' when viewing a [gravityview] shortcode-embedded single entry
1307
 *
1308
 * @global GravityView_View $gravityview_view
1309
 * @deprecated since 2.0.6.2 Use `gravityview()->request`
1310 5
 * @return string View context "directory", "single", "edit", or empty string if not GravityView
1311
 */
1312
function gravityview_get_context() {
1313
	global $wp_query;
1314
1315
	if ( isset( $wp_query ) && $wp_query->post_count > 1 ) {
1316
		return '';
1317
	}
1318
1319
	/**
1320
	 * @filter `gravityview_is_edit_entry` Whether we're currently on the Edit Entry screen \n
1321
	 * The Edit Entry functionality overrides this value.
1322
	 * @param boolean $is_edit_entry
1323
	 */
1324
	$is_edit_entry = apply_filters( 'gravityview_is_edit_entry', false );
1325
1326 1
	if ( $is_edit_entry ) {
1327 1
		return 'edit';
1328
	} else if ( gravityview()->request->is_entry() ) {
1329 1
		return 'single';
1330
	} else if ( gravityview()->request->is_view() ) {
1331 1
		return 'directory';
1332
	}
1333 1
1334
	return '';
1335
}
1336
1337
1338
/**
1339
 * Return an array of files prepared for output. Wrapper for GravityView_Field_FileUpload::get_files_array()
1340
 *
1341 1
 * Processes files by file type and generates unique output for each.
1342
 *
1343 1
 * Returns array for each file, with the following keys:
1344
 *
1345
 * `file_path` => The file path of the file, with a line break
1346
 * `html` => The file output HTML formatted
1347
 *
1348
 * @see GravityView_Field_FileUpload::get_files_array()
1349
 *
1350
 * @since  1.2
1351
 * @param  string $value    Field value passed by Gravity Forms. String of file URL, or serialized string of file URL array
1352
 * @param  string $gv_class Field class to add to the output HTML
1353
 * @since  2.0
1354
 * @param  \GV\Template_Context $context The context
1355
 * @return array           Array of file output, with `file_path` and `html` keys (see comments above)
1356
 */
1357
function gravityview_get_files_array( $value, $gv_class = '', $context = null ) {
1358
	/** @define "GRAVITYVIEW_DIR" "../" */
1359
1360
	if( !class_exists( 'GravityView_Field' ) ) {
1361
		include_once( GRAVITYVIEW_DIR .'includes/fields/class-gravityview-field.php' );
1362
	}
1363
1364
	if( !class_exists( 'GravityView_Field_FileUpload' ) ) {
1365
		include_once( GRAVITYVIEW_DIR .'includes/fields/class-gravityview-field-fileupload.php' );
1366 34
	}
1367
1368
	if ( is_null( $context ) ) {
1369
		_doing_it_wrong( __FUNCTION__, '2.0', 'Please pass an \GV\Template_Context object as the 3rd parameter' );
1370
	}
1371
1372
	return GravityView_Field_FileUpload::get_files_array( $value, $gv_class, $context );
1373
}
1374
1375
/**
1376 34
 * Generate a mapping link from an address
1377
 *
1378
 * The address should be plain text with new line (`\n`) or `<br />` line breaks separating sections
1379
 *
1380
 * @todo use GF's field get_export_value() instead
1381
 *
1382
 * @see https://gravityview.co/support/documentation/201608159 Read how to modify the link
1383
 * @param  string $address Address
1384
 * @return string          URL of link to map of address
1385
 */
1386
function gravityview_get_map_link( $address ) {
1387 34
1388
	$address_qs = str_replace( array( '<br />', "\n" ), ' ', $address ); // Replace \n with spaces
1389
	$address_qs = urlencode( $address_qs );
1390
1391
	$url = "https://maps.google.com/maps?q={$address_qs}";
1392
1393
	$link_text = esc_html__( 'Map It', 'gravityview' );
1394
1395
	$link = gravityview_get_link( $url, $link_text, 'class=map-it-link' );
1396 34
1397
	/**
1398 34
	 * @filter `gravityview_map_link` Modify the map link generated. You can use a different mapping service, for example.
1399 32
	 * @param[in,out]  string $link Map link
1400
	 * @param[in] string $address Address to generate link for
1401 32
	 * @param[in] string $url URL generated by the function
1402
	 */
1403
	$link = apply_filters( 'gravityview_map_link', $link, $address, $url );
1404
1405
	return $link;
1406 2
}
1407
1408
1409
/**
1410
 * Output field based on a certain html markup
1411
 *
1412 34
 *   markup - string to be used on a sprintf statement.
1413 32
 *      Use:
1414 32
 *         {{label}} - field label
1415 32
 *         {{value}} - entry field value
1416
 *         {{class}} - field class
1417
 *
1418 2
 *   wpautop - true will filter the value using wpautop function
1419 2
 *
1420 2
 * @since  1.1.5
1421
 * @param  array $passed_args Associative array with field data. `field` and `form` are required.
1422
 * @since  2.0
1423
 * @param  \GV\Template_Context The template context.
1424
 * @return string Field output. If empty value and hide empty is true, return empty.
1425
 */
1426
function gravityview_field_output( $passed_args, $context = null ) {
1427
	$defaults = array(
1428 34
		'entry' => null,
1429
		'field' => null,
1430
		'form' => null,
1431
		'hide_empty' => true,
1432
		'markup' => '<div id="{{ field_id }}" class="{{ class }}">{{ label }}{{ value }}</div>',
1433
		'label_markup' => '',
1434
		'wpautop' => false,
1435
		'zone_id' => null,
1436
	);
1437
1438
	$args = wp_parse_args( $passed_args, $defaults );
1439 34
1440 32
	/**
1441
	 * @filter `gravityview/field_output/args` Modify the args before generation begins
1442
	 * @since 1.7
1443 2
	 * @param array $args Associative array; `field` and `form` is required.
1444
	 * @param array $passed_args Original associative array with field data. `field` and `form` are required.
1445
	 * @since 2.0
1446
	 * @param \GV\Template_Context $context The context.
1447 34
	 * @deprecated
1448 5
	 */
1449
	$args = apply_filters( 'gravityview/field_output/args', $args, $passed_args, $context );
1450
1451 34
	/**
1452 5
	 * @filter `gravityview/template/field_output/context` Modify the context before generation begins.
1453
	 * @since 2.0
1454
	 * @param[in,out] \GV\Template_Context $context The context.
1455
	 * @param array $args The sanitized arguments, these should not be trusted any longer.
1456 34
	 * @param array $passed_args The passed arguments, these should not be trusted any longer.
1457
	 */
1458
	$context = apply_filters( 'gravityview/template/field_output/context', $context, $args, $passed_args );
1459 34
1460
	if ( $context instanceof \GV\Template_Context ) {
1461
		if ( ! $context->field || ! $context->view || ! $context->view->form ) {
1462 34
			gravityview()->log->error( 'Field or form are empty.', array( 'data' => array( $context->field, $context->view->form ) ) );
1463 34
			return '';
1464
		}
1465 34
	} else {
1466 32
		// @deprecated path
1467
		// Required fields.
1468
		if ( empty( $args['field'] ) || empty( $args['form'] ) ) {
1469 2
			gravityview()->log->error( 'Field or form are empty.', array( 'data' => $args ) );
1470
			return '';
1471
		}
1472 34
	}
1473 34
1474
	if ( $context instanceof \GV\Template_Context ) {
1475 34
		$entry = $args['entry'] ? : ( $context->entry ? $context->entry->as_entry() : array() );
1476 34
		$field = $args['field'] ? : ( $context->field ? $context->field->as_configuration() : array() );
1477
		$form = $args['form'] ? : ( $context->view->form ? $context->view->form->form : array() );
0 ignored issues
show
Documentation introduced by
The property $form is declared private in GV\Form. Since you implemented __get(), maybe consider adding a @property or @property-read annotation. This makes it easier for IDEs to provide auto-completion.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
1478
	} else {
1479
		// @deprecated path
1480
		$entry = empty( $args['entry'] ) ? array() : $args['entry'];
1481
		$field = $args['field'];
1482
		$form = $args['form'];
1483
	}
1484
1485
	/**
1486
	 * Create the content variables for replacing.
1487 34
	 * @since 1.11
1488
	 */
1489
	$placeholders = array(
1490
		'value' => '',
1491
		'width' => '',
1492
		'width:style' => '',
1493
		'label' => '',
1494
		'label_value' => '',
1495
		'label_value:esc_attr' => '',
1496 34
		'label_value:data-label' => '',
1497
		'class' => '',
1498
		'field_id' => '',
1499
	);
1500
1501
	if ( $context instanceof \GV\Template_Context ) {
1502
		$placeholders['value'] = \GV\Utils::get( $args, 'value', '' );
1503
	} else {
1504
		// @deprecated path
1505 34
		$placeholders['value'] = gv_value( $entry, $field );
0 ignored issues
show
Deprecated Code introduced by
The function gv_value() has been deprecated with message: Use \GV\Field_Template::render()

This function has been deprecated. The supplier of the file has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed from the class and what other function to use instead.

Loading history...
1506
	}
1507
1508
	// If the value is empty and we're hiding empty, return empty.
1509
	if ( $placeholders['value'] === '' && ! empty( $args['hide_empty'] ) ) {
1510
		return '';
1511 34
	}
1512
1513
	if ( $placeholders['value'] !== '' && ! empty( $args['wpautop'] ) ) {
1514 34
		$placeholders['value'] = wpautop( $placeholders['value'] );
1515 34
	}
1516
1517
	// Get width setting, if exists
1518
	$placeholders['width'] = GravityView_API::field_width( $field );
1519
1520 34
	// If replacing with CSS inline formatting, let's do it.
1521 34
	$placeholders['width:style'] = GravityView_API::field_width( $field, 'width:' . $placeholders['width'] . '%;' );
1522
1523
	// Grab the Class using `gv_class`
1524
	$placeholders['class'] = gv_class( $field, $form, $entry );
1525
	$placeholders['field_id'] = GravityView_API::field_html_attr_id( $field, $form, $entry );
1526
1527
	if ( $context instanceof \GV\Template_Context ) {
1528
		$placeholders['label_value'] = \GV\Utils::get( $args, 'label' );
1529
	} else {
1530
		// Default Label value
1531
		$placeholders['label_value'] = gv_label( $field, $entry );
0 ignored issues
show
Deprecated Code introduced by
The function gv_label() has been deprecated with message: Use \GV\Field::get_label()

This function has been deprecated. The supplier of the file has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed from the class and what other function to use instead.

Loading history...
1532 34
	}
1533
1534
	$placeholders['label_value:data-label'] = trim( esc_attr( strip_tags( str_replace( '>&nbsp;', '>', $placeholders['label_value'] ) ) ) );
1535 34
	$placeholders['label_value:esc_attr'] = esc_attr( $placeholders['label_value'] );
1536
1537
	if ( empty( $placeholders['label'] ) && ! empty( $placeholders['label_value'] ) ){
1538
		$placeholders['label'] = '<span class="gv-field-label">{{ label_value }}</span>';
1539
	}
1540
1541
	/**
1542
	 * @filter `gravityview/field_output/pre_html` Allow Pre filtering of the HTML
1543
	 * @since 1.11
1544
	 * @param string $markup The HTML for the markup
1545 34
	 * @param array $args All args for the field output
1546
	 * @since 2.0
1547
	 * @param \GV\Template_Context $context The context.
1548
	 */
1549
	$html = apply_filters( 'gravityview/field_output/pre_html', $args['markup'], $args, $context );
1550
1551
	/**
1552
	 * @filter `gravityview/field_output/open_tag` Modify the opening tags for the template content placeholders
1553
	 * @since 1.11
1554 34
	 * @param string $open_tag Open tag for template content placeholders. Default: `{{`
1555
	 * @since 2.0
1556
	 * @param \GV\Template_Context $context The context.
1557 34
	 */
1558
	$open_tag = apply_filters( 'gravityview/field_output/open_tag', '{{', $args, $context );
1559 34
1560
	/**
1561
	 * @filter `gravityview/field_output/close_tag` Modify the closing tags for the template content placeholders
1562
	 * @since 1.11
1563
	 * @param string $close_tag Close tag for template content placeholders. Default: `}}`
1564
	 * @since 2.0
1565
	 * @param \GV\Template_Context $context The context.
1566
	 */
1567
	$close_tag = apply_filters( 'gravityview/field_output/close_tag', '}}', $args, $context );
1568
1569
	/**
1570
	 * Loop through each of the tags to replace and replace both `{{tag}}` and `{{ tag }}` with the values
1571
	 * @since 1.11
1572
	 */
1573
	foreach ( $placeholders as $tag => $value ) {
1574
1575
		// If the tag doesn't exist just skip it
1576
		if ( false === strpos( $html, $open_tag . $tag . $close_tag ) && false === strpos( $html, $open_tag . ' ' . $tag . ' ' . $close_tag ) ){
1577
			continue;
1578
		}
1579
1580
		// Array to search
1581
		$search = array(
1582
			$open_tag . $tag . $close_tag,
1583
			$open_tag . ' ' . $tag . ' ' . $close_tag,
1584
		);
1585
1586
		/**
1587
		 * `gravityview/field_output/context/{$tag}` Allow users to filter content on context
1588
		 * @since 1.11
1589
		 * @param string $value The content to be shown instead of the {{tag}} placeholder
1590
		 * @param array $args Arguments passed to the function
1591
		 * @since 2.0
1592
		 * @param \GV\Template_Context $context The context.
1593
		 */
1594
		$value = apply_filters( 'gravityview/field_output/context/' . $tag, $value, $args, $context );
1595
1596
		// Finally do the replace
1597
		$html = str_replace( $search, $value, $html );
1598
	}
1599
1600
	/**
1601
	 * @filter `gravityview_field_output` Modify field HTML output
1602
	 * @param string $html Existing HTML output
1603
	 * @param array $args Arguments passed to the function
1604
	 * @since 2.0
1605
	 * @param \GV\Template_Context $context The context.
1606
	 */
1607
	$html = apply_filters( 'gravityview_field_output', $html, $args, $context );
1608
1609
	/**
1610
	 * @filter `gravityview/field_output/html` Modify field HTML output
1611
	 * @param string $html Existing HTML output
1612
	 * @param array $args Arguments passed to the function
1613
	 * @since 2.0
1614
	 * @param \GV\Template_Context $context The context.
1615
	 */
1616
	$html = apply_filters( 'gravityview/field_output/html', $html, $args, $context );
1617
1618
	/** @since 2.0.8 Remove unused atts */
1619
	$html = str_replace( array( ' style=""', ' class=""', ' id=""' ), '', $html );
1620
1621
	return $html;
1622
}
1623