Completed
Push — develop ( 24a577...777f39 )
by Gennady
16:23
created

GravityView_API::field_class()   B

Complexity

Conditions 7
Paths 12

Size

Total Lines 40

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 8.1426

Importance

Changes 0
Metric Value
cc 7
nc 12
nop 3
dl 0
loc 40
ccs 5
cts 7
cp 0.7143
crap 8.1426
rs 8.3466
c 0
b 0
f 0
1
<?php
2
/**
3
 * GravityView template tags API
4
 *
5
 * @package   GravityView
6
 * @license   GPL2+
7
 * @author    Katz Web Services, Inc.
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
	 * @access public
22
	 * @static
23
	 * @param array $field GravityView field array
24
	 * @param array $entry Gravity Forms entry array
25
	 * @param boolean $force_show_label Whether to always show the label, regardless of field settings
26
	 * @return string
27
	 */
28 3
	public static function field_label( $field, $entry = array(), $force_show_label = false ) {
29
30 3
		$gravityview_view = GravityView_View::getInstance();
31
32 3
		$form = $gravityview_view->getForm();
33
34 3
		if ( defined( 'DOING_GRAVITYVIEW_TESTS' ) && ! empty( $GLOBALS['GravityView_API_field_label_override'] ) ) {
0 ignored issues
show
Unused Code introduced by
This if statement is empty and can be removed.

This check looks for the bodies of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These if bodies can be removed. If you have an empty if but statements in the else branch, consider inverting the condition.

if (rand(1, 6) > 3) {
//print "Check failed";
} else {
    print "Check succeeded";
}

could be turned into

if (rand(1, 6) <= 3) {
    print "Check succeeded";
}

This is much more concise to read.

Loading history...
35
			/** Allow to fall through for back compatibility testing purposes. */
36
		} else {
37 3
			return \GV\Mocks\GravityView_API_field_label( $form, $field, $entry, $force_show_label );
38
		}
39 1
40
		$label = '';
41
42
		if( !empty( $field['show_label'] ) || $force_show_label ) {
0 ignored issues
show
introduced by
Expected 1 space after "!"; 0 found
Loading history...
43
44
			$label = $field['label'];
45
46
			// Support Gravity Forms 1.9+
47
			if( class_exists( 'GF_Field' ) ) {
48
49
				$field_object = RGFormsModel::get_field( $form, $field['id'] );
50
51
				if( $field_object ) {
52
53
					$input = GFFormsModel::get_input( $field_object, $field['id'] );
54
55
					// This is a complex field, with labels on a per-input basis
56
					if( $input ) {
57 26
58 26
						// Does the input have a custom label on a per-input basis? Otherwise, default label.
59
						$label = ! empty( $input['customLabel'] ) ? $input['customLabel'] : $input['label'];
60
61
					} else {
62
63
						// This is a field with one label
64
						$label = $field_object->get_field_label( true, $field['label'] );
65
66
					}
67
68
				}
69
70
			}
71 29
72
			// Use Gravity Forms label by default, but if a custom label is defined in GV, use it.
73 29
			if ( !empty( $field['custom_label'] ) ) {
0 ignored issues
show
introduced by
Expected 1 space after "!"; 0 found
Loading history...
74
75 29
				$label = self::replace_variables( $field['custom_label'], $form, $entry );
76 1
77
			}
78
79 1
			/**
80 1
			 * @filter `gravityview_render_after_label` Append content to a field label
81
			 * @param[in,out] string $appended_content Content you can add after a label. Empty by default.
82
			 * @param[in] array $field GravityView field array
83 1
			 */
84
			$label .= apply_filters( 'gravityview_render_after_label', '', $field );
85
86 29
		} // End $field['show_label']
0 ignored issues
show
Unused Code Comprehensibility introduced by
58% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
87
88
		/**
89
		 * @filter `gravityview/template/field_label` Modify field label output
90
		 * @since 1.7
91
		 * @param[in,out] string $label Field label HTML
92
		 * @param[in] array $field GravityView field array
93
		 * @param[in] array $form Gravity Forms form array
94
		 * @param[in] array $entry Gravity Forms entry array
95
		 *
96
		 * @deprecated Use the context-aware version `gravityview/template/field/label`
97 32
		 */
98 32
		$label = apply_filters( 'gravityview/template/field_label', $label, $field, $form, $entry );
99
100 32
		return $label;
101
	}
102 2
103
	/**
104 2
	 * Alias for GravityView_Merge_Tags::replace_variables()
105
	 *
106
	 * @see GravityView_Merge_Tags::replace_variables() Moved in 1.8.4
107
	 * @since 1.22.4 - Added $nl2br, $format, $aux_data args
108
	 *
109 2
	 * @param  string     $text         Text to replace variables in
110
	 * @param  array      $form         GF Form array
111 2
	 * @param  array      $entry        GF Entry array
112
	 * @param  bool       $url_encode   Pass return value through `url_encode()`
113
	 * @param  bool       $esc_html     Pass return value through `esc_html()`
114 2
	 * @param  bool       $nl2br        Convert newlines to <br> HTML tags
115
	 * @param  string     $format       The format requested for the location the merge is being used. Possible values: html, text or url.
116
	 * @param  array      $aux_data     Additional data to be used to replace merge tags {@see https://www.gravityhelp.com/documentation/article/gform_merge_tag_data/}
117
	 * @return string                   Text with variables maybe replaced
118 2
	 */
119
	public static function replace_variables( $text, $form = array(), $entry = array(), $url_encode = false, $esc_html = true, $nl2br = true, $format = 'html', $aux_data = array() ) {
120
		return GravityView_Merge_Tags::replace_variables( $text, $form, $entry, $url_encode, $esc_html, $nl2br, $format, $aux_data );
121
	}
122 32
123 32
	/**
124 32
	 * Get column width from the field setting
125
	 *
126
	 * @since 1.9
127
	 *
128
	 * @param array $field Array of settings for the field
129
	 * @param string $format Format for width. "%" (default) will return
130
	 *
131
	 * @return string|null If not empty, string in $format format. Otherwise, null.
132 32
	 */
133
	public static function field_width( $field, $format = '%d%%' ) {
134
135 32
		$width = NULL;
0 ignored issues
show
Coding Style introduced by
TRUE, FALSE and NULL must be lowercase; expected null, but found NULL.
Loading history...
136
137
		if( !empty( $field['width'] ) ) {
0 ignored issues
show
introduced by
Expected 1 space after "!"; 0 found
Loading history...
138
			$width = absint( $field['width'] );
139
140
			// If using percentages, limit to 100%
141
			if( '%d%%' === $format && $width > 100 ) {
142
				$width = 100;
143
			}
144
145
			$width = sprintf( $format, $width );
146
		}
147
148
		return $width;
149
	}
150 28
151 28
	/**
152
	 * Fetch Field class
153 28
	 *
154 28
	 * @access public
155 28
	 * @static
156
	 * @param mixed $field
157
	 * @return string
158
	 */
