Completed
Push — develop ( cef228...0db488 )
by Zack
07:44
created

class-api.php ➔ gv_container_class()   F

Complexity

Conditions 13
Paths 416

Size

Total Lines 58

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 29
CRAP Score 13

Importance

Changes 0
Metric Value
cc 13
nc 416
nop 3
dl 0
loc 58
ccs 29
cts 29
cp 1
crap 13
rs 3.2611
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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