159
	public static function field_class( $field, $form = NULL, $entry = NULL ) {
0 ignored issues
show
Coding Style introduced by
TRUE, FALSE and NULL must be lowercase; expected null, but found NULL.
Loading history...
160
		$classes = array();
161
162
		if( !empty( $field['custom_class'] ) ) {
0 ignored issues
show
introduced by
Expected 1 space after "!"; 0 found
Loading history...
163 28
164
            $custom_class = $field['custom_class'];
165
166 28
            if( !empty( $entry ) ) {
0 ignored issues
show
introduced by
Expected 1 space after "!"; 0 found
Loading history...
167
168
                // We want the merge tag to be formatted as a class. The merge tag may be
169
                // replaced by a multiple-word value that should be output as a single class.
170
                // "Office Manager" will be formatted as `.OfficeManager`, not `.Office` and `.Manager`
0 ignored issues
show
Unused Code Comprehensibility introduced by
38% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
171
                add_filter('gform_merge_tag_filter', 'sanitize_html_class');
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
172
173
                $custom_class = self::replace_variables( $custom_class, $form, $entry);
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
174
175
                // And then we want life to return to normal
176
                remove_filter('gform_merge_tag_filter', 'sanitize_html_class');
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
177
            }
178
179
			// And now we want the spaces to be handled nicely.
180 3
			$classes[] = gravityview_sanitize_html_class( $custom_class );
181 3
182 3
		}
183
184
		if(!empty($field['id'])) {
0 ignored issues
show
introduced by
No space after opening parenthesis is prohibited
Loading history...
introduced by
Expected 1 space before "!"; 0 found
Loading history...
introduced by
Expected 1 space after "!"; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
introduced by
No space before closing parenthesis is prohibited
Loading history...
185
			if( !empty( $form ) && !empty( $form['id'] ) ) {
0 ignored issues
show
introduced by
Expected 1 space after "!"; 0 found
Loading history...
186
				$form_id = '-'.$form['id'];
187
			} else {
188
				// @deprecated path. Form should always be given.
189
				gravityview()->log->warning( 'GravityView_View::getInstance() legacy API called' );
190
				$gravityview_view = GravityView_View::getInstance();
191
				$form_id = $gravityview_view->getFormId() ? '-'. $gravityview_view->getFormId() : '';
192
			}
193
194
			$classes[] = 'gv-field'.$form_id.'-'.$field['id'];
195
		}
196
197
		return esc_attr(implode(' ', $classes));
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
198
	}
199
200
	/**
201 2
	 * Fetch Field HTML ID
202
	 *
203 2
	 * @since 1.11
204 1
	 *
205 1
	 * @access public
206
	 * @static
207
	 * @param array $field GravityView field array passed to gravityview_field_output()
208 2
	 * @param array $form Gravity Forms form array, if set.
209
	 * @param array $entry Gravity Forms entry array
210 2
	 * @return string Sanitized unique HTML `id` attribute for the field
211
	 */
212
	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...
213
		$id = $field['id'];
214 2
215
		if ( ! empty( $id ) ) {
216
			if ( ! empty( $form ) && ! empty( $form['id'] ) ) {
217
				$form_id = '-' . $form['id'];
218
			} else {
219
				// @deprecated path. Form should always be given.
220
				gravityview()->log->warning( 'GravityView_View::getInstance() legacy API called' );
221
				$gravityview_view = GravityView_View::getInstance();
222
				$form_id = $gravityview_view->getFormId() ? '-' . $gravityview_view->getFormId() : '';
223 2
			}
224
225 2
			$id = 'gv-field' . $form_id . '-' . $field['id'];
226
		}
227
228
		return esc_attr( $id );
229
	}
230
231
232
	/**
233
	 * Given an entry and a form field id, calculate the entry value for that field.
234
	 *
235
	 * @deprecated Use \GV\Field_Template::render() or the more low-level \GV\Field::get_value()
236
	 *
237 9
	 * @access public
238 9
	 * @param array $entry
239
	 * @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...
240 9
	 * @return null|string
241 7
	 */
242 7
	public static function field_value( $entry, $field_settings, $format = 'html' ) {
243
		gravityview()->log->notice( '\GravityView_API::field_value is deprecated. Use \GV\Field_Template::render() or \GV\Field::get_value()' );
244
		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...
245 2
	}
246
247 2
	/**
248 1
	 * Generate an anchor tag that links to an entry.
249
	 *
250
	 * @since 1.6
251
	 * @see GVCommon::get_link_html()
252 9
	 *
253 1
	 * @param string $anchor_text The text or HTML inside the link
254
	 * @param array $entry Gravity Forms entry array
255 9
	 * @param array|string $passed_tag_atts Attributes to be added to the anchor tag, such as `title` or `rel`.
256
	 * @param array $field_settings Array of field settings. Optional, but passed to the `gravityview_field_entry_link` filter
257
	 *
258
	 * @since 2.0
259
	 * @param int $base_id The post or the view that this entry is linked from.
260
	 *
261
	 * @return string|null Returns HTML for an anchor link. Null if $entry isn't defined or is missing an ID.
262
	 */
263
	public static function entry_link_html( $entry = array(), $anchor_text = '', $passed_tag_atts = array(), $field_settings = array(), $base_id = null ) {
264
265
		if ( empty( $entry ) || ! is_array( $entry ) || ! isset( $entry['id'] ) ) {
266 9
			gravityview()->log->debug( 'Entry not defined; returning null', array( 'data' => $entry ) );
267
			return NULL;
0 ignored issues
show
Coding Style introduced by
TRUE, FALSE and NULL must be lowercase; expected null, but found NULL.
Loading history...
268
		}
269
270
		$href = self::entry_link( $entry, $base_id );
271
272
		if( '' === $href ) {
273
			return NULL;
0 ignored issues
show
Coding Style introduced by
TRUE, FALSE and NULL must be lowercase; expected null, but found NULL.
Loading history...
274
		}
275
276 9
		$link = gravityview_get_link( $href, $anchor_text, $passed_tag_atts );
277
278 9
		/**
279
		 * @filter `gravityview_field_entry_link` Modify the link HTML
280
		 * @param string $link HTML output of the link
281
		 * @param string $href URL of the link
282
		 * @param array  $entry The GF entry array
283
		 * @param  array $field_settings Settings for the particular GV field
284
		 */
285
		$output = apply_filters( 'gravityview_field_entry_link', $link, $href, $entry, $field_settings );
286
287
		return $output;
288
	}
289
290
	/**
291
	 * Get the "No Results" text depending on whether there were results.
292
	 * @param  boolean     $wpautop Apply wpautop() to the output?
293
	 *
294 33
	 * @since 2.0
295 33
	 * @param \GV\Template_Context $context The context
296
	 *
297 33
	 * @return string               HTML of "no results" text
298
	 */
299 18
	public static function no_results( $wpautop = true, $context = null ) {
300
		$is_search = false;
301
302 18
		if ( $context instanceof \GV\Template_Context ) {
303
			if ( $context->request->is_search() ) {
304 14
				$is_search = true;
305 3
			}
306
		} else {
307
			$gravityview_view = GravityView_View::getInstance();
308
309 14
			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...
310
				$is_search = true;
311
			}
312
		}
313 4
314
		if ( $is_search ) {
315
			$output = __( 'This search returned no results.', 'gravityview' );
316 4
		} else {
317 2
			$output = __( 'No entries match your request.', 'gravityview' );
318
		}
319
320 2
		/**
321
		 * @filter `gravitview_no_entries_text` Modify the text displayed when there are no entries.
322
		 * Note: this filter is, and always has been, misspelled. This will not be fixed, since the filter is deprecated.
323
		 * @param string $output The existing "No Entries" text
324 2
		 * @param boolean $is_search Is the current page a search result, or just a multiple entries screen?
325
		 * @return string The modified text.
326 2
		 * @deprecated Use `gravityview/template/text/no_entries`
327
		 */
328
		$output = apply_filters( 'gravitview_no_entries_text', $output, $is_search );
329 1
330
		/**
331
		 * @filter `gravityview/template/text/no_entries` Modify the text displayed when there are no entries.
332
		 * @since 2.0
333
		 * @param string $output The existing "No Entries" text
334
		 * @param boolean $is_search Is the current page a search result, or just a multiple entries screen?
335
		 * @param \GV\Template_Context $context The context.
336
		 * @return string The modified text.
337
		 */
338 33
		$output = apply_filters( 'gravityview/template/text/no_entries', $output, $is_search, $context );
339 1
340
		return $wpautop ? wpautop( $output ) : $output;
341
	}
342
343
	/**
344 32
	 * Generate a URL to the Directory context
345
	 *
346 32
	 * 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!
347
	 *
348
	 * @param int $post_id Post ID
349
	 * @param boolean $add_query_args Add pagination and sorting arguments
350 32
	 *
351 32
	 * @since 2.0
352
	 * @param \GV\Template_Context $context The context this is being used in.
353
	 *
354
	 * @return string      Permalink to multiple entries view
355 32
	 */
356
	public static function directory_link( $post_id = NULL, $add_query_args = true, $context = null ) {
0 ignored issues
show
Coding Style introduced by
TRUE, FALSE and NULL must be lowercase; expected null, but found NULL.
Loading history...
357
		global $post;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
358
359 32
		if ( empty( $post_id ) ) {
360
			// DataTables passes the Post ID
361 28
			if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
362
				$post_id = \GV\Utils::_POST( 'post_id', false );
363 28
			} else {
364 1
				if ( $context instanceof \GV\Template_Context ) {
365
					// Shortcodes, embeds
366
					if ( is_a( $post, 'WP_Post' ) ) {
367 28
						$post_id = $post->ID;
368
369
					// Actual views
370
					} else {
371
						$post_id = $context->view ? $context->view->ID : false;
372 28
					}
373
				} else {
374
					/** @deprecated path of execution */
375
					$gravityview_view = GravityView_View::getInstance();
376
377
					// The Post ID has been passed via the shortcode
378
					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...
379
						$post_id = $gravityview_view->getPostId();
380
					} else {
381 32
						// This is a GravityView post type
382
						if ( GravityView_frontend::getInstance()->isGravityviewPostType() ) {
383
							$post_id = isset( $gravityview_view ) ? $gravityview_view->getViewId() : $post->ID;
384
						} else {
385
							// This is an embedded GravityView; use the embedded post's ID as the base.
386
							if ( GravityView_frontend::getInstance()->isPostHasShortcode() && is_a( $post, 'WP_Post' ) ) {
387
								$post_id = $post->ID;
388
							} elseif ( $gravityview_view->getViewId() ) {
389 32
								// The GravityView has been embedded in a widget or in a template, and
390
								// is not in the current content. Thus, we defer to the View's own ID.
391
								$post_id = $gravityview_view->getViewId();
392
							}
393
						}
394
					}
395
				}
396
			}
397
		}
398
399
		// No post ID, get outta here.
400
		if ( empty( $post_id ) ) {
401
			return null;
402
		}
403 3
404
		// If we've saved the permalink in memory, use it
405
		// @since 1.3
406 3
		$link = wp_cache_get( 'gv_directory_link_'.$post_id );
407
408
		if ( (int) $post_id === (int) get_option( 'page_on_front' ) ) {
409
			$link = home_url();
410
		}
411
412
		if ( empty( $link ) ) {
413
			$link = get_permalink( $post_id );
414 3
415
			// If not yet saved, cache the permalink.
416
			// @since 1.3
417 3
			wp_cache_set( 'gv_directory_link_'.$post_id, $link );
418
		}
419
420
		// Deal with returning to proper pagination for embedded views
421 3
		if ( $link && $add_query_args ) {
422
423
			$args = array();
424
425
			if( $pagenum = \GV\Utils::_GET( 'pagenum' ) ) {
426
				$args['pagenum'] = intval( $pagenum );
427
			}
428
429
			if( $sort = \GV\Utils::_GET( 'sort' ) ) {
430
				$args['sort'] = $sort;
431
				$args['dir'] = \GV\Utils::_GET( 'dir' );
432
			}
433
434
			$link = add_query_arg( $args, $link );
435 91
		}
436
437
		/**
438
		 * @filter `gravityview_directory_link` Modify the URL to the View "directory" context
439
		 * @since 1.19.4
440 91
		 * @param string $link URL to the View's "directory" context (Multiple Entries screen)
441
		 * @param int $post_id ID of the post to link to. If the View is embedded, it is the post or page ID
442
		 */
443
		$link = apply_filters( 'gravityview_directory_link', $link, $post_id );
444
445
		/**
446 91
		 * @filter `gravityview/view/links/directory` Modify the URL to the View "directory" context
447
		 * @since 2.0
448
		 * @param string $link URL to the View's "directory" context (Multiple Entries screen)
449 91
		 * @param \GV\Template_Context $context 
450
		 */
451
		return apply_filters( 'gravityview/view/links/directory', $link, $context );
452 3
	}
453
454
	/**
455 3
	 * Calculate an *unique* hash for an entry based on the entry ID
456
	 *
457 3
	 * 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.
458 3
	 *
459
	 * The hashed value MUST be unique, otherwise multiple entries will share the same URL, which leads to obvious problems.
460 3
	 *
461 3
	 * @param  int|string $id Entry ID to generate the hash for.
462 3
	 * @param  array  $entry        Entry data passed to provide additional information when generating the hash. Optional - don't rely on it being available.
463
	 * @return string               Hashed unique value for entry
464
	 */
465
	private static function get_custom_entry_slug( $id, $entry = array() ) {
466
467
		// Generate an unique hash to use as the default value
468 3
		$slug = substr( wp_hash( $id, 'gravityview'.$id ), 0, 8 );
469
470 3
		/**
471
		 * @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}`
472
		 * @param string $hash Existing hash generated by GravityView
473
		 * @param  string $id The entry ID
474 3
		 * @param  array $entry Entry data array. May be empty.
475 3
		 */
476
		$slug = apply_filters( 'gravityview_entry_slug', $slug, $id, $entry );
477
478
		// Make sure we have something - use the original ID as backup.
479 3
		if( empty( $slug ) ) {
480
			$slug = $id;
481
		}
482
483
		return sanitize_title( $slug );
484 3
	}
485 3
486 3
	/**
487
	 * Get the entry slug for the entry. By default, it is the entry ID.
488
	 *
489 3
	 *
490
	 * @see gravityview_get_entry()
491 3
	 * @uses GravityView_API::get_custom_entry_slug() If using custom slug, gets the custom slug value
492
	 * @since 1.4
493
	 * @param  int|string $id_or_string ID of the entry, or custom slug string
494 91
	 * @param  array  $entry        Gravity Forms Entry array, optional. Used only to provide data to customize the `gravityview_entry_slug` filter
495
	 * @return string               Unique slug ID, passed through `sanitize_title()`
496
	 */
497
	public static function get_entry_slug( $id_or_string, $entry = array() ) {
498
499
		/**
500
		 * Default: use the entry ID as the unique identifier
501
		 */
502
		$slug = $id_or_string;
503
504
		/**
505
		 * @filter `gravityview_custom_entry_slug` Whether to enable and use custom entry slugs.
506
		 * @param boolean True: Allow for slugs based on entry values. False: always use entry IDs (default)
507
		 */
508
		$custom = apply_filters( 'gravityview_custom_entry_slug', false );
509
510
		// If we're using custom slug...
511
		if ( $custom ) {
512
513
			// Get the entry hash
514
			$hash = self::get_custom_entry_slug( $id_or_string, $entry );
515
516
			// Cache the slugs
517
			static $cache = array();
518
519
			if ( ! isset( $cache[ $id_or_string ] ) ) {
520
				global $wpdb;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
521
522
				if ( version_compare( GFFormsModel::get_database_version(), '2.3-dev-1', '>=' ) ) {
523
					$table = GFFormsModel::get_entry_meta_table_name();
524
					$column = 'entry_id';
525
				} else {
526
					$table = RGFormsModel::get_lead_meta_table_name();
527
					$column = 'lead_id';
528
				}
529
530
				$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 ) );
0 ignored issues
show
introduced by
Usage of a direct database call is discouraged.
Loading history...
introduced by
Usage of a direct database call without caching is prohibited. Use wp_cache_get / wp_cache_set.
Loading history...
531
532
				if ( $results ) {
533
					$cache = array_replace( $cache, array_combine( wp_list_pluck( $results, $column ), wp_list_pluck( $results, 'meta_value' ) ) );
534 6
				}
535
536 6
				if ( ! isset( $cache[ $id_or_string ] ) ) {
537
					$cache[ $id_or_string ] = false;
538 6
				}
539
			}
540
541
			$value = $cache[ $id_or_string ];
542
543
			// If it does have a hash set, and the hash is expected, use it.
544 6
			// This check allows users to change the hash structure using the
545 1
			// gravityview_entry_hash filter and have the old hashes expire.
546
			if ( empty( $value ) || $value !== $hash ) {
547
				gravityview()->log->debug( 'Setting hash for entry {entry}: {hash}', array( 'entry' => $id_or_string, 'hash' => $hash ) );
548
				gform_update_meta( $id_or_string, 'gravityview_unique_id', $hash, \GV\Utils::get( $entry, 'form_id' ) );
549 6
			}
550
551
			$slug = $hash;
552 6
553 1
			unset( $value, $hash );
554
		}
555
556 5
		return sanitize_title( $slug );
557
	}
558 5
559
    /**
560 5
     * If using the entry custom slug feature, make sure the new entries have the custom slug created and saved as meta
561
     *
562
     * Triggered by add_action( 'gform_entry_created', array( 'GravityView_API', 'entry_create_custom_slug' ), 10, 2 );
563
     *
564
     * @param $entry array Gravity Forms entry object
565
     * @param $form array Gravity Forms form object
566
     */
567
    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...
568
        /**
569
         * @filter `gravityview_custom_entry_slug` On entry creation, check if we are using the custom entry slug feature and update the meta
570
         * @param boolean $custom Should we process the custom entry slug?
571
         */
572
        $custom = apply_filters( 'gravityview_custom_entry_slug', false );
573
        if( $custom ) {
574
            // create the gravityview_unique_id and save it
575
576 5
            // Get the entry hash
577
            $hash = self::get_custom_entry_slug( $entry['id'], $entry );
578
579
	        gravityview()->log->debug( 'Setting hash for entry {entry_id}: {hash}', array( 'entry_id' => $entry['id'], 'hash' => $hash ) );
580
581
            gform_update_meta( $entry['id'], 'gravityview_unique_id', $hash, \GV\Utils::get( $entry, 'form_id' ) );
582 5
583
        }
584 5
    }
585
586
587
588
589
	/**
590
	 * return href for single entry
591 5
	 * @param  array|int $entry   Entry array or entry ID
592
	 * @param  int|null $post_id If wanting to define the parent post, pass a post ID
593
	 * @param boolean $add_directory_args True: Add args to help return to directory; False: only include args required to get to entry {@since 1.7.3}
594
	 * @return string          Link to the entry with the directory parent slug, or empty string if embedded post or View doesn't exist
595
	 */
596
	public static function entry_link( $entry, $post_id = NULL, $add_directory_args = true ) {
0 ignored issues
show
Coding Style introduced by
TRUE, FALSE and NULL must be lowercase; expected null, but found NULL.
Loading history...
597
598 5
		if ( ! empty( $entry ) && ! is_array( $entry ) ) {
599 5
			$entry = GVCommon::get_entry( $entry );
600 5
		} else if( empty( $entry ) ) {
601 5
			// @deprecated path
602
			$entry = GravityView_frontend::getInstance()->getEntry();
603
		}
604
605
		// Second parameter used to be passed as $field; this makes sure it's not an array
606 5
		if ( ! is_numeric( $post_id ) ) {
607 1
			$post_id = NULL;
0 ignored issues
show
Coding Style introduced by
TRUE, FALSE and NULL must be lowercase; expected null, but found NULL.
Loading history...
608
		}
609
610 5
		// Get the permalink to the View
611
		$directory_link = self::directory_link( $post_id, false );
612
613
		// No post ID? Get outta here.
614
		if ( empty( $directory_link ) ) {
615
			return '';
616
		}
617
618
		$query_arg_name = \GV\Entry::get_endpoint_name();
619
620
		$entry_slug = self::get_entry_slug( $entry['id'], $entry );
621
622
		if ( get_option('permalink_structure') && !is_preview() ) {
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
introduced by
Expected 1 space after "!"; 0 found
Loading history...
623
624 2
			$args = array();
625
626
			/**
627
			 * Make sure the $directory_link doesn't contain any query otherwise it will break when adding the entry slug.
628 31
			 * @since 1.16.5
629
			 */
630
			$link_parts = explode( '?', $directory_link );
631
632
			$query = !empty( $link_parts[1] ) ? '?'.$link_parts[1] : '';
0 ignored issues
show
introduced by
Expected 1 space after "!"; 0 found
Loading history...
633
634
			$directory_link = trailingslashit( $link_parts[0] ) . $query_arg_name . '/'. $entry_slug .'/' . $query;
635
636
		} else {
637
638
			$args = array( $query_arg_name => $entry_slug );
639
		}
640
641
		/**
642
		 * @since 1.7.3
643
		 */
644
		if ( $add_directory_args ) {
645 32
646 30
			if ( ! empty( $_GET['pagenum'] ) ) {
647 30
				$args['pagenum'] = intval( $_GET['pagenum'] );
0 ignored issues
show
introduced by
Detected access of super global var $_GET, probably need manual inspection.
Loading history...
648 30
			}
649 30
650 30
			/**
651 30
			 * @since 1.7
652 4
			 */
653
			if ( $sort = \GV\Utils::_GET( 'sort' ) ) {
654
				$args['sort'] = $sort;
655 30
				$args['dir'] = \GV\Utils::_GET( 'dir' );
656 18
			}
657 14
658 30
		}
659
660
		if( $post_id ) {
661
			$passed_post = get_post( $post_id );
662 3
			$views       = \GV\View_Collection::from_post( $passed_post );
663 3
			$has_multiple_views = $views->count() > 1;
664 3
		} else {
665
			$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...
666
		}
667 32
668
		if ( $has_multiple_views ) {
669 32
			$args['gvid'] = gravityview_get_view_id();
670
		}
671 32
672 4
		return add_query_arg( $args, $directory_link );
673
674
	}
675 32
676 7
677
}
678
679 32
680
// inside loop functions
681
682
/**
683
 * @deprecated Use \GV\Field::get_label()
684
 */
685
function gv_label( $field, $entry = NULL ) {
0 ignored issues
show
Coding Style introduced by
TRUE, FALSE and NULL must be lowercase; expected null, but found NULL.
Loading history...
686
	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...
687
}
688 32
689
function gv_class( $field, $form = NULL, $entry = array() ) {
0 ignored issues
show
Coding Style introduced by
TRUE, FALSE and NULL must be lowercase; expected null, but found NULL.
Loading history...
690 32
	return GravityView_API::field_class( $field, $form, $entry  );
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces before closing bracket; 2 found
Loading history...
691
}
692 32
693 32
/**
694
 * Generate a CSS class to be added to the wrapper <div> of a View
695
 *
696 32
 * @since 1.5.4
697
 * @since 1.16 Added $echo parameter.
698
 * @since 2.0 Added $context parameter.
699
 *
700
 * @param string $passed_css_class Default: `gv-container gv-container-{view id}`. If View is hidden until search, adds ` hidden`
701
 * @param boolean $echo Whether to echo the output. Default: true
702
 * @param \GV\Template_Context $context The template context.
703
 *
704 2
 * @return string CSS class, sanitized by gravityview_sanitize_html_class()
705
 */
706 2
function gv_container_class( $passed_css_class = '', $echo = true, $context = null ) {
707
	if ( $context instanceof \GV\Template_Context ) {
708
		$hide_until_searched = false;
709
		$total_entries = 0;
710
		$view_id = 0;
711 1
		if ( $context->view ) {
712
			$view_id = $context->view->ID;
713
			if( $context->view->settings->get( 'hide_until_searched' ) ) {
714 2
				$hide_until_searched = ( empty( $context->entry ) && ! $context->request->is_search() );
715
			}
716
		}
717
		if ( $context->entries ) {
718 15
			$total_entries = $context->entries->total();
719
		} else if ( $context->entry ) {
720
			$total_entries = 1;
721
		}
722 2
	} else {
723
		/** @deprecated legacy execution path */
724
		$view_id = GravityView_View::getInstance()->getViewId();
725
		$hide_until_searched = GravityView_View::getInstance()->isHideUntilSearched();
726 8
		$total_entries = GravityView_View::getInstance()->getTotalEntries();
727
	}
728
729
	$passed_css_class = trim( $passed_css_class );
730
731
	$default_css_class = ! empty( $view_id ) ? sprintf( 'gv-container gv-container-%d', $view_id ) : 'gv-container';
732
733
	if ( $hide_until_searched ) {
734
		$default_css_class .= ' hidden';
735
	}
736
737
	if ( 0 === $total_entries ) {
738 14
		$default_css_class .= ' gv-container-no-results';
739
	}
740
741
	$css_class = trim( $passed_css_class . ' '. $default_css_class );
742
743
	/**
744
	 * @filter `gravityview/render/container/class` Modify the CSS class to be added to the wrapper <div> of a View
745
	 * @since 1.5.4
746
	 * @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`
747 14
	 * @since 2.0
748
	 * @param \GV\Template_Context $context The context.
749
	 */
750
	$css_class = apply_filters( 'gravityview/render/container/class', $css_class, $context );
751
752
	$css_class = gravityview_sanitize_html_class( $css_class );
753
754
	if ( $echo ) {
755
		echo $css_class;
0 ignored issues
show
introduced by
Expected next thing to be a escaping function, not '$css_class'
Loading history...
756 14
	}
757
758 14
	return $css_class;
759 3
}
760
761
/**
762 12
 * @deprecated Use \GV\Field_Template::render()
763 12
 */
764 12
function gv_value( $entry, $field ) {
765
766
	$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...
767
768
	if( $value === '' ) {
769
		/**
770
		 * @filter `gravityview_empty_value` What to display when a field is empty
771
		 * @param string $value (empty string)
772
		 */
773 12
		$value = apply_filters( 'gravityview_empty_value', '' );
774
	}
775
776
	return $value;
777
}
778
779
function gv_directory_link( $post = NULL, $add_pagination = true, $context = null ) {
0 ignored issues
show
introduced by
Overridding WordPress globals is prohibited
Loading history...
Coding Style introduced by
TRUE, FALSE and NULL must be lowercase; expected null, but found NULL.
Loading history...
780
	return GravityView_API::directory_link( $post, $add_pagination, $context );
781 12
}
782
783
function gv_entry_link( $entry, $post_id = NULL ) {
0 ignored issues
show
Coding Style introduced by
TRUE, FALSE and NULL must be lowercase; expected null, but found NULL.
Loading history...
784
	return GravityView_API::entry_link( $entry, $post_id );
785
}
786
787
function gv_no_results( $wpautop = true, $context = null ) {
788
	return GravityView_API::no_results( $wpautop, $context );
789
}
790 12
791
/**
792
 * Generate HTML for the back link from single entry view
793
 * @since 1.0.1
794
 * @since 2.0
795
 * @param \GV\Template_Context $context The context this link is being displayed from.
796
 * @return string|null      If no GV post exists, null. Otherwise, HTML string of back link.
797
 */
798 12
function gravityview_back_link( $context = null ) {
799
800 12
	$href = gv_directory_link( null, true, $context );
801
802 12
	/**
803
	 * @filter `gravityview_go_back_url` Modify the back link URL
804
	 * @since 1.17.5
805
	 * @see gv_directory_link() Generated the original back link
806
	 * @param string $href Existing label URL
807
	 * @deprecated Use `gravityview/template/links/back/url`
808
	 */
809
	$href = apply_filters( 'gravityview_go_back_url', $href );
810
811
	/**
812
	 * @filter `gravityview/template/links/back/url` Modify the back link URL
813
	 * @since 2.0
814
	 * @see gv_directory_link() Generated the original back link
815
	 * @param string $href Existing label URL
816
	 * @param \GV\Template_Context The context.
817
	 */
818
	$href = apply_filters( 'gravityview/template/links/back/url', $href, $context );
819 9
820
	if ( empty( $href ) ) {
821
		return NULL;
0 ignored issues
show
Coding Style introduced by
TRUE, FALSE and NULL must be lowercase; expected null, but found NULL.
Loading history...
822 6
	}
823
824
	if ( $context instanceof \GV\Template_Context ) {
825
		$view_id = $context->view->ID;
826
		$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...
827 7
	} else {
828
		/** @deprecated legacy path */
829
		$gravityview_view = GravityView_View::getInstance();
830
		$view_id = $gravityview_view->getViewId();
831
		$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...
832
	}
833
834
	/** Default */
835
	$label = $view_label ? $view_label : __( '&larr; Go back', 'gravityview' );
836
837
	/**
838
	 * @filter `gravityview_go_back_label` Modify the back link text
839
	 * @since 1.0.9
840
	 * @param string $label Existing label text
841
	 * @deprecated Use `gravityview/template/links/back/label`
842
	 */
843
	$label = apply_filters( 'gravityview_go_back_label', $label );
844
845 1
	/**
846
	 * @filter `gravityview/template/links/back/label` Modify the back link text
847 1
	 * @since 2.0
848 1
	 * @see gv_directory_link() Generated the original back link
849
	 * @param string $label Existing label text
850 1
	 * @param \GV\Template_Context The context.
851
	 */
852
	$label = apply_filters( 'gravityview/template/links/back/label', $label, $context );
853 1
854
	/**
855
	 * @filter `gravityview/template/links/back/atts` Modify the attributes used on the back link anchor tag
856 1
	 * @since 2.1
857
	 * @param array $atts Original attributes, default: [ data-viewid => $view_id ]
858
	 * @param \GV\Template_Context The context.
859 1
	 */
860
	$atts = apply_filters( 'gravityview/template/links/back/atts', array( 'data-viewid' => $view_id ), $context );
861
862 1
	$link = gravityview_get_link( $href, esc_html( $label ), $atts );
863 1
864
	return $link;
865
}
866 1
867
/**
868
 * Handle getting values for complex Gravity Forms fields
869
 *
870
 * If the field is complex, like a product, the field ID, for example, 11, won't exist. Instead,
871 1
 * it will be 11.1, 11.2, and 11.3. This handles being passed 11 and 11.2 with the same function.
872
 *
873
 * @since 1.0.4
874
 * @param  array      $entry    GF entry array
875 1
 * @param  string      $field_id [description]
876
 * @param  string 	$display_value The value generated by Gravity Forms
877 1
 * @return string                Value
878
 */
879
function gravityview_get_field_value( $entry, $field_id, $display_value ) {
880 1
881
	if( floatval( $field_id ) === floor( floatval( $field_id ) ) ) {
882
883
		// For the complete field value as generated by Gravity Forms
884 1
		return $display_value;
885
886
	} else {
887
888 1
		// For one part of the address (City, ZIP, etc.)
889
		return isset( $entry[ $field_id ] ) ? $entry[ $field_id ] : '';
890
891
	}
892
893
}
894
895
/**
896
 * Take a passed CSV of terms and generate a linked list of terms
897
 *
898
 * Gravity Forms passes categories as "Name:ID" so we handle that using the ID, which
899
 * is more accurate than checking the name, which is more likely to change.
900 1
 *
901
 * @param  string      $value    Existing value
902 1
 * @param  string      $taxonomy Type of term (`post_tag` or `category`)
903 1
 * @return string                CSV of linked terms
904
 */
905
function gravityview_convert_value_to_term_list( $value, $taxonomy = 'post_tag' ) {
906 1
907
	$output = array();
908
909
	if ( is_array( $value ) ) {
910
		$terms = array_filter( array_values( $value ), 'strlen' );
911
	} else {
912
		$terms = explode( ', ', $value );
913
	}
914
915
	foreach ($terms as $term_name ) {
0 ignored issues
show
introduced by
No space after opening parenthesis is prohibited
Loading history...
916
917
		// If we're processing a category,
918
		if( $taxonomy === 'category' ) {
0 ignored issues
show
introduced by
Found "=== '". Use Yoda Condition checks, you must
Loading history...
919 1
920
			// Use rgexplode to prevent errors if : doesn't exist
921
			list( $term_name, $term_id ) = rgexplode( ':', $term_name, 2 );
922 1
923
			// The explode was succesful; we have the category ID
924 1
			if( !empty( $term_id )) {
0 ignored issues
show
introduced by
Expected 1 space after "!"; 0 found
Loading history...
introduced by
No space before closing parenthesis is prohibited
Loading history...
925
				$term = get_term_by( 'id', $term_id, $taxonomy );
926 1
			} else {
927
			// We have to fall back to the name
928
				$term = get_term_by( 'name', $term_name, $taxonomy );
929
			}
930 1
931
		} else {
932
			// Use the name of the tag to get the full term information
933
			$term = get_term_by( 'name', $term_name, $taxonomy );
934
		}
935
936
		// There's still a tag/category here.
937 1
		if( $term ) {
938
939
			$term_link = get_term_link( $term, $taxonomy );
940
941
			// If there was an error, continue to the next term.
942
			if ( is_wp_error( $term_link ) ) {
943
			    continue;
944
			}
945
946
			$output[] = gravityview_get_link( $term_link, esc_html( $term->name ) );
947
		}
948
	}
949
950
	return implode(', ', $output );
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
951
}
952
953
/**
954
 * Get the links for post_tags and post_category output based on post ID
955
 * @param  int      $post_id  The ID of the post
956
 * @param  boolean     $link     Add links or no?
957
 * @param  string      $taxonomy Taxonomy of term to fetch.
958
 * @return string                String with terms
959
 */
960
function gravityview_get_the_term_list( $post_id, $link = true, $taxonomy = 'post_tag' ) {
961
962
	$output = get_the_term_list( $post_id, $taxonomy, NULL, ', ' );
0 ignored issues
show
Coding Style introduced by
TRUE, FALSE and NULL must be lowercase; expected null, but found NULL.
Loading history...
963
964
	if( empty( $link ) ) {
965
		return strip_tags( $output);
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
966 31
	}
967 29
968 29
	return $output;
969
970
}
971
972
973 29
/**
974
 * Get all views processed so far for the current page load
975
 *
976
 * @see  GravityView_View_Data::add_view()
977
 * @return array Array of View data, each View data with `id`, `view_id`, `form_id`, `template_id`, `atts`, `fields`, `widgets`, `form` keys.
978 29
 */
979
function gravityview_get_current_views() {
980
981
	$fe = GravityView_frontend::getInstance();
982
983
	// Solve problem when loading content via admin-ajax.php
984
	if( ! $fe->getGvOutputData() ) {
985
986
		gravityview()->log->debug( 'gv_output_data not defined; parsing content.' );
987 2
988 2
		$fe->parse_content();
989
	}
990
991
	// Make 100% sure that we're dealing with a properly called situation
992
	if( !is_a( $fe->getGvOutputData(), 'GravityView_View_Data' ) ) {
0 ignored issues
show
introduced by
Expected 1 space after "!"; 0 found
Loading history...
993
994
		gravityview()->log->debug( 'gv_output_data not an object or get_view not callable.', array( 'data' => $fe->getGvOutputData() ) );
995 27
996 25
		return array();
997 25
	}
998
999
	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...
1000
}
1001
1002 25
/**
1003
 * Get data for a specific view
1004
 *
1005
 * @see  GravityView_View_Data::get_view()
1006
 * @return array View data with `id`, `view_id`, `form_id`, `template_id`, `atts`, `fields`, `widgets`, `form` keys.
1007 25
 */
1008
function gravityview_get_current_view_data( $view_id = 0 ) {
1009
1010
	$fe = GravityView_frontend::getInstance();
1011
1012
	// If not set, grab the current view ID
1013
	if ( empty( $view_id ) ) {
1014
		$view_id = $fe->get_context_view_id();
1015
	}
1016 2
1017 2
	if ( ! $fe->getGvOutputData() ) { return array(); }
1018
1019
	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...
1020
}
1021
1022
// Templates' hooks
1023
function gravityview_before() {
1024 27
	/**
1025 25
	 * @action `gravityview/template/before` Append content to the view.
1026 25
	 * @param object $gravityview The $gravityview object available in templates.
1027
	 */
1028
	if ( count( $args = func_get_args() ) ) {
1029
		$gravityview = reset( $args );
1030
		if ( $gravityview instanceof \GV\Template_Context ) {
1031 25
			/**
1032
			 * @action `gravityview/template/before` Prepend content to the view.
1033
			 * @param \GV\Template_Context $gravityview The $gravityview object available in templates.
1034
			 */
1035
			do_action( 'gravityview/template/before', $gravityview );
1036 25
1037
			/**
1038
			 * @deprecated Use `gravityview/template/before`
1039
			 */
1040
			return do_action( 'gravityview_before', $gravityview->view->ID );
1041
		}
1042
	}
1043
1044
	/**
1045 2
	 * @action `gravityview_before` Prepend content to the View container `<div>`
1046 2
	 * @deprecated Use `gravityview/template/before`.
1047
	 * @param int $view_id The ID of the View being displayed
1048
	 */
1049 31
	do_action( 'gravityview_before', gravityview_get_view_id() );
1050 29
}
1051 29
1052
function gravityview_header() {
1053
	/**
1054
	 * @action `gravityview/template/header` Append content to the view.
1055
	 * @param object $gravityview The $gravityview object available in templates.
1056 29
	 */
1057
	if ( count( $args = func_get_args() ) ) {
1058
		$gravityview = reset( $args );
1059
		if ( $gravityview instanceof \GV\Template_Context ) {
1060
			/**
1061 29
			 * @action `gravityview/template/header` Prepend content to the view container <div>.
1062
			 * @param \GV\Template_Context $gravityview The $gravityview object available in templates.
1063 29
			 */
1064
			do_action( 'gravityview/template/header', $gravityview );
1065
1066
			/**
1067
			 * @deprecated Use `gravityview/template/header`
1068
			 */
1069
			return do_action( 'gravityview_header', $gravityview->view->ID );
1070
		}
1071
	}
1072 2
1073 2
	/**
1074
	 * @action `gravityview_header` Prepend content to the View container `<div>`
1075
	 * @deprecated Use `gravityview/template/header`.
1076
	 * @param int $view_id The ID of the View being displayed
1077
	 */
1078
	do_action( 'gravityview_header', gravityview_get_view_id() );
1079
}
1080
1081
function gravityview_footer() {
1082
	/**
1083
	 * @action `gravityview/template/footer` Append content to the view.
1084 2
	 * @param object $gravityview The $gravityview object available in templates.
1085
	 */
1086
	if ( count( $args = func_get_args() ) ) {
1087
		$gravityview = reset( $args );
1088 2
		if ( $gravityview instanceof \GV\Template_Context ) {
1089
			/**
1090
			 * @action `gravityview/template/footer` Prepend outside of the view container <div>.
1091
			 * @param \GV\Template_Context $gravityview The $gravityview object available in templates.
1092
			 */
1093
			do_action( 'gravityview/template/footer', $gravityview );
1094
1095
			/**
1096
			 * @deprecated Use `gravityview/template/footer`
1097
			 */
1098
			return do_action( 'gravityview_footer', $gravityview->view->ID );
1099
		}
1100
	}
1101
1102
	/**
1103
	 * @action `gravityview_after` Display content after a View. Used to render footer widget areas. Rendered outside the View container `<div>`
1104
	 * @deprecated Use `gravityview/template/footer`.
1105 4
	 * @param int $view_id The ID of the View being displayed
1106
	 */
1107 4
	do_action( 'gravityview_footer', gravityview_get_view_id() );
1108
}
1109
1110
function gravityview_after() {
1111
	if ( count( $args = func_get_args() ) ) {
1112
		$gravityview = reset( $args );
1113
		if ( $gravityview instanceof \GV\Template_Context ) {
1114
			/**
1115
			 * @action `gravityview/template/after` Append content to the view.
1116 4
			 * @param \GV\Template_Context $gravityview The $gravityview object available in templates.
1117
			 */
1118 4
			do_action( 'gravityview/template/after', $gravityview );
1119
1120 4
			/**
1121 1
			 * @deprecated Use `gravityview/template/after`
1122 3
			 */
1123 2
			do_action( 'gravityview_after', $gravityview->view->ID );
1124
1125
			return;
1126 1
		}
1127
	}
1128
1129
	/**
1130
	 * @action `gravityview_after` Append content to the View container `<div>`
1131
	 * @deprecated Use `gravityview/template/after`
1132
	 * @param int $view_id The ID of the View being displayed
1133
	 */
1134
	do_action( 'gravityview_after', gravityview_get_view_id() );
1135
}
1136
1137
/**
1138
 * Get the current View ID being rendered
1139
 *
1140
 * @global GravityView_View $gravityview_view
1141
 *
1142
 * @return int View ID, if exists. `0` if `GravityView_View` doesn't exist, like in the admin, or no View is set.
1143
 */
1144
function gravityview_get_view_id() {
1145
1146
	if ( ! class_exists( 'GravityView_View' ) ) {
1147
		return 0;
1148
	}
1149
1150
	return GravityView_View::getInstance()->getViewId();
1151
}
1152 3
1153
/**
1154
 * Returns the current GravityView context, or empty string if not GravityView
1155
 *
1156 3
 * - Returns empty string on GravityView archive pages
1157
 * - Returns empty string on archive pages containing embedded Views
1158
 * - Returns empty string for embedded Views, not 'directory'
1159
 * - Returns empty string for embedded entries (oEmbed or [gventry]), not 'single'
1160 3
 * - Returns 'single' when viewing a [gravityview] shortcode-embedded single entry
1161
 *
1162
 * @global GravityView_View $gravityview_view
1163
 * @deprecated since 2.0.6.2 Use `gravityview()->request`
1164 3
 * @return string View context "directory", "single", "edit", or empty string if not GravityView
1165
 */
1166
function gravityview_get_context() {
1167
	global $wp_query;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
1168
1169
	if ( isset( $wp_query ) && $wp_query->post_count > 1 ) {
1170
		return '';
1171
	}
1172
1173
	/**
1174
	 * @filter `gravityview_is_edit_entry` Whether we're currently on the Edit Entry screen \n
1175
	 * The Edit Entry functionality overrides this value.
1176
	 * @param boolean $is_edit_entry
1177
	 */
1178
	$is_edit_entry = apply_filters( 'gravityview_is_edit_entry', false );
1179
1180
	if ( $is_edit_entry ) {
1181
		return 'edit';
1182
	} else if ( gravityview()->request->is_entry() ) {
1183
		return 'single';
1184
	} else if ( gravityview()->request->is_view() ) {
1185
		return 'directory';
1186
	}
1187
1188
	return '';
1189
}
1190
1191
1192
/**
1193
 * Return an array of files prepared for output. Wrapper for GravityView_Field_FileUpload::get_files_array()
1194
 *
1195
 * Processes files by file type and generates unique output for each.
1196
 *
1197
 * Returns array for each file, with the following keys:
1198
 *
1199
 * `file_path` => The file path of the file, with a line break
1200
 * `html` => The file output HTML formatted
1201
 *
1202
 * @see GravityView_Field_FileUpload::get_files_array()
1203
 *
1204
 * @since  1.2
1205
 * @param  string $value    Field value passed by Gravity Forms. String of file URL, or serialized string of file URL array
1206
 * @param  string $gv_class Field class to add to the output HTML
1207
 * @since  2.0
1208
 * @param  \GV\Template_Context $context The context
1209
 * @return array           Array of file output, with `file_path` and `html` keys (see comments above)
1210
 */
1211
function gravityview_get_files_array( $value, $gv_class = '', $context = null ) {
1212
	/** @define "GRAVITYVIEW_DIR" "../" */
1213
1214
	if( !class_exists( 'GravityView_Field' ) ) {
0 ignored issues
show
introduced by
Expected 1 space after "!"; 0 found
Loading history...
1215
		include_once( GRAVITYVIEW_DIR .'includes/fields/class-gravityview-field.php' );
1216
	}
1217
1218
	if( !class_exists( 'GravityView_Field_FileUpload' ) ) {
0 ignored issues
show
introduced by
Expected 1 space after "!"; 0 found
Loading history...
1219
		include_once( GRAVITYVIEW_DIR .'includes/fields/class-gravityview-field-fileupload.php' );
1220 28
	}
1221
1222
	if ( is_null( $context ) ) {
1223
		_doing_it_wrong( __FUNCTION__, '2.0', 'Please pass an \GV\Template_Context object as the 3rd parameter' );
1224
	}
1225
1226
	return GravityView_Field_FileUpload::get_files_array( $value, $gv_class, $context );
1227
}
1228
1229
/**
1230 28
 * Generate a mapping link from an address
1231
 *
1232
 * The address should be plain text with new line (`\n`) or `<br />` line breaks separating sections
1233
 *
1234
 * @todo use GF's field get_export_value() instead
1235
 *
1236
 * @see https://gravityview.co/support/documentation/201608159 Read how to modify the link
1237
 * @param  string $address Address
1238
 * @return string          URL of link to map of address
1239
 */
1240
function gravityview_get_map_link( $address ) {
1241 28
1242
	$address_qs = str_replace( array( '<br />', "\n" ), ' ', $address ); // Replace \n with spaces
1243
	$address_qs = urlencode( $address_qs );
1244
1245
	$url = "https://maps.google.com/maps?q={$address_qs}";
1246
1247
	$link_text = esc_html__( 'Map It', 'gravityview' );
1248
1249
	$link = gravityview_get_link( $url, $link_text, 'class=map-it-link' );
1250 28
1251
	/**
1252 28
	 * @filter `gravityview_map_link` Modify the map link generated. You can use a different mapping service, for example.
1253 26
	 * @param[in,out]  string $link Map link
1254
	 * @param[in] string $address Address to generate link for
1255 26
	 * @param[in] string $url URL generated by the function
1256
	 */
1257
	$link = apply_filters( 'gravityview_map_link', $link, $address, $url );
1258
1259
	return $link;
1260 2
}
1261
1262
1263
/**
1264
 * Output field based on a certain html markup
1265
 *
1266 28
 *   markup - string to be used on a sprintf statement.
1267 26
 *      Use:
1268 26
 *         {{label}} - field label
1269 26
 *         {{value}} - entry field value
1270
 *         {{class}} - field class
1271
 *
1272 2
 *   wpautop - true will filter the value using wpautop function
1273 2
 *
1274 2
 * @since  1.1.5
1275
 * @param  array $passed_args Associative array with field data. `field` and `form` are required.
1276
 * @since  2.0
1277
 * @param  \GV\Template_Context The template context.
1278
 * @return string Field output. If empty value and hide empty is true, return empty.
1279
 */
1280
function gravityview_field_output( $passed_args, $context = null ) {
1281
	$defaults = array(
1282 28
		'entry' => null,
1283
		'field' => null,
1284
		'form' => null,
1285
		'hide_empty' => true,
1286
		'markup' => '<div id="{{ field_id }}" class="{{ class }}">{{ label }}{{ value }}</div>',
1287
		'label_markup' => '',
1288
		'wpautop' => false,
1289
		'zone_id' => null,
1290
	);
1291
1292
	$args = wp_parse_args( $passed_args, $defaults );
1293 28
1294 26
	/**
1295
	 * @filter `gravityview/field_output/args` Modify the args before generation begins
1296
	 * @since 1.7
1297 2
	 * @param array $args Associative array; `field` and `form` is required.
1298
	 * @param array $passed_args Original associative array with field data. `field` and `form` are required.
1299
	 * @since 2.0
1300
	 * @param \GV\Template_Context $context The context.
1301 28
	 * @deprecated
1302 5
	 */
1303
	$args = apply_filters( 'gravityview/field_output/args', $args, $passed_args, $context );
1304
1305 28
	/**
1306 5
	 * @filter `gravityview/template/field_output/context` Modify the context before generation begins.
1307
	 * @since 2.0
1308
	 * @param[in,out] \GV\Template_Context $context The context.
1309
	 * @param array $args The sanitized arguments, these should not be trusted any longer.
1310 28
	 * @param array $passed_args The passed arguments, these should not be trusted any longer.
1311
	 */
1312
	$context = apply_filters( 'gravityview/template/field_output/context', $context, $args, $passed_args );
1313 28
1314
	if ( $context instanceof \GV\Template_Context ) {
1315
		if ( ! $context->field || ! $context->view || ! $context->view->form ) {
1316 28
			gravityview()->log->error( 'Field or form are empty.', array( 'data' => array( $context->field, $context->view->form ) ) );
1317 28
			return '';
1318
		}
1319 28
	} else {
1320 26
		// @deprecated path
1321
		// Required fields.
1322
		if ( empty( $args['field'] ) || empty( $args['form'] ) ) {
1323 2
			gravityview()->log->error( 'Field or form are empty.', array( 'data' => $args ) );
1324
			return '';
1325
		}
1326 28
	}
1327 28
1328
	if ( $context instanceof \GV\Template_Context ) {
1329 28
		$entry = $args['entry'] ? : ( $context->entry ? $context->entry->as_entry() : array() );
1330 28
		$field = $args['field'] ? : ( $context->field ? $context->field->as_configuration() : array() );
1331
		$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...
1332
	} else {
1333
		// @deprecated path
1334
		$entry = empty( $args['entry'] ) ? array() : $args['entry'];
1335
		$field = $args['field'];
1336
		$form = $args['form'];
1337
	}
1338
1339
	/**
1340
	 * Create the content variables for replacing.
1341 28
	 * @since 1.11
1342
	 */
1343
	$placeholders = array(
1344
		'value' => '',
1345
		'width' => '',
1346
		'width:style' => '',
1347
		'label' => '',
1348
		'label_value' => '',
1349
		'label_value:esc_attr' => '',
1350 28
		'label_value:data-label' => '',
1351
		'class' => '',
1352
		'field_id' => '',
1353
	);
1354
1355
	if ( $context instanceof \GV\Template_Context ) {
1356
		$placeholders['value'] = \GV\Utils::get( $args, 'value', '' );
1357
	} else {
1358
		// @deprecated path
1359 28
		$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...
1360
	}
1361
1362
	// If the value is empty and we're hiding empty, return empty.
1363
	if ( $placeholders['value'] === '' && ! empty( $args['hide_empty'] ) ) {
1364
		return '';
1365 28
	}
1366
1367
	if ( $placeholders['value'] !== '' && ! empty( $args['wpautop'] ) ) {
1368 28
		$placeholders['value'] = wpautop( $placeholders['value'] );
1369 28
	}
1370
1371
	// Get width setting, if exists
1372
	$placeholders['width'] = GravityView_API::field_width( $field );
1373
1374 28
	// If replacing with CSS inline formatting, let's do it.
1375 28
	$placeholders['width:style'] = GravityView_API::field_width( $field, 'width:' . $placeholders['width'] . '%;' );
1376
1377
	// Grab the Class using `gv_class`
1378
	$placeholders['class'] = gv_class( $field, $form, $entry );
1379
	$placeholders['field_id'] = GravityView_API::field_html_attr_id( $field, $form, $entry );
1380
1381
	if ( $context instanceof \GV\Template_Context ) {
1382
		$placeholders['label_value'] = \GV\Utils::get( $args, 'label' );
1383
	} else {
1384
		// Default Label value
1385
		$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...
1386 28
	}
1387
1388
	$placeholders['label_value:data-label'] = trim( esc_attr( strip_tags( str_replace( '>&nbsp;', '>', $placeholders['label_value'] ) ) ) );
1389 28
	$placeholders['label_value:esc_attr'] = esc_attr( $placeholders['label_value'] );
1390
1391
	if ( empty( $placeholders['label'] ) && ! empty( $placeholders['label_value'] ) ){
1392
		$placeholders['label'] = '<span class="gv-field-label">{{ label_value }}</span>';
1393
	}
1394
1395
	/**
1396
	 * @filter `gravityview/field_output/pre_html` Allow Pre filtering of the HTML
1397
	 * @since 1.11
1398
	 * @param string $markup The HTML for the markup
1399 28
	 * @param array $args All args for the field output
1400
	 * @since 2.0
1401
	 * @param \GV\Template_Context $context The context.
1402
	 */
1403
	$html = apply_filters( 'gravityview/field_output/pre_html', $args['markup'], $args, $context );
1404
1405
	/**
1406
	 * @filter `gravityview/field_output/open_tag` Modify the opening tags for the template content placeholders
1407
	 * @since 1.11
1408 28
	 * @param string $open_tag Open tag for template content placeholders. Default: `{{`
1409
	 * @since 2.0
1410
	 * @param \GV\Template_Context $context The context.
1411 28
	 */
1412
	$open_tag = apply_filters( 'gravityview/field_output/open_tag', '{{', $args, $context );
1413 28
1414
	/**
1415
	 * @filter `gravityview/field_output/close_tag` Modify the closing tags for the template content placeholders
1416
	 * @since 1.11
1417
	 * @param string $close_tag Close tag for template content placeholders. Default: `}}`
1418
	 * @since 2.0
1419
	 * @param \GV\Template_Context $context The context.
1420
	 */
1421
	$close_tag = apply_filters( 'gravityview/field_output/close_tag', '}}', $args, $context );
1422
1423
	/**
1424
	 * Loop through each of the tags to replace and replace both `{{tag}}` and `{{ tag }}` with the values
1425
	 * @since 1.11
1426
	 */
1427
	foreach ( $placeholders as $tag => $value ) {
1428
1429
		// If the tag doesn't exist just skip it
1430
		if ( false === strpos( $html, $open_tag . $tag . $close_tag ) && false === strpos( $html, $open_tag . ' ' . $tag . ' ' . $close_tag ) ){
1431
			continue;
1432
		}
1433
1434
		// Array to search
1435
		$search = array(
1436
			$open_tag . $tag . $close_tag,
1437
			$open_tag . ' ' . $tag . ' ' . $close_tag,
1438
		);
1439
1440
		/**
1441
		 * `gravityview/field_output/context/{$tag}` Allow users to filter content on context
1442
		 * @since 1.11
1443
		 * @param string $value The content to be shown instead of the {{tag}} placeholder
1444
		 * @param array $args Arguments passed to the function
1445
		 * @since 2.0
1446
		 * @param \GV\Template_Context $context The context.
1447
		 */
1448
		$value = apply_filters( 'gravityview/field_output/context/' . $tag, $value, $args, $context );
1449
1450
		// Finally do the replace
1451
		$html = str_replace( $search, $value, $html );
1452
	}
1453
1454
	/**
1455
	 * @filter `gravityview_field_output` Modify field HTML output
1456
	 * @param string $html Existing HTML output
1457
	 * @param array $args Arguments passed to the function
1458
	 * @since 2.0
1459
	 * @param \GV\Template_Context $context The context.
1460
	 */
1461
	$html = apply_filters( 'gravityview_field_output', $html, $args, $context );
1462
1463
	/**
1464
	 * @filter `gravityview/field_output/html` Modify field HTML output
1465
	 * @param string $html Existing HTML output
1466
	 * @param array $args Arguments passed to the function
1467
	 * @since 2.0
1468
	 * @param \GV\Template_Context $context The context.
1469
	 */
1470
	$html = apply_filters( 'gravityview/field_output/html', $html, $args, $context );
1471
1472
	/** @since 2.0.8 Remove unused atts */
1473
	$html = str_replace( array( ' style=""', ' class=""', ' id=""' ), '', $html );
1474
1475
	return $html;
1476
}
1